Modern Jenkins Unit 3 / Part 3: Managing Secrets in GitHub

Reading time ~10 minutes

Encrypting files in the repo with Transcrypt

Encryption

In production we will hopefully have a secrets management system, or at a very minimum private repos to store encrypted secrets in. For the purpose of this demo though I will be using a public repo and do not want to expose any sensitive data that we may need to add to this repo. WARNING: To be clear, storing any kind of secrets in a git repo, encrypted or not, may not be a good idea. Consult your local security team for advice. We however, don’t have any state secrets for this demo and very few options.

OpenSSL

Transcrypt is a shell script that uses OpenSSL to encrypt and decrypt files in your git repo that are noted in the .gitattributes file. Let’s initialize our repo and confirm that it is working.


PWD: ~/code/modern-jenkins/

# On MacOS you can use brew
brew install transcrypt

# On Linux you have to install OpenSSL then place the script in your path
yum install openssl
  
# Download the script to our PATH
wget -O /usr/local/sbin/transcrypt https://raw.githubusercontent.com/elasticdog/transcrypt/master/transcrypt
  
# Make it executable
sudo chmod +x /usr/local/sbin/transcrypt

# Confirm it works
trancrypt --help

NOTE: More information on the software can be found on the README here: https://github.com/elasticdog/transcrypt

Initialize the repo

We will initialize Transcrypt within the repo on a clean branch. This will hopefully ensure that we can configure Transcrypt prior to adding any secrets to the repo.


PWD: ~/code/modern-jenkins/

# Check out a branch and initialize transcrypt
git checkout -b chore-install_transcrypt

transcrypt
# Encrypt using which cipher? [aes-256-cbc]
# Generate a random password? [Y/n]
# 
# Repository metadata:
# 
#   GIT_WORK_TREE:  /Users/matt.bajor/code/modern-jenkins
#   GIT_DIR:        /Users/matt.bajor/code/modern-jenkins/.git
#   GIT_ATTRIBUTES: /Users/matt.bajor/code/modern-jenkins/.gitattributes
# 
# The following configuration will be saved:
# 
#   CIPHER:   aes-256-cbc
#   PASSWORD: <a really good password, trust me>
# 
# Does this look correct? [Y/n]
# 
# The repository has been successfully configured by transcrypt.

Add the generated PASSWORD to your LastPass, keychain, text document on your desktop, or wherever you store secure passwords. It is very important to not lose that passphrase.

We now want to get the .gitattributes file added up and merged in so we can test if secrets encryption is working as expected so let’s branch, commit, push and PR.


PWD: ~/code/modern-jenkins/

git add .
git commit -m "Initialize Transcrypt in the repo"
git push origin chore-install_transcrypt

# PR, review, merge and then catchup master
git checkout master
git pull
git checkout -b test-secrets

Let’s create a secrets dir and initialize it with a README to confirm that transcrypt is working as expected without potentially exposing secrets on the internet. The way transcrypt works is that it looks at the .gitattributes in the repo root for files to encrypt. If it sees that there are paths to encrypt, it will encrypt them before adding to the tree. It does still allow you to view the changes as plaintext locally which sometimes can lead to confusion as to whether or not its working.


PWD: ~/code/modern-jenkins/

# Look at the .gitattributes
cat .gitattributes
# #pattern  filter=crypt diff=crypt
  
# Echo our new pattern in there
echo 'secure/* filter=crypt diff=crypt' >> .gitattributes
  
# Confirm that the file looks good:
cat .gitattributes
# #pattern  filter=crypt diff=crypt
# secure/* filter=crypt diff=crypt 

# Add a README with a bit of info
mkdir -p secure/
echo "# Transcrypt Secrets\n\n This repo is encrypted with transcrypt" > secure/README.md

# Commit and push
git add .
git commit -m "Add test secrets"
git push origin test-secrets

When opening the PR, you should notice that there are two files changed:

  • .gitattributes
  • secure/README.md

Transcrypt Commit

You should also notice that the contents of README.md is encrypted. If this is the case, give yourself a thumbs up, merge the PR, and update your local branch.

DangerDanger

NOTE: If you see that README.md is not encrypted, do not open the PR. Instead, delete your branch and start over. Follow the instructions on the Transcrypt site if you need more help or information. It is important to confirm that the encryption mechanism is working the way we expect before we put secrets into the repo.

Let’s take this time to add a line to the PULL_REQUEST_TEMPLATE.md file reminding us to check for unencrypted secrets:


./PULL_REQUEST_TEMPLATE.MD

...
# #### Contribution checklist
#
  - [ ] THERE ARE NO UNENCRYPTED SECRETS HERE
# - [ ] The branch is named something meaningful
# - [ ] The branch is rebased off of current master}
...

Now that the repo has been initialized with Transcrypt, we can begin adding some configuration that depends on credentials. In the next segment, we will create a machine user for GitHub and configure the Git plugin to use those credentials when cloning.

The repo from this section can be found under the unit3-part3 tag here: https://github.com/technolo-g/modern-jenkins/tree/unit3-part3

Next Post: Configuring the Jenkins GitHub plugin programmatically with Groovy

Making HTTP GET and POST Requests to Docker Hub in a Jenkinsfile

Serialization requirements of pipeline makes this harder than it needs to be, but here are examples of making GET and POST requests in a Jenkinsfile Continue reading