Warning: This is currently a Work-in-progress, do not expect any kind of usability nor stability
This repository serves as a base for setting up a dockerized Jenkins instance with all configuration automated and managed in SCM.
It builds upon a great framework founded by:
- Jenkins
- Jenkins Configuration-as-Code plugin
- Jenkins JobDSL plugin
- HashiCorp Vault
Jenkins configuration taken from Git repository via Configuration-as-Code plugin.
Secrets downloaded from HashiCorp Vault.
Multiple configuration pieces possible, with user-defined priority, so it's possible to have several Jenkins instances that share a lot of configuration.
Possible uses:
- Cloning Jenkins instance with overriding e.g. notifications and agents, for testing upgrades
- Several instances sharing some parts of common configuration, while having different tweaks in every configuration.
On startup, the bootstrap script connects to Vault. The Vault's URL, credentials and path within the Vault are provided via environment variables/files, e.g. using Docker secrets. From there the scripts get the SSH keys that are preconfigured into Jenkins as a Credential, and a location of git repository containing configuration.
Later the scripts sets up and schedules a job that will clone the selected
repository, assemble configuration into the $JENKINS_HOME
folder and apply it
to the running instance.
This process ensures that:
a) There are no configuration parts present in the image, everything comes in (directly or indirectly) via environment variables.
b) The configuration process is repeatable - user can re-run the configuration job to revert to stored configuration, or periodically
c) The configuration is modular, that is an organization can have global configuration for all it's instances, with some more specific overrides.
The following configuration variables are supported:
- CASCB_VAULT_URL - The URL to Vault server
- CASCB_VAULT_USER - The username used to login
- CASCB_VAULT_PW - The password used to login
- CASCB_VAULT_TOKEN - The Vault token used to access Vault
- CASCB_VAULT_APPROLE - The Vault application role ID used to authenticate
- CASCB_VAULT_APPROLE_SECRET - The Vault application role secret ID used to authenticate
- CASCB_VAULT_APPROLE_SECRET_WRAPPED - The wrapping token that can be used to retrieve secret ID
- CASCB_VAULT_APPROLE_SECRET_WRAPPED_PATH - If passed, the wrapping token's issue path will be checked
- CASCB_VAULT_PATHS - Comma-separated list of paths from which plugin should retrieve configuration
- CASCB_VAULT_MOUNT - the path used for authentication with the selected mechanism. Use it when the authentication mechanism is bound in a non-default location, as well as for authentication methods that also accept a user-password pair, e.g. ldap.
- CASCB_VAULT_FILE - Path to properties file that will be scanned for above variables
Each of the variables is supported with either CASCB_
prefix as indicated in
the above list or with CASC_
prefix used also by the Configuration-as-Code
plugin. If the CASCB_VAULT_FILE
or CASC_VAULT_FILE
variable is present the
file it points at will be scanned for the same variables. The file indicated by
CASCB_VAULT_FILE
is scanned only for variables with CASCB_
prefix.
At least one way of authenticating to Vault has to be present - either CASCB_VAULT_TOKEN
,
a CASCB_VAULT_USER
/CASCB_VAULT_PW
pair or CASCB_VAULT_APPROLE
/CASCB_VAULT_APPROLE_SECRET
pair. If more than one is present, the order in which they are tried is not specified.
It's possible not to pass the secret ID directly, but instead use Vault's response wrapping mechanism
to wrap the response with secret ID and pass it using CASCB_VAULT_APPROLE_SECRET_WRAPPED
.
The value of this variable will be passed to Vault for unwrapping. It's expected that the unwrapped response
contains the key secret_id
, and the value of this key is further used in place of CASCB_VAULT_APPROLE_SECRET
.
If the variable CASCB_VAULT_APPROLE_SECRET_WRAPPED_PATH
is passed, along with
CASCB_VAULT_APPROLE_SECRET_WRAPPED
, the path that issued the wrapping token will be checked
and has to start with the value of CASCB_VAULT_APPROLE_SECRET_WRAPPED_PATH
. According to Hashicorp's
recommendations
failure to verify might mean a security incidend and as such causes Jenkins to be stopped immediately.
In case a variable is present in several places the following precedence applies, from least important:
- CASC-prefixed variable in
CASC_VAULT_FILE
- CASCB-prefixed variable in
CASC_VAULT_FILE
- CASC-prefixed variable in environment
- CASCB-prefixed variable in
CASCB_VAULT_FILE
- CASCB-prefixed variable in environment
The following values are retrieved from Vault:
- cascb_ssh_key - the SSH key used to connect to repository with configuration. Required.
- cascb_ssh_user - the username to use for git authentication. Required.
- cascb_ssh_description - the description to use for the created SSH credential. Defaults to empty if not provided.
- cascb_ssh_id - the ID the generated credential will use. Defaults to 'ssh-key' if not provided.
- cascb_repo_url - the URL of git repository containing configuration. Required.
- cascb_repo_branch - the branch that should be checked out and contain configuration. Defaults to 'master' if not provided.
- cascb_repo_directories - the comma separated list of directories within that branch that contain configuration. All
.yaml
files directly within any of those directories (not in subdirectory) will have their contents applied. If a file with same name exists in more than one directory, the last one takes precedence. Missing directories are ignored. If not provided, defaults to '.', the root directory of repository. - cascb_job_name - the name of generated job. Full path, where each /-separated component will be converted to a folder. Defaults to 'config' if not provided.
- cascb_job_description - the description that will be added to generated job. Defaults to empty if not provided.
- cascb_job_poll_schedule - sets up Jenkins to periodically poll git and re-apply configuration if changes are found. Needs to be a proper Jenkins cron expression. Defaults to empty, that is do not set polling.
If any of those values exists in more than one path from CASCB_VAULT_PATHS, than the last value takes precedence. As an exception, if the directory list begins with (+), the rest of list is appended to the previous value of the field (if any).
Simply use the provided ./build.sh
script or use plain docker build .
command to create the image.
You can customize plugins.txt
beforehand to provide the plugins you need.
Run maven build to run tests for the functionality, the resulting maven artifact is not used anywhere and needs not be published.
- Support Vault namespaces
- Better logging and error handling
- Provide images with minimal required set of plugins as well as Jenkins recommended set