Overview
This guide walks through configuring HashiCorp Vault to dynamically generate and manage Artifactory access tokens for Jenkins pipelines. The setup ensures secure authentication and eliminates the need for storing long-lived credentials in Jenkins.
At a high level, the process involves:
- Installing, registering, and enabling the Vault Artifactory Secrets Plugin
- Configure the Artifactory secrets engine by providing an admin token. This allows Vault to generate dynamic, time-limited tokens for Jenkins to use when interacting with Artifactory. In Artifactory, we ensure the proper permissions are set for the Jenkins role, defining access to specific resources.
- A role is created in Vault for Jenkins, specifying that the generated tokens will have access to the Artifactory secrets engine. A policy is then defined and applied to grant Jenkins the necessary permissions to access the secrets it needs. The AppRole authentication method is enabled, and a new AppRole is created with the appropriate policy granting access to Artifactory.
- Jenkins is configured to authenticate with Vault using the AppRole method, with the Role ID and Secret ID generated from the AppRole creation in Vault. Jenkins is then set up with the Hashicorp Vault plugin, specifying the Vault URL and credentials.
- In the Jenkins pipeline, the Vault plugin is used to retrieve an Artifactory token dynamically. This token is injected into the environment and used to authenticate requests to Artifactory, such as uploading an artifact. The process is verified when the pipeline successfully retrieves a token, performs an upload, and Artifactory confirms the request.
Find the step-by-step below:
Configure Vault
1. Download the Vault Artifactory Secrets Plugin binary from this link.
2. Move it to a directory of your choice (e.g., /usr/local/vault-plugins) and rename it to artifactory:
mkdir -p /usr/local/vault-plugins mv /path/to/downloaded-binary /usr/local/vault-plugins/artifactory
3. Make the binary executable:
chmod +x /usr/local/vault-plugins/artifactory
4. Edit (or create) your Vault configuration file (config.hcl) and specify the plugin directory:
vim path/to/vault/config.hcl # Then, add the plugin_directory configuration: plugin_directory = "/usr/local/vault-plugins"
5. Start Vault using the config file:
vault server -config=path/to/vault/config.hcl
6. Register the artifactory plugin and enable as a secrets engine:
vault plugin register \ -sha256=$(sha256sum /usr/local/vault-plugins/artifactory | cut -d " " -f 1) \ -command=artifactory \ secret artifactory vault secrets enable artifactory
7. In Artifactory, create an Admin Access Token without expiration, and configure the Artifactory secrets engine with it:
vault write artifactory/config/admin \ url=https://artifactory.example.org \ access_token=$TOKEN
Verify the results:
vault read artifactory/config/admin
8. In Artifactory, create a permissions target allowing the group or user access to the desired resources. In this example, I’ve given the group automation read/deploy access to the example-repo-local repository.
9. Create a Secrets Engine role for Jenkins, defining the scope for which dynamic tokens will be generated:
vault write artifactory/roles/jenkins \ scope="applied-permissions/groups:automation " \ default_ttl=3600 max_ttl=10800
10. Confirm the role was created and generate a token for the role:
vault list artifactory/roles
vault read artifactory/token/jenkins
11. Define a policy that grants Jenkins access to the required secrets. Save the following as
jenkins-policy.hcl: path "artifactory/token/jenkins" { capabilities = ["read"] }
12. Write the policy to Vault:
vault policy write jenkins-policy jenkins-policy.hcl
13. Ensure AppRole Auth method is enabled in Vault and create an AppRole:
vault auth enable approle vault write auth/approle/role/jenkins \ token_policies="jenkins-policy" \ token_ttl=2h \ token_max_ttl=4h
14. Retrieve Role ID and Secret ID:
vault read auth/approle/role/jenkins/role-id vault write -f auth/approle/role/jenkins/secret-id
Configure Jenkins:
15.
- Install Hashicorp Vault Plugin (Manage Jenkins > Plugins)
- Set up Vault credentials:
- Go to Manage Jenkins > Credentials > System > Global credentials (unrestricted)
- For Kind, select Vault App Role Credential
- Add the Role ID and Secret ID from the previous step
- Keep Path on “approle”
- Set Id to vault and Create
- For Kind, select Vault App Role Credential
16. Go to Manage Jenkins > Configure System
- Scroll down to find Vault Plugin Configuration.
- Add a new Vault configuration.
- Vault URL: http://127.0.0.1:8200
- Vault Credential: Choose the vault credential
- Save
- Vault URL: http://127.0.0.1:8200
17. Test In Pipeline:
- Create a new Jenkins Pipeline
- Add the following script and Save:
pipeline { agent any stages { stage('Get Dynamic Token') { steps { script { withVault( vaultSecrets: [ [ path: '/artifactory/token/jenkins', secretValues: [ [envVar: 'ARTIFACTORY_TOKEN', vaultKey: 'access_token'] ] ] ], configuration: [ vaultUrl: 'http://127.0.0.1:8200', vaultCredentialId: 'vault', // The ID of the Vault AppRole authentication configuration in Jenkins timeout: 60, engineVersion: 1 ] ) { // Use the fetched token echo "Retrieved Artifactory token: ${env.ARTIFACTORY_TOKEN}" // Generate a simple text file sh 'echo "This is a test file." > artifact.txt' // Upload the file to Artifactory using the token sh """ curl -X PUT -H "Authorization: Bearer ${env.ARTIFACTORY_TOKEN}" -T artifact.txt http://<JFROG_HOST>/artifactory/example-repo-local/artifact.txt """ } } } } } }
* The Artifactory secrets engine does not support versioning (i.e., there is no concept of V1 or V2). This means it operates simply under non-versioned storage principles similar to the KV V1 engine. In our script, we specify engineVersion: 1 to simplify secret path resolution for the Jenkins Vault plugin.
18. Trigger the pipeline and observe the output:
Started by user admin Running on Jenkins in /Users/jeremyl/.jenkins/workspace/vault-test [Get Dynamic Token] Retrieving secret: /artifactory/token/jenkins Retrieved Artifactory token: **** Executing script: + echo 'This is a test file.' + curl -X PUT -H 'Authorization: Bearer ****' -T artifact.txt http://<JFROG_HOST>:8082/artifactory/example-repo-local/artifact.txt { "repo": "example-repo-local", "path": "/artifact.txt", "createdBy": "token:v-jenkins-s2f0hek5", "downloadUri": "http://<JFROG_HOST>:8082/artifactory/example-repo-local/artifact.txt", "mimeType": "text/plain", "size": "21", "checksums": { "sha1": "e6c4fbd4fe7607f3e6ebf68b2ea4ef694da7b4fe", "md5": "2d282102fa671256327d4767ec23bc6b", "sha256": "649b8b471e7d7bc175eec758a7006ac693c434c8297c07db15286788c837154a" } } Finished: SUCCESS