SSH access using Jenkins pipeline and Ansible Playbook
Jenkins is a great tool with lot of powerful features inclined towards automation. I was testing out few of the features in Jenkins and found the Pipeline feature of Jenkins.
Jenkins Pipline
There is a detailed description of Jenkins Pipeline in their website, but the basic idea is this.
A file which contains step by step instruction on how to execute. For example, if you have a code repository and if you are using jenkins to create a build from this code repository, you can create a Jenkinsfile and list down step by step instructions to do that. Traditionally people used to configure this per jenkins job which would make management of each job difficult. With this approach, you can include Jenkinsfile in your code repository and do version control.
SSH Access
I created a jenkins job using pipeline feature. I’ve decided to implement a simple job which would ask for public key and list of IP address and the jenkins job will take care of adding the requested user to the boxes. I am using ansible to actually do the work of giving ssh access. Jenkins job would call the ansible playbook with right parameters.
prerequisite
Couple of things that I’ve already configured and not covered in this post.
* I've setup a jenkins in a box.
* Configured google authentication.
* Installed Build Vars plugin in jenkins to get the user details.
* Installed ansible plugin for jenkins and installed ansible in the jenkins box.
* I've a common user which have sudo access to the remote machines.
* Configured credentials of this common user in jenkins
With that said here’s my configurations,
Jenkinsfile
node {
wrap([$class: 'BuildUser']) {
username = env.BUILD_USER_ID.split('@')[0]
}
stage('downloading') {
git branch: 'master', credentialsId: 'common-user-private-key', url: '<repo_url>'
sh 'echo $pub_key > id_rsa.pub'
}
ansiblePlaybook(
playbook: 'ssh_access.yml',
inventory: env.INVENTORY_LIST + ',',
credentialsId: 'conman',
hostKeyChecking: false,
extras: '-e username=' + username
)
stage('clearout') {
deleteDir()
}
}
Shown above is a general syntax of a scripted pipeline in Jenkins.
wrap([$class: 'BuildUser']) {
username = env.BUILD_USER_ID.split('@')[0]
}
This part takes care of getting us the username of the user who triggered the build. As I said, I’ve already configured Google Auth and build user vars plugin. This would mean that we would get the email address of the user as BUILD_USER_ID.
stage('downloading') {
git branch: 'master', credentialsId: 'common-user-private-key', url: '<repo_url>'
sh 'echo $pub_key > id_rsa.pub'
}
This takes care of downloading the repo which contains our ansible playbook, for the curious one’s here’s how my directory structure looks like.
giveme-ssh-access
├── Jenkinsfile
└── ssh_access.yml
In second line of this step, we are copying the public key we received from user to a file id_rsa.pub
ansiblePlaybook(
playbook: 'ssh_access.yml',
inventory: env.INVENTORY_LIST + ',',
credentialsId: 'common-user-private-key',
hostKeyChecking: false,
extras: '-e username=' + username
)
Since we installed ansible plugin for jenkins, it would allow us to call ansible playbooks using above syntax. env.INVENTORY_LIST
will be a list of IP addresses we would be getting from the user as an input.
Here’s how my ansible-playbook would look like
---
- hosts: all
sudo: yes
tasks:
- name: make direcotry
file:
path: "/home//.ssh"
state: directory
owner: ""
group: ""
- name: copying public key
copy:
src: id_rsa.pub
dest: /home//.ssh/authorized_keys
- file:
path: /home//.ssh/authorized_keys
owner: ""
group: ""
- name: adding existing user to group sudo
user:
name: ""
groups: users
append: yes
With these done, you can now create a pipeline jenkins job. For pipeline jenkins job, select option for loading scm from Jenkins file, point it your repo containing above files. Don’t forget to configure parameters for the jenkins job,
* String parameter for getting inventory list
* Multiline string parameter for getting public key
Thats it.