You've already forked sap-jenkins-library
mirror of
https://github.com/SAP/jenkins-library.git
synced 2025-09-16 09:26:22 +02:00
feat(Vault): custom prefix for test credentials (#3043)
Co-authored-by: Sven Merk <33895725+nevskrem@users.noreply.github.com>
This commit is contained in:
@@ -117,4 +117,10 @@ The `vaultTestCredentialPath` parameter is the endpoint of your credential path
|
|||||||
|
|
||||||
The `vaultTestCredentialKeys`parameter is a list of credential IDs. The secret value of the credential will be exposed as an environment variable prefixed by "PIPER_TESTCREDENTIAL_" and transformed to a valid variable name. For a credential ID named `myAppId` the forwarded environment variable to the step will be `PIPER_TESTCREDENTIAL_MYAPPID` containing the secret. Hyphens will be replaced by underscores and other non-alphanumeric characters will be removed.
|
The `vaultTestCredentialKeys`parameter is a list of credential IDs. The secret value of the credential will be exposed as an environment variable prefixed by "PIPER_TESTCREDENTIAL_" and transformed to a valid variable name. For a credential ID named `myAppId` the forwarded environment variable to the step will be `PIPER_TESTCREDENTIAL_MYAPPID` containing the secret. Hyphens will be replaced by underscores and other non-alphanumeric characters will be removed.
|
||||||
|
|
||||||
|
!!! hint "Using a custom prefix for test credentials"
|
||||||
|
By default the prefix for test credentials is `PIPER_TESTCREDENTIAL_`.
|
||||||
|
|
||||||
|
It is possible to use a custom prefix by setting for example `vaultTestCredentialEnvPrefix: MY_CUSTOM_PREFIX` in your configuration.
|
||||||
|
With this above credential ID named `myAppId` will be populated into an environment variable with the name `MY_CUSTOM_PREFIX_MYAPPID`.
|
||||||
|
|
||||||
Extended logging for vault secret fetching (e.g. found credentials and environment variable names) can be activated via `verbose: true` configuration.
|
Extended logging for vault secret fetching (e.g. found credentials and environment variable names) can be activated via `verbose: true` configuration.
|
||||||
|
@@ -13,9 +13,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
vaultTestCredentialPath = "vaultTestCredentialPath"
|
vaultTestCredentialPath = "vaultTestCredentialPath"
|
||||||
vaultTestCredentialKeys = "vaultTestCredentialKeys"
|
vaultTestCredentialKeys = "vaultTestCredentialKeys"
|
||||||
vaultTestCredentialEnvPrefix = "PIPER_TESTCREDENTIAL_"
|
vaultTestCredentialEnvPrefix_Default = "PIPER_TESTCREDENTIAL_"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -27,6 +27,7 @@ var (
|
|||||||
"vaultBasePath",
|
"vaultBasePath",
|
||||||
"vaultPipelineName",
|
"vaultPipelineName",
|
||||||
"vaultPath",
|
"vaultPath",
|
||||||
|
"vaultTestCredentialEnvPrefix",
|
||||||
"skipVault",
|
"skipVault",
|
||||||
"vaultDisableOverwrite",
|
"vaultDisableOverwrite",
|
||||||
vaultTestCredentialPath,
|
vaultTestCredentialPath,
|
||||||
@@ -165,7 +166,7 @@ func resolveVaultTestCredentials(config *StepConfig, client vaultClient) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
secretsResolved := false
|
secretsResolved := false
|
||||||
secretsResolved = populateTestCredentialsAsEnvs(secret, keys)
|
secretsResolved = populateTestCredentialsAsEnvs(config, secret, keys)
|
||||||
if secretsResolved {
|
if secretsResolved {
|
||||||
// prevent overwriting resolved secrets
|
// prevent overwriting resolved secrets
|
||||||
// only allows vault test credentials on one / the same vault path
|
// only allows vault test credentials on one / the same vault path
|
||||||
@@ -174,7 +175,12 @@ func resolveVaultTestCredentials(config *StepConfig, client vaultClient) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func populateTestCredentialsAsEnvs(secret map[string]string, keys []string) (matched bool) {
|
func populateTestCredentialsAsEnvs(config *StepConfig, secret map[string]string, keys []string) (matched bool) {
|
||||||
|
|
||||||
|
vaultTestCredentialEnvPrefix, ok := config.Config["vaultTestCredentialEnvPrefix"].(string)
|
||||||
|
if !ok || len(vaultTestCredentialEnvPrefix) == 0 {
|
||||||
|
vaultTestCredentialEnvPrefix = vaultTestCredentialEnvPrefix_Default
|
||||||
|
}
|
||||||
for secretKey, secretValue := range secret {
|
for secretKey, secretValue := range secret {
|
||||||
for _, key := range keys {
|
for _, key := range keys {
|
||||||
if secretKey == key {
|
if secretKey == key {
|
||||||
|
@@ -219,32 +219,66 @@ func addAlias(param *StepParameters, aliasName string) {
|
|||||||
param.Aliases = append(param.Aliases, alias)
|
param.Aliases = append(param.Aliases, alias)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_resolveVaultTestCredentials(t *testing.T) {
|
func TestResolveVaultTestCredentials(t *testing.T) {
|
||||||
// init
|
t.Parallel()
|
||||||
vaultMock := &mocks.VaultMock{}
|
t.Run("Default credential prefix", func(t *testing.T) {
|
||||||
envPrefix := "PIPER_TESTCREDENTIAL_"
|
t.Parallel()
|
||||||
stepConfig := StepConfig{Config: map[string]interface{}{
|
// init
|
||||||
"vaultPath": "team1",
|
vaultMock := &mocks.VaultMock{}
|
||||||
"vaultTestCredentialPath": "appCredentials",
|
envPrefix := "PIPER_TESTCREDENTIAL_"
|
||||||
"vaultTestCredentialKeys": []interface{}{"appUser", "appUserPw"},
|
stepConfig := StepConfig{Config: map[string]interface{}{
|
||||||
}}
|
"vaultPath": "team1",
|
||||||
|
"vaultTestCredentialPath": "appCredentials",
|
||||||
|
"vaultTestCredentialKeys": []interface{}{"appUser", "appUserPw"},
|
||||||
|
}}
|
||||||
|
|
||||||
defer os.Unsetenv("PIPER_TESTCREDENTIAL_APPUSER")
|
defer os.Unsetenv("PIPER_TESTCREDENTIAL_APPUSER")
|
||||||
defer os.Unsetenv("PIPER_TESTCREDENTIAL_APPUSERPW")
|
defer os.Unsetenv("PIPER_TESTCREDENTIAL_APPUSERPW")
|
||||||
|
|
||||||
// mock
|
// mock
|
||||||
vaultData := map[string]string{"appUser": "test-user", "appUserPw": "password1234"}
|
vaultData := map[string]string{"appUser": "test-user", "appUserPw": "password1234"}
|
||||||
vaultMock.On("GetKvSecret", "team1/appCredentials").Return(vaultData, nil)
|
vaultMock.On("GetKvSecret", "team1/appCredentials").Return(vaultData, nil)
|
||||||
|
|
||||||
// test
|
// test
|
||||||
resolveVaultTestCredentials(&stepConfig, vaultMock)
|
resolveVaultTestCredentials(&stepConfig, vaultMock)
|
||||||
|
|
||||||
// assert
|
// assert
|
||||||
for k, v := range vaultData {
|
for k, v := range vaultData {
|
||||||
env := envPrefix + strings.ToUpper(k)
|
env := envPrefix + strings.ToUpper(k)
|
||||||
assert.NotEmpty(t, os.Getenv(env))
|
assert.NotEmpty(t, os.Getenv(env))
|
||||||
assert.Equal(t, os.Getenv(env), v)
|
assert.Equal(t, os.Getenv(env), v)
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Custom credential prefix", func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
// init
|
||||||
|
vaultMock := &mocks.VaultMock{}
|
||||||
|
envPrefix := "CUSTOM_CREDENTIAL_"
|
||||||
|
stepConfig := StepConfig{Config: map[string]interface{}{
|
||||||
|
"vaultPath": "team1",
|
||||||
|
"vaultTestCredentialPath": "appCredentials",
|
||||||
|
"vaultTestCredentialKeys": []interface{}{"appUser", "appUserPw"},
|
||||||
|
"vaultTestCredentialEnvPrefix": envPrefix,
|
||||||
|
}}
|
||||||
|
|
||||||
|
defer os.Unsetenv("CUSTOM_CREDENTIAL_APPUSER")
|
||||||
|
defer os.Unsetenv("CUSTOM_CREDENTIAL_APPUSERPW")
|
||||||
|
|
||||||
|
// mock
|
||||||
|
vaultData := map[string]string{"appUser": "test-user", "appUserPw": "password1234"}
|
||||||
|
vaultMock.On("GetKvSecret", "team1/appCredentials").Return(vaultData, nil)
|
||||||
|
|
||||||
|
// test
|
||||||
|
resolveVaultTestCredentials(&stepConfig, vaultMock)
|
||||||
|
|
||||||
|
// assert
|
||||||
|
for k, v := range vaultData {
|
||||||
|
env := envPrefix + strings.ToUpper(k)
|
||||||
|
assert.NotEmpty(t, os.Getenv(env))
|
||||||
|
assert.Equal(t, os.Getenv(env), v)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_convertEnvVar(t *testing.T) {
|
func Test_convertEnvVar(t *testing.T) {
|
||||||
|
Reference in New Issue
Block a user