diff --git a/documentation/docs/images/jenkins-vault-credential.png b/documentation/docs/images/jenkins-vault-credential.png new file mode 100644 index 000000000..9a1613af2 Binary files /dev/null and b/documentation/docs/images/jenkins-vault-credential.png differ diff --git a/documentation/docs/images/parameter-with-vault-support.png b/documentation/docs/images/parameter-with-vault-support.png new file mode 100644 index 000000000..3e43ee52b Binary files /dev/null and b/documentation/docs/images/parameter-with-vault-support.png differ diff --git a/documentation/docs/infrastructure/vault.md b/documentation/docs/infrastructure/vault.md new file mode 100644 index 000000000..50b5c016d --- /dev/null +++ b/documentation/docs/infrastructure/vault.md @@ -0,0 +1,36 @@ +# Vault for Pipeline Secrets + +Project "Piper" also supports fetching your pipeline secrets directly from [Vault](https://www.hashicorp.com/products/vault). +Currently Vault's key value engine is supported in version 1 and 2, although we recommend version 2 since it supports versioning of secrets + +Parameters that support being fetched from Vault are marked with the Vault Label in the Step Documentation. + +![Vault Label](../images/parameter-with-vault-support.png) + + +## Vault Setup + +The first step to store your pipeline secrets in vault, is to enable a the [Key-Value Engine](https://www.vaultproject.io/docs/secrets/kv/kv-v2). And then create a policy which grants read access to the key value engine. +For Piper to authenticate against Vault, [AppRole](https://www.vaultproject.io/docs/auth/approle) authentication must be enabled in your Vault instance. +You have to [create an AppRole Role](https://www.vaultproject.io/api-docs/auth/approle#create-update-approle) for Piper and assign it the necessary policies. + +## Store Your Vault Credentials In Jenkins + +Take the role ID from your Vault AppRole and create a Jenkins `Secret Text` credential. Do the same for the Vault AppRole secret ID. + +![Create two jenkins secret text credentials](../images/jenkins-vault-credential.png) + +## Pipline Configuration + +For pipelines to actually use the secrets stored in Vault you need to adjust your `config.yml` + +```yml +general: + ... + vaultAppRoleTokenCredentialsId: '' + vaultAppRoleSecretTokenCredentialsId: 'JENKINS_CREDENTIAL_ID_FOR_VAULT_APPROLE_SECRET_ID' + vaultPath: 'kv/my-pipeline' # the path under which your jenkins secrets are stored + vaultServerUrl: '' + vaultNamespace: '' # if you are not using vault's namespace feature you can remove this line + ... +``` diff --git a/documentation/mkdocs.yml b/documentation/mkdocs.yml index da22dff4a..c29eb13c8 100644 --- a/documentation/mkdocs.yml +++ b/documentation/mkdocs.yml @@ -6,6 +6,7 @@ nav: - 'Infrastructure': - 'Overview': infrastructure/overview.md - 'Custom Jenkins Setup': infrastructure/customjenkins.md + - 'Vault For Pipline Secrets': infrastructure/vault.md - 'Pipelines': - 'ABAP Environment pipeline': - 'Introduction': pipelines/abapEnvironment/introduction.md diff --git a/pkg/documentation/generator/parameters.go b/pkg/documentation/generator/parameters.go index b60f0bc9d..e8855c409 100644 --- a/pkg/documentation/generator/parameters.go +++ b/pkg/documentation/generator/parameters.go @@ -66,6 +66,10 @@ func parameterFurtherInfo(paramName string, stepData *config.StepData) string { if paramName == param.Name { if param.Secret { secretInfo := "[![Secret](https://img.shields.io/badge/-Secret-yellowgreen)](#) pass via ENV or Jenkins credentials" + if param.GetReference("vaultSecret") != nil { + secretInfo = " [![Vault](https://img.shields.io/badge/-Vault-lightgrey)](#) [![Secret](https://img.shields.io/badge/-Secret-yellowgreen)](/) pass via ENV, Vault or Jenkins credentials" + + } for _, res := range param.ResourceRef { if res.Type == "secret" { secretInfo += fmt.Sprintf(" ([`%v`](#%v))", res.Name, strings.ToLower(res.Name)) @@ -251,9 +255,18 @@ func resourceReferenceDetails(resourceRef []config.ResourceReference) string { resourceDetails += fmt.Sprintf("  - `%v`%v
", alias.Name, ifThenElse(alias.Deprecated, " (**Deprecated**)", "")) } resourceDetails += fmt.Sprintf("  id: [`%v`](#%v)
", resource.Name, strings.ToLower(resource.Name)) - resourceDetails += fmt.Sprintf("  reference to: `%v`
", resource.Param) + resourceDetails += fmt.Sprintf("  reference to: `%v`

", resource.Param) continue } + + if resource.Type == "vaultSecret" { + resourceDetails += "Vault paths:
" + resourceDetails += "
    " + for _, path := range resource.Paths[0:1] { + resourceDetails += fmt.Sprintf("
  • `%s`
  • ", path) + } + resourceDetails += "
" + } } return resourceDetails diff --git a/pkg/documentation/generator/parameters_test.go b/pkg/documentation/generator/parameters_test.go index fa1ec9f83..0ea9bf055 100644 --- a/pkg/documentation/generator/parameters_test.go +++ b/pkg/documentation/generator/parameters_test.go @@ -263,7 +263,7 @@ func TestResourceReferenceDetails(t *testing.T) { resourceRef: []config.ResourceReference{ {Name: "testCredentialId", Aliases: []config.Alias{}, Type: "secret", Param: "password"}, }, - expected: "Jenkins credential id:
  id: [`testCredentialId`](#testcredentialid)
  reference to: `password`
", + expected: "Jenkins credential id:
  id: [`testCredentialId`](#testcredentialid)
  reference to: `password`

", }, { resourceRef: []config.ResourceReference{