From 66d4680324310790d41b70eed7421d121aac0e03 Mon Sep 17 00:00:00 2001 From: jliempt <35920075+jliempt@users.noreply.github.com> Date: Tue, 17 Dec 2024 16:05:51 +0100 Subject: [PATCH] rename Trust Engine to System Trust --- cmd/piper.go | 10 +- cmd/sonarExecuteScan_generated.go | 4 +- pkg/config/config.go | 12 +- ...rustengine_test.go => systemtrust_test.go} | 33 ++--- pkg/config/trustengine.go | 67 --------- pkg/documentation/generator/parameters.go | 16 +-- pkg/trustengine/trustengine.go | 135 ------------------ pkg/trustengine/trustengine_test.go | 80 ----------- resources/metadata/sonarExecuteScan.yaml | 4 +- 9 files changed, 40 insertions(+), 321 deletions(-) rename pkg/config/{trustengine_test.go => systemtrust_test.go} (70%) delete mode 100644 pkg/config/trustengine.go delete mode 100644 pkg/trustengine/trustengine.go delete mode 100644 pkg/trustengine/trustengine_test.go diff --git a/cmd/piper.go b/cmd/piper.go index 1b4972987a..6387df3c9c 100644 --- a/cmd/piper.go +++ b/cmd/piper.go @@ -41,7 +41,7 @@ type GeneralConfigOptions struct { VaultServerURL string VaultNamespace string VaultPath string - TrustEngineToken string + SystemTrustToken string HookConfig HookConfiguration MetaDataResolver func() map[string]config.StepData GCPJsonKeyFilePath string @@ -57,7 +57,7 @@ type HookConfiguration struct { SplunkConfig SplunkConfiguration `json:"splunk,omitempty"` PendoConfig PendoConfiguration `json:"pendo,omitempty"` OIDCConfig OIDCConfiguration `json:"oidc,omitempty"` - TrustEngineConfig TrustEngineConfiguration `json:"trustengine,omitempty"` + SystemTrustConfig SystemTrustConfiguration `json:"systemtrust,omitempty"` } type GCPPubSubConfiguration struct { @@ -93,7 +93,7 @@ type OIDCConfiguration struct { RoleID string `json:",roleID,omitempty"` } -type TrustEngineConfiguration struct { +type SystemTrustConfiguration struct { ServerURL string `json:"baseURL,omitempty"` TokenEndPoint string `json:"tokenEndPoint,omitempty"` TokenQueryParamName string `json:"tokenQueryParamName,omitempty"` @@ -386,8 +386,8 @@ func PrepareConfig(cmd *cobra.Command, metadata *config.StepData, stepName strin } myConfig.SetVaultCredentials(GeneralConfig.VaultRoleID, GeneralConfig.VaultRoleSecretID, GeneralConfig.VaultToken) - GeneralConfig.TrustEngineToken = os.Getenv("PIPER_trustEngineToken") - myConfig.SetTrustEngineToken(GeneralConfig.TrustEngineToken) + GeneralConfig.SystemTrustToken = os.Getenv("PIPER_systemTrustToken") + myConfig.SetSystemTrustToken(GeneralConfig.SystemTrustToken) if len(GeneralConfig.StepConfigJSON) != 0 { // ignore config & defaults in favor of passed stepConfigJSON diff --git a/cmd/sonarExecuteScan_generated.go b/cmd/sonarExecuteScan_generated.go index 293ae88926..e2a1f8389b 100644 --- a/cmd/sonarExecuteScan_generated.go +++ b/cmd/sonarExecuteScan_generated.go @@ -355,8 +355,8 @@ func sonarExecuteScanMetadata() config.StepData { }, { - Name: "sonarTrustengineSecretName", - Type: "trustengineSecret", + Name: "sonarSystemtrustSecretName", + Type: "systemtrustSecret", Default: "sonar", }, }, diff --git a/pkg/config/config.go b/pkg/config/config.go index 05bce93f7e..4ed06554b4 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -11,7 +11,7 @@ import ( "regexp" "strings" - "github.com/SAP/jenkins-library/pkg/trustengine" + "github.com/SAP/jenkins-library/pkg/systemtrust" piperhttp "github.com/SAP/jenkins-library/pkg/http" "github.com/SAP/jenkins-library/pkg/log" @@ -33,7 +33,7 @@ type Config struct { accessTokens map[string]string openFile func(s string, t map[string]string) (io.ReadCloser, error) vaultCredentials VaultCredentials - trustEngineConfiguration trustengine.Configuration + systemTrustConfiguration systemtrust.Configuration } // StepConfig defines the structure for merged step configuration @@ -295,12 +295,12 @@ func (c *Config) GetStepConfig(flagValues map[string]interface{}, paramJSON stri } // hooks need to have been loaded from the defaults before the server URL is known - err = c.setTrustEngineConfiguration(stepConfig.HookConfig) + err = c.setSystemTrustConfiguration(stepConfig.HookConfig) if err != nil { - log.Entry().WithError(err).Debug("Trust Engine lookup skipped due to missing or incorrect configuration") + log.Entry().WithError(err).Debug("System Trust lookup skipped due to missing or incorrect configuration") } else { - trustengineClient := trustengine.PrepareClient(&piperhttp.Client{}, c.trustEngineConfiguration) - resolveAllTrustEngineReferences(&stepConfig, append(parameters, ReportingParameters.Parameters...), c.trustEngineConfiguration, trustengineClient) + systemtrustClient := systemtrust.PrepareClient(&piperhttp.Client{}, c.systemTrustConfiguration) + resolveAllSystemTrustReferences(&stepConfig, append(parameters, ReportingParameters.Parameters...), c.systemTrustConfiguration, systemtrustClient) } // finally do the condition evaluation post processing diff --git a/pkg/config/trustengine_test.go b/pkg/config/systemtrust_test.go similarity index 70% rename from pkg/config/trustengine_test.go rename to pkg/config/systemtrust_test.go index c475a9e8b2..f50f674e21 100644 --- a/pkg/config/trustengine_test.go +++ b/pkg/config/systemtrust_test.go @@ -5,17 +5,18 @@ package config import ( "fmt" - piperhttp "github.com/SAP/jenkins-library/pkg/http" - "github.com/SAP/jenkins-library/pkg/trustengine" - "github.com/jarcoal/httpmock" "net/http" "testing" + piperhttp "github.com/SAP/jenkins-library/pkg/http" + "github.com/SAP/jenkins-library/pkg/systemtrust" + "github.com/jarcoal/httpmock" + "github.com/stretchr/testify/assert" ) const secretName = "sonar" -const secretNameInTrustEngine = "sonarTrustengineSecretName" +const secretNameInSystemTrust = "sonarSystemtrustSecretName" const testServerURL = "https://www.project-piper.io" const testTokenEndPoint = "tokens" const testTokenQueryParamName = "systems" @@ -24,14 +25,14 @@ const mockSonarToken = "mockSonarToken" var testFullURL = fmt.Sprintf("%s/%s?%s=", testServerURL, testTokenEndPoint, testTokenQueryParamName) var mockSingleTokenResponse = fmt.Sprintf("{\"sonar\": \"%s\"}", mockSonarToken) -func TestTrustEngineConfig(t *testing.T) { +func TestSystemTrustConfig(t *testing.T) { httpmock.Activate() defer httpmock.DeactivateAndReset() httpmock.RegisterResponder(http.MethodGet, testFullURL+"sonar", httpmock.NewStringResponder(200, mockSingleTokenResponse)) - stepParams := []StepParameters{createStepParam(secretName, RefTypeTrustengineSecret, secretNameInTrustEngine, secretName)} - - var trustEngineConfiguration = trustengine.Configuration{ + stepParams := []StepParameters{createStepParam(secretName, RefTypeSystemtrustSecret, secretNameInSystemTrust, secretName)} +systemtrust + var systemTrustConfiguration = systemtrust.Configuration{ Token: "testToken", ServerURL: testServerURL, TokenEndPoint: testTokenEndPoint, @@ -40,33 +41,33 @@ func TestTrustEngineConfig(t *testing.T) { client := &piperhttp.Client{} client.SetOptions(piperhttp.ClientOptions{MaxRetries: -1, UseDefaultTransport: true}) - t.Run("Load secret from Trust Engine - secret not set yet by Vault or config.yml", func(t *testing.T) { + t.Run("Load secret from System Trust - secret not set yet by Vault or config.yml", func(t *testing.T) { stepConfig := &StepConfig{Config: map[string]interface{}{ secretName: "", }} - resolveAllTrustEngineReferences(stepConfig, stepParams, trustEngineConfiguration, client) + resolveAllSystemTrustReferences(stepConfig, stepParams, systemTrustConfiguration, client) assert.Equal(t, mockSonarToken, stepConfig.Config[secretName]) }) - t.Run("Load secret from Trust Engine - secret already by Vault or config.yml", func(t *testing.T) { + t.Run("Load secret from System Trust - secret already by Vault or config.yml", func(t *testing.T) { stepConfig := &StepConfig{Config: map[string]interface{}{ secretName: "aMockTokenFromVault", }} - resolveAllTrustEngineReferences(stepConfig, stepParams, trustEngineConfiguration, client) + resolveAllSystemTrustReferences(stepConfig, stepParams, systemTrustConfiguration, client) assert.NotEqual(t, mockSonarToken, stepConfig.Config[secretName]) }) } - -func createStepParam(name, refType, trustengineSecretNameProperty, defaultSecretNameName string) StepParameters { +systemtrust +func createStepParam(name, refType, systemtrustSecretNameProperty, defaultSecretNameName string) StepParameters { return StepParameters{ Name: name, Aliases: []Alias{}, ResourceRef: []ResourceReference{ { - Type: refType, - Name: trustengineSecretNameProperty, + Type: systemtrust + Name: systemtrustSecretNameProperty, Default: defaultSecretNameName, }, }, diff --git a/pkg/config/trustengine.go b/pkg/config/trustengine.go deleted file mode 100644 index 2cd3e00010..0000000000 --- a/pkg/config/trustengine.go +++ /dev/null @@ -1,67 +0,0 @@ -package config - -import ( - "errors" - - piperhttp "github.com/SAP/jenkins-library/pkg/http" - "github.com/SAP/jenkins-library/pkg/log" - "github.com/SAP/jenkins-library/pkg/trustengine" -) - -// const RefTypeTrustengineSecretFile = "trustengineSecretFile" -const RefTypeTrustengineSecret = "trustengineSecret" - -// resolveAllTrustEngineReferences retrieves all the step's secrets from the Trust Engine -func resolveAllTrustEngineReferences(config *StepConfig, params []StepParameters, trustEngineConfiguration trustengine.Configuration, client *piperhttp.Client) { - for _, param := range params { - if ref := param.GetReference(RefTypeTrustengineSecret); ref != nil { - if config.Config[param.Name] == "" { - log.Entry().Infof("Getting '%s' from Trust Engine", param.Name) - token, err := trustengine.GetToken(ref.Default, client, trustEngineConfiguration) - if err != nil { - log.Entry().Info(" failed") - log.Entry().WithError(err).Debugf("Couldn't get '%s' token from Trust Engine", ref.Default) - continue - } - log.RegisterSecret(token) - config.Config[param.Name] = token - log.Entry().Info(" succeeded") - } else { - log.Entry().Debugf("Skipping retrieval of '%s' from Trust Engine: parameter already set", param.Name) - } - } - } -} - -// setTrustEngineConfiguration sets the server URL for the Trust Engine by taking it from the hooks -func (c *Config) setTrustEngineConfiguration(hookConfig map[string]interface{}) error { - trustEngineHook, ok := hookConfig["trustengine"].(map[string]interface{}) - if !ok { - return errors.New("no Trust Engine hook configuration found") - } - if serverURL, ok := trustEngineHook["serverURL"].(string); ok { - c.trustEngineConfiguration.ServerURL = serverURL - } else { - return errors.New("no Trust Engine server URL found") - } - if tokenEndPoint, ok := trustEngineHook["tokenEndPoint"].(string); ok { - c.trustEngineConfiguration.TokenEndPoint = tokenEndPoint - } else { - return errors.New("no Trust Engine service endpoint found") - } - if tokenQueryParamName, ok := trustEngineHook["tokenQueryParamName"].(string); ok { - c.trustEngineConfiguration.TokenQueryParamName = tokenQueryParamName - } else { - return errors.New("no Trust Engine query parameter name found") - } - - if len(c.trustEngineConfiguration.Token) == 0 { - return errors.New("no Trust Engine token found and envvar is empty") - } - return nil -} - -// SetTrustEngineToken sets the token for the Trust Engine -func (c *Config) SetTrustEngineToken(token string) { - c.trustEngineConfiguration.Token = token -} diff --git a/pkg/documentation/generator/parameters.go b/pkg/documentation/generator/parameters.go index eeb35d6aee..a78135754f 100644 --- a/pkg/documentation/generator/parameters.go +++ b/pkg/documentation/generator/parameters.go @@ -13,7 +13,7 @@ const ( vaultBadge = "![Vault](https://img.shields.io/badge/-Vault-lightgrey)" jenkinsOnlyBadge = "![Jenkins only](https://img.shields.io/badge/-Jenkins%20only-yellowgreen)" secretBadge = "![Secret](https://img.shields.io/badge/-Secret-yellowgreen)" - trustengineBadge = "![Trust Engine](https://img.shields.io/badge/-Trust%20Engine-lightblue)" + systemtrustBadge = "![System Trust](https://img.shields.io/badge/-System%20Trust-lightblue)" deprecatedBadge = "![deprecated](https://img.shields.io/badge/-deprecated-red)" ) @@ -122,9 +122,9 @@ func parameterFurtherInfo(paramName string, stepData *config.StepData, execution secretInfo := fmt.Sprintf("%s pass via ENV or Jenkins credentials", secretBadge) isVaultSecret := param.GetReference("vaultSecret") != nil || param.GetReference("vaultSecretFile") != nil - isTrustengineSecret := param.GetReference(config.RefTypeTrustengineSecret) != nil - if isVaultSecret && isTrustengineSecret { - secretInfo = fmt.Sprintf(" %s %s %s pass via ENV, Vault, Trust Engine or Jenkins credentials", vaultBadge, trustengineBadge, secretBadge) + isSystemtrustSecret := param.GetReference(config.RefTypeSystemtrustSecret) != nil + if isVaultSecret && isSystemtrustSecret { + secretInfo = fmt.Sprintf(" %s %s %s pass via ENV, Vault, System Trust or Jenkins credentials", vaultBadge, systemtrustBadge, secretBadge) } else if isVaultSecret { secretInfo = fmt.Sprintf(" %s %s pass via ENV, Vault or Jenkins credentials", vaultBadge, secretBadge) } @@ -347,8 +347,8 @@ func resourceReferenceDetails(resourceRef []config.ResourceReference) string { resourceDetails = addVaultResourceDetails(resource, resourceDetails) continue } - if resource.Type == config.RefTypeTrustengineSecret { - resourceDetails = addTrustEngineResourceDetails(resource, resourceDetails) + if resource.Type == config.RefTypeSystemtrustSecret { + resourceDetails = addSystemTrustResourceDetails(resource, resourceDetails) } } @@ -369,8 +369,8 @@ func addVaultResourceDetails(resource config.ResourceReference, resourceDetails return resourceDetails } -func addTrustEngineResourceDetails(resource config.ResourceReference, resourceDetails string) string { - resourceDetails += "
Trust Engine resource:
" +func addSystemTrustResourceDetails(resource config.ResourceReference, resourceDetails string) string { + resourceDetails += "
System Trust resource:
" resourceDetails += fmt.Sprintf("  name: `%v`
", resource.Name) resourceDetails += fmt.Sprintf("  value: `%v`
", resource.Default) diff --git a/pkg/trustengine/trustengine.go b/pkg/trustengine/trustengine.go deleted file mode 100644 index 99caf500ae..0000000000 --- a/pkg/trustengine/trustengine.go +++ /dev/null @@ -1,135 +0,0 @@ -package trustengine - -import ( - "encoding/json" - "fmt" - "io" - "net/http" - "net/url" - "strings" - - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - - piperhttp "github.com/SAP/jenkins-library/pkg/http" - "github.com/SAP/jenkins-library/pkg/log" -) - -type Secret struct { - Token string - System string -} - -type Response struct { - Secrets []Secret -} - -type Configuration struct { - ServerURL string - TokenEndPoint string - TokenQueryParamName string - Token string -} - -// GetToken requests a single token -func GetToken(refName string, client *piperhttp.Client, trustEngineConfiguration Configuration) (string, error) { - secrets, err := GetSecrets([]string{refName}, client, trustEngineConfiguration) - if err != nil { - return "", errors.Wrap(err, "couldn't get token from trust engine") - } - for _, s := range secrets { - if s.System == refName { - return s.Token, nil - } - } - return "", errors.New("could not find token in trust engine response") -} - -// GetSecrets transforms the trust engine JSON response into trust engine secrets, and can be used to request multiple tokens -func GetSecrets(refNames []string, client *piperhttp.Client, trustEngineConfiguration Configuration) ([]Secret, error) { - var secrets []Secret - query := url.Values{ - trustEngineConfiguration.TokenQueryParamName: { - strings.Join(refNames, ","), - }, - } - response, err := getResponse(trustEngineConfiguration.ServerURL, trustEngineConfiguration.TokenEndPoint, query, client) - if err != nil { - return secrets, errors.Wrap(err, "getting secrets from trust engine failed") - } - for k, v := range response { - secrets = append(secrets, Secret{ - System: k, - Token: v}) - } - - return secrets, nil -} - -// getResponse returns a map of the JSON response that the trust engine puts out -func getResponse(serverURL, endpoint string, query url.Values, client *piperhttp.Client) (map[string]string, error) { - var secrets map[string]string - - rawURL, err := parseURL(serverURL, endpoint, query) - if err != nil { - return secrets, errors.Wrap(err, "parsing trust engine url failed") - } - header := make(http.Header) - header.Add("Accept", "application/json") - - log.Entry().Debugf(" with URL %s", rawURL) - response, err := client.SendRequest(http.MethodGet, rawURL, nil, header, nil) - if err != nil { - if response != nil { - // the body contains full error message which we want to log - defer response.Body.Close() - bodyBytes, bodyErr := io.ReadAll(response.Body) - if bodyErr == nil { - err = errors.Wrap(err, string(bodyBytes)) - } - } - return secrets, errors.Wrap(err, "getting response from trust engine failed") - } - defer response.Body.Close() - - err = json.NewDecoder(response.Body).Decode(&secrets) - if err != nil { - return secrets, errors.Wrap(err, "getting response from trust engine failed") - } - - return secrets, nil -} - -// parseURL creates the full URL for a Trust Engine GET request -func parseURL(serverURL, endpoint string, query url.Values) (string, error) { - rawFullEndpoint, err := url.JoinPath(serverURL, endpoint) - if err != nil { - return "", errors.New("error parsing trust engine URL") - } - fullURL, err := url.Parse(rawFullEndpoint) - if err != nil { - return "", errors.New("error parsing trust engine URL") - } - // commas and spaces shouldn't be escaped since the Trust Engine won't accept it - unescapedRawQuery, err := url.QueryUnescape(query.Encode()) - if err != nil { - return "", errors.New("error parsing trust engine URL") - } - fullURL.RawQuery = unescapedRawQuery - return fullURL.String(), nil -} - -// PrepareClient adds the Trust Engine authentication token to the client -func PrepareClient(client *piperhttp.Client, trustEngineConfiguration Configuration) *piperhttp.Client { - var logEntry *logrus.Entry - if logrus.GetLevel() < logrus.DebugLevel { - logger := logrus.New() - logger.SetOutput(io.Discard) - logEntry = logrus.NewEntry(logger) - } - client.SetOptions(piperhttp.ClientOptions{ - Token: fmt.Sprintf("Bearer %s", trustEngineConfiguration.Token), - Logger: logEntry, - }) - return client -} diff --git a/pkg/trustengine/trustengine_test.go b/pkg/trustengine/trustengine_test.go deleted file mode 100644 index d1ca1b1793..0000000000 --- a/pkg/trustengine/trustengine_test.go +++ /dev/null @@ -1,80 +0,0 @@ -//go:build unit -// +build unit - -package trustengine - -import ( - "fmt" - "github.com/jarcoal/httpmock" - "net/http" - "testing" - - piperhttp "github.com/SAP/jenkins-library/pkg/http" - "github.com/stretchr/testify/assert" -) - -const testServerURL = "https://www.project-piper.io" -const testTokenEndPoint = "tokens" -const testTokenQueryParamName = "systems" -const mockSonarToken = "mockSonarToken" -const mockblackduckToken = "mockblackduckToken" -const errorMsg403 = "unauthorized to request token" - -var testFullURL = fmt.Sprintf("%s/%s?%s=", testServerURL, testTokenEndPoint, testTokenQueryParamName) -var mockSingleTokenResponse = fmt.Sprintf("{\"sonar\": \"%s\"}", mockSonarToken) -var mockTwoTokensResponse = fmt.Sprintf("{\"sonar\": \"%s\", \"blackduck\": \"%s\"}", mockSonarToken, mockblackduckToken) -var trustEngineConfiguration = Configuration{ - Token: "testToken", - ServerURL: testServerURL, - TokenEndPoint: testTokenEndPoint, - TokenQueryParamName: testTokenQueryParamName, -} - -func TestTrustEngine(t *testing.T) { - httpmock.Activate() - defer httpmock.DeactivateAndReset() - - t.Run("Get Sonar token - happy path", func(t *testing.T) { - httpmock.RegisterResponder(http.MethodGet, testFullURL+"sonar", httpmock.NewStringResponder(200, mockSingleTokenResponse)) - - client := &piperhttp.Client{} - client.SetOptions(piperhttp.ClientOptions{MaxRetries: -1, UseDefaultTransport: true}) - - token, err := GetToken("sonar", client, trustEngineConfiguration) - assert.NoError(t, err) - assert.Equal(t, mockSonarToken, token) - }) - - t.Run("Get multiple tokens - happy path", func(t *testing.T) { - httpmock.RegisterResponder(http.MethodGet, testFullURL+"sonar,blackduck", httpmock.NewStringResponder(200, mockTwoTokensResponse)) - - client := &piperhttp.Client{} - client.SetOptions(piperhttp.ClientOptions{MaxRetries: -1, UseDefaultTransport: true}) - - secrets, err := GetSecrets([]string{"sonar", "blackduck"}, client, trustEngineConfiguration) - - assert.NoError(t, err) - assert.Len(t, secrets, 2) - for _, s := range secrets { - switch system := s.System; system { - case "sonar": - assert.Equal(t, mockSonarToken, s.Token) - case "blackduck": - assert.Equal(t, mockblackduckToken, s.Token) - default: - continue - } - } - }) - - t.Run("Get Sonar token - 403 error", func(t *testing.T) { - httpmock.RegisterResponder(http.MethodGet, testFullURL+"sonar", httpmock.NewStringResponder(403, errorMsg403)) - - client := &piperhttp.Client{} - client.SetOptions(piperhttp.ClientOptions{MaxRetries: -1, UseDefaultTransport: true}) - - _, err := GetToken("sonar", client, trustEngineConfiguration) - assert.Error(t, err) - }) - -} diff --git a/resources/metadata/sonarExecuteScan.yaml b/resources/metadata/sonarExecuteScan.yaml index eb1b0c6819..f0e7445fd6 100644 --- a/resources/metadata/sonarExecuteScan.yaml +++ b/resources/metadata/sonarExecuteScan.yaml @@ -53,8 +53,8 @@ spec: default: sonar - name: sonarTokenCredentialsId type: secret - - type: trustengineSecret - name: sonarTrustengineSecretName + - type: systemtrustSecret + name: sonarSystemtrustSecretName default: sonar aliases: - name: sonarToken