nass
nass

Reputation: 347

Pass Jenkins credentials to Docker build for Composer usage

I've got a composer packages in our company's private repository on BitBucket. To access it I need to use credentials stored in Jenkins. Currently the whole build is based on Declarative Pipeline and Dockerfile. To pass credentials to Composer I need those credentials in build stage to pass them to Dockerfile.

How can I achieve it?

I've tried:

// Jenkinsfile
agent {
    dockerfile {
        label 'mylabel'
        filename '.docker/php/Dockerfile'
        args '-v /net/jenkins-ex-work/workspace:/net/jenkins-ex-work/workspace'
        additionalBuildArgs '--build-arg jenkins_usr=${JENKINS_CREDENTIALS_USR} --build-arg jenkins_credentials=${JENKINS_CREDENTIALS} --build-arg test_arg=test'
    }
}

// Dockerfile
ARG jenkins_usr
ARG jenkins_credentials
ARG test_arg

But the args are empty.

Upvotes: 4

Views: 4655

Answers (2)

BoomShaka
BoomShaka

Reputation: 1791

TL;DR Use jenkins withCredentials([sshUserPrivateKey()]) and echo the private key into id_rsa in the container.

EDITED: Removed the "run as root" step, as I think this caused issues. Instead a jenkins user is created inside the docker container with the same UID as the jenkins user that builds the docker container (no idea if that matters, but we need a user with a home dir so we can create ~/.ssh/id_rsa)

For those that suffered like me... My solution is below. It is NOT ideal as:

  1. it risks exposing your private key in the build logs if you are not careful (the below is careful, but it's easy to forget). (Although with that in mind, it appears extracting jenkins credentials is extremely easy for anyone with naughty intentions?)

So use with caution...

In my (legacy) git project, a simple php app with internal git based composer dependencies, I have

Dockerfile.build

FROM php:7.4-alpine
# install git, openssh, composer... whatever u need here, then:
# create a jenkins user inside the docker image
ARG UID=1001
RUN adduser -D -g jenkins -s /bin/sh -u $UID jenkins \
    && mkdir -p /home/jenkins/.ssh \
    && touch /home/jenkins/.ssh/id_rsa \
    && chmod 600 /home/jenkins/.ssh/id_rsa \
    && chown -R jenkins:jenkins /home/jenkins/.ssh
USER jenkins
# I think only ONE of the below are needed, not sure.
RUN echo "Host bitbucket.org\n\tStrictHostKeyChecking no\n" >> /home/jenkins/.ssh/config \ 
    && ssh-keyscan bitbucket.org >> /home/jenkins/.ssh/known_hosts

Then in my Jenkinsfile:

def sshKey = ''

pipeline {
    agent any

    environment {
        userId = sh(script: "id -u ${USER}", returnStdout: true).trim()
    }
    
    stages {
        stage('Prep') {
            steps {
                script {
                    withCredentials([
                        sshUserPrivateKey(
                            credentialsId: 'bitbucket-key',
                            keyFileVariable: 'keyFile',
                            passphraseVariable: 'passphrase',
                            usernameVariable: 'username'
                        )
                    ]) {
                        sshKey = readFile(keyFile).trim()
                    }
                }
            }
        }
        
        stage('Build') {
            agent {
                dockerfile {
                    filename 'Dockerfile.build'
                    additionalBuildArgs "--build-arg UID=${userId}"
                }
            }
            steps {
                // Turn off command trace for next line, as we dont want to log ssh key
                sh '#!/bin/sh -e\n' + "echo '${sshKey}' > /home/jenkins/.ssh/id_rsa"
                // .. proceed with whatever else, like composer install, etc

To be fair, I think some of the RUN commands in the docker container aren't even necessary, or could be run from the jenkins file? ¯_(ツ)_/¯

Upvotes: 1

VonC
VonC

Reputation: 1324947

There was a similar issue, supposedly fixed in PR 327, with pipeline-model-definition-1.3.9

So start checking the version of your plugin.

But heed also the Dockerfile warning:

It is not recommended to use build-time variables for passing secrets like github keys, user credentials etc.
Build-time variable values are visible to any user of the image with the docker history command.

Using buildkit with --secret is a better approach for that.

Upvotes: 0

Related Questions