-
Notifications
You must be signed in to change notification settings - Fork 45
Secure secrets in repositories
Secrets in a repository need to be hidden from unauthorized parties. This document outlines how Jervis accomplishes that. See also Travis CI documentation on the subject. The security in this project is loosely based on my research in respository-secrets.
Jervis provides secure field support through the securityIO
class (see Jervis groovydoc). By default Jervis uses asymmetric encryption to secure the fields; specifically RSA public-key encryption. The option to make the encryption stronger is available. All decrypted strings are then used as environment variables in the build. This functionality is provided by the Mask Passwords plugin.
There are a few fields in the .jervis.yml
YAML file that support security. Here's example YAML.
jenkins:
secrets_id: "<Jenkins RSA key identifier>"
secrets:
- key: MY_ENVIRONMENT_VAR
secret: <rsa encrypted string>
- key: ANOTHER_ENVIRON_VAR
secret: <rsa encypted string>
The `secrets_id
The Job DSL runtime runs on the master. The private key only exists on the Jenkins master when decrypting properties. In general, the following practices are advised.
- The master should have
0
executors. If it has executors then it should be an EXCLUSIVE slave and all jobs on the system must have labels to execute on their appropriate agent. - Build jobs should never execute on the master. If a user gets a hold of the master
${JENKINS_HOME}/secret.key
file then they can effectively compromise all secrets and passwords on the system. - Additionally, jobs executing on the master can disable security by modifying
${JENKINS_HOME}/config.xml
.
Since the users can access passwords via secure properties (environment variables) then they can manage their own secure file support using symmetric encryption. They could simply store the symmetric key pass phrase as an environment variable.
A user can configure Jenkins with their own RSA private key to decrypt secrets. This means they can decide what key length they want and aren't limited by the key size other than what openssl supports. In Jervis, projects are generated in the format of <Jenkins folder>/<project name>
. The Jenkins folder
is where the credentials must be stored. This separates credentials on a per-folder basis.
Generate private and public RSA keys. The public key is used to encrypt secure properties and the private key is used within Jenkins to decrypt.
#generate private key (recommended to use 2048-bit or 4096-bit RSA keys)
openssl genrsa -out ./id_rsa 2048
openssl rsa -in ./id_rsa -pubout -outform pem -out ./id_rsa.pub
Add the RSA private key to Jenkins.
- Go to the project folder in Jenkins.
- Click on the
Credentials
link in the left hand menu. - Add a new domain and call it
secrets
. - Add a new include filter and set it to
localhost
or some other arbitrary value so that it can't be referenced in jobs. - Save the domain and enter the domain.
- Click Add Credentials.
- Add SSH Username with private key. The username doesn't matter so just set it to
secret
. - Enter the private key directly and paste in the RSA private key.
- Click on the advanced button and set the
ID
to a unique string. This is called the Jenkins credentials ID. - For clarity, set the description to be the same as the credentials ID.
Once you've configured your key in Jenkins add the following to your Jervis YAML file.
jenkins:
secrets_id: "<Jenkins credentials ID>"
Now that you have the private key installed in Jenkins let's encrypt secure properties using the public key.
echo -n 'secretplaintext' | openssl rsautl -encrypt -inkey ./id_rsa.pub -pubin | base64 -w0
In the example above, secretplaintext
is the text one wishes to encrypt. The result will be cipher text.
Add to your Jervis YAML the cipher text and give the key an environment variable name. This secure property will then be accessible in build jobs as an environment variable.
jenkins:
secrets_id: "<Jenkins credentials ID>"
secrets:
- key: "ENV_VAR"
secret: "<cipher text of secretplaintext>"
Now, when you generate a Jenkins job it will be generated with secure properties added via the Masked Passwords plugin.
- Build overview
- Supported languages
- Supported build tools
- Publish results
- Additional topics:
- Quickstart
- Background information
- Knowledge checklist
- Required Jenkins Plugins
- Labels for Jenkins Agents
- Key security concepts
- Operationalize Jenkins
- High availability
- Disaster recovery
- Pipeline support
- Extending support