Jenkins: Credentials Binding Plugin и использование нескольких Secret file в Jenkins pipeline

Автор: | 03/07/2018

Задача – запустить ansible-playbook, которому необходимо передать RSA ключ для EC2 и файл с паролем для ansible-vault, т.к. в задачах плейбука используются зашифрованные переменные.

Для этого используем Jenkins credentials, где сохраним два файла, а потом через Credentials Binding Plugin – передадим их в контейнер с задачей.

Secret file в Credentials

Сначала добавляем файлы в Jenkins.

Переходим в Credentials > Add сredentials, выбираем тип Secret file и загружаем RSA-ключ:

ID нам потребуется в Jenkins-файле для передачи в Binding plugin.

Аналогично – загружаем файл с паролем для ansbile-vault:

Jenkinsfile и Credentials Binding Plugin

Задача описывается в дух файлах – main.groovy с функциями, тут пример только одной функции ansibleApply():

def ansibleApply(tags='1', limit='2', playbookFile='3', connection='4') {

    docker.image('bm/bm-ansible:1.0').inside('-v /var/run/docker.sock:/var/run/docker.sock') {

        stage('Ansible apply') {

            withCredentials([
                file(credentialsId: 'bm-backend-dev-pem', variable: 'RSA'),
                file(credentialsId: 'backend-ansible-vault-pass', variable: 'PASSFILE')
            ]) {
                sh "ansible-playbook --private-key ${RSA} --tags ${tags} --limit=${limit} ${playbookFile} --vault-password-file ${PASSFILE} --extra-vars ansible_connection=${connection}"
            }
        }
    }
}

Собственно тут мы и используем Credentials Binding Plugin – в вызове withCredentials() задаём два файла, разделяя их запятой и используя их ID из Credentials:

...
            file(credentialsId: 'be-example-rsa', variable: 'RSA'),
            file(credentialsId: 'bm-ansible-pass-file', variable: 'PASSFILE')
...

Путь к первому сохраняем в переменной RSA, путь ко второму – в переменной PASSFILE, а затем обе переменные передаём ansible-playbok:

...
sh "ansible-playbook --private-key ${RSA} --tags ${tags} --limit=${limit} ${playbookFile} --vault-password-file ${PASSFILE} --extra-vars ansible_connection=${connection}"
...

Второй файл – mobilebackend-provision.groovy, импортирует main.groovy и вызывает ansibleApply():

#!/usr/bin/env groovy

node {

    git branch: "${BACKEND_REPO_BRANCH}", url: "${BACKEND_REPO_URL}", credentialsId: "jenkins-dev-ci-github"

    dir ('projects/mobilebackend') {

        def provision = load 'ci/main.groovy'

        provision.ansibleRolesInstall()
        provision.ansbileSyntaxCheck()

        //from the Jenkins Credentials Parameter
        // RSA = set in withCredentials()

        // infra for CloudFormation
        // from Jenkins job's parameters
        TAGS = "${env.TAGS}"

        // limit for hosts.ini
        LIMIT = "mobilebackend-dev"

        // playbook to run
        PLAYBOOK = "mobilebackend.yml"

        // file with ansible vault password
        // PASSFILE = set in withCredentials()

        // ansible_connection parameter
        // local for CloudFormation job
        // ssh for Ansible
        if ("${env.TAGS}" == "infra") {
            CONN = "local"
        } else {
            CONN = "ssh"
        }

        // ansibleApply(tags='1', limit='2', playbookFile='3', connection='4')
        provision.ansibleApply("${TAGS}", "${LIMIT}", "${PLAYBOOK}", "${CONN}")
    }
}

Переменная $TAGS используется для выбора ролей для запуска – infra будет применена к роли cloudformation, app – ко всем остальным ролям, см. пост Ansible: теги, include_vars и приоритеты переменных.

На время билда – Jenkins добавит эти Secret files из своего хранилища в контейнер, а после билда – удалит их из workspace.

Запускаем:

Готово.