From 4f29b1dca70539321757dfe638ce47a0feadff91 Mon Sep 17 00:00:00 2001 From: marcos-albornoz <74274513+marcos-albornoz@users.noreply.github.com> Date: Mon, 14 Aug 2023 09:17:20 -0600 Subject: [PATCH 01/10] Update error.go --- pkg/venafi/firefly/error.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkg/venafi/firefly/error.go b/pkg/venafi/firefly/error.go index 5e8f12f4..00037b2a 100644 --- a/pkg/venafi/firefly/error.go +++ b/pkg/venafi/firefly/error.go @@ -22,7 +22,8 @@ import ( ) type responseError struct { - error string `json:"error,omitempty"` + ErrorKey string `json:"error,omitempty"` + ErrorDescription string `json:"error_description,omitempty"` } func NewResponseError(b []byte) (*responseError, error) { @@ -38,5 +39,5 @@ func NewResponseError(b []byte) (*responseError, error) { } func (e *responseError) Error() string { - return e.error + return e.ErrorKey } From b9f9b8d9758941cec5e9993e9e079c50caf985a9 Mon Sep 17 00:00:00 2001 From: Luis Presuel Date: Sat, 12 Aug 2023 01:14:34 -0600 Subject: [PATCH 02/10] Adds tests for getting credentials of Identity Provider Okta for Firefly --- .../features/firefly/credmgmt-firefly.feature | 45 ++++++++++++++++ .../firefly/step_definitions/my_steps.rb | 51 +++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 aruba/features/firefly/credmgmt-firefly.feature create mode 100644 aruba/features/firefly/step_definitions/my_steps.rb diff --git a/aruba/features/firefly/credmgmt-firefly.feature b/aruba/features/firefly/credmgmt-firefly.feature new file mode 100644 index 00000000..cfe64c1b --- /dev/null +++ b/aruba/features/firefly/credmgmt-firefly.feature @@ -0,0 +1,45 @@ +@FIREFLY +Feature: Managing credentials tokens from Identity Providers + + As a user + I want to get credentials for Firefly with Okta as IdP + + Background: + Given the default aruba exit timeout is 180 seconds + + Scenario Outline: request access token from IdP + When I get credentials from "" + And I remember the output + And it should output access token + + Examples: + | identity-provider | + | Okta | + + Scenario Outline: request access token from IdP in JSON format + When I get credentials from "" with -format json + And I remember the output + And it should output access token in JSON + + Examples: + | identity-provider | + | Okta | + + Scenario Outline: request access token from IdP using password flow + When I get credentials from "" with username and password + And I remember the output + And it should output access token + + Examples: + | identity-provider | + | Okta | + + @TODO # currently interactive mode is not working for Idp for Firefly + Scenario Outline: request access token from IdP using password flow interactively + When I interactively get credentials from "" with username and no password + And I remember the output + And it should output access token + + Examples: + | identity-provider | + | Okta | \ No newline at end of file diff --git a/aruba/features/firefly/step_definitions/my_steps.rb b/aruba/features/firefly/step_definitions/my_steps.rb new file mode 100644 index 00000000..b52b4467 --- /dev/null +++ b/aruba/features/firefly/step_definitions/my_steps.rb @@ -0,0 +1,51 @@ + +When(/^I( interactively)? get credentials from "(.*)"(?: with)?(.+)?$/) do |interactively, identity_provider, flags| + + idp_token_url = "" + idp_user = "" + idp_password = "" + idp_client_id = "" + idp_client_secret = "" + idp_scope = "" + + case identity_provider + when "Okta" + idp_token_url = "#{ENV['OKTA_AUTH_SERVER']}/v1/token" + idp_user = ENV['OKTA_USER'] + idp_password = ENV['OKTA_PASSWORD'] + if flags === " username and no password" || flags === " username and password" + idp_client_id = ENV['OKTA_CLIENT_ID_PASS'] + else + idp_client_id = ENV['OKTA_CLIENT_ID'] + end + idp_client_secret = ENV['OKTA_CLIENT_SECRET'] + idp_scope = ENV['OKTA_SCOPE'] + else + fail(ArgumentError.new("Unknown Identity Provider: #{identity_provider}")) + end + + if flags === " username and no password" + cmd = "vcert getcred -platform firefly -token-url '#{idp_token_url}' -client-id '#{idp_client_id}'" + + " -username '#{idp_user}' -scope '#{idp_scope}'" + elsif flags === " username and password" + cmd = "vcert getcred -platform firefly -token-url '#{idp_token_url}' -client-id '#{idp_client_id}'" + + " -username '#{idp_user}' -password '#{idp_password}' -scope '#{idp_scope}'" + else + # client id is our default + cmd = "vcert getcred -platform firefly -token-url '#{idp_token_url}'" + + " -client-id '#{idp_client_id}' -client-secret #{idp_client_secret} -scope '#{idp_scope}' #{flags}" + end + + if interactively + Kernel.puts cmd + steps %{ + Then I run `#{cmd}` interactively + And I type "#{idp_password}" + Then the exit status should be 0 + } + else + steps %{ + Then I try to run `#{cmd}` + } + end +end \ No newline at end of file From a826160f3aecdbd4548cf0c3da73358442a3449c Mon Sep 17 00:00:00 2001 From: Luis Presuel Date: Mon, 14 Aug 2023 11:35:38 -0600 Subject: [PATCH 03/10] enables OKTA environment variables for cucumber tests --- aruba/cucumber.sh | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/aruba/cucumber.sh b/aruba/cucumber.sh index c349f492..9a872b92 100755 --- a/aruba/cucumber.sh +++ b/aruba/cucumber.sh @@ -14,7 +14,14 @@ RUN_COMMAND="docker run -t --rm \ -e CLOUD_APIKEY \ -e CLOUD_ZONE \ -e TPP_IP \ - -e TPP_CN" + -e TPP_CN \ + -e OKTA_CLIENT_ID \ + -e OKTA_CLIENT_ID_PASS \ + -e OKTA_AUTH_SERVER \ + -e OKTA_ACCESS_TOKEN \ + -e OKTA_USER \ + -e OKTA_PASSWORD \ + -e OKTA_SCOPE" # Use getopts to handle command-line options while getopts "a:b:" opt; do From 5cd8ae38c8e05cbbd38b0604689e51cb44db9bb5 Mon Sep 17 00:00:00 2001 From: Luis Presuel Date: Mon, 14 Aug 2023 11:41:23 -0600 Subject: [PATCH 04/10] Adds missing OKTA env --- aruba/cucumber.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/aruba/cucumber.sh b/aruba/cucumber.sh index 9a872b92..6ab3763d 100755 --- a/aruba/cucumber.sh +++ b/aruba/cucumber.sh @@ -18,6 +18,7 @@ RUN_COMMAND="docker run -t --rm \ -e OKTA_CLIENT_ID \ -e OKTA_CLIENT_ID_PASS \ -e OKTA_AUTH_SERVER \ + -e OKTA_CLIENT_SECRET \ -e OKTA_ACCESS_TOKEN \ -e OKTA_USER \ -e OKTA_PASSWORD \ From d790d9a54f07fe70b3edf1f3fcea1f4899722e39 Mon Sep 17 00:00:00 2001 From: Luis Presuel Date: Mon, 14 Aug 2023 12:54:21 -0600 Subject: [PATCH 05/10] updates envs for OKTA user and password --- aruba/cucumber.sh | 4 ++-- aruba/features/firefly/step_definitions/my_steps.rb | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/aruba/cucumber.sh b/aruba/cucumber.sh index 6ab3763d..9409e038 100755 --- a/aruba/cucumber.sh +++ b/aruba/cucumber.sh @@ -20,8 +20,8 @@ RUN_COMMAND="docker run -t --rm \ -e OKTA_AUTH_SERVER \ -e OKTA_CLIENT_SECRET \ -e OKTA_ACCESS_TOKEN \ - -e OKTA_USER \ - -e OKTA_PASSWORD \ + -e OKTA_CREDS_USR \ + -e OKTA_CREDS_PSW \ -e OKTA_SCOPE" # Use getopts to handle command-line options diff --git a/aruba/features/firefly/step_definitions/my_steps.rb b/aruba/features/firefly/step_definitions/my_steps.rb index b52b4467..7e47105d 100644 --- a/aruba/features/firefly/step_definitions/my_steps.rb +++ b/aruba/features/firefly/step_definitions/my_steps.rb @@ -11,8 +11,8 @@ case identity_provider when "Okta" idp_token_url = "#{ENV['OKTA_AUTH_SERVER']}/v1/token" - idp_user = ENV['OKTA_USER'] - idp_password = ENV['OKTA_PASSWORD'] + idp_user = ENV['OKTA_CREDS_USR'] + idp_password = ENV['OKTA_CREDS_PSW'] if flags === " username and no password" || flags === " username and password" idp_client_id = ENV['OKTA_CLIENT_ID_PASS'] else From ce5f9385f5bce587f26cb87072583b1ace94712a Mon Sep 17 00:00:00 2001 From: Luis Presuel Date: Mon, 14 Aug 2023 13:29:48 -0600 Subject: [PATCH 06/10] fixes lint issue --- pkg/venafi/firefly/firefly.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkg/venafi/firefly/firefly.go b/pkg/venafi/firefly/firefly.go index 4fbabf6a..f7ca32de 100644 --- a/pkg/venafi/firefly/firefly.go +++ b/pkg/venafi/firefly/firefly.go @@ -22,7 +22,6 @@ import ( "encoding/json" "fmt" "io" - "io/ioutil" "log" "net" "net/http" @@ -117,7 +116,7 @@ func (c *Connector) request(method string, resource urlResource, data interface{ } defer res.Body.Close() - body, err = ioutil.ReadAll(res.Body) + body, err = io.ReadAll(res.Body) // Do not enable trace in production trace := false // IMPORTANT: sensitive information can be diclosured // I hope you know what are you doing From fdf4258f9cd9d703027b272919c7602905e2f610 Mon Sep 17 00:00:00 2001 From: Luis Presuel Date: Mon, 14 Aug 2023 13:36:32 -0600 Subject: [PATCH 07/10] Adds newlines to files --- aruba/features/firefly/credmgmt-firefly.feature | 2 +- aruba/features/firefly/step_definitions/my_steps.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/aruba/features/firefly/credmgmt-firefly.feature b/aruba/features/firefly/credmgmt-firefly.feature index cfe64c1b..804944fe 100644 --- a/aruba/features/firefly/credmgmt-firefly.feature +++ b/aruba/features/firefly/credmgmt-firefly.feature @@ -42,4 +42,4 @@ Feature: Managing credentials tokens from Identity Providers Examples: | identity-provider | - | Okta | \ No newline at end of file + | Okta | diff --git a/aruba/features/firefly/step_definitions/my_steps.rb b/aruba/features/firefly/step_definitions/my_steps.rb index 7e47105d..ed0fdb71 100644 --- a/aruba/features/firefly/step_definitions/my_steps.rb +++ b/aruba/features/firefly/step_definitions/my_steps.rb @@ -48,4 +48,4 @@ Then I try to run `#{cmd}` } end -end \ No newline at end of file +end From 7cf7212362699869b3a3594c7d3dd4e959284451 Mon Sep 17 00:00:00 2001 From: Russel Vela Date: Mon, 14 Aug 2023 16:32:01 -0600 Subject: [PATCH 08/10] fix(platform): removed redundant Platform and Authentication code Make Playbook feature to use the Platform constants from venafi package instead of their own. Make Playbook feature reuse the endpoint.Authentication struct instead of their own. Playbook still has its own Authentication object but depends on the endpoint.Authentication struct. --- cmd/vcert/args.go | 2 +- cmd/vcert/playbook.go | 7 +- pkg/endpoint/authentication.go | 39 ++++++++ pkg/endpoint/endpoint.go | 24 ----- pkg/playbook/app/domain/authentication.go | 95 +++++++++++++++++-- pkg/playbook/app/domain/connection.go | 23 ++--- pkg/playbook/app/domain/connection_test.go | 41 +++++--- pkg/playbook/app/domain/platform.go | 95 ------------------- pkg/playbook/app/domain/playbook.go | 4 +- pkg/playbook/app/domain/playbook_test.go | 22 +++-- pkg/playbook/app/parser/writer_test.go | 8 +- pkg/playbook/app/vcertutil/vcertutil.go | 10 +- pkg/venafi/platform.go | 74 ++++++++++----- .../app/domain => venafi}/platform_test.go | 27 +++--- test-files/playbook/sample.yaml | 6 +- 15 files changed, 271 insertions(+), 206 deletions(-) create mode 100644 pkg/endpoint/authentication.go delete mode 100644 pkg/playbook/app/domain/platform.go rename pkg/{playbook/app/domain => venafi}/platform_test.go (71%) diff --git a/cmd/vcert/args.go b/cmd/vcert/args.go index dfd370a8..5b0864c5 100644 --- a/cmd/vcert/args.go +++ b/cmd/vcert/args.go @@ -115,7 +115,7 @@ type commandFlags struct { validDays string validPeriod string platformString string - platform venafi.PlatformType + platform venafi.Platform policyName string policySpecLocation string policyConfigStarter bool diff --git a/cmd/vcert/playbook.go b/cmd/vcert/playbook.go index 402aceb8..4896f04d 100644 --- a/cmd/vcert/playbook.go +++ b/cmd/vcert/playbook.go @@ -23,6 +23,7 @@ import ( "net/http" "os" + "github.com/Venafi/vcert/v5/pkg/venafi" "github.com/urfave/cli/v2" "go.uber.org/zap" "golang.org/x/crypto/pkcs12" @@ -129,7 +130,7 @@ func doRunPlaybook(_ *cli.Context) error { os.Exit(1) } - if playbook.Config.Connection.Platform == domain.CTypeTPP { + if playbook.Config.Connection.Platform == venafi.TPP { err = service.ValidateTPPCredentials(&playbook) if err != nil { zap.L().Error("invalid tpp credentials", zap.Error(err)) @@ -158,7 +159,7 @@ func setPlaybookTLSConfig(playbook domain.Playbook) error { // and to enable certificate authentication // Set RenegotiateFreelyAsClient in case of we're communicating with MTLS enabled TPP server - if playbook.Config.Connection.Platform == domain.CTypeTPP { + if playbook.Config.Connection.Platform == venafi.TPP { tlsConfig.Renegotiation = tls.RenegotiateFreelyAsClient } @@ -167,7 +168,7 @@ func setPlaybookTLSConfig(playbook domain.Playbook) error { } // Try to set up certificate authentication if enabled - if playbook.Config.Connection.Platform == domain.CTypeTPP && playbook.Config.Connection.Credentials.P12Task != "" { + if playbook.Config.Connection.Platform == venafi.TPP && playbook.Config.Connection.Credentials.P12Task != "" { zap.L().Info("attempting to enable certificate authentication to TPP") var p12FileLocation string var p12Password string diff --git a/pkg/endpoint/authentication.go b/pkg/endpoint/authentication.go new file mode 100644 index 00000000..47bdc663 --- /dev/null +++ b/pkg/endpoint/authentication.go @@ -0,0 +1,39 @@ +/* + * Copyright 2023 Venafi, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package endpoint + +// Authentication provides a struct for authentication data. Either specify User and Password for Trust Protection Platform +// or Firefly or ClientId and ClientSecret for Firefly or specify an APIKey for TLS Protect Cloud. +type Authentication struct { + User string `yaml:"-"` + Password string `yaml:"-"` + APIKey string `yaml:"apiKey,omitempty"` + RefreshToken string `yaml:"refreshToken,omitempty"` + Scope string `yaml:"scope,omitempty"` + ClientId string `yaml:"clientId,omitempty"` + ClientSecret string `yaml:"clientSecret,omitempty"` + AccessToken string `yaml:"accessToken,omitempty"` + ClientPKCS12 bool `yaml:"-"` + // IdentityProvider specify the OAuth 2.0 which VCert will be working for authorization purposes + IdentityProvider *OAuthProvider `yaml:"idP,omitempty"` +} + +// OAuthProvider provides a struct for the OAuth 2.0 providers information +type OAuthProvider struct { + TokenURL string `yaml:"tokenURL,omitempty"` + Audience string `yaml:"audience,omitempty"` +} diff --git a/pkg/endpoint/endpoint.go b/pkg/endpoint/endpoint.go index db7c6c4b..d0976c07 100644 --- a/pkg/endpoint/endpoint.go +++ b/pkg/endpoint/endpoint.go @@ -140,30 +140,6 @@ type Filter struct { WithExpired bool } -// Authentication provides a struct for authentication data. Either specify User and Password for Trust Protection Platform -// or Firefly or ClientId and ClientSecret for Firefly or specify an APIKey for TLS Protect Cloud. -type Authentication struct { - User string - Password string - APIKey string - RefreshToken string - Scope string - ClientId string - ClientSecret string - AccessToken string - ClientPKCS12 bool - // IdentityProvider specify the OAuth 2.0 which VCert will be working for authorization purposes - IdentityProvider *OAuthProvider -} - -// OAuthProvider provides a struct for the OAuth 2.0 providers information -type OAuthProvider struct { - //OAuthProviderType string - //AuthURL string - TokenURL string - Audience string -} - // todo: replace with verror // ErrRetrieveCertificateTimeout provides a common error structure for a timeout while retrieving a certificate type ErrRetrieveCertificateTimeout struct { diff --git a/pkg/playbook/app/domain/authentication.go b/pkg/playbook/app/domain/authentication.go index efda01f1..dcf56b14 100644 --- a/pkg/playbook/app/domain/authentication.go +++ b/pkg/playbook/app/domain/authentication.go @@ -16,21 +16,102 @@ package domain +import ( + "github.com/Venafi/vcert/v5/pkg/endpoint" + "gopkg.in/yaml.v3" +) + +const ( + accessToken = "accessToken" + apiKey = "apiKey" + clientID = "clientId" + clientSecret = "clientSecret" + idP = "idP" + refreshToken = "refreshToken" + p12Task = "p12Task" + scope = "scope" +) + // Authentication holds the credentials to connect to Venafi platforms: TPP and TLSPC type Authentication struct { - AccessToken string `yaml:"accessToken,omitempty"` - Apikey string `yaml:"apiKey,omitempty"` - ClientID string `yaml:"clientId,omitempty"` - RefreshToken string `yaml:"refreshToken,omitempty"` - Scope string `yaml:"scope,omitempty"` - P12Task string `yaml:"p12Task,omitempty"` + endpoint.Authentication `yaml:"-"` + P12Task string `yaml:"p12Task,omitempty"` } // IsEmpty returns true if not credentials are set func (a Authentication) IsEmpty() bool { // TODO: This is very hacky.. need specifics based on connection type - if a.Apikey == "" && a.AccessToken == "" && a.RefreshToken == "" && a.P12Task == "" { + if a.APIKey == "" && a.AccessToken == "" && a.RefreshToken == "" && a.P12Task == "" { return true } return false } + +// MarshalYAML customizes the behavior of Authentication when being marshaled into a YAML document. +// The returned value is marshaled in place of the original value implementing Marshaller +func (a Authentication) MarshalYAML() (interface{}, error) { + values := make(map[string]interface{}) + + if a.AccessToken != "" { + values[accessToken] = a.AccessToken + } + if a.APIKey != "" { + values[apiKey] = a.APIKey + } + if a.ClientId != "" { + values[clientID] = a.ClientId + } + if a.ClientSecret != "" { + values[clientSecret] = a.ClientSecret + } + if a.IdentityProvider != nil { + values[idP] = a.IdentityProvider + } + if a.RefreshToken != "" { + values[refreshToken] = a.RefreshToken + } + if a.P12Task != "" { + values[p12Task] = a.P12Task + } + if a.Scope != "" { + values[scope] = a.Scope + } + + return values, nil +} + +// UnmarshalYAML customizes the behavior when being unmarshalled from a YAML document +func (a *Authentication) UnmarshalYAML(value *yaml.Node) error { + var authMap map[string]interface{} + err := value.Decode(&authMap) + if err != nil { + return err + } + + if _, found := authMap[accessToken]; found { + a.AccessToken = authMap[accessToken].(string) + } + if _, found := authMap[apiKey]; found { + a.APIKey = authMap[apiKey].(string) + } + if _, found := authMap[clientID]; found { + a.ClientId = authMap[clientID].(string) + } + if _, found := authMap[clientSecret]; found { + a.ClientSecret = authMap[clientSecret].(string) + } + if _, found := authMap[idP]; found { + //a.IdentityProvider = authMap[].(string) + } + if _, found := authMap[refreshToken]; found { + a.RefreshToken = authMap[refreshToken].(string) + } + if _, found := authMap[p12Task]; found { + a.P12Task = authMap[p12Task].(string) + } + if _, found := authMap[scope]; found { + a.Scope = authMap[scope].(string) + } + + return nil +} diff --git a/pkg/playbook/app/domain/connection.go b/pkg/playbook/app/domain/connection.go index 9312b5fe..394eb317 100644 --- a/pkg/playbook/app/domain/connection.go +++ b/pkg/playbook/app/domain/connection.go @@ -22,26 +22,27 @@ import ( "os" "github.com/Venafi/vcert/v5/pkg/endpoint" + "github.com/Venafi/vcert/v5/pkg/venafi" ) // Connection represents the issuer that vCert will connect to // in order to issue certificates type Connection struct { - Credentials Authentication `yaml:"credentials,omitempty"` - Insecure bool `yaml:"insecure,omitempty"` - Platform Platform `yaml:"platform,omitempty"` - TrustBundlePath string `yaml:"trustBundle,omitempty"` - URL string `yaml:"url,omitempty"` + Credentials Authentication `yaml:"credentials,omitempty"` + Insecure bool `yaml:"insecure,omitempty"` + Platform venafi.Platform `yaml:"platform,omitempty"` + TrustBundlePath string `yaml:"trustBundle,omitempty"` + URL string `yaml:"url,omitempty"` } // GetConnectorType returns the type of vcert Connector this config will create func (c Connection) GetConnectorType() endpoint.ConnectorType { switch c.Platform { - case CTypeFirefly: + case venafi.Firefly: return endpoint.ConnectorTypeFirefly - case CTypeTPP: + case venafi.TPP: return endpoint.ConnectorTypeTPP - case CTypeVaaS: + case venafi.TLSPCloud: return endpoint.ConnectorTypeCloud default: return endpoint.ConnectorTypeFake @@ -63,11 +64,11 @@ func (c Connection) validateTrustBundle() error { // and has the necessary values to connect to the given platform func (c Connection) IsValid() (bool, error) { switch c.Platform { - case CTypeTPP: + case venafi.TPP: return isValidTpp(c) - case CTypeVaaS: + case venafi.TLSPCloud: return isValidVaaS(c) - case CTypeFirefly: + case venafi.Firefly: return isValidFirefly(c) default: return false, fmt.Errorf("invalid connection type %v", c.Platform) diff --git a/pkg/playbook/app/domain/connection_test.go b/pkg/playbook/app/domain/connection_test.go index 181abc3c..bcbcc6ac 100644 --- a/pkg/playbook/app/domain/connection_test.go +++ b/pkg/playbook/app/domain/connection_test.go @@ -20,6 +20,7 @@ import ( "fmt" "testing" + "github.com/Venafi/vcert/v5/pkg/venafi" "github.com/stretchr/testify/suite" "github.com/Venafi/vcert/v5/pkg/endpoint" @@ -48,9 +49,11 @@ func (s *ConnectionSuite) SetupTest() { { name: "Firefly_valid", c: Connection{ - Platform: CTypeFirefly, + Platform: venafi.Firefly, Credentials: Authentication{ - Apikey: "asdasdadsd", + Authentication: endpoint.Authentication{ + APIKey: "asdasdadsd", + }, }, }, expectedCType: endpoint.ConnectorTypeFirefly, @@ -59,7 +62,7 @@ func (s *ConnectionSuite) SetupTest() { { name: "Firefly_invalid_empty_credentials", c: Connection{ - Platform: CTypeFirefly, + Platform: venafi.Firefly, Credentials: Authentication{}, }, expectedCType: endpoint.ConnectorTypeFirefly, @@ -69,9 +72,11 @@ func (s *ConnectionSuite) SetupTest() { { name: "TPP_valid", c: Connection{ - Platform: CTypeTPP, + Platform: venafi.TPP, Credentials: Authentication{ - AccessToken: "123abc###", + Authentication: endpoint.Authentication{ + AccessToken: "123abc###", + }, }, URL: "https://my.tpp.instance.com", TrustBundlePath: "", @@ -83,7 +88,7 @@ func (s *ConnectionSuite) SetupTest() { { name: "TPP_invalid_empty_credentials", c: Connection{ - Platform: CTypeTPP, + Platform: venafi.TPP, Credentials: Authentication{}, URL: "https://my.tpp.instance.com", }, @@ -94,9 +99,11 @@ func (s *ConnectionSuite) SetupTest() { { name: "TPP_invalid_no_url", c: Connection{ - Platform: CTypeTPP, + Platform: venafi.TPP, Credentials: Authentication{ - AccessToken: "123abc###", + Authentication: endpoint.Authentication{ + AccessToken: "123abc###", + }, }, }, expectedCType: endpoint.ConnectorTypeTPP, @@ -106,9 +113,11 @@ func (s *ConnectionSuite) SetupTest() { { name: "TPP_invalid_trustbundle_not_exist", c: Connection{ - Platform: CTypeTPP, + Platform: venafi.TPP, Credentials: Authentication{ - AccessToken: "123abc###", + Authentication: endpoint.Authentication{ + AccessToken: "123abc###", + }, }, URL: "https://my.tpp.instance.com", TrustBundlePath: "/foo/bar/trustbundle.pem", @@ -120,9 +129,11 @@ func (s *ConnectionSuite) SetupTest() { { name: "VaaS_valid", c: Connection{ - Platform: CTypeVaaS, + Platform: venafi.TLSPCloud, Credentials: Authentication{ - Apikey: "xxx-XXX-xxx", + Authentication: endpoint.Authentication{ + APIKey: "xxx-XXX-xxx", + }, }, }, expectedCType: endpoint.ConnectorTypeCloud, @@ -131,7 +142,7 @@ func (s *ConnectionSuite) SetupTest() { { name: "VaaS_invalid_empty_credentials", c: Connection{ - Platform: CTypeVaaS, + Platform: venafi.TLSPCloud, Credentials: Authentication{}, }, expectedCType: endpoint.ConnectorTypeCloud, @@ -141,11 +152,11 @@ func (s *ConnectionSuite) SetupTest() { { name: "Unknown_invalid", c: Connection{ - Platform: CTypeUnknown, + Platform: venafi.Undefined, }, expectedCType: endpoint.ConnectorTypeFake, expectedValid: false, - expectedErr: fmt.Errorf("invalid connection type %v", CTypeUnknown), + expectedErr: fmt.Errorf("invalid connection type %v", venafi.Undefined), }, } } diff --git a/pkg/playbook/app/domain/platform.go b/pkg/playbook/app/domain/platform.go deleted file mode 100644 index 1ca04f2a..00000000 --- a/pkg/playbook/app/domain/platform.go +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2023 Venafi, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package domain - -import ( - "strings" - - "gopkg.in/yaml.v3" -) - -// Platform represents the type of connection for certificate issuance: -// TPP, TLSPC, Firefly, etc. -type Platform int64 - -const ( - // CTypeUnknown represents an invalid Platform - CTypeUnknown Platform = iota - // CTypeTPP represents a connection to TPP - CTypeTPP - // CTypeVaaS represents a connection to VaaS - CTypeVaaS - // CTypeFirefly represents a connection to Firefly - CTypeFirefly - - // String representations of the Platform types - stringCTypeTPP = "TPP" - stringCTypeVaaS = "VAAS" - stringCTypeFirefly = "FIREFLY" - stringCTypeUnknown = "Unknown" - - // Some alias names for TPP & VaaS - stringCTypeTLSPDC = "TLSPDC" - stringCTypeTLSPC = "TLSPC" -) - -// String returns a string representation of this object -func (ct *Platform) String() string { - switch *ct { - case CTypeTPP: - return stringCTypeTPP - case CTypeVaaS: - return stringCTypeVaaS - case CTypeFirefly: - return stringCTypeFirefly - default: - return stringCTypeUnknown - } -} - -// MarshalYAML customizes the behavior of ChainOption when being marshaled into a YAML document. -// The returned value is marshaled in place of the original value implementing Marshaller -func (ct Platform) MarshalYAML() (interface{}, error) { - return ct.String(), nil -} - -// UnmarshalYAML customizes the behavior when being unmarshalled from a YAML document -func (ct *Platform) UnmarshalYAML(value *yaml.Node) error { - var strValue string - err := value.Decode(&strValue) - if err != nil { - return err - } - *ct, err = parseConnectionType(strValue) - if err != nil { - return err - } - return nil -} - -func parseConnectionType(strConnectionType string) (Platform, error) { - switch strings.ToUpper(strConnectionType) { - case stringCTypeTPP, stringCTypeTLSPDC: - return CTypeTPP, nil - case stringCTypeVaaS, stringCTypeTLSPC: - return CTypeVaaS, nil - case stringCTypeFirefly: - return CTypeFirefly, nil - default: - return CTypeUnknown, nil - } -} diff --git a/pkg/playbook/app/domain/playbook.go b/pkg/playbook/app/domain/playbook.go index 66b05a17..11a88db0 100644 --- a/pkg/playbook/app/domain/playbook.go +++ b/pkg/playbook/app/domain/playbook.go @@ -19,6 +19,8 @@ package domain import ( "errors" "fmt" + + "github.com/Venafi/vcert/v5/pkg/venafi" ) const ( @@ -45,7 +47,7 @@ func NewPlaybook() Playbook { CertificateTasks: make(CertificateTasks, 0), Config: Config{ Connection: Connection{ - Platform: CTypeVaaS, + Platform: venafi.TLSPCloud, URL: tlspcURL, TrustBundlePath: "", }, diff --git a/pkg/playbook/app/domain/playbook_test.go b/pkg/playbook/app/domain/playbook_test.go index f198fef3..2d990ef1 100644 --- a/pkg/playbook/app/domain/playbook_test.go +++ b/pkg/playbook/app/domain/playbook_test.go @@ -21,6 +21,8 @@ import ( "runtime" "testing" + "github.com/Venafi/vcert/v5/pkg/endpoint" + "github.com/Venafi/vcert/v5/pkg/venafi" "github.com/stretchr/testify/suite" ) @@ -48,9 +50,11 @@ func (s *PlaybookSuite) SetupTest() { config := Config{ Connection: Connection{ - Platform: CTypeVaaS, + Platform: venafi.TLSPCloud, Credentials: Authentication{ - Apikey: "foobarGibberish123", + Authentication: endpoint.Authentication{ + APIKey: "foobarGibberish123", + }, }, }, } @@ -82,8 +86,10 @@ func (s *PlaybookSuite) SetupTest() { Config: Config{ Connection: Connection{ Credentials: Authentication{ - AccessToken: "foobar123", - Apikey: "xyz456abc", + Authentication: endpoint.Authentication{ + AccessToken: "foobar123", + APIKey: "xyz456abc", + }, }, }, }, @@ -96,7 +102,9 @@ func (s *PlaybookSuite) SetupTest() { Config: Config{ Connection: Connection{ Credentials: Authentication{ - AccessToken: "someToken", + Authentication: endpoint.Authentication{ + AccessToken: "someToken", + }, }, }, }, @@ -109,7 +117,9 @@ func (s *PlaybookSuite) SetupTest() { Config: Config{ Connection: Connection{ Credentials: Authentication{ - AccessToken: "someToken", + Authentication: endpoint.Authentication{ + AccessToken: "someToken", + }, }, URL: "https://foo.bar.kwan", TrustBundlePath: "/foo/bar/bundle.pem", diff --git a/pkg/playbook/app/parser/writer_test.go b/pkg/playbook/app/parser/writer_test.go index ab2dd418..9f76b5ee 100644 --- a/pkg/playbook/app/parser/writer_test.go +++ b/pkg/playbook/app/parser/writer_test.go @@ -21,6 +21,7 @@ import ( "os" "testing" + "github.com/Venafi/vcert/v5/pkg/endpoint" "github.com/stretchr/testify/suite" "github.com/Venafi/vcert/v5/pkg/certificate" @@ -73,8 +74,11 @@ func (s *WriterSuite) SetupTest() { URL: "https://foo.bar.venafi.com", TrustBundlePath: "path/to/my/trustbundle.pem", Credentials: domain.Authentication{ - AccessToken: "123fooBar", - RefreshToken: "456XyzABc", + Authentication: endpoint.Authentication{ + AccessToken: "123fooBar", + RefreshToken: "456XyzABc", + }, + P12Task: "", }, }, }, diff --git a/pkg/playbook/app/vcertutil/vcertutil.go b/pkg/playbook/app/vcertutil/vcertutil.go index c204ae66..059ae0cc 100644 --- a/pkg/playbook/app/vcertutil/vcertutil.go +++ b/pkg/playbook/app/vcertutil/vcertutil.go @@ -79,9 +79,9 @@ func buildClient(config domain.Config, zone string) (endpoint.Connector, error) BaseUrl: config.Connection.URL, Zone: zone, Credentials: &endpoint.Authentication{ - APIKey: config.Connection.Credentials.Apikey, + APIKey: config.Connection.Credentials.APIKey, Scope: config.Connection.Credentials.Scope, - ClientId: config.Connection.Credentials.ClientID, + ClientId: config.Connection.Credentials.ClientId, AccessToken: config.Connection.Credentials.AccessToken, }, ConnectionTrust: loadTrustBundle(config.Connection.TrustBundlePath), @@ -162,7 +162,7 @@ func IsValidAccessToken(config domain.Config) (bool, error) { BaseUrl: config.Connection.URL, Credentials: &endpoint.Authentication{ Scope: config.Connection.Credentials.Scope, - ClientId: config.Connection.Credentials.ClientID, + ClientId: config.Connection.Credentials.ClientId, AccessToken: config.Connection.Credentials.AccessToken, }, ConnectionTrust: loadTrustBundle(config.Connection.TrustBundlePath), @@ -186,7 +186,7 @@ func RefreshTPPTokens(config domain.Config) (string, string, error) { BaseUrl: config.Connection.URL, Credentials: &endpoint.Authentication{ Scope: config.Connection.Credentials.Scope, - ClientId: config.Connection.Credentials.ClientID, + ClientId: config.Connection.Credentials.ClientId, }, ConnectionTrust: loadTrustBundle(config.Connection.TrustBundlePath), LogVerbose: false, @@ -202,7 +202,7 @@ func RefreshTPPTokens(config domain.Config) (string, string, error) { RefreshToken: config.Connection.Credentials.RefreshToken, ClientPKCS12: config.Connection.Credentials.P12Task != "", Scope: config.Connection.Credentials.Scope, - ClientId: config.Connection.Credentials.ClientID, + ClientId: config.Connection.Credentials.ClientId, } if auth.RefreshToken != "" { diff --git a/pkg/venafi/platform.go b/pkg/venafi/platform.go index 9f18e9f8..8418eb78 100644 --- a/pkg/venafi/platform.go +++ b/pkg/venafi/platform.go @@ -17,14 +17,16 @@ package venafi import ( - "fmt" "strings" + + "gopkg.in/yaml.v3" ) -type PlatformType int +type Platform int const ( - Undefined PlatformType = iota + // Undefined represents an invalid Platform + Undefined Platform = iota // Fake is a fake platform for tests Fake // TLSPCloud represents the TLS Protect Cloud platform type @@ -33,35 +35,63 @@ const ( TPP // Firefly represents the Firefly platform type Firefly + + // String representations of the Platform types + strPlatformFake = "FAKE" + strPlatformFirefly = "FIREFLY" + strPlatformTPP = "TPP" + strPlatformVaaS = "VAAS" + strPlatformUnknown = "Unknown" + + // alias for TPP + strPlatformTLSPDC = "TLSPDC" + // alias for VaaS + strPlatformTLSPC = "TLSPC" ) -func (t PlatformType) String() string { - switch t { - case Undefined: - return "Undefined platform" +// String returns a string representation of this object +func (p Platform) String() string { + switch p { case Fake: - return "Fake platform" - case TLSPCloud: - return "TLS Protect Cloud" - case TPP: - return "Trust Protection Platform" + return strPlatformFake case Firefly: - return "Firefly" + return strPlatformFirefly + case TPP: + return strPlatformTPP + case TLSPCloud: + return strPlatformVaaS default: - return fmt.Sprintf("unexpected platform type: %d", t) + return strPlatformUnknown + } +} + +// MarshalYAML customizes the behavior of Platform when being marshaled into a YAML document. +// The returned value is marshaled in place of the original value implementing Marshaller +func (p Platform) MarshalYAML() (interface{}, error) { + return p.String(), nil +} + +// UnmarshalYAML customizes the behavior when being unmarshalled from a YAML document +func (p *Platform) UnmarshalYAML(value *yaml.Node) error { + var strValue string + err := value.Decode(&strValue) + if err != nil { + return err } + *p = GetPlatformType(strValue) + return nil } -func GetPlatformType(platformString string) PlatformType { - switch strings.ToLower(platformString) { - case "fake": +func GetPlatformType(platformString string) Platform { + switch strings.ToUpper(platformString) { + case strPlatformFake: return Fake - case "tlspdatacenter": - return TLSPCloud - case "tlspcloud": - return TPP - case "firefly": + case strPlatformFirefly: return Firefly + case strPlatformTPP, strPlatformTLSPDC: + return TPP + case strPlatformVaaS, strPlatformTLSPC: + return TLSPCloud default: return Undefined } diff --git a/pkg/playbook/app/domain/platform_test.go b/pkg/venafi/platform_test.go similarity index 71% rename from pkg/playbook/app/domain/platform_test.go rename to pkg/venafi/platform_test.go index 7962a405..07a8f4db 100644 --- a/pkg/playbook/app/domain/platform_test.go +++ b/pkg/venafi/platform_test.go @@ -14,7 +14,7 @@ * limitations under the License. */ -package domain +package venafi import ( "fmt" @@ -24,7 +24,7 @@ import ( "gopkg.in/yaml.v3" ) -type ConnectionTypeSuite struct { +type PlatformSuite struct { suite.Suite testYaml string testCases []struct { @@ -33,15 +33,15 @@ type ConnectionTypeSuite struct { } } -func (s *ConnectionTypeSuite) SetupTest() { +func (s *PlatformSuite) SetupTest() { s.testCases = []struct { ct Platform strValue string }{ - {ct: CTypeUnknown, strValue: stringCTypeUnknown}, - {ct: CTypeTPP, strValue: stringCTypeTPP}, - {ct: CTypeVaaS, strValue: stringCTypeVaaS}, - {ct: CTypeFirefly, strValue: stringCTypeFirefly}, + {ct: Undefined, strValue: strPlatformUnknown}, + {ct: TPP, strValue: strPlatformTPP}, + {ct: TLSPCloud, strValue: strPlatformVaaS}, + {ct: Firefly, strValue: strPlatformFirefly}, } s.testYaml = `--- @@ -51,10 +51,10 @@ url: https://something.com } func TestConnectionType(t *testing.T) { - suite.Run(t, new(ConnectionTypeSuite)) + suite.Run(t, new(PlatformSuite)) } -func (s *ConnectionTypeSuite) TestConnectionType_MarshalYAML() { +func (s *PlatformSuite) TestConnectionType_MarshalYAML() { for _, tc := range s.testCases { s.Run(tc.strValue, func() { data, err := tc.ct.MarshalYAML() @@ -64,7 +64,7 @@ func (s *ConnectionTypeSuite) TestConnectionType_MarshalYAML() { } } -func (s *ConnectionTypeSuite) TestConnectionType_String() { +func (s *PlatformSuite) TestConnectionType_String() { for _, tc := range s.testCases { s.Run(tc.strValue, func() { str := tc.ct.String() @@ -73,10 +73,13 @@ func (s *ConnectionTypeSuite) TestConnectionType_String() { } } -func (s *ConnectionTypeSuite) TestConnectionType_UnmarshalYAML() { +func (s *PlatformSuite) TestConnectionType_UnmarshalYAML() { for _, tc := range s.testCases { s.Run(tc.strValue, func() { - var c Connection + var c struct { + Platform Platform `yaml:"platform,omitempty"` + Url string `yaml:"url,omitempty"` + } parsedYaml := fmt.Sprintf(s.testYaml, tc.strValue) err := yaml.Unmarshal([]byte(parsedYaml), &c) diff --git a/test-files/playbook/sample.yaml b/test-files/playbook/sample.yaml index c470cdff..01c46c16 100644 --- a/test-files/playbook/sample.yaml +++ b/test-files/playbook/sample.yaml @@ -1,6 +1,8 @@ config: - credentials: - apikey: fooo123bar! + connection: + type: TLSPC + credentials: + apiKey: fooo123bar! certificateTasks: - name: mtls request: From c49a2251f56be83a9218c9151c33968085441311 Mon Sep 17 00:00:00 2001 From: Russel Vela Date: Mon, 14 Aug 2023 16:40:21 -0600 Subject: [PATCH 09/10] fix(platform): fix linter check --- pkg/playbook/app/domain/authentication.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/playbook/app/domain/authentication.go b/pkg/playbook/app/domain/authentication.go index dcf56b14..db01ab66 100644 --- a/pkg/playbook/app/domain/authentication.go +++ b/pkg/playbook/app/domain/authentication.go @@ -100,9 +100,9 @@ func (a *Authentication) UnmarshalYAML(value *yaml.Node) error { if _, found := authMap[clientSecret]; found { a.ClientSecret = authMap[clientSecret].(string) } - if _, found := authMap[idP]; found { - //a.IdentityProvider = authMap[].(string) - } + //if _, found := authMap[idP]; found { + // a.IdentityProvider = authMap[].(string) + //} if _, found := authMap[refreshToken]; found { a.RefreshToken = authMap[refreshToken].(string) } From 1f6a252bc4922b1ac5f955f29fb77a0a974478f5 Mon Sep 17 00:00:00 2001 From: Russel Vela Date: Mon, 14 Aug 2023 17:27:10 -0600 Subject: [PATCH 10/10] fix(platform): fix tests --- cmd/vcert/playbook_test.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cmd/vcert/playbook_test.go b/cmd/vcert/playbook_test.go index 0948707a..8a592ea0 100644 --- a/cmd/vcert/playbook_test.go +++ b/cmd/vcert/playbook_test.go @@ -15,6 +15,7 @@ import ( "golang.org/x/crypto/pkcs12" "github.com/Venafi/vcert/v5/pkg/playbook/app/domain" + "github.com/Venafi/vcert/v5/pkg/venafi" ) type logLine struct { @@ -55,7 +56,7 @@ func (s *PlaybookSuite) TestPlaybook_SetTLSConfig() { }, Config: domain.Config{ Connection: domain.Connection{ - Platform: domain.CTypeTPP, + Platform: venafi.TPP, Credentials: domain.Authentication{P12Task: "p12Auth"}, }, }, @@ -114,7 +115,7 @@ func (s *PlaybookSuite) TestPlaybook_SetTLSConfig_noP12Certificate() { }, Config: domain.Config{ Connection: domain.Connection{ - Platform: domain.CTypeTPP, + Platform: venafi.TPP, Credentials: domain.Authentication{P12Task: "p12Auth"}, Insecure: true, }, @@ -165,7 +166,7 @@ func (s *PlaybookSuite) TestPlaybook_SetTLSConfig_noCertAuth() { CertificateTasks: nil, Config: domain.Config{ Connection: domain.Connection{ - Platform: domain.CTypeVaaS, + Platform: venafi.TLSPCloud, Credentials: domain.Authentication{}, }, },