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 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 RUN apk add --no-cache binutils
# Build small JRE image # Build small JRE image
...@@ -14,14 +14,17 @@ RUN $JAVA_HOME/bin/jlink \ ...@@ -14,14 +14,17 @@ RUN $JAVA_HOME/bin/jlink \
--compress=2 \ --compress=2 \
--output /customjre --output /customjre
# main app image # Main app image
FROM alpine:latest FROM alpine:latest
ENV JAVA_HOME=/jre ENV JAVA_HOME=/jre
ENV PATH="${JAVA_HOME}/bin:${PATH}" 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 COPY --from=corretto-jdk /customjre $JAVA_HOME
# Add app user # Add app user
...@@ -35,16 +38,32 @@ ARG BUILD_NUMBER= ...@@ -35,16 +38,32 @@ ARG BUILD_NUMBER=
RUN addgroup --gid $GID --system docker RUN addgroup --gid $GID --system docker
RUN adduser --no-create-home -u 1000 --ingroup docker --disabled-password $USER RUN adduser --no-create-home -u 1000 --ingroup docker --disabled-password $USER
# Prepare environment. # Prepare environment
# Create needed folders # Create needed folders
RUN mkdir /data && \ RUN mkdir -p /data /home/$USER/.ssh && \
mkdir /data/config && \ chown -R $USER:$GID /data /home/$USER/.ssh && \
chown -R $USER /data chmod 700 /home/$USER/.ssh
VOLUME /data 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 COPY --chown=1000:$GID target/dta-backend-$BUILD_NUMBER.jar app.jar
# Switch to non-root user
USER 1000:$GID 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"] ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
...@@ -8,10 +8,7 @@ import org.eclipse.jgit.api.errors.GitAPIException; ...@@ -8,10 +8,7 @@ import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider; import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.util.FileSystemUtils; import org.springframework.util.FileSystemUtils;
import org.tmatesoft.svn.core.SVNDepth; import org.tmatesoft.svn.core.*;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.auth.BasicAuthenticationManager;
import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager; import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager;
import org.tmatesoft.svn.core.wc.SVNWCUtil; import org.tmatesoft.svn.core.wc.SVNWCUtil;
import org.tmatesoft.svn.core.wc2.SvnCheckout; import org.tmatesoft.svn.core.wc2.SvnCheckout;
...@@ -20,7 +17,6 @@ import org.tmatesoft.svn.core.wc2.SvnTarget; ...@@ -20,7 +17,6 @@ import org.tmatesoft.svn.core.wc2.SvnTarget;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.net.URL;
import java.util.regex.Matcher; import java.util.regex.Matcher;
@Component @Component
...@@ -38,9 +34,9 @@ public class RepoUtil { ...@@ -38,9 +34,9 @@ public class RepoUtil {
String repoUrl = config.group(1); String repoUrl = config.group(1);
String username = config.group(2); String username = config.group(2);
String password = config.group(3); String password = config.group(3); // Not used for SSH authentication
LOG.debug(String.format("Cloning repository: %s", repoUrl)); LOG.debug("Cloning repository: {}", repoUrl);
File targetDirectory = new File(targetPath); File targetDirectory = new File(targetPath);
if (targetDirectory.exists()) { if (targetDirectory.exists()) {
...@@ -59,7 +55,9 @@ public class RepoUtil { ...@@ -59,7 +55,9 @@ public class RepoUtil {
try { try {
LOG.debug("Preparing clone..."); LOG.debug("Preparing clone...");
if (repoUrl.endsWith(".git")) { if (repoUrl.endsWith(".git")) {
// GIT Repository Clone
CloneCommand cloneCommand = Git.cloneRepository() CloneCommand cloneCommand = Git.cloneRepository()
.setDirectory(checkoutDirectory) .setDirectory(checkoutDirectory)
.setURI(repoUrl); .setURI(repoUrl);
...@@ -71,25 +69,38 @@ public class RepoUtil { ...@@ -71,25 +69,38 @@ public class RepoUtil {
LOG.debug("Cloning Git repository..."); LOG.debug("Cloning Git repository...");
cloneCommand.call().close(); cloneCommand.call().close();
} else { } else {
// SVN Repository Clone (including svn+ssh support)
SvnOperationFactory operationFactory = new SvnOperationFactory(); SvnOperationFactory operationFactory = new SvnOperationFactory();
try { try {
URL sourceUrl = new URL(repoUrl); SVNURL svnUrl = SVNURL.parseURIEncoded(repoUrl);
SVNURL svnUrl = SVNURL.create(sourceUrl.getProtocol(), null, sourceUrl.getHost(), sourceUrl.getPort(), sourceUrl.getPath(), false);
SvnCheckout checkout = operationFactory.createCheckout(); SvnCheckout checkout = operationFactory.createCheckout();
checkout.setSingleTarget(SvnTarget.fromFile(new File(targetPath))); checkout.setSingleTarget(SvnTarget.fromFile(checkoutDirectory));
checkout.setSource(SvnTarget.fromURL(svnUrl)); checkout.setSource(SvnTarget.fromURL(svnUrl));
checkout.setDepth(SVNDepth.INFINITY); checkout.setDepth(SVNDepth.INFINITY);
if (!"none".equals(username) && !"none".equals(password)) { // **Use SSH authentication if URL starts with svn+ssh://**
if (repoUrl.startsWith("https")) { if (repoUrl.startsWith("svn+ssh://")) {
LOG.debug("Setting SVN credentials for HTTPS."); LOG.debug("Setting up SSH authentication for SVN...");
operationFactory.setAuthenticationManager(new BasicAuthenticationManager(username, password));
} else if (repoUrl.startsWith("svn+ssh")) { String sshPrivateKeyPath = "/home/appuser/.ssh/id_rsa";
LOG.debug("Setting SVN credentials for SSH."); File privateKeyFile = new File(sshPrivateKeyPath);
ISVNAuthenticationManager authManager = SVNWCUtil.createDefaultAuthenticationManager(username, password.toCharArray());
operationFactory.setAuthenticationManager(authManager); 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..."); LOG.debug("Performing SVN checkout...");
...@@ -99,6 +110,7 @@ public class RepoUtil { ...@@ -99,6 +110,7 @@ public class RepoUtil {
} }
} }
// Handle subdirectory case
if (!subDir.isEmpty()) { if (!subDir.isEmpty()) {
File sourceSubDir = new File(checkoutDirectory, subDir); File sourceSubDir = new File(checkoutDirectory, subDir);
if (sourceSubDir.exists()) { if (sourceSubDir.exists()) {
...@@ -108,9 +120,11 @@ public class RepoUtil { ...@@ -108,9 +120,11 @@ public class RepoUtil {
} }
} }
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) { } catch (IOException | GitAPIException | SVNException e) {
LOG.error("Error while cloning repository: " + repoUrl, e); LOG.error("Error while cloning repository: " + repoUrl, e);
} }
} }
} }
...@@ -15,3 +15,9 @@ data.dir=/data ...@@ -15,3 +15,9 @@ data.dir=/data
data.dir.test.folder.name=UnitTests data.dir.test.folder.name=UnitTests
logging.level.de.hftstuttgart=TRACE 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