Skip to content

Secure secrets in repositories

Sam Gleske edited this page Jan 8, 2015 · 24 revisions

Encryption Keys and secure field support

Secrets in a repository need to be hidden from unauthorized parties. This document outlines how Jervis accomplishes that. See what Travis CI documentation on the subject.

Jervis provides secure field support through the securityIO class (see Jervis groovydoc). By default Jervis uses asynchronous encryption to secure the fields; specifically 1024-bit RSA public-key encryption. The option to make the encryption stronger is available. All decrypted strings are then interpreted normally including readFile() string support. Decryption will occur before any other steps in the build process.

Note: this would generate the secure contents as plain text inside of the Jenkins job so only Jenkins administrators should be able to see the Job configuration.

Secure field support

There are a few fields in the .jervis.yml YAML file that support security. Those fields currently include:

env:
  - secure: "<secure string>"
before_install:
  - secure: "<secure string>"
install:
  - secure: "<secure string>"
before_script:
  - secure: "<secure string>"
script:
  - secure: "<secure string>"
after_success:
  - secure: "<secure string>"
after_failure:
  - secure: "<secure string>"
after_script:
  - secure: "<secure string>"

Secure from unauthorized parties

It should never be possible to see the private RSA key. The Jervis script that writes out other jobs should run on the Jenkins master. The private key should only exist on the Jenkins master. The master slave should never execute any builds as it is only dedicated to execute Jervis which is writing out other jobs.

Encrypted file support

This feature will not be released with Jervis 0.1.0. However, I'm creating this section to vent some of my ideas around how it should work.

Typically when encypting files it is desireable for the developer to be able to decrypt the files and modify them. The best way I see around doing this is by using GPG. The developer can encrypt the file using the Jervis server GPG key as well as include their own plus any developers they want to be able to decrypt that file. Then in the .jervis.yml file will need to explicitly state which files need to be decrypted. For example:

secure:
  gpg: 7257E65F
  files:
    - path/to/file.sh.gpg
    - /path/to/afile.sh.gpg

Files will be decrypted before any other steps are executed. For example, the following yaml works because the success.sh script is first decrypted and then executed.

after_success:
  - chmod 755 ./scripts/success.sh
  - ./scripts/success.sh
secure:
  gpg: 7257E65F
  files:
    - ./scripts/sucess.sh.gpg

A user can combine the secure file property with the readFile() string to include the contents in the .jervis.yml securely.

before_script:
  - secure: "encrypted string containing readFile(/scripts/success.sh)"
secure:
  gpg: 7257E65F
  files:
    - ./scripts/sucess.sh.gpg

By allowing the GPG key fingerprint used to decrypt the file to be specified in the .jervis.yml, it provides more flexibility of not requiring and Jervis source code to be modified to select the key to be used. This may instead be an environment variable. Perhaps it will be a global value as part of the Jervis configuration with the ability to optionally override in the YAML file.

Secure from unauthorized parties

Encrypted file support should only be available in an environment with disposable build images (such as docker). Disposable build images should be built with the GPG private key as part of the image. As a security measure the GPG private key should be deleted immediately after decrypting the files before executing any user code in the build process. This way developers can't write a script that dumps the private GPG key and effectively get all other users' secure files in the build system.

Deployment strategies

This feature will not be released with Jervis 0.1.0. However, I'm creating this section to vent some of my ideas around how it should work.

In addition to collecting build artifacts, perhaps Jervis should collect .jervis.yml as well as collect all encrypted *.gpg files listed in the .jervis.yml. The reason for this is typically in a large enterprise environment Development, QA, and Staging/Production networks are typically in different security zones unable to talk to each other. So builds will happen in Development only. Artifacts from the Development environment will get copied over and deployed in the QA environment. Eventually those same artifacts will land in the Staging/Production environment. That means since no clone is happening in QA or Staging/Production then no secure artifacts can be used as part of the deployment. Collecting the .jervis.yml as well as the secure *.gpg files listed in .jervis.yml would resolve this.