Commit cf30aa1a authored by mamunozgil's avatar mamunozgil
Browse files

Add ssh to the backend container

No related merge requests found
Pipeline #10986 passed with stage
in 17 seconds
Showing with 81 additions and 42 deletions
+81 -42
# base image to build a JRE
# Base image to build a JRE
FROM eclipse-temurin:21-jdk-alpine as corretto-jdk
# required for strip-debug to work
# Required for strip-debug to work
RUN apk add --no-cache binutils
# Build small JRE image
......@@ -14,14 +14,17 @@ RUN $JAVA_HOME/bin/jlink \
--compress=2 \
--output /customjre
# main app image
# Main app image
FROM alpine:latest
ENV JAVA_HOME=/jre
ENV PATH="${JAVA_HOME}/bin:${PATH}"
ENV SPRING_CONFIG_ADDITIONAL_LOCATION "file:/data/config/"
ENV SPRING_CONFIG_ADDITIONAL_LOCATION="file:/data/config/"
# copy JRE from the base image
# Install OpenSSH client and required dependencies
RUN apk add --no-cache openssh-client bash
# Copy JRE from the base image
COPY --from=corretto-jdk /customjre $JAVA_HOME
# Add app user
......@@ -35,16 +38,32 @@ ARG BUILD_NUMBER=
RUN addgroup --gid $GID --system docker
RUN adduser --no-create-home -u 1000 --ingroup docker --disabled-password $USER
# Prepare environment.
# Prepare environment
# Create needed folders
RUN mkdir /data && \
mkdir /data/config && \
chown -R $USER /data
RUN mkdir -p /data /home/$USER/.ssh && \
chown -R $USER:$GID /data /home/$USER/.ssh && \
chmod 700 /home/$USER/.ssh
VOLUME /data
# Copy SSH keys from build context (MAKE SURE TO ADD THEM TO .dockerignore)
COPY --chown=1000:$GID id_rsa /home/$USER/.ssh/id_rsa
COPY --chown=1000:$GID known_hosts /home/$USER/.ssh/known_hosts
# Set proper permissions for SSH keys
RUN chmod 600 /home/$USER/.ssh/id_rsa && \
chmod 644 /home/$USER/.ssh/known_hosts && \
chown -R $USER:$GID /home/$USER/.ssh
# Copy application JAR
COPY --chown=1000:$GID target/dta-backend-$BUILD_NUMBER.jar app.jar
# Switch to non-root user
USER 1000:$GID
# Set environment variables for SVNKit SSH authentication
ENV SVN_SSH="/usr/bin/ssh"
ENV SVN_SSH_KEY="/home/$USER/.ssh/id_rsa"
# Start application
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
......@@ -8,10 +8,7 @@ import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
import org.springframework.stereotype.Component;
import org.springframework.util.FileSystemUtils;
import org.tmatesoft.svn.core.SVNDepth;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.auth.BasicAuthenticationManager;
import org.tmatesoft.svn.core.*;
import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager;
import org.tmatesoft.svn.core.wc.SVNWCUtil;
import org.tmatesoft.svn.core.wc2.SvnCheckout;
......@@ -20,7 +17,6 @@ import org.tmatesoft.svn.core.wc2.SvnTarget;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.regex.Matcher;
@Component
......@@ -35,19 +31,19 @@ public class RepoUtil {
LOG.error("Invalid repository URL format.");
return;
}
String repoUrl = config.group(1);
String username = config.group(2);
String password = config.group(3);
LOG.debug(String.format("Cloning repository: %s", repoUrl));
String password = config.group(3); // Not used for SSH authentication
LOG.debug("Cloning repository: {}", repoUrl);
File targetDirectory = new File(targetPath);
if (targetDirectory.exists()) {
LOG.debug("Target directory exists, deleting it.");
FileSystemUtils.deleteRecursively(targetDirectory);
}
File checkoutDirectory = targetDirectory;
if (!subDir.isEmpty()) {
checkoutDirectory = new File(targetPath + "_checkout");
......@@ -56,49 +52,65 @@ public class RepoUtil {
FileSystemUtils.deleteRecursively(checkoutDirectory);
}
}
try {
LOG.debug("Preparing clone...");
if (repoUrl.endsWith(".git")) {
// GIT Repository Clone
CloneCommand cloneCommand = Git.cloneRepository()
.setDirectory(checkoutDirectory)
.setURI(repoUrl);
if (!"none".equals(username) && !"none".equals(password)) {
LOG.debug("Setting Git credentials.");
cloneCommand.setCredentialsProvider(new UsernamePasswordCredentialsProvider(username, password));
}
LOG.debug("Cloning Git repository...");
cloneCommand.call().close();
} else {
// SVN Repository Clone (including svn+ssh support)
SvnOperationFactory operationFactory = new SvnOperationFactory();
try {
URL sourceUrl = new URL(repoUrl);
SVNURL svnUrl = SVNURL.create(sourceUrl.getProtocol(), null, sourceUrl.getHost(), sourceUrl.getPort(), sourceUrl.getPath(), false);
SVNURL svnUrl = SVNURL.parseURIEncoded(repoUrl);
SvnCheckout checkout = operationFactory.createCheckout();
checkout.setSingleTarget(SvnTarget.fromFile(new File(targetPath)));
checkout.setSingleTarget(SvnTarget.fromFile(checkoutDirectory));
checkout.setSource(SvnTarget.fromURL(svnUrl));
checkout.setDepth(SVNDepth.INFINITY);
if (!"none".equals(username) && !"none".equals(password)) {
if (repoUrl.startsWith("https")) {
LOG.debug("Setting SVN credentials for HTTPS.");
operationFactory.setAuthenticationManager(new BasicAuthenticationManager(username, password));
} else if (repoUrl.startsWith("svn+ssh")) {
LOG.debug("Setting SVN credentials for SSH.");
ISVNAuthenticationManager authManager = SVNWCUtil.createDefaultAuthenticationManager(username, password.toCharArray());
operationFactory.setAuthenticationManager(authManager);
// **Use SSH authentication if URL starts with svn+ssh://**
if (repoUrl.startsWith("svn+ssh://")) {
LOG.debug("Setting up SSH authentication for SVN...");
String sshPrivateKeyPath = "/home/appuser/.ssh/id_rsa";
File privateKeyFile = new File(sshPrivateKeyPath);
if (!privateKeyFile.exists()) {
LOG.error("SSH private key not found at: {}", sshPrivateKeyPath);
throw new SVNException(SVNErrorMessage.create(SVNErrorCode.AUTHN_CREDS_UNAVAILABLE, "SSH key not found"));
}
ISVNAuthenticationManager authManager = SVNWCUtil.createDefaultAuthenticationManager(
new File("/home/appuser/.ssh/id_rsa"), // Explicit SSH Key
username,
null,
new File("/home/appuser/.ssh/known_hosts"), // Explicit Known Hosts
false
);
operationFactory.setAuthenticationManager(authManager);
}
LOG.debug("Performing SVN checkout...");
checkout.run();
} finally {
operationFactory.dispose();
operationFactory.dispose();
}
}
// Handle subdirectory case
if (!subDir.isEmpty()) {
File sourceSubDir = new File(checkoutDirectory, subDir);
if (sourceSubDir.exists()) {
......@@ -107,10 +119,12 @@ public class RepoUtil {
LOG.error("Specified subdirectory does not exist.");
}
}
LOG.debug(String.format("Repository cloned from %s to %s", repoUrl, targetDirectory));
LOG.debug("Repository successfully cloned from {} to {}", repoUrl, targetDirectory);
} catch (IOException | GitAPIException | SVNException e) {
LOG.error("Error while cloning repository: " + repoUrl, e);
}
}
}
}
......@@ -14,4 +14,10 @@ host.tests.tmp.dir=${tests.tmp.dir}
data.dir=/data
data.dir.test.folder.name=UnitTests
logging.level.de.hftstuttgart=TRACE
\ No newline at end of file
logging.level.de.hftstuttgart=TRACE
################################################
# SSH directory
################################################
ssh.file=/home/appuser/.ssh/id_rsa
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment