diff --git a/README-CLI-CLOUD.md b/README-CLI-CLOUD.md index 29d3d5ca..9f085e97 100644 --- a/README-CLI-CLOUD.md +++ b/README-CLI-CLOUD.md @@ -226,27 +226,28 @@ Options: ## Certificate Provisioning Parameters API key: ``` -vcert provisioning cloudkeystore -p vcp -k [--certificate-id | --pickup-id | --pickup-id-file ] [ --keystore-id | --keystore-name --provider-name ] +vcert provisioning cloudkeystore -p vcp -k [--certificate-id | --pickup-id | --pickup-id-file ] [ --keystore-id | --keystore-name --provider-name ] --certificate-name --gcm-cert-scope ``` Access token: ``` -vcert provisioning cloudkeystore -p vcp -t [--certificate-id | --pickup-id | --pickup-id-file ] [ --keystore-id | --keystore-name --provider-name ] +vcert provisioning cloudkeystore -p vcp -t [--certificate-id | --pickup-id | --pickup-id-file ] [ --keystore-id | --keystore-name --provider-name ] --certificate-name --gcm-cert-scope ``` Options: -| Command | Description | -|-------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `--arn` | Use to specify AWS Resource Name which provisioned certificate will replace (only for AWS Certificate Manager) | -| `--certificate-id` | The id of the certificate to be provisioned to a cloud keystore. | -| `--certificate-id-file` | Use to specify a file name that contains the unique identifier of the certificate. Required when `--certificate-id` is not specified. | -| `--certificate-name` | Use to specify Cloud Keystore Certificate Name to be set or replaced by provisioned certificate (only for Azure Key Vault and Google Certificate Manager) | -| `--file` | Use to specify a file name and a location where the output should be written. Example: --file /path-to/provision-output | -| `--format` | The format of the operation output: text or JSON. Defaults to text. | -| `--keystore-id` | The id of the cloud keystore where the certificate will be provisioned. | -| `--keystore-name` | The name of the cloud keystore where the certificate will be provisioned. Must be set along with provider-name flag. | -| `--pickup-id` | Use to specify the unique identifier of the certificate returned by the enroll or renew actions. Required when `--pickup-id-file` is not specified. | -| `--pickup-id-file` | Use to specify a file name that contains the unique identifier of the certificate returned by the enroll or renew actions if --no-pickup was used or a timeout occurred. Required when `--pickup-id` is not specified. | -| `--provider-name` | The name of the cloud provider which owns the cloud keystore where the certificate will be provisioned. Must be set along with keystore-name flag. | +| Command | Description | +|-------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `--arn` | Use to specify AWS Resource Name which provisioned certificate will replace (only for AWS Certificate Manager) | +| `--gcm-cert-scope` | Use to specify Certificate Scope of the certificate to be provisioned (only for Google Cloud Certificate Manager). Supported values from GCM API documentation: DEFAULT, EDGE_CACHE, ALL_REGIONS. If --certificate-name is not provided it will be ignored | +| `--certificate-id` | The id of the certificate to be provisioned to a cloud keystore. | +| `--certificate-id-file` | Use to specify a file name that contains the unique identifier of the certificate. Required when `--certificate-id` is not specified. | +| `--certificate-name` | Use to specify Cloud Keystore Certificate Name to be set or replaced by provisioned certificate (only for Azure Key Vault and Google Certificate Manager) | +| `--file` | Use to specify a file name and a location where the output should be written. Example: --file /path-to/provision-output | +| `--format` | The format of the operation output: text or JSON. Defaults to text. | +| `--keystore-id` | The id of the cloud keystore where the certificate will be provisioned. | +| `--keystore-name` | The name of the cloud keystore where the certificate will be provisioned. Must be set along with provider-name flag. | +| `--pickup-id` | Use to specify the unique identifier of the certificate returned by the enroll or renew actions. Required when `--pickup-id-file` is not specified. | +| `--pickup-id-file` | Use to specify a file name that contains the unique identifier of the certificate returned by the enroll or renew actions if --no-pickup was used or a timeout occurred. Required when `--pickup-id` is not specified. | +| `--provider-name` | The name of the cloud provider which owns the cloud keystore where the certificate will be provisioned. Must be set along with keystore-name flag. | ## Parameters for Applying Certificate Policy API key: diff --git a/aruba/features/provision/cloudkeystore/provision_cloudkeystore.feature b/aruba/features/provision/cloudkeystore/provision_cloudkeystore.feature index 4b89a371..548d5af0 100644 --- a/aruba/features/provision/cloudkeystore/provision_cloudkeystore.feature +++ b/aruba/features/provision/cloudkeystore/provision_cloudkeystore.feature @@ -66,3 +66,16 @@ Feature: provision to cloud keystore | AWS | | GOOGLE | | AZURE | + + + Scenario Outline: Enroll certificate and execute provisioning for cloud keystore on GCM using certificate's scopes + Given I enroll a random certificate with defined platform VCP with -csr service -no-prompt + And I remember the output + And I use previous Pickup ID to provision from VCP a certificate to cloudkeystore "" setting keystore and provider names with -gcm-cert-scope DEFAULT + And I remember the output + And the output should not contain "Warning: --platform not set. Attempting to best-guess platform from connection flags" + And I grab cloud ID from output + Then I clean up previous installed certificate from cloudkeystore + Examples: + | cloudkeystore | + | GOOGLE | diff --git a/aruba/features/provision/cloudkeystore/steps_definitions/my_steps.rb b/aruba/features/provision/cloudkeystore/steps_definitions/my_steps.rb index fba796a5..00ae0053 100644 --- a/aruba/features/provision/cloudkeystore/steps_definitions/my_steps.rb +++ b/aruba/features/provision/cloudkeystore/steps_definitions/my_steps.rb @@ -77,6 +77,8 @@ def build_provision_cmd(platform, cloudkeystore_type, keystore_provider_names, f else keystore_id = GCP_KEYSTORE_ID end + cert_name_flag = " -certificate-name vcert-cert-" + random_string + cmd = cmd + cert_name_flag else fail(ArgumentError.new("Unexpected : #{cloudkeystore_type}")) end diff --git a/cmd/vcert/args.go b/cmd/vcert/args.go index 9471fb89..63e6f3cf 100644 --- a/cmd/vcert/args.go +++ b/cmd/vcert/args.go @@ -153,6 +153,7 @@ type commandFlags struct { keystoreName string keystoreCertName string keystoreARN string + gcmCertScope string provisionOutputFile string provisionPickupID string provisionFormat string diff --git a/cmd/vcert/flags.go b/cmd/vcert/flags.go index 470b186c..128071d3 100644 --- a/cmd/vcert/flags.go +++ b/cmd/vcert/flags.go @@ -759,6 +759,15 @@ var ( Destination: &flags.keystoreARN, } + flagGCMCertScope = &cli.StringFlag{ + Name: "gcm-cert-scope", + Usage: "Use to specify Certificate Scope of the certificate to be provisioned (only for Google Cloud Certificate Manager).\n" + + "\t\t The possible values are the same defined by the 'scope' field in the certificatemanagercertificate API documentation: DEFAULT | EDGE_CACHE | ALL_REGIONS.\n" + + "\t\t https://cloud.google.com/config-connector/docs/reference/resource-docs/certificatemanager/certificatemanagercertificate\n" + + "\t\t Note: Only it will be take into account when the \"--" + flagKeystoreCertName.Name + "\" is provided. Otherwise it will be ignored.", + Destination: &flags.gcmCertScope, + } + flagProvisionOutputFile = &cli.StringFlag{ Name: "file", Usage: "Use to specify a file name and a location where the output should be written. " + @@ -927,6 +936,7 @@ var ( credentialsFlags, flagPlatform, flagKeystoreARN, + flagGCMCertScope, flagCertificateID, flagCertificateIDFile, flagKeystoreCertName, diff --git a/cmd/vcert/utils.go b/cmd/vcert/utils.go index 209d3e0a..d7ccac1c 100644 --- a/cmd/vcert/utils.go +++ b/cmd/vcert/utils.go @@ -635,6 +635,9 @@ func fillProvisioningRequest(req *domain.ProvisioningRequest, keystore domain.Cl options = &domain.ProvisioningOptions{} options.CloudCertificateName = cf.keystoreCertName options.ARN = cf.keystoreARN + if cf.gcmCertScope != "" { + options.GCMCertificateScope = domain.GetScopeFromString(cf.gcmCertScope) + } } return req, options diff --git a/cmd/vcert/validators.go b/cmd/vcert/validators.go index c1876ff2..049be51e 100644 --- a/cmd/vcert/validators.go +++ b/cmd/vcert/validators.go @@ -24,6 +24,7 @@ import ( "strings" "github.com/Venafi/vcert/v5/pkg/certificate" + "github.com/Venafi/vcert/v5/pkg/domain" "github.com/Venafi/vcert/v5/pkg/util" "github.com/Venafi/vcert/v5/pkg/venafi" ) @@ -728,6 +729,10 @@ func validateProvisionFlags(commandName string) error { return err } + if flags.gcmCertScope != "" && domain.GetScopeFromString(flags.gcmCertScope) == domain.GCMCertificateScopeUnknow { + return fmt.Errorf("unexpected Google Cloud Certificate Scope provided in --%s: %s", flagGCMCertScope.Name, flags.gcmCertScope) + } + if flags.provisionFormat != "" && flags.provisionFormat != "json" { return fmt.Errorf("unexpected output format: %s", flags.format) } diff --git a/pkg/domain/gcm.go b/pkg/domain/gcm.go new file mode 100644 index 00000000..ca3bd518 --- /dev/null +++ b/pkg/domain/gcm.go @@ -0,0 +1,50 @@ +package domain + +import "strings" + +// GCMCertificateScope Indicates the Scope for a certificate provisioned to GCP Certificate Manager +type GCMCertificateScope string + +var ( + // GCMCertificateScopeDefault Certificates with default scope are served from core Google data centers. + // If unsure, choose this option. + GCMCertificateScopeDefault GCMCertificateScope = addCertificateScope("DEFAULT") + + // GCMCertificateScopeEdgeCache Certificates with scope EDGE_CACHE are special-purposed certificates, + // served from Edge Points of Presence. + // See https://cloud.google.com/vpc/docs/edge-locations. + GCMCertificateScopeEdgeCache GCMCertificateScope = addCertificateScope("EDGE_CACHE") + + // GCMCertificateScopeAllRegions Certificates with ALL_REGIONS scope are served from all Google Cloud regions + // See https://cloud.google.com/compute/docs/regions-zones. + GCMCertificateScopeAllRegions GCMCertificateScope = addCertificateScope("ALL_REGIONS") + + // GCMCertificateScopeUnknow value to set that the Certificate Scope is not matching to any of the valid scopes. + GCMCertificateScopeUnknow GCMCertificateScope = addCertificateScope("UNKNOWN") +) + +var GCMCertificateScopes = map[GCMCertificateScope]bool{} + +func addCertificateScope(scope string) GCMCertificateScope { + scope = strings.ToUpper(scope) + + certificateScope := GCMCertificateScope(scope) + + if !GCMCertificateScopes[certificateScope] { + GCMCertificateScopes[certificateScope] = true + } + + return certificateScope +} + +func GetScopeFromString(scope string) GCMCertificateScope { + scope = strings.ToUpper(scope) + + certificateScope := GCMCertificateScope(scope) + + if !GCMCertificateScopes[certificateScope] { + return GCMCertificateScopeUnknow + } + + return certificateScope +} diff --git a/pkg/domain/provisioning.go b/pkg/domain/provisioning.go index 798ba5bc..62664ddd 100644 --- a/pkg/domain/provisioning.go +++ b/pkg/domain/provisioning.go @@ -29,4 +29,6 @@ type ProvisioningOptions struct { ARN string // for AKV and GCM only CloudCertificateName string + //GCM Certificate Scope + GCMCertificateScope GCMCertificateScope } diff --git a/pkg/venafi/cloud/cloudproviders.go b/pkg/venafi/cloud/cloudproviders.go index 16bc23ba..47733462 100644 --- a/pkg/venafi/cloud/cloudproviders.go +++ b/pkg/venafi/cloud/cloudproviders.go @@ -26,19 +26,6 @@ type CloudKeystoreProvisioningResult struct { Error error `json:"error"` } -// GCMCertificateScope Indicates the Scope for a certificate provisioned to GCP Certificate Manager -type GCMCertificateScope string - -const ( - // GCMCertificateScopeDefault Certificates with default scope are served from core Google data centers. - // If unsure, choose this option. - GCMCertificateScopeDefault GCMCertificateScope = "DEFAULT" - // GCMCertificateScopeEdgeCache Certificates with scope EDGE_CACHE are special-purposed certificates, - // served from Edge Points of Presence. - // See https://cloud.google.com/vpc/docs/edge-locations. - GCMCertificateScopeEdgeCache GCMCertificateScope = "EDGE_CACHE" -) - func (c *Connector) ProvisionCertificate(req *domain.ProvisioningRequest, options *domain.ProvisioningOptions) (*domain.ProvisioningMetadata, error) { log.Printf("Starting Provisioning Flow") @@ -288,6 +275,15 @@ func setProvisioningOptions(options domain.ProvisioningOptions, keystoreType dom azureOptions.Name = &options.CloudCertificateName case domain.CloudKeystoreTypeGCM: gcpOptions.Id = &options.CloudCertificateName + + //determining if it was provided a valid scope + if options.GCMCertificateScope == domain.GCMCertificateScopeUnknow { + return nil, fmt.Errorf("unknown GCM certificate scope") + } + gcmCertScope := GetGCMCertificateScope(options.GCMCertificateScope) + if gcmCertScope != nil { + gcpOptions.Scope = gcmCertScope + } default: return nil, fmt.Errorf("unknown cloud keystore type: %s", keystoreType) } @@ -385,3 +381,19 @@ func getCloudMetadataFromWebsocketResponse(resultMap interface{}, keystoreType d return cloudMetadata, err } + +func GetGCMCertificateScope(scope domain.GCMCertificateScope) *cloudproviders.GCMCertificateScope { + + switch scope { + case domain.GCMCertificateScopeDefault: + gcmCertificateScope := cloudproviders.GCMCertificateScopeDefault + return &gcmCertificateScope + case domain.GCMCertificateScopeEdgeCache: + gcmCertificateScope := cloudproviders.GCMCertificateScopeEdgeCache + return &gcmCertificateScope + case domain.GCMCertificateScopeAllRegions: + gcmCertificateScope := cloudproviders.GCMCertificateScopeAllRegions + return &gcmCertificateScope + } + return nil +} diff --git a/pkg/webclient/cloudproviders/cloudproviders.gen.go b/pkg/webclient/cloudproviders/cloudproviders.gen.go index 7e4ac38a..ee1c3200 100644 --- a/pkg/webclient/cloudproviders/cloudproviders.gen.go +++ b/pkg/webclient/cloudproviders/cloudproviders.gen.go @@ -158,6 +158,9 @@ const ( // Certificates with scope EDGE_CACHE are special-purposed certificates, served from Edge Points of Presence. // See https://cloud.google.com/vpc/docs/edge-locations. GCMCertificateScopeEdgeCache GCMCertificateScope = "EDGE_CACHE" + // Certificates with ALL_REGIONS scope are served from all Google Cloud + // regions. See https://cloud.google.com/compute/docs/regions-zones. + GCMCertificateScopeAllRegions GCMCertificateScope = "ALL_REGIONS" ) // GetCloudKeystoresCloudKeystoresCloudKeystoreConnection includes the requested fields of the GraphQL type CloudKeystoreConnection. diff --git a/pkg/webclient/cloudproviders/schema.graphql b/pkg/webclient/cloudproviders/schema.graphql index b234d9bb..9d19f010 100644 --- a/pkg/webclient/cloudproviders/schema.graphql +++ b/pkg/webclient/cloudproviders/schema.graphql @@ -2647,6 +2647,12 @@ enum GCMCertificateScope See https://cloud.google.com/vpc/docs/edge-locations. """ EDGE_CACHE @join__enumValue(graph: CLOUD_PROVIDERS) + + """ + Certificates with ALL_REGIONS scope are served from all Google Cloud + regions. See https://cloud.google.com/compute/docs/regions-zones. + """ + ALL_REGIONS @join__enumValue(graph: CLOUD_PROVIDERS) } type GCPCertificateMetadata