Skip to content

CzapBran/azure-keyvault-plugin

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Azure Key Vault Plugin

Build Status Jenkins Plugin GitHub release Jenkins Plugin Installs

This plugin enables Jenkins to fetch secrets from Azure Key Vault and inject them directly into build jobs. It works similarly to the Credential Binding Plugin and borrows much from the Hashicorp Vault Plugin. The plugin acts as an Azure Active Directory Application and must be configured with a valid credential.

System Configuration

Via UI

In the Jenkins Configure System page, configure the following two options in the Azure Key Vault Plugin section

  • Key Vault URL - The url where your Key Vault resides (e.g. https://myvault.vault.azure.net/)
  • Credential ID - The ID associated with a secret in the Jenkins secret store. Supported types are:
    • Azure Service Principal
    • Azure Managed Identity (both user and system assigned)

Via configuration-as-code

This plugin supports the configuration as code plugin:

Example yaml:

credentials:
  system:
    domainCredentials:
      - credentials:
        - azure:
            azureEnvironmentName: "Azure"
            clientId: "d63d9de6-5f7a-48c1-ac1d-e90d4f5e5dcc"
            clientSecret: "${CLIENT_SECRET}"
            description: "An azure service principal"
            id: "service-principal"
            scope: SYSTEM
            subscriptionId: "d63d9de6-5f7a-48c1-ac1d-e90d4f5e5dcc"
            tenant: "d63d9de6-5f7a-48c1-ac1d-e90d4f5e5dcc"

unclassified:
  azureKeyVault:
    keyVaultURL: https://not-a-real-vault.vault.azure.net
    credentialID: service-principal

Via system properties

URL:

-Djenkins.azure-keyvault.url=https://my.vault.azure.net

User or System Assigned Managed Identity:

-Djenkins.azure-keyvault.uami.enabled=true

Service principal:

-Djenkins.azure-keyvault.sp.client_id=...
-Djenkins.azure-keyvault.sp.client_secret=...
-Djenkins.azure-keyvault.sp.subscription_id=...
-Djenkins.azure-keyvault.sp.tenant_id=...

Via environment variables

URL:

AZURE_KEYVAULT_URL=https://my.vault.azure.net

User or System Assigned Managed Identity:

AZURE_KEYVAULT_UAMI_ENABLED=true

Service principal:

AZURE_KEYVAULT_SP_CLIENT_ID=...
AZURE_KEYVAULT_SP_CLIENT_SECRET=...
AZURE_KEYVAULT_SP_SUBSCRIPTION_ID=...
AZURE_KEYVAULT_SP_TENANT_ID=...

Passing a Secret File

It's possible to pass the secret from a file instead of passing the client secret as is. Simply provide the path to the secret file.

-Djenkins.azure-keyvault.sp.client_id=...
-Djenkins.azure-keyvault.sp.client_secret_file=/path/to/secret/secretFile
-Djenkins.azure-keyvault.sp.subscription_id=...
-Djenkins.azure-keyvault.sp.tenant_id=...
AZURE_KEYVAULT_SP_CLIENT_ID=...
AZURE_KEYVAULT_SP_CLIENT_SECRET_FILE=/path/to/secret/secretFile
AZURE_KEYVAULT_SP_SUBSCRIPTION_ID=...
AZURE_KEYVAULT_SP_TENANT_ID=...

The plugin will parse the contents of the file as is. The file should only contain the client_secret value.

Building the Plugin

  • Run mvn package, an .hpi file will be generated in the target folder.

Plugin Usage

Usage in Jenkinsfile

Note that the example echos below will only show *****'s as the plugin redacts secrets found in the build log inside the withAzureKeyvault build wrapper.

Scripted

Snippet generator is fully supported for generating the possible values (along with inline help): Go to any pipeline job and click Pipeline Syntax

Or visit the URL: /job/<job-name>/pipeline-syntax/

Simple version:

node {
    def secrets = [
        [ secretType: 'Certificate', name: 'MyCert00', envVariable: 'CERTIFICATE' ],
        [ secretType: 'Secret', name: 'MySecret00', envVariable: 'SECRET' ],
        [ secretType: 'Secret', name: 'MySecret00', version: '342432lkjhdasjld', envVariable: 'SECRET' ]
    ]

    withAzureKeyvault(secrets) {
        sh 'echo $CERTIFICATE'
        sh 'echo $SECRET'
    }
}

With overrides:

static LinkedHashMap<String, Object> secret(String secretName, String envVar) {
  [ 
    secretType: 'Secret',
    name: secretName,
    version: '342432lkjhdasjld',
    envVariable: envVar
  ]
}

node {
    def secrets = [
        secret('my-secret', 'MY_SECRET')
    ]

    withAzureKeyvault(
            azureKeyVaultSecrets: secrets, 
            keyVaultURLOverride: 'https://mykeyvault.vault.azure.net',
            credentialIDOverride: 'service-principal'
    ) {
        sh 'echo $MY_SECRET'
     }
}

Declarative

Snippet generator is fully supported for generating the possible values (along with inline help): Go to any pipeline job and click Pipeline Syntax -> Declarative Directive Generator

Or visit the URL: /job/<job-name>/directive-generator/

Simple:

pipeline {
    agent any
    stages {
        stage('Build') {
            options {
              azureKeyVault([[envVariable: 'MY_SECRET', name: 'my-secret', secretType: 'Secret']])
            }
            steps {
                sh "echo $SECRET"
            }
        }
    }
}

With overrides:

pipeline {
    agent any
    stages {
        stage('Build') {
            options {
              azureKeyVault(
                credentialID: 'my-sp', 
                keyVaultURL: 'https://my.vault.azure.net', 
                secrets: [
                    [envVariable: 'MY_SECRET', name: 'my-secret', secretType: 'Secret']
                ]
              )
            }
            steps {
                sh "echo $SECRET"
            }
        }
    }
}

Certificate:

pipeline {
    agent any
    stages {
        stage('Build') {
            options {
              azureKeyVault([[envVariable: 'CERT_LOCATION', name: 'my-cert-name', secretType: 'Certificate']])
            }
            steps {
                sh "openssl pkcs12 -in $CERT_LOCATION  -nodes -password 'pass:' -out keyvault.pem"
            }
        }
    }
}

The shell command above will convert the PFX file to a pem key file (also containing the certificate), note that Azure Key Vault removes the password on the pfx when you import it, if you're importing it back into Azure somewhere else you may need to convert it to pem and convert back to a pfx with a password.

Azure Key Vault Credentials Provider

Note: It is not supported to configure the credential provider with the Configuration as Code plugin and resolving credentials from Azure Key Vault in the same configuration file. Please use one of the other options (system properties, environment variables) if you want to retrieve secrets for use in Configuration as Code files

This plugin enables the retrieval of Secrets directly from Azure Key Vault. After the configuration is set up, secrets from the key vault can be viewed in the credentials page like this:

provider

Note These credentials are read-only and metadata caching(10 minutes) means newly created secrets may not be here immediately. You can reload the cache on the system configuration page if you need a new secret to appear.

Use these credentials just as other normal credentials in Jenkins.

There are multiple supported credential types, string is used by default. To use a different type add a tag called type with one of the below values:

  • string - Secret text
  • username - Username with password
    • add a tag username for the username of the credential
  • sshUserPrivateKey - SSH Private key
    • add a tag username for the username of the credential
    • (optional) add a tag username-is-secret and set it to true to hide the username in the build logs

Declarative Pipeline:

pipeline {
    agent any
    environment {
        GITHUB_API_TOKEN = credentials('github-api-token')
    }
    stages {
        stage('Foo') {
            steps {
                echo '$GITHUB_API_TOKEN'
            }
        }
    }
}

Scripted Pipeline:

node {
    withCredentials([string(credentialsId: 'github-api-token', variable: 'GITHUB_API_TOKEN')]) {
        echo '$GITHUB_API_TOKEN'
    }
}

Username with password

az keyvault secret set --vault-name my-vault \
  --name github-pat \
  --value my-pat \
  --tags username=github-user type=username

Scripted Pipeline:

job('my example') {
    scm {
        git {
            remote {
                github('my-repo', 'https')
                credentials('github-pat')
            }
        }
    }
}

SSH Username with private key

az keyvault secret set --tags type=sshUserPrivateKey username=my-username \
  --vault-name my-vault \
  --name test-ssh \
  -f ~/.ssh/my-ssh-key

Scripted pipeline:

# This is a docker image that can be used to test out this feature
docker run --rm -it --publish 2222:2222 \
  -e "PUBLIC_KEY=my-public-key" linuxserver/openssh-server
node {
    withCredentials([sshUserPrivateKey(credentialsId: "test-ssh", keyFileVariable: "my_ssh_key", usernameVariable: "my_username")]) {
     sh 'ssh -i $my_ssh_key -p 2222 $my_username@localhost "uname -r"'
    }
}

Declarative pipeline:

pipeline {
    agent any
    environment {
        SSH_PRIVATE_KEY = credentials('test-ssh')
    }
    stages {
        stage('Foo') {
            steps {
                sh 'ssh -i $SSH_PRIVATE_KEY -p 2222 $SSH_PRIVATE_KEY_USR@localhost "cat world"'
            }
        }
    }
}

SecretSource

The plugin allows the Configuration as Code plugin to interpolate string secrets from Azure KeyVault.

Example

az cli:

az keyvault secret set --vault-name my-vault --name my-password --value password

JCasC:

jenkins:
  securityRealm:
    local:
      allowsSignup: false
      users:
      - id: "foo"
        password: "${my-password}"

About

Jenkins plugin for Azure Keyvault

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Java 95.8%
  • Groovy 2.3%
  • HTML 1.9%