CloudBees HashiCorp Vault Plugin

7 minute readSecurity

HashiCorp Vault is a secrets management system where users or vault clients can manage their sensitive details (for example, passwords, keys, certificates, and access tokens) via Secret Engines.

The CloudBees HashiCorp Vault plugin enables a credential store for CloudBees CI. Credentials are stored in a remote HashiCorp Vault instance and secrets are accessed on demand. With this plugin, you can manage credentials in a centralized location for all of your controllers.

Prerequisities

The CloudBees HashiCorp Vault Plugin requires the following:

  • CloudBees CI on modern cloud platforms or CloudBees CI on traditional platforms 2.387.2.3 (or newer)

  • HashiCorp Vault v1.8.0 (or newer)

  • Controller access to the HashiCorp Vault instance

Credentials retrieval process

The following diagram illustrates the credential retrieval process.

HashiCorp Vault Credential Retrieval Process
Figure 1. HashiCorp Vault Credential Retrieval Process

Install the HashiCorp Vault plugin

There are two options to install the HashiCorp Vault plugin:

Configure authentications for the HashiCorp Vault credential provider

The HashiCorp Vault credentials provider must be configured before you can use the HashiCorp Vault as a secret storage for your CloudBees CI instance. Once the provider is configured, it enables a new store (HashiCorp Vault) on the Credentials page. This new store is scoped to Jenkins. You can configure authentications (HashiCorp Vault auth methods) at the global and folder level.

Configure HashiCorp Vault credential provider at the global level

Only administrators can configure authentications for the HashiCorp Vault credential provider at the global level.

To configure a global HashiCorp Vault Credentials provider:

  1. From the Dashboard, select Manage Jenkins on the left navigation pane.

  2. Under Security, select Configure Credential Providers and navigate to HashiCorp Vault Credential Provider.

    Configure HashiCorp Vault Credential Providers
    Figure 2. HashiCorp Vault Credential Provider
  3. In the Vault URL field, enter the URL of the HashiCorp Vault server. The URL can begin with http or https.

  4. Select Skip SSL Verification to skip SSL certificate verification. This option is left blank by default.

    CloudBees recommends leaving this option blank. Leaving this option blank ensures each SSL connection to the Vault instance is secure by verifying the server’s SSL certificate.
  5. Select Add vault authentication  AppRole. Vault authentication is required to connect to the HashiCorp Vault server. The only supported authentication method is AppRole.

  6. Under AppRole, you can configure multiple HashiCorp Vault namespaces. Complete the following fields:

    Add vault authentication
    Figure 3. Add vault authentication
    View HashiCorp Vault Credential Provider details
    Label Description

    Authentication ID

    The ID by which the authentication is identified from credentials.

    Namespace

    The HashiCorp Vault namespace where secrets are stored. Leave this field blank if namespaces are not enabled or the secret is part of the root namespace.

    Role Id

    A unique identifier associated with the AppRole. To get the RoleID, refer to Get RoleID.

    Secret Id

    A unique identifier that authenticates and access secrets within the Vault. To get the SecretID, refer to SecretID.

    By default, the SecretID generated by the HashiCorp Vault instance has a TTL (time-to-live) attribute or a num_uses attribute. Once those limitations are reached, the HashiCorp Vault credentials provider cannot retrieve secrets. CloudBees recommends configuring the AppRole with secret_id_num_uses = 0 and secret_id_ttl = 0.

  7. Repeat steps 5-6 to create additional vault authentications and namespaces.

  8. Select Test connection to validate the HashiCorp Vault connection details.

    • If CloudBees CI connects to the configured HashiCorp Vault instance, a Connected message displays.

    • If the connection fails, you can troubleshoot using the information contained in these error messages:

      • An error occurred while contacting Vault: invalid secret ID

      • An error occurred while contacting Vault: invalid role ID

      • An error occurred while contacting Vault: permission denied connect timed out

      • {url} nodename nor servname provided, or not known

  9. Select Save.

    Creating vault authentications at the global level, makes the credential accessible to users with the Credentials permission. Those users can then add and edit the HashiCorp Vault credentials to their folders and jobs.

Configure HashiCorp Vault credential provider authentications at folder-level

Only users with the HashiCorp Vault Configuration permission can configure authentications for the HashiCorp Vault provider at the folder level.

To configure Authentications for the HashiCorp Vault credential provider at folder-level:

  1. On the Dashboard, select the desired folder.

  2. On the left navigation pane, select Configure. The folder configuration page displays.

  3. Navigate to Vault Authentications Folder Property.

  4. Select Add vault authentication  AppRole. Vault authentication is required to connect to the HashiCorp Vault server. The only supported authentication method is AppRole.

    Vault Authentications Folder Property
    Figure 4. Vault Authentications Folder Property
  5. Under AppRole, you can configure multiple HashiCorp Vault namespaces. Complete the following fields:

    Add folder vault authentication
    Figure 5. Add folder vault authentication
    View HashiCorp Vault Credential Provider details
    Label Description

    Authentication ID

    The ID by which the authentication is identified from credentials.

    Namespace

    The HashiCorp Vault namespace where secrets are stored. Leave this field blank if namespaces are not enabled or the secret is part of the root namespace.

    Role Id

    A unique identifier associated with the AppRole. To get the RoleID, refer to Get RoleID.

    Secret Id

    A unique identifier that authenticates and access secrets within the Vault. To get the SecretID, refer to SecretID.

    By default, the SecretID generated by the HashiCorp Vault instance has a TTL (time-to-live) attribute or a num_uses attribute. Once those limitations are reached, the HashiCorp Vault credentials provider cannot retrieve secrets. CloudBees recommends configuring the AppRole with secret_id_num_uses = 0 and secret_id_ttl = 0.

  6. Repeat steps 4-5 to create additional vault authentications and namespaces.

  7. Select Test connection to validate the HashiCorp Vault connection details.

    • If CloudBees CI connects to the configured HashiCorp Vault instance, a Connected message displays.

    • If the connection fails, you can troubleshoot using the information contained in these error messages:

      • An error occurred while contacting Vault: invalid secret ID

      • An error occurred while contacting Vault: invalid role ID

      • An error occurred while contacting Vault: permission denied connect timed out

      • {url} nodename nor servname provided, or not known

  8. Select Save.

Configure HashiCorp Vault credentials

Once the HashiCorp Vault credential provider is created at either the global or folder level, a new Vault credential store is visible on the Credentials page.

HashiCorp Vault credential store at the global level
Figure 6. HashiCorp Vault credential store at the global level
HashiCorp Vault credential store at the folder leve
Figure 7. HashiCorp Vault credential store at the folder level

After configuring the HashiCorp Vault provider, you can create two new types of credentials: Vault Username Password and Vault Secret Text. HashiCorp Vault credentials only read actual secrets from the HashiCorp Vault instance and are not used to delete, update, or create secrets.

If the HashiCorp Vault credentials need to be restricted, install the Restricted Credentials plugin.

To configure a HashiCorp Vault credential:

  1. Open the Credentials page.

    1. For the global-level credential: From the Dashboard, select Manage Jenkins  Manage Credentials.

    2. For the folder-level credential: From the Dashboard, select menu:[Folder Name][Credentials].

  2. Add credentials.

    1. For the global-level crendential provider, navigate to Stores scoped to Jenkins and hover your cursor over the (global) domain and select Add credentials.

    2. For the folder-level credential, navigate to Stores scoped to [Folder Name] and hover your cursor over the (global) domain and select Add credentials.

      Select *Add credentials*
      Figure 8. Add credentials
  3. On the New credentials page, enter details about the credential.

    New credentials page
    Figure 9. New credentials page
    View HashiCorp Vault Credentials details
    Label Description

    Kind

    Select the type of credential: Vault Secret Text or Vault Username Password.

    Vault Secret Engine

    Select the appropriate type of Vault Secret Engine where secrets are stored.

    * Key/Value Secret Engine v2 is a Versioned Key/Value secret engine.

    * Key/Value Secret Engine v1 is a Static Secrets: Key/Value secret engine.

    Vault Secret Engine » Authentication

    Select the HashiCorp Vault authentication defined in Configure authentications for the HashiCorp Vault credential provider.

    Vault Secret Engine » Path

    Enter the path where the HashiCorp Vault secret is stored. This is a required field.

    The Vault Secret Engine validates whether the path for the HashiCorp Vault secret is correct. If the path is correct, a Path was found message displays. If CloudBees CI cannot retrieve secrets from the provided path you may receive one of the following error messages:

    * An error occurred while contacting Vault: the requested Vault resource was not found: This message displays if the path is incorrect.

    * An error occurred while contacting Vault: 1 error occurred: *permission denied. This message displays if the AppRole does not have permission to access the path.

    Vault username key

    Enter the key that points to the actual username stored in the Path field.

    Vault password key

    Enter a key that points to the actual password stored in the Path field.

    Description

    Enter a description of the credential. This is an optional field.

    ID

    Enter the credential ID. If this field is left blank, the ID is automatically generated.

  4. Select Create.

Adding a credential within a job

You can add HashiCorp Vault credentials from the configuration page of a specific job.

To create a HashiCorp Vault credential within a job:

  1. From the Dashboard, select a controller.

  2. Navigate to a specific job and select Configure from the dropdown list.

  3. Navigate to the Build Environment section and select Use secret text(s) or files(s).

    Add HashiCorp Vault credential to a job
  4. Under Bindings, select Add  Secret text.

  5. Enter details about the Secret text.

    • Variable: Enter the name of an environment variable to be set during the build.

    • Credentials: Select Specific credentials to set a specific credential type for the variable.

    • Select Add and then select a Vault Credential Provider.

Adding credentials to pipelines

Run the following commands to add a HashiCorp Vault credential to a pipeline.

  • Vault Username Password

    withCredentials([usernamePassword(credentialsId: 'vault-creds', passwordVariable: 'PASS', usernameVariable: 'USER')]) {
        sh 'echo USER=$USER'
        sh 'echo PASS=$PASS'
    }
  • Vault Secret Text

    withCredentials([string(credentialsId: 'vault-creds', variable: 'TOKEN')]) {
        sh 'echo TOKEN=$TOKEN'
    }

Using the HashiCorp Vault credential in CasC yaml file

You can use Configuration as Code to configure the HashiCorp Vault plugin on your CloudBees CI instance. On your controller bundle, add the following code to the jenkins.yaml and items.yaml files:

jenkins.yaml

globalCredentialsConfiguration:
  vaultGlobalConfiguration:
    url: "https://vault-cluster-public-vault-****.z1.hashicorp.cloud:8200"
    skipSslVerification: false
    authentications:
      - appRoleAuthentication:
          id: "global-admin-approle"
          namespace: "admin"
          roleId: "****"
          secretId: "****"
      - appRoleAuthentication:
          id: "ci-approle"
          namespace: "ci"
          roleId: "****"
          secretId: "****"

credentials:
  cloudbeesHashicorpVault:
    domainCredentials:
      - credentials:
        - vaultUsernamePassword:
            scope: GLOBAL
            id: "test-username-password-id"
            description: "test vault username password"
            usernameKey: "user"
            passwordKey: "password"
            vaultSecretEngine:
              genericKV1SecretEngine:
                authenticationId: "ci-approle"
                path: "jenkins/secrets"
        - vaultSecretText:
            scope: GLOBAL
            id: "test-secret-text-id"
            description: "test vault secret text"
            secretKey: "password"
            vaultSecretEngine:
              genericKV2SecretEngine:
                authenticationId: "global-admin-approle"
                path: "jenkins/pldi"

items.yaml

removeStrategy:
  rbac: SYNC
  items: NONE
items:
- kind: folder
  name: Performance Team
  description: ''
  displayName: Ops Team
  properties:
  - envVars: {}
  - itemRestrictions:
      filter: false
- kind: folder
  name: CI Team
  description: ''
  displayName: CI Team
  properties:
  - envVars: {}
  - itemRestrictions:
      filter: false
  - vaultAuthenticationsFolderProperty:
      authentications:
      - appRoleAuthentication:
          roleId: ****
          namespace: admin/demo/name
          secretId: ****
          id: developers-approle
      - appRoleAuthentication:
          roleId: ****
          namespace: ops-namespace
          secretId: ****
          id: ops-approle
      credentials:
      - vaultUsernamePassword:
          usernameKey: username
          vaultSecretEngine:
            genericKV2SecretEngine:
              path: jenkins-kv/user1
              authenticationId: developers-approle
          scope: GLOBAL
          description: test vault username password with namespace admin/demo/dima
          id: folder-username-password-id
          passwordKey: password
      - vaultSecretText:
          secretKey: password
          vaultSecretEngine:
            genericKV2SecretEngine:
              path: jenkins/pldi
              authenticationId: global-admin-approle
          scope: GLOBAL
          description: test vault secret text with global namespace admin
          id: folder-secret-text-id