From c1005866ef72ed9941495bd6ea2c89f574bac79c Mon Sep 17 00:00:00 2001 From: salrashid123 Date: Tue, 2 Feb 2021 21:47:06 -0500 Subject: [PATCH] Adds support to manage GCP PrivateCA Certificates (#4449) --- mmv1/products/privateca/api.yaml | 548 +++++++++++++++++- mmv1/products/privateca/terraform.yaml | 37 ++ .../privateca_certificate.go.erb | 19 + .../privateca_certificate_config.tf.erb | 62 ++ .../examples/privateca_certificate_csr.tf.erb | 37 ++ .../terraform/utils/test-fixtures/rsa_csr.pem | 19 + 6 files changed, 705 insertions(+), 17 deletions(-) create mode 100644 mmv1/templates/terraform/custom_check_destroy/privateca_certificate.go.erb create mode 100644 mmv1/templates/terraform/examples/privateca_certificate_config.tf.erb create mode 100644 mmv1/templates/terraform/examples/privateca_certificate_csr.tf.erb create mode 100644 mmv1/third_party/terraform/utils/test-fixtures/rsa_csr.pem diff --git a/mmv1/products/privateca/api.yaml b/mmv1/products/privateca/api.yaml index ad5832bf0df4..fb4f3c6f7d8c 100644 --- a/mmv1/products/privateca/api.yaml +++ b/mmv1/products/privateca/api.yaml @@ -24,23 +24,6 @@ apis_required: - !ruby/object:Api::Product::ApiReference name: Certificate Authority API url: https://console.cloud.google.com/apis/api/privateca.googleapis.com -async: !ruby/object:Api::OpAsync - operation: !ruby/object:Api::OpAsync::Operation - base_url: '{{op_id}}' - path: 'name' - wait_ms: 1000 - result: !ruby/object:Api::OpAsync::Result - path: 'response' - resource_inside_response: true - status: !ruby/object:Api::OpAsync::Status - path: 'done' - complete: True - allowed: - - True - - False - error: !ruby/object:Api::OpAsync::Error - path: 'error' - message: 'message' objects: # CertificateAuthority - !ruby/object:Api::Resource @@ -57,6 +40,23 @@ objects: update_mask: true delete_url: '{{name}}:scheduleDelete' delete_verb: :POST + async: !ruby/object:Api::OpAsync + operation: !ruby/object:Api::OpAsync::Operation + base_url: '{{op_id}}' + path: 'name' + wait_ms: 1000 + result: !ruby/object:Api::OpAsync::Result + path: 'response' + resource_inside_response: true + status: !ruby/object:Api::OpAsync::Status + path: 'done' + complete: True + allowed: + - True + - False + error: !ruby/object:Api::OpAsync::Error + path: 'error' + message: 'message' references: !ruby/object:Api::Resource::ReferenceLinks guides: 'Official Documentation': @@ -339,3 +339,517 @@ objects: An object containing a list of "key": value pairs. Example: { "name": "wrench", "mass": "1.3kg", "count": "3" }. + + + # Certificate + - !ruby/object:Api::Resource + name: 'Certificate' + base_url: 'projects/{{project}}/locations/{{location}}/certificateAuthorities/{{certificate_authority}}/certificates' + create_url: 'projects/{{project}}/locations/{{location}}/certificateAuthorities/{{certificate_authority}}/certificates?certificateId={{name}}' + self_link: 'projects/{{project}}/locations/{{location}}/certificateAuthorities/{{certificate_authority}}/certificates/{{name}}' + min_version: beta + delete_url: 'projects/{{project}}/locations/{{location}}/certificateAuthorities/{{certificate_authority}}/certificates/{{name}}:revoke' + delete_verb: :POST + input: true + description: | + A Certificate corresponds to a signed X.509 certificate issued by a CertificateAuthority. + parameters: + - !ruby/object:Api::Type::String + name: location + description: | + Location of the CertificateAuthority. A full list of valid locations can be found by + running `gcloud beta privateca locations list`. + required: true + input: true + url_param_only: true + - !ruby/object:Api::Type::String + name: certificate_authority + description: | + Certificate Authority name. + required: true + input: true + url_param_only: true + properties: + - !ruby/object:Api::Type::String + name: 'name' + description: | + The name for this Certificate . + required: true + input: true + url_param_only: true + - !ruby/object:Api::Type::String + name: 'lifetime' + description: | + The desired lifetime of the CA certificate. Used to create the "notBeforeTime" and + "notAfterTime" fields inside an X.509 certificate. A duration in seconds with up to nine + fractional digits, terminated by 's'. Example: "3.5s". + default_value: 315360000s # 10 years + input: true + - !ruby/object:Api::Type::NestedObject + name: 'revocationDetails' + description: | + Output only. Details regarding the revocation of this Certificate. This Certificate is + considered revoked if and only if this field is present. + output: true + properties: + - !ruby/object:Api::Type::Enum + name: 'revocationState' + description: | + Indicates why a Certificate was revoked. + values: + - "REVOCATION_REASON_UNSPECIFIED" + - "KEY_COMPROMISE" + - "CERTIFICATE_AUTHORITY_COMPROMISE" + - "AFFILIATION_CHANGED" + - "SUPERSEDED" + - "CESSATION_OF_OPERATION" + - "CERTIFICATE_HOLD" + - "PRIVILEGE_WITHDRAWN" + - "ATTRIBUTE_AUTHORITY_COMPROMISE" + - !ruby/object:Api::Type::String + name: 'revocationTime' + description: | + The time at which this Certificate was revoked. + - !ruby/object:Api::Type::String + name: 'pemCertificate' + output: true + description: | + Output only. The pem-encoded, signed X.509 certificate. + - !ruby/object:Api::Type::NestedObject + name: 'certificateDescription' + description: | + Output only. Details regarding the revocation of this Certificate. This Certificate is considered revoked if and only if this field is present. + output: true + properties: + - !ruby/object:Api::Type::NestedObject + name: 'subjectDescription' + description: | + Describes some of the values in a certificate that are related to the subject and lifetime. + properties: + - !ruby/object:Api::Type::NestedObject + name: 'subject' + description: | + Required. Contains distinguished name fields such as the location and organization. + properties: + - !ruby/object:Api::Type::String + name: 'countryCode' + description: | + The country code of the subject. + - !ruby/object:Api::Type::String + name: 'organization' + description: | + The organization of the subject. + - !ruby/object:Api::Type::String + name: 'organizationalUnit' + description: | + The organizationalUnit of the subject. + - !ruby/object:Api::Type::String + name: 'locality' + description: | + The locality or city of the subject. + - !ruby/object:Api::Type::String + name: 'province' + description: | + The province of the subject. + - !ruby/object:Api::Type::String + name: 'streetAddress' + description: | + The streetAddress or city of the subject. + - !ruby/object:Api::Type::String + name: 'postalCode' + description: | + The postalCode or city of the subject. + - !ruby/object:Api::Type::String + name: 'commonName' + description: | + The "common name" of the distinguished name. + - !ruby/object:Api::Type::NestedObject + name: 'subjectAltName' + description: | + Optional. The subject alternative name fields. + properties: + - !ruby/object:Api::Type::Array + name: 'dnsNames' + description: | + Contains only valid, fully-qualified host names. + required: false + item_type: Api::Type::String + - !ruby/object:Api::Type::Array + name: 'uris' + description: | + Contains only valid RFC 3986 URIs. + item_type: Api::Type::String + required: false + - !ruby/object:Api::Type::Array + name: 'emailAddresses' + item_type: Api::Type::String + description: | + Contains only valid RFC 2822 E-mail addresses. + required: false + - !ruby/object:Api::Type::Array + name: 'ipAddresses' + item_type: Api::Type::String + description: | + Contains only valid 32-bit IPv4 addresses or RFC 4291 IPv6 addresses. + required: false + - !ruby/object:Api::Type::Array + name: 'customSans' + required: true + description: | + Contains additional subject alternative name values. + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::NestedObject + name: 'obectId' + required: true + description: | + Required. Describes how some of the technical fields in a certificate should be populated. + properties: + - !ruby/object:Api::Type::Array + name: 'objectIdPath' + required: true + item_type: Api::Type::Integer + description: | + An ObjectId specifies an object identifier (OID). These provide context and describe types in ASN.1 messages. + - !ruby/object:Api::Type::Boolean + name: 'critical' + required: true + description: | + Required. Indicates whether or not this extension is critical (i.e., if the client does not know how to handle this extension, the client should consider this to be an error). + - !ruby/object:Api::Type::String + name: 'value' + description: | + Required. The value of this X.509 extension. + - !ruby/object:Api::Type::String + name: 'hexSerialNumber' + description: | + The serial number encoded in lowercase hexadecimal. + - !ruby/object:Api::Type::String + name: 'lifetime' + description: | + For convenience, the actual lifetime of an issued certificate. Corresponds to 'notAfterTime' - 'notBeforeTime'. + - !ruby/object:Api::Type::String + name: 'notBeforeTime' + description: | + The time at which the certificate becomes valid. + - !ruby/object:Api::Type::String + name: 'notAfterTime' + description: | + The time at which the certificate expires. + - !ruby/object:Api::Type::NestedObject + name: 'configValues' + description: | + Describes some of the technical fields in a certificate. + properties: + - !ruby/object:Api::Type::NestedObject + name: 'keyUsage' + description: | + Optional. Indicates the intended use for keys that correspond to a certificate. + properties: + - !ruby/object:Api::Type::NestedObject + name: 'baseKeyUsage' + description: | + Describes high-level ways in which a key may be used. + properties: + - !ruby/object:Api::Type::NestedObject + name: 'keyUsageOptions' + description: | + Describes high-level ways in which a key may be used. + properties: + - !ruby/object:Api::Type::Boolean + name: 'digitalSignature' + description: | + The key may be used for digital signatures. + - !ruby/object:Api::Type::Boolean + name: 'contentCommitment' + description: | + The key may be used for cryptographic commitments. Note that this may also be referred to as "non-repudiation". + - !ruby/object:Api::Type::Boolean + name: 'keyEncipherment' + description: | + The key may be used to encipher other keys. + - !ruby/object:Api::Type::Boolean + name: 'dataEncipherment' + description: | + The key may be used to encipher data. + - !ruby/object:Api::Type::Boolean + name: 'keyAgreement' + description: | + The key may be used in a key agreement protocol. + - !ruby/object:Api::Type::Boolean + name: 'certSign' + description: | + The key may be used to sign certificates. + - !ruby/object:Api::Type::Boolean + name: 'crlSign' + description: | + The key may be used sign certificate revocation lists. + - !ruby/object:Api::Type::Boolean + name: 'encipherOnly' + description: | + The key may be used to encipher only. + - !ruby/object:Api::Type::Boolean + name: 'decipherOnly' + description: | + The key may be used to decipher only. + - !ruby/object:Api::Type::NestedObject + name: 'extendedKeyUsage' + description: | + Describes high-level ways in which a key may be used. + properties: + - !ruby/object:Api::Type::Boolean + name: 'serverAuth' + description: | + Corresponds to OID 1.3.6.1.5.5.7.3.1. Officially described as "TLS WWW server authentication", though regularly used for non-WWW TLS. + - !ruby/object:Api::Type::Boolean + name: 'clientAuth' + description: | + Corresponds to OID 1.3.6.1.5.5.7.3.2. Officially described as "TLS WWW client authentication", though regularly used for non-WWW TLS. + - !ruby/object:Api::Type::Boolean + name: 'codeSigning' + description: | + Corresponds to OID 1.3.6.1.5.5.7.3.3. Officially described as "Signing of downloadable executable code client authentication". + - !ruby/object:Api::Type::Boolean + name: 'emailProtection' + description: | + Corresponds to OID 1.3.6.1.5.5.7.3.4. Officially described as "Email protection". + - !ruby/object:Api::Type::Boolean + name: 'timeStamping' + description: | + Corresponds to OID 1.3.6.1.5.5.7.3.8. Officially described as "Binding the hash of an object to a time". + - !ruby/object:Api::Type::Boolean + name: 'ocspSigning' + description: | + Corresponds to OID 1.3.6.1.5.5.7.3.9. Officially described as "Signing OCSP responses". + - !ruby/object:Api::Type::Array + name: 'unknownExtendedKeyUsages' + required: true + description: | + An ObjectId specifies an object identifier (OID). These provide context and describe types in ASN.1 messages. + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::NestedObject + name: 'obectId' + required: true + description: | + Required. Describes how some of the technical fields in a certificate should be populated. + properties: + - !ruby/object:Api::Type::Array + name: 'objectIdPath' + required: true + item_type: Api::Type::Integer + description: | + An ObjectId specifies an object identifier (OID). These provide context and describe types in ASN.1 messages. + - !ruby/object:Api::Type::NestedObject + name: 'publicKey' + required: true + description: | + A PublicKey describes a public key. + properties: + - !ruby/object:Api::Type::String + name: 'key' + description: | + Required. A public key. When this is specified in a request, the padding and encoding can be any of the options described by the respective 'KeyType' value. When this is generated by the service, it will always be an RFC 5280 SubjectPublicKeyInfo structure containing an algorithm identifier and a key. A base64-encoded string. + - !ruby/object:Api::Type::Enum + name: 'type' + required: true + description: | + Types of public keys that are supported. At a minimum, we support RSA and ECDSA, for the key sizes or curves listed: https://cloud.google.com/kms/docs/algorithms#asymmetric_signing_algorithms + values: + - "KEY_TYPE_UNSPECIFIED" + - "PEM_RSA_KEY" + - "PEM_EC_KEY" + - !ruby/object:Api::Type::NestedObject + name: 'subjectKeyId' + description: | + Provides a means of identifiying certificates that contain a particular public key, per https://tools.ietf.org/html/rfc5280#section-4.2.1.2. + properties: + - !ruby/object:Api::Type::String + name: 'keyId' + description: | + Optional. The value of this KeyId encoded in lowercase hexadecimal. This is most likely the 160 bit SHA-1 hash of the public key. + - !ruby/object:Api::Type::NestedObject + name: 'authorityKeyId' + description: | + Identifies the subjectKeyId of the parent certificate, per https://tools.ietf.org/html/rfc5280#section-4.2.1.1 + properties: + - !ruby/object:Api::Type::String + name: 'keyId' + description: | + Optional. The value of this KeyId encoded in lowercase hexadecimal. This is most likely the 160 bit SHA-1 hash of the public key. + - !ruby/object:Api::Type::Array + name: 'crlDistributionPoints' + description: | + Describes a list of locations to obtain CRL information, i.e. the DistributionPoint.fullName described by https://tools.ietf.org/html/rfc5280#section-4.2.1.13 + item_type: Api::Type::String + - !ruby/object:Api::Type::Array + name: 'aiaIssuingCertificateUrls' + description: | + Describes lists of issuer CA certificate URLs that appear in the "Authority Information Access" extension in the certificate. + item_type: Api::Type::String + - !ruby/object:Api::Type::NestedObject + name: 'certFingerprint' + description: | + The hash of the x.509 certificate. + properties: + - !ruby/object:Api::Type::String + name: 'sha256Hash' + description: | + The SHA 256 hash, encoded in hexadecimal, of the DER x509 certificate. + - !ruby/object:Api::Type::Array + name: 'pemCertificates' + output: true + description: | + Required. Expected to be in leaf-to-root order according to RFC 5246. + item_type: Api::Type::String + - !ruby/object:Api::Type::Time + name: 'createTime' + description: | + The time that this resource was created on the server. + This is in RFC3339 text format. + output: true + - !ruby/object:Api::Type::Time + name: 'updateTime' + description: | + Output only. The time at which this CertificateAuthority was updated. + This is in RFC3339 text format. + output: true + - !ruby/object:Api::Type::KeyValuePairs + name: 'labels' + description: | + Labels with user-defined metadata to apply to this resource. + - !ruby/object:Api::Type::String + name: 'pemCsr' + description: | + Immutable. A pem-encoded X.509 certificate signing request (CSR). + exactly_one_of: + - pemCsr + - config + - !ruby/object:Api::Type::NestedObject + name: 'config' + description: The config used to create a self-signed X.509 certificate or CSR. + exactly_one_of: + - pemCsr + - config + input: true + properties: + - !ruby/object:Api::Type::NestedObject + name: 'subjectConfig' + description: | + Specifies some of the values in a certificate that are related to the subject. + required: true + properties: + - !ruby/object:Api::Type::NestedObject + name: 'subject' + description: Contains distinguished name fields such as the location and organization. + required: true + properties: + - !ruby/object:Api::Type::String + name: 'countryCode' + description: The country code of the subject. + input: true + - !ruby/object:Api::Type::String + name: 'organization' + description: The organization of the subject. + input: true + required: true + - !ruby/object:Api::Type::String + name: 'organizationalUnit' + description: The organizational unit of the subject. + input: true + - !ruby/object:Api::Type::String + name: 'locality' + description: The locality or city of the subject. + input: true + - !ruby/object:Api::Type::String + name: 'province' + description: The province, territory, or regional state of the subject. + input: true + - !ruby/object:Api::Type::String + name: 'streetAddress' + description: The street address of the subject. + input: true + - !ruby/object:Api::Type::String + name: 'postalCode' + description: The postal code of the subject. + input: true + - !ruby/object:Api::Type::String + name: 'commonName' + description: The common name of the distinguished name. + required: true + - !ruby/object:Api::Type::NestedObject + name: 'subjectAltName' + description: The subject alternative name fields. + properties: + - !ruby/object:Api::Type::Array + name: 'dnsNames' + description: Contains only valid, fully-qualified host names. + item_type: Api::Type::String + at_least_one_of: + - config.0.subject_config.0.subject_alt_name.0.dns_names + - config.0.subject_config.0.subject_alt_name.0.uris + - config.0.subject_config.0.subject_alt_name.0.email_addresses + - config.0.subject_config.0.subject_alt_name.0.ip_addresses + input: true + - !ruby/object:Api::Type::Array + name: 'uris' + description: Contains only valid RFC 3986 URIs. + item_type: Api::Type::String + at_least_one_of: + - config.0.subject_config.0.subject_alt_name.0.dns_names + - config.0.subject_config.0.subject_alt_name.0.uris + - config.0.subject_config.0.subject_alt_name.0.email_addresses + - config.0.subject_config.0.subject_alt_name.0.ip_addresses + input: true + - !ruby/object:Api::Type::Array + name: 'emailAddresses' + description: Contains only valid RFC 2822 E-mail addresses. + item_type: Api::Type::String + at_least_one_of: + - config.0.subject_config.0.subject_alt_name.0.dns_names + - config.0.subject_config.0.subject_alt_name.0.uris + - config.0.subject_config.0.subject_alt_name.0.email_addresses + - config.0.subject_config.0.subject_alt_name.0.ip_addresses + input: true + - !ruby/object:Api::Type::Array + name: 'ipAddresses' + description: Contains only valid 32-bit IPv4 addresses or RFC 4291 IPv6 addresses. + item_type: Api::Type::String + at_least_one_of: + - config.0.subject_config.0.subject_alt_name.0.dns_names + - config.0.subject_config.0.subject_alt_name.0.uris + - config.0.subject_config.0.subject_alt_name.0.email_addresses + - config.0.subject_config.0.subject_alt_name.0.ip_addresses + input: true + - !ruby/object:Api::Type::NestedObject + name: 'reusableConfig' + description: | + Specifies some of the values in a certificate that are related to the subject. + required: true + properties: + - !ruby/object:Api::Type::String + name: 'reusableConfig' + description: | + A resource path to a ReusableConfig in the format + `projects/*/locations/*/reusableConfigs/*`. + required: true + input: true + - !ruby/object:Api::Type::NestedObject + name: 'publicKey' + required: true + description: | + A PublicKey describes a public key. + properties: + - !ruby/object:Api::Type::String + name: 'key' + description: | + Required. A public key. When this is specified in a request, the padding and encoding can be any of the options described by the respective 'KeyType' value. When this is generated by the service, it will always be an RFC 5280 SubjectPublicKeyInfo structure containing an algorithm identifier and a key. A base64-encoded string. + - !ruby/object:Api::Type::Enum + name: 'type' + required: true + description: | + Types of public keys that are supported. At a minimum, we support RSA and ECDSA, for the key sizes or curves listed: https://cloud.google.com/kms/docs/algorithms#asymmetric_signing_algorithms + values: + - "KEY_TYPE_UNSPECIFIED" + - "PEM_RSA_KEY" + - "PEM_EC_KEY" diff --git a/mmv1/products/privateca/terraform.yaml b/mmv1/products/privateca/terraform.yaml index 7a5e6d228614..c2abaf75f2dc 100644 --- a/mmv1/products/privateca/terraform.yaml +++ b/mmv1/products/privateca/terraform.yaml @@ -76,3 +76,40 @@ overrides: !ruby/object:Overrides::ResourceOverrides encoder: templates/terraform/encoders/certificate_authority.go.erb pre_delete: templates/terraform/pre_delete/privateca_certificate_authority.go.erb test_check_destroy: templates/terraform/custom_check_destroy/privateca_certificate_authority.go.erb + + Certificate: !ruby/object:Overrides::Terraform::ResourceOverride + autogen_async: true + # This resource is a child resource + skip_sweeper: true + description: | + {{description}} + + ~> **Note:** The Certificate Authority that is referenced by this resource **must** be + `tier = "ENTERPRISE"` + + ~> **Warning:** Please remember that all resources created during preview (via the terraform-provider-google-beta) + will be deleted when CA service transitions to General Availability (GA). Relying on these + certificate authorities for production traffic is discouraged. + import_format: ["projects/{{project}}/locations/{{location}}/certificateAuthorities/{{certificate_authority}}/certificates/{{name}}"] + examples: + - !ruby/object:Provider::Terraform::Examples + name: "privateca_certificate_config" + min_version: "beta" + primary_resource_id: "default" + vars: + certificate_authority_id: "my-certificate-authority" + certificate_name: "my-certificate" + test_env_vars: + project: :PROJECT_NAME + - !ruby/object:Provider::Terraform::Examples + name: "privateca_certificate_csr" + min_version: "beta" + primary_resource_id: "default" + vars: + certificate_name: "my-certificate" + certificate_authority_id: "my-certificate-authority" + test_env_vars: + project: :PROJECT_NAME + custom_code: !ruby/object:Provider::Terraform::CustomCode + test_check_destroy: templates/terraform/custom_check_destroy/privateca_certificate.go.erb + diff --git a/mmv1/templates/terraform/custom_check_destroy/privateca_certificate.go.erb b/mmv1/templates/terraform/custom_check_destroy/privateca_certificate.go.erb new file mode 100644 index 000000000000..9dccc2241b36 --- /dev/null +++ b/mmv1/templates/terraform/custom_check_destroy/privateca_certificate.go.erb @@ -0,0 +1,19 @@ +config := googleProviderConfig(t) + +url, err := replaceVarsForTest(config, rs, "{{PrivatecaBasePath}}projects/{{project}}/locations/{{location}}/certificateAuthorities/{{certificate_authority}}/certificates/{{name}}") + +if err != nil { + return err +} + +res, err := sendRequest(config, "GET", "", url, config.userAgent, nil) +if err != nil { + return err +} + + +if _, ok := res["revocationDetails"]; !ok { + return fmt.Errorf("CertificateAuthority.Certificate Revocation expected %s got %s, want revocationDetails.revocationTime", url, s) +} + +return nil \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/privateca_certificate_config.tf.erb b/mmv1/templates/terraform/examples/privateca_certificate_config.tf.erb new file mode 100644 index 000000000000..61d128871448 --- /dev/null +++ b/mmv1/templates/terraform/examples/privateca_certificate_config.tf.erb @@ -0,0 +1,62 @@ +resource "google_privateca_certificate_authority" "test-ca" { + provider = google-beta + certificate_authority_id = "<%= ctx[:vars]["certificate_authority_id"] %>" + location = "us-central1" + tier = "ENTERPRISE" + config { + subject_config { + subject { + organization = "HashiCorp" + } + common_name = "my-certificate-authority" + subject_alt_name { + dns_names = ["hashicorp.com"] + } + } + reusable_config { + reusable_config = "projects/568668481468/locations/us-central1/reusableConfigs/root-unconstrained" + } + } + key_spec { + algorithm = "RSA_PKCS1_4096_SHA256" + } + disable_on_delete = true +} + + +resource "google_privateca_certificate" "<%= ctx[:primary_resource_id] %>" { + provider = google-beta + project = "<%= ctx[:test_env_vars]['project'] %>" + location = "us-central1" + certificate_authority = google_privateca_certificate_authority.test-ca.certificate_authority_id + lifetime = "860s" + name = "<%= ctx[:vars]["certificate_name"] %>" + config { + reusable_config { + reusable_config= "projects/568668481468/locations/us-central1/reusableConfigs/leaf-server-tls" + } + subject_config { + common_name = "san1.example.com" + subject { + country_code = "us" + organization = "google" + organizational_unit = "enterprise" + locality = "mountain view" + province = "california" + street_address = "1600 amphitheatre parkway" + postal_code = "94109" + } + subject_alt_name { + dns_names = ["hashicorp.com"] + email_addresses = ["email@example.com"] + ip_addresses = ["127.0.0.1"] + uris = ["http://www.ietf.org/rfc/rfc3986.txt"] + } + } + + public_key { + type = "PEM_RSA_KEY" + key = filebase64("test-fixtures/rsa_public.pem") + } + } +} \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/privateca_certificate_csr.tf.erb b/mmv1/templates/terraform/examples/privateca_certificate_csr.tf.erb new file mode 100644 index 000000000000..5ce90d5632ad --- /dev/null +++ b/mmv1/templates/terraform/examples/privateca_certificate_csr.tf.erb @@ -0,0 +1,37 @@ +resource "google_privateca_certificate_authority" "test-ca" { + provider = google-beta + certificate_authority_id = "<%= ctx[:vars]["certificate_authority_id"] %>" + location = "us-central1" + tier = "ENTERPRISE" + config { + subject_config { + subject { + organization = "HashiCorp" + } + common_name = "my-certificate-authority" + subject_alt_name { + dns_names = ["hashicorp.com"] + } + } + reusable_config { + reusable_config = "projects/568668481468/locations/us-central1/reusableConfigs/root-unconstrained" + } + } + key_spec { + algorithm = "RSA_PKCS1_4096_SHA256" + } + disable_on_delete = true +} + + + + +resource "google_privateca_certificate" "<%= ctx[:primary_resource_id] %>" { + provider = google-beta + project = "<%= ctx[:test_env_vars]['project'] %>" + location = "us-central1" + certificate_authority = google_privateca_certificate_authority.test-ca.certificate_authority_id + lifetime = "860s" + name = "<%= ctx[:vars]["certificate_name"] %>" + pem_csr = file("test-fixtures/rsa_csr.pem") +} \ No newline at end of file diff --git a/mmv1/third_party/terraform/utils/test-fixtures/rsa_csr.pem b/mmv1/third_party/terraform/utils/test-fixtures/rsa_csr.pem new file mode 100644 index 000000000000..acb70eb670ef --- /dev/null +++ b/mmv1/third_party/terraform/utils/test-fixtures/rsa_csr.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIDETCCAfkCAQAwVDELMAkGA1UEBhMCVVMxDzANBgNVBAoMBkdvb2dsZTETMBEG +A1UECwwKRW50ZXJwcmlzZTEfMB0GA1UEAwwWc2VydmVyLmVzb2RlbW9hcHAyLmNv +bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMZThbWkUvD8wxzP/v/t +918Z0fhDYgSrow75G1kIbUf5Z3qG+l0AyLadIo3SqN3ENQYf2+O1VP9Hk90tyvCS +iGqjXJLCLXdrwLLqHoqFDxwm3bQ0/AlOIpmilS++BdHUew0HfqZq9lJOFPAF3EtL +LPaE0eRbA2HguHe4q/7jIIr999vYuafCtetrzIBI8ke9+S2VvPPw+ni2KZvmTb1+ +DnIqq7QX/t92Y9RW1UgeXqvc/LbYwnIfSyCpea1IvHILup+eQ/R2aeIgzFrDbuS4 +ULrxdJrMu4UXXPJMbw7xSOAdhJoX+uky08bR3pbUbt6wNwwjuDLNLBIdlYZK6seL +QRsCAwEAAaB4MHYGCSqGSIb3DQEJDjFpMGcwDgYDVR0PAQH/BAQDAgeAMBMGA1Ud +JQQMMAoGCCsGAQUFBwMBMB0GA1UdDgQWBBQ/ZBWqbeL7spn5xkS9awVgZ5L1ITAh +BgNVHREEGjAYghZzZXJ2ZXIuZXNvZGVtb2FwcDIuY29tMA0GCSqGSIb3DQEBBQUA +A4IBAQAJoFccsGUrdoPRuhjvhrtjnj2D8hEAA0bt+numzT5E26Cte7HHRg2Jn2f7 +5qxNunesf86FBjOtg/dr3tKIAPAQ7H6yojq/XFFrKkbDpYodigdxeD4pQ2NaZxPU +2FJZoGyoxoUMb7wozROTJDRI0hAmkVUtUgta3UHtDuVXLYTwpKCBHqFi6Nshv8jO +XTHsr7G/a0ky0nnbzYvhilyzZQS7k1F2pQIhzTFZtvwzM9JvpWyzS7I8W8QX5YqG +bqDgRvIy7MHu0sWjOPvSKtU5ivW+wawEytspDxdEapivIAzY7wvMH27ixm0sfCxN +tRlgsGSzkSXGk9c4MHDtmGFFfD0U +-----END CERTIFICATE REQUEST-----