Skip to content

Commit

Permalink
feat(vault): Facilitate Vault OIDC token (SAP#4916)
Browse files Browse the repository at this point in the history
* add functionality to retrieve Vault OIDC token

* fix tests for now

* update error

Co-authored-by: Christopher Fenner <[email protected]>

* implement commented tests

* run mockery for config pkg

---------

Co-authored-by: jliempt <>
Co-authored-by: Christopher Fenner <[email protected]>
  • Loading branch information
2 people authored and maxatsap committed Jul 23, 2024
1 parent 768baf4 commit 29e6f02
Show file tree
Hide file tree
Showing 9 changed files with 369 additions and 40 deletions.
5 changes: 5 additions & 0 deletions .mockery.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,8 @@ packages:
dir: pkg/influx/mocks
interfaces:
WriteAPIBlocking:
github.com/SAP/jenkins-library/pkg/config:
config:
dir: pkg/config/mocks
interfaces:
VaultClient:
6 changes: 6 additions & 0 deletions cmd/piper.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ type HookConfiguration struct {
SentryConfig SentryConfiguration `json:"sentry,omitempty"`
SplunkConfig SplunkConfiguration `json:"splunk,omitempty"`
PendoConfig PendoConfiguration `json:"pendo,omitempty"`
OIDCConfig OIDCConfiguration `json:"oidc,omitempty"`
}

// SentryConfiguration defines the configuration options for the Sentry logging system
Expand All @@ -76,6 +77,11 @@ type PendoConfiguration struct {
Token string `json:"token,omitempty"`
}

// OIDCConfiguration defines the configuration options for the OpenID Connect authentication system
type OIDCConfiguration struct {
RoleID string `json:",roleID,omitempty"`
}

var rootCmd = &cobra.Command{
Use: "piper",
Short: "Executes CI/CD steps from project 'Piper' ",
Expand Down
2 changes: 1 addition & 1 deletion pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ func (c *Config) GetStepConfig(flagValues map[string]interface{}, paramJSON stri
// check whether vault should be skipped
if skip, ok := stepConfig.Config["skipVault"].(bool); !ok || !skip {
// fetch secrets from vault
vaultClient, err := getVaultClientFromConfig(stepConfig, c.vaultCredentials)
vaultClient, err := GetVaultClientFromConfig(stepConfig.Config, c.vaultCredentials)
if err != nil {
return StepConfig{}, err
}
Expand Down
150 changes: 145 additions & 5 deletions pkg/config/mocks/vaultClient.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

33 changes: 17 additions & 16 deletions pkg/config/vault.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,11 @@ type VaultCredentials struct {
VaultToken string
}

// vaultClient interface for mocking
type vaultClient interface {
// VaultClient interface for mocking
type VaultClient interface {
GetKvSecret(string) (map[string]string, error)
MustRevokeToken()
GetOIDCTokenByValidation(string) (string, error)
}

func (s *StepConfig) mixinVaultConfig(parameters []StepParameters, configs ...map[string]interface{}) {
Expand All @@ -91,8 +92,8 @@ func (s *StepConfig) mixinVaultConfig(parameters []StepParameters, configs ...ma
}
}

func getVaultClientFromConfig(config StepConfig, creds VaultCredentials) (vaultClient, error) {
address, addressOk := config.Config["vaultServerUrl"].(string)
func GetVaultClientFromConfig(config map[string]interface{}, creds VaultCredentials) (VaultClient, error) {
address, addressOk := config["vaultServerUrl"].(string)
// if vault isn't used it's not an error
if !addressOk || creds.VaultToken == "" && (creds.AppRoleID == "" || creds.AppRoleSecretID == "") {
log.Entry().Debug("Vault not configured")
Expand All @@ -102,11 +103,11 @@ func getVaultClientFromConfig(config StepConfig, creds VaultCredentials) (vaultC
log.Entry().Debugf(" with URL %s", address)
namespace := ""
// namespaces are only available in vault enterprise so using them should be optional
if config.Config["vaultNamespace"] != nil {
namespace = config.Config["vaultNamespace"].(string)
if config["vaultNamespace"] != nil {
namespace = config["vaultNamespace"].(string)
log.Entry().Debugf(" with namespace %s", namespace)
}
var client vaultClient
var client VaultClient
var err error
clientConfig := &vault.Config{Config: &api.Config{Address: address}, Namespace: namespace}
if creds.VaultToken != "" {
Expand All @@ -124,7 +125,7 @@ func getVaultClientFromConfig(config StepConfig, creds VaultCredentials) (vaultC
return client, nil
}

func resolveAllVaultReferences(config *StepConfig, client vaultClient, params []StepParameters) {
func resolveAllVaultReferences(config *StepConfig, client VaultClient, params []StepParameters) {
for _, param := range params {
if ref := param.GetReference("vaultSecret"); ref != nil {
resolveVaultReference(ref, config, client, param)
Expand All @@ -135,7 +136,7 @@ func resolveAllVaultReferences(config *StepConfig, client vaultClient, params []
}
}

func resolveVaultReference(ref *ResourceReference, config *StepConfig, client vaultClient, param StepParameters) {
func resolveVaultReference(ref *ResourceReference, config *StepConfig, client VaultClient, param StepParameters) {
vaultDisableOverwrite, _ := config.Config["vaultDisableOverwrite"].(bool)
if _, ok := config.Config[param.Name].(string); vaultDisableOverwrite && ok {
log.Entry().Debugf("Not fetching '%s' from Vault since it has already been set", param.Name)
Expand Down Expand Up @@ -173,20 +174,20 @@ func resolveVaultReference(ref *ResourceReference, config *StepConfig, client va
}
}

func resolveVaultTestCredentialsWrapper(config *StepConfig, client vaultClient) {
func resolveVaultTestCredentialsWrapper(config *StepConfig, client VaultClient) {
log.Entry().Infof("Resolving test credentials wrapper")
resolveVaultCredentialsWrapperBase(config, client, vaultTestCredentialPath, vaultTestCredentialKeys, vaultTestCredentialEnvPrefix, resolveVaultTestCredentials)
}

func resolveVaultCredentialsWrapper(config *StepConfig, client vaultClient) {
func resolveVaultCredentialsWrapper(config *StepConfig, client VaultClient) {
log.Entry().Infof("Resolving credentials wrapper")
resolveVaultCredentialsWrapperBase(config, client, vaultCredentialPath, vaultCredentialKeys, vaultCredentialEnvPrefix, resolveVaultCredentials)
}

func resolveVaultCredentialsWrapperBase(
config *StepConfig, client vaultClient,
config *StepConfig, client VaultClient,
vaultCredPath, vaultCredKeys, vaultCredEnvPrefix string,
resolveVaultCredentials func(config *StepConfig, client vaultClient),
resolveVaultCredentials func(config *StepConfig, client VaultClient),
) {
switch config.Config[vaultCredPath].(type) {
case string:
Expand Down Expand Up @@ -230,7 +231,7 @@ func resolveVaultCredentialsWrapperBase(
}

// resolve test credential keys and expose as environment variables
func resolveVaultTestCredentials(config *StepConfig, client vaultClient) {
func resolveVaultTestCredentials(config *StepConfig, client VaultClient) {
credPath, pathOk := config.Config[vaultTestCredentialPath].(string)
keys := getTestCredentialKeys(config)
if !(pathOk && keys != nil) || credPath == "" || len(keys) == 0 {
Expand Down Expand Up @@ -267,7 +268,7 @@ func resolveVaultTestCredentials(config *StepConfig, client vaultClient) {
}
}

func resolveVaultCredentials(config *StepConfig, client vaultClient) {
func resolveVaultCredentials(config *StepConfig, client VaultClient) {
credPath, pathOk := config.Config[vaultCredentialPath].(string)
keys := getCredentialKeys(config)
if !(pathOk && keys != nil) || credPath == "" || len(keys) == 0 {
Expand Down Expand Up @@ -449,7 +450,7 @@ func createTemporarySecretFile(namePattern string, content string) (string, erro
return file.Name(), nil
}

func lookupPath(client vaultClient, path string, param *StepParameters) *string {
func lookupPath(client VaultClient, path string, param *StepParameters) *string {
log.Entry().Debugf(" with Vault path '%s'", path)
secret, err := client.GetKvSecret(path)
if err != nil {
Expand Down
Loading

0 comments on commit 29e6f02

Please sign in to comment.