Restricted connectivity per repository
For a long time CI/CD using jenkins has always been considered as the cornerstone for the DevOps environment and a key player for fast and stable deliveries thereby creating chances of security leakages within the integration.
In this article, we will discuss on the procedure to setup a production grade connectivity between github and jenkins in a secure and reliable way especially when we need one job in jenkins per github repository.
Before reading this article I expect one to be aware of few things:
- Web hooks
- Github Personal Access Management(PAM) tokens
If unaware, I’ll try to cover brief details regarding them within the article
It is always suggested to validate the signature of the incoming http request for client validation. Once a webhook fires from github,
- It initiates a hook event acting as a client to Jenkins
- In the same way , Jenkins act as a client to github while fetching the code
In both the cases it is necessary to setup establish authentication mechanism at both ends. Please refer to the rest of the article to setup this secure tunnel.
Setup Tokens in Github
For client authentication, github accept multiple approaches.
- While calling github api over HTTPS, users pass their personal user id and password as basic auth within the request. But this approach is not suggested as the process is autonomous hence it becomes a necessity to save userid/password in jenkins, which is not recommended.
- To overcome this, we can also use SSH keys where a combination of private and public keys can help, but the drawback I found here is that in this approach there is no way to manage authorization roles. For more details refer this link.
Personal Access Token
To resolve such issues, this token is the key to success. It has the capability to manage webhooks internally over HTTPS protocol which is a highly suggested approach.
Login to the Github account and click your profile photo, then click Settings.
- Click developer settings
- Click Personal Access Tokens
- Click Generate new token and select scopes(a.k.a. roles) as per the need. Generally these scopes are considered
- admin:repo_hook :- Managing hooks at repository level
- repo :- to manage private repositories
- repo:status:- manipulate commit status
- repo:repo_deployment:- manage deployment status
- repo:public_repo:- makes public repositories accessible
- user:email:- access user’s email address
For more details refer this link
The role shown above is for admin user of the github organization. Change the roles as per the user privileges(if member type) within the organization because this token belongs to a user.
After selecting scopes, click Generate token and for now copy it somewhere.
Shared Secret for secure connectivity
Disclaimer: The main reason behind writing this article is the usage of blue highlighted text box shown in the next section i.e. Secret
After configuring the jenkins server to accept webhooks, it can receive payloads from any repository. Generally, a shared secret is common to a Github organization, so it is designated as shared, but a github organization with repositories from different verticals can prefer this approach where verification of client is necessary. To create a random secret, open any bash shell and run this command,
openssl rand -base64 31
#You can keep bytes size even as this will add padding and it is #better for security. But downside is that it will have larger block #size. For more details you can refer: padding, base64
Put this secret into secret textbox while creating hooks for repositories. Now, github will create the hash signature and append this in the header “X-Hub-Signature” of each webhook payload. For more details refer this link
In Jenkins, we shall validate this hash signature to filter the incoming webhook requests using the same secret key.
Setup webhook in Github
To get webhook url from jenkins follow below written steps
- Open Jenkins and then click Manage Jenkins
- Go to Configure System
3. Scroll Down and click the highlighted Advanced Button
4. Select check box and copy the complete github webhook url and just uncheck it again
keep this configuration page open and we will come back to this
5. Now, jump to github and open your github repository setting
6. Select Hooks
7. After this, select Add webhook
- Now, paste the webhook url, copied at step 4, in payload url text box.
- Events can be anything as per requirement, but it is preferred to select “Let me select individual events” and choose specific events as per need. Generally, Pushes is enough.
- Paste the shared secret in the highlighted secret text box created in previous section.
Setup webhook & credentials in Jenkins
Till now we have,
- Shared Secret
- Personal Access Token
To begin with, jump to the Jenkins configuration page and input the github api url. (Replace the hostname with the appropriate value)
As discussed in the previous section, once the webhook is setup, the server automatically manages all events, the reason behind this is Manage hooks option.
Now, for the maintenance of all secrets and tokens we use jenkins credential manager.
Quick Tips: Tokens for jenkins management should be saved in credential manager, but token to be used within pipeline must be saved into vault systems like Hashicorp or Cyberark as a part of DevSecOps
For personal access token, create 2 entries(No need to edit ID. Let it be blank and jenkins will create it dynamically)
1. Add this token in secret text for hooks management
2. As username password for downloading code from repository
3. For shared secret create another credential of secret type and set secret as shared secret
One thing to remember is the user whom this token belongs to should have at least member type privileges in github organization
- Now in the drop down above, select personal access token saved as secret
- Next, click this button and click Add Shared Secret
- Select the shared secret credential in the drop down.
Once setup, every time jenkins receive a webhook, it will verify the signature against this key to validate the signature
To add shared secrets for different repositories, simply click Add shared secret again and jenkins will validate the signature of incoming request by their respective keys
In a nutshell, this is how secure tunnel between Github and Jenkins will setup. Now, to pull the code from Github via pipeline or any other job use personal access token credential saved as username/password. Make sure that the first webhook has must be manual and successful, and after that everything shall work automatically.