I've just dealt with this last week. With the caveat that every time I
use Jenkins I feel like I've been assaulted by aliens, here's the only
solution I found that actually worked:
- the jenkins slave has a passwordless ssh key provided to it that
*only* enables ssh to the ansible box. It cannot be used elsewhere in
the infrastructure. The key lives in $HOME of the jenkins user -
$HOME/.ssh/id_ed25519 (or id_rsa whatever key you use) as putting the
private key directly into the Jenkins config did not work.
ssh-keygen -o -t ed25519 -f /home/jenkins/.ssh/id_ed25519
"jenkins@example.org"
- the ansible server has an authorized_keys file that restricts the
above key to run a pre-selected command and 1 parameter
# /home/ansible/.ssh/authorized_keys
command="/home/ansible/src/ansible/jenkins.sh
$SSH_ORIGINAL_COMMAND",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty
ssh-ed25519 <pubkey> jenkins@example.org
- the jenkins job calls ssh and passes in 1 parameter which will be
provided to ansible
# Jenkinsfile
stage('Deploy') {
steps {
echo 'Deploy step ...'
script {
switch(env.BRANCH_NAME){
case "master" : sh 'ssh ansible@example.org production'
case "develop" : sh 'ssh ansible@example.org develop'
default : echo "... ignored in this branch"
}
}
}
- this is the script spawned by ssh
# /home/ansible/src/ansible/jenkins.sh
#!/bin/sh -xe
# restricted command for ssh to run ansible via make targets
cd /home/ansible/src/ansible
case $1 in
production) make production ;;
development) make development ;;
esac
- there is a Makefile in the root of the ansible dir that picks up the
parameter and uses it as a makefile target
# /home/ansible/src/ansible/Makefile
clean::
@git reset --hard
@git clean -fdx
@git pull --ff-only
production:: clean
ansible-playbook app.yml --limit prod,lb --diff
There is also an ssh_config and ansible.cfg files that specify ports,
private key to use, and a few other useful parameters.
There are a few things you can do to tighten security, making sure that
there is no way for jenkins to do anything other than ssh in and run
make.
- make jenkins.sh immutable
- move the authorized_keys file to somewhere like /etc/ssh/ to ensure
the command cannot be trimmed
- find a better way to handle the ansible-side ssh key. I use
hashicorp's vault here to handle that but thats a story for another day
- get the jenkins hashicorp plug to work, it doesn't for me
I'd really like to tell ansible to display output in ANSI colour even
though its running as a background task.
A+
Dave