diff --git a/mmv1/products/privateca/api.yaml b/mmv1/products/privateca/api.yaml index 65f6b1a2cd45..f24f75e440ac 100644 --- a/mmv1/products/privateca/api.yaml +++ b/mmv1/products/privateca/api.yaml @@ -16,8 +16,8 @@ name: Privateca display_name: Certificate Authority Service versions: - !ruby/object:Api::Product::Version - name: beta - base_url: https://privateca.googleapis.com/v1beta1/ + name: ga + base_url: https://privateca.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/cloud-platform apis_required: @@ -31,15 +31,11 @@ objects: description: | A CertificateAuthority represents an individual Certificate Authority. A CertificateAuthority can be used to create Certificates. - base_url: projects/{{project}}/locations/{{location}}/certificateAuthorities - create_url: projects/{{project}}/locations/{{location}}/certificateAuthorities?certificateAuthorityId={{certificate_authority_id}} - self_link: projects/{{project}}/locations/{{location}}/certificateAuthorities/{{certificate_authority_id}} - min_version: beta - create_verb: :POST - update_verb: :PATCH - update_mask: true - delete_url: '{{name}}:scheduleDelete' - delete_verb: :POST + base_url: projects/{{project}}/locations/{{location}}/caPools/{{pool}}/certificateAuthorities + create_url: projects/{{project}}/locations/{{location}}/caPools/{{pool}}/certificateAuthorities?certificateAuthorityId={{certificate_authority_id}} + self_link: projects/{{project}}/locations/{{location}}/caPools/{{pool}}/certificateAuthorities/{{certificate_authority_id}} + delete_url: projects/{{project}}/locations/{{location}}/caPools/{{pool}}/certificateAuthorities/{{certificate_authority_id}}?ignoreActiveCertificates={{ignore_active_certificates}} + input: true async: !ruby/object:Api::OpAsync operation: !ruby/object:Api::OpAsync::Operation base_url: '{{op_id}}' @@ -63,11 +59,19 @@ objects: 'https://cloud.google.com/certificate-authority-service' api: 'https://cloud.google.com/certificate-authority-service/docs/reference/rest' properties: + - !ruby/object:Api::Type::Boolean + name: 'ignore_active_certificates' + default_value: false + input: true + url_param_only: true + description: | + This field allows the CA to be deleted even if the CA has active certs. Active certs include both unrevoked and unexpired certs. + Use with care. Defaults to `false`. - !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`. + running `gcloud privateca locations list`. required: true input: true url_param_only: true @@ -77,6 +81,12 @@ objects: required: true input: true url_param_only: true + - !ruby/object:Api::Type::String + name: pool + description: The name of the CaPool this Certificate Authority belongs to. + required: true + input: true + url_param_only: true - !ruby/object:Api::Type::String name: 'name' description: | @@ -108,107 +118,255 @@ objects: required: true 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. + name: 'x509Config' required: true + description: | + Describes how some of the technical X.509 fields in a certificate should be populated. 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::Array + name: 'additionalExtensions' + description: | + Specifies an X.509 extension, which may be used in different parts of X.509 objects like certificates, CSRs, and CRLs. + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::Boolean + name: 'critical' + required: true + description: | + 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' + required: true + description: | + The value of this X.509 extension. A base64-encoded string. + - !ruby/object:Api::Type::NestedObject + name: 'objectId' + required: true + description: | + Describes values that are relevant in a CA certificate. + 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::Array + name: 'policyIds' + description: | + Describes the X.509 certificate policy object identifiers, per https://tools.ietf.org/html/rfc5280#section-4.2.1.4. + item_type: !ruby/object:Api::Type::NestedObject + 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::Array + name: 'aiaOcspServers' + item_type: Api::Type::String + description: | + Describes Online Certificate Status Protocol (OCSP) endpoint addresses that appear in the + "Authority Information Access" extension in the certificate. + - !ruby/object:Api::Type::NestedObject + name: 'caOptions' + required: true + description: | + Describes values that are relevant in a CA certificate. + properties: + - !ruby/object:Api::Type::Boolean + name: 'isCa' + required: true + description: | + Refers to the "CA" X.509 extension, which is a boolean value. When this value is missing, + the extension will be omitted from the CA certificate. + - !ruby/object:Api::Type::Integer + name: 'maxIssuerPathLength' + description: | + Refers to the path length restriction X.509 extension. For a CA certificate, this value describes the depth of + subordinate CA certificates that are allowed. If this value is less than 0, the request will fail. If this + value is missing, the max path length will be omitted from the CA certificate. + - !ruby/object:Api::Type::NestedObject + name: 'keyUsage' + required: true + description: | + Indicates the intended use for keys that correspond to a certificate. + properties: + - !ruby/object:Api::Type::NestedObject + name: 'baseKeyUsage' + required: true + 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' + required: true + 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' + 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::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: 'subjectAltName' - description: The subject alternative name fields. + name: 'subjectConfig' + description: | + Specifies some of the values in a certificate that are related to the subject. + required: true 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/*`. + - !ruby/object:Api::Type::NestedObject + name: 'subject' + description: Contains distinguished name fields such as the location and organization. required: true - input: 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::String name: 'lifetime' description: | @@ -252,24 +410,6 @@ objects: exactly_one_of: - key_spec.0.cloud_kms_key_version - key_spec.0.algorithm - - !ruby/object:Api::Type::NestedObject - name: 'issuingOptions' - description: | - Options that affect all certificates issued by a CertificateAuthority. - properties: - - !ruby/object:Api::Type::Boolean - name: 'includeCaCertUrl' - description: | - When true, includes a URL to the issuing CA certificate in the "authority - information access" X.509 extension. - default_value: true - - !ruby/object:Api::Type::Boolean - name: 'includeCrlAccessUrl' - description: | - When true, includes a URL to the CRL corresponding to certificates issued from a - CertificateAuthority. CRLs will expire 7 days from their creation. However, we will - rebuild daily. CRLs are also rebuilt shortly after a certificate is revoked. - default_value: false - !ruby/object:Api::Type::Enum name: 'state' description: The State for this CertificateAuthority. @@ -344,21 +484,19 @@ objects: # 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 + base_url: 'projects/{{project}}/locations/{{location}}/caPools/{{pool}}/certificates' + create_url: 'projects/{{project}}/locations/{{location}}/caPools/{{pool}}/certificates?certificateId={{name}}' + delete_url: 'projects/{{project}}/locations/{{location}}/caPools/{{pool}}/certificates/{{name}}:revoke' + delete_verb: :POST input: true description: | - A Certificate corresponds to a signed X.509 certificate issued by a CertificateAuthority. + A Certificate corresponds to a signed X.509 certificate issued by a Certificate. 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`. + Location of the Certificate. A full list of valid locations can be found by + running `gcloud privateca locations list`. required: true input: true url_param_only: true @@ -366,14 +504,19 @@ objects: name: certificate_authority description: | Certificate Authority name. - required: true input: true url_param_only: true properties: + - !ruby/object:Api::Type::String + name: pool + description: The name of the CaPool this Certificate belongs to. + required: true + input: true + url_param_only: true - !ruby/object:Api::Type::String name: 'name' description: | - The name for this Certificate . + The name for this Certificate. required: true input: true url_param_only: true @@ -394,6 +537,7 @@ objects: properties: - !ruby/object:Api::Type::Enum name: 'revocationState' + output: true description: | Indicates why a Certificate was revoked. values: @@ -408,6 +552,7 @@ objects: - "ATTRIBUTE_AUTHORITY_COMPROMISE" - !ruby/object:Api::Type::String name: 'revocationTime' + output: true description: | The time at which this Certificate was revoked. - !ruby/object:Api::Type::String @@ -419,281 +564,325 @@ objects: 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 + output: true properties: - !ruby/object:Api::Type::NestedObject name: 'subjectDescription' + output: true 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' + output: true description: | - Required. Contains distinguished name fields such as the location and organization. + Contains distinguished name fields such as the location and organization. properties: - !ruby/object:Api::Type::String name: 'countryCode' + output: true description: | The country code of the subject. - !ruby/object:Api::Type::String name: 'organization' + output: true description: | The organization of the subject. - !ruby/object:Api::Type::String name: 'organizationalUnit' + output: true description: | The organizationalUnit of the subject. - !ruby/object:Api::Type::String name: 'locality' + output: true description: | The locality or city of the subject. - !ruby/object:Api::Type::String name: 'province' + output: true description: | The province of the subject. - !ruby/object:Api::Type::String name: 'streetAddress' + output: true description: | The streetAddress or city of the subject. - !ruby/object:Api::Type::String name: 'postalCode' + output: true 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::String + name: 'commonName' + output: true + description: | + The "common name" of the distinguished name. - !ruby/object:Api::Type::NestedObject name: 'subjectAltName' + output: true description: | - Optional. The subject alternative name fields. + The subject alternative name fields. properties: - !ruby/object:Api::Type::Array name: 'dnsNames' + output: true description: | Contains only valid, fully-qualified host names. - required: false item_type: Api::Type::String - !ruby/object:Api::Type::Array + output: true name: 'uris' description: | Contains only valid RFC 3986 URIs. item_type: Api::Type::String - required: false - !ruby/object:Api::Type::Array name: 'emailAddresses' + output: true item_type: Api::Type::String description: | Contains only valid RFC 2822 E-mail addresses. - required: false - !ruby/object:Api::Type::Array name: 'ipAddresses' + output: true 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 + output: 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 + output: true description: | - Required. Describes how some of the technical fields in a certificate should be populated. + Describes how some of the technical fields in a certificate should be populated. properties: - !ruby/object:Api::Type::Array name: 'objectIdPath' - required: true + output: 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 + output: 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' + output: true description: | - Required. The value of this X.509 extension. + The value of this X.509 extension. - !ruby/object:Api::Type::String name: 'hexSerialNumber' + output: true description: | The serial number encoded in lowercase hexadecimal. - !ruby/object:Api::Type::String name: 'lifetime' + output: true description: | For convenience, the actual lifetime of an issued certificate. Corresponds to 'notAfterTime' - 'notBeforeTime'. - !ruby/object:Api::Type::String name: 'notBeforeTime' + output: true description: | The time at which the certificate becomes valid. - !ruby/object:Api::Type::String name: 'notAfterTime' + output: true description: | The time at which the certificate expires. - !ruby/object:Api::Type::NestedObject name: 'configValues' + output: true description: | Describes some of the technical fields in a certificate. properties: - !ruby/object:Api::Type::NestedObject name: 'keyUsage' + output: true description: | - Optional. Indicates the intended use for keys that correspond to a certificate. + Indicates the intended use for keys that correspond to a certificate. properties: - !ruby/object:Api::Type::NestedObject name: 'baseKeyUsage' + output: true description: | Describes high-level ways in which a key may be used. properties: - !ruby/object:Api::Type::NestedObject name: 'keyUsageOptions' + output: true description: | Describes high-level ways in which a key may be used. properties: - !ruby/object:Api::Type::Boolean name: 'digitalSignature' + output: true description: | The key may be used for digital signatures. - !ruby/object:Api::Type::Boolean name: 'contentCommitment' + output: true 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' + output: true description: | The key may be used to encipher other keys. - !ruby/object:Api::Type::Boolean name: 'dataEncipherment' + output: true description: | The key may be used to encipher data. - !ruby/object:Api::Type::Boolean name: 'keyAgreement' + output: true description: | The key may be used in a key agreement protocol. - !ruby/object:Api::Type::Boolean name: 'certSign' + output: true description: | The key may be used to sign certificates. - !ruby/object:Api::Type::Boolean name: 'crlSign' + output: true description: | The key may be used sign certificate revocation lists. - !ruby/object:Api::Type::Boolean name: 'encipherOnly' + output: true description: | The key may be used to encipher only. - !ruby/object:Api::Type::Boolean name: 'decipherOnly' + output: true description: | The key may be used to decipher only. - !ruby/object:Api::Type::NestedObject name: 'extendedKeyUsage' + output: true description: | Describes high-level ways in which a key may be used. properties: - !ruby/object:Api::Type::Boolean name: 'serverAuth' + output: true 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' + output: true 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' + output: true 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' + output: true 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' + output: true 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' + output: true 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 + output: 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 + name: 'obectId' + output: 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 + output: 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 + output: true description: | A PublicKey describes a public key. properties: - !ruby/object:Api::Type::String name: 'key' + output: true 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 + name: 'format' + output: 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 + Types of public keys that are supported. At a minimum, we support RSA, 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" + - "PEM" - !ruby/object:Api::Type::NestedObject name: 'subjectKeyId' + output: true 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' + output: true 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' + output: true 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' + output: true 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' + output: true 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' + output: true 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' + output: true description: | The hash of the x.509 certificate. properties: - !ruby/object:Api::Type::String name: 'sha256Hash' + output: true description: | The SHA 256 hash, encoded in hexadecimal, of the DER x509 certificate. - !ruby/object:Api::Type::Array @@ -733,6 +922,167 @@ objects: - config input: true properties: + - !ruby/object:Api::Type::NestedObject + name: 'x509Config' + required: true + send_empty_value: true + description: | + Describes how some of the technical X.509 fields in a certificate should be populated. + properties: + - !ruby/object:Api::Type::Array + name: 'additionalExtensions' + description: | + Specifies an X.509 extension, which may be used in different parts of X.509 objects like certificates, CSRs, and CRLs. + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::Boolean + name: 'critical' + required: true + description: | + 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' + required: true + description: | + The value of this X.509 extension. A base64-encoded string. + - !ruby/object:Api::Type::NestedObject + name: 'objectId' + required: true + description: | + Describes values that are relevant in a CA certificate. + 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::Array + name: 'policyIds' + description: | + Describes the X.509 certificate policy object identifiers, per https://tools.ietf.org/html/rfc5280#section-4.2.1.4. + item_type: !ruby/object:Api::Type::NestedObject + 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::Array + name: 'aiaOcspServers' + item_type: Api::Type::String + description: | + Describes Online Certificate Status Protocol (OCSP) endpoint addresses that appear in the + "Authority Information Access" extension in the certificate. + - !ruby/object:Api::Type::NestedObject + name: 'caOptions' + send_empty_value: true + description: | + Describes values that are relevant in a CA certificate. + properties: + - !ruby/object:Api::Type::Boolean + name: 'isCa' + description: | + Refers to the "CA" X.509 extension, which is a boolean value. When this value is missing, + the extension will be omitted from the CA certificate. + - !ruby/object:Api::Type::Integer + name: 'maxIssuerPathLength' + description: | + Refers to the path length restriction X.509 extension. For a CA certificate, this value describes the depth of + subordinate CA certificates that are allowed. If this value is less than 0, the request will fail. If this + value is missing, the max path length will be omitted from the CA certificate. + - !ruby/object:Api::Type::NestedObject + name: 'keyUsage' + required: true + description: | + Indicates the intended use for keys that correspond to a certificate. + properties: + - !ruby/object:Api::Type::NestedObject + name: 'baseKeyUsage' + required: true + 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' + required: true + 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' + 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::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: 'subjectConfig' description: | @@ -773,10 +1123,10 @@ objects: 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::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. @@ -821,19 +1171,6 @@ objects: - 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 @@ -845,11 +1182,358 @@ objects: 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' + name: 'format' 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 + Types of public keys that are supported. At a minimum, we support RSA, 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" + - "PEM" + - !ruby/object:Api::Resource + name: 'CaPool' + base_url: 'projects/{{project}}/locations/{{location}}/caPools' + create_url: 'projects/{{project}}/locations/{{location}}/caPools?caPoolId={{name}}' + self_link: 'projects/{{project}}/locations/{{location}}/caPools/{{name}}' + update_verb: :PATCH + update_mask: true + 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' + description: | + A CaPool represents a group of CertificateAuthorities that form a trust anchor. A CaPool can be used to manage + issuance policies for one or more CertificateAuthority resources and to rotate CA certificates in and out of the + trust anchor. + parameters: + - !ruby/object:Api::Type::String + name: location + description: | + Location of the CaPool. A full list of valid locations can be found by + running `gcloud privateca locations list`. + required: true + input: true + url_param_only: true + properties: + - !ruby/object:Api::Type::String + name: 'name' + description: | + The name for this CaPool. + required: true + input: true + url_param_only: true + - !ruby/object:Api::Type::Enum + name: 'tier' + description: | + The Tier of this CaPool. + values: + - "ENTERPRISE" + - "DEVOPS" + input: true + required: true + - !ruby/object:Api::Type::NestedObject + name: 'issuancePolicy' + description: | + The IssuancePolicy to control how Certificates will be issued from this CaPool. + properties: + - !ruby/object:Api::Type::Array + name: 'allowedKeyTypes' + description: | + If any AllowedKeyType is specified, then the certificate request's public key must match one of the key types listed here. + Otherwise, any key may be used. + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::NestedObject + name: 'rsa' + description: | + Describes an RSA key that may be used in a Certificate issued from a CaPool. + properties: + - !ruby/object:Api::Type::String + name: 'minModulusSize' + description: | + The minimum allowed RSA modulus size, in bits. If this is not set, or if set to zero, the + service-level min RSA modulus size will continue to apply. + - !ruby/object:Api::Type::String + name: 'maxModulusSize' + description: | + The maximum allowed RSA modulus size, in bits. If this is not set, or if set to zero, the + service will not enforce an explicit upper bound on RSA modulus sizes. + - !ruby/object:Api::Type::NestedObject + name: 'ellipticCurve' + description: | + Represents an allowed Elliptic Curve key type. + properties: + - !ruby/object:Api::Type::Enum + name: 'signatureAlgorithm' + description: | + The algorithm used. + required: true + values: + - ECDSA_P256 + - ECDSA_P384 + - EDDSA_25519 + - !ruby/object:Api::Type::String + name: 'maximumLifetime' + description: | + The maximum lifetime allowed for issued Certificates. Note that if the issuing CertificateAuthority + expires before a Certificate's requested maximumLifetime, the effective lifetime will be explicitly truncated to match it. + - !ruby/object:Api::Type::NestedObject + name: 'allowedIssuanceModes' + description: | + IssuanceModes specifies the allowed ways in which Certificates may be requested from this CaPool. + properties: + - !ruby/object:Api::Type::Boolean + name: 'allowCsrBasedIssuance' + required: true + description: | + When true, allows callers to create Certificates by specifying a CSR. + - !ruby/object:Api::Type::Boolean + name: 'allowConfigBasedIssuance' + required: true + description: | + When true, allows callers to create Certificates by specifying a CertificateConfig. + - !ruby/object:Api::Type::NestedObject + name: 'identityConstraints' + description: | + Describes constraints on identities that may appear in Certificates issued through this CaPool. + If this is omitted, then this CaPool will not add restrictions on a certificate's identity. + properties: + - !ruby/object:Api::Type::Boolean + name: 'allowSubjectPassthrough' + description: | + If this is set, the Subject field may be copied from a certificate request into the signed certificate. + Otherwise, the requested Subject will be discarded. + - !ruby/object:Api::Type::Boolean + name: 'allowSubjectAltNamesPassthrough' + description: | + If this is set, the SubjectAltNames extension may be copied from a certificate request into the signed certificate. + Otherwise, the requested SubjectAltNames will be discarded. + - !ruby/object:Api::Type::NestedObject + name: 'celExpression' + description: | + A CEL expression that may be used to validate the resolved X.509 Subject and/or Subject Alternative Name before a + certificate is signed. To see the full allowed syntax and some examples, + see https://cloud.google.com/certificate-authority-service/docs/cel-guide + properties: + - !ruby/object:Api::Type::String + name: 'expression' + required: true + description: | + Textual representation of an expression in Common Expression Language syntax. + - !ruby/object:Api::Type::String + name: 'title' + description: | + Title for the expression, i.e. a short string describing its purpose. This can be used e.g. in UIs which allow to enter the expression. + - !ruby/object:Api::Type::String + name: 'description' + description: | + Description of the expression. This is a longer text which describes the expression, e.g. when hovered over it in a UI. + - !ruby/object:Api::Type::String + name: 'location' + description: | + String indicating the location of the expression for error reporting, e.g. a file name and a position in the file. + - !ruby/object:Api::Type::NestedObject + name: 'baselineValues' + description: | + A set of X.509 values that will be applied to all certificates issued through this CaPool. If a certificate request + includes conflicting values for the same properties, they will be overwritten by the values defined here. If a certificate + request uses a CertificateTemplate that defines conflicting predefinedValues for the same properties, the certificate + issuance request will fail. + properties: + - !ruby/object:Api::Type::Array + name: 'additionalExtensions' + description: | + Specifies an X.509 extension, which may be used in different parts of X.509 objects like certificates, CSRs, and CRLs. + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::Boolean + name: 'critical' + required: true + description: | + 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' + required: true + description: | + The value of this X.509 extension. A base64-encoded string. + - !ruby/object:Api::Type::NestedObject + name: 'objectId' + required: true + description: | + Describes values that are relevant in a CA certificate. + 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::Array + name: 'policyIds' + description: | + Describes the X.509 certificate policy object identifiers, per https://tools.ietf.org/html/rfc5280#section-4.2.1.4. + item_type: !ruby/object:Api::Type::NestedObject + 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::Array + name: 'aiaOcspServers' + item_type: Api::Type::String + description: | + Describes Online Certificate Status Protocol (OCSP) endpoint addresses that appear in the + "Authority Information Access" extension in the certificate. + - !ruby/object:Api::Type::NestedObject + name: 'caOptions' + required: true + description: | + Describes values that are relevant in a CA certificate. + properties: + - !ruby/object:Api::Type::Boolean + name: 'isCa' + description: | + Refers to the "CA" X.509 extension, which is a boolean value. When this value is missing, + the extension will be omitted from the CA certificate. + - !ruby/object:Api::Type::Integer + name: 'maxIssuerPathLength' + description: | + Refers to the path length restriction X.509 extension. For a CA certificate, this value describes the depth of + subordinate CA certificates that are allowed. If this value is less than 0, the request will fail. If this + value is missing, the max path length will be omitted from the CA certificate. + - !ruby/object:Api::Type::NestedObject + name: 'keyUsage' + required: true + description: | + Indicates the intended use for keys that correspond to a certificate. + properties: + - !ruby/object:Api::Type::NestedObject + name: 'baseKeyUsage' + required: true + 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' + required: true + 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' + 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::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: 'publishingOptions' + description: | + The PublishingOptions to follow when issuing Certificates from any CertificateAuthority in this CaPool. + properties: + - !ruby/object:Api::Type::Boolean + name: 'publishCaCert' + required: true + description: | + When true, publishes each CertificateAuthority's CA certificate and includes its URL in the "Authority Information Access" + X.509 extension in all issued Certificates. If this is false, the CA certificate will not be published and the corresponding + X.509 extension will not be written in issued certificates. + - !ruby/object:Api::Type::Boolean + name: 'publishCrl' + required: true + description: | + When true, publishes each CertificateAuthority's CRL and includes its URL in the "CRL Distribution Points" X.509 extension + in all issued Certificates. If this is false, CRLs will not be published and the corresponding X.509 extension will not + be written in issued certificates. CRLs will expire 7 days from their creation. However, we will rebuild daily. CRLs are + also rebuilt shortly after a certificate is revoked. + - !ruby/object:Api::Type::KeyValuePairs + name: labels + description: | + Labels with user-defined metadata. + + An object containing a list of "key": value pairs. Example: { "name": "wrench", "mass": + "1.3kg", "count": "3" }. + + + + diff --git a/mmv1/products/privateca/terraform.yaml b/mmv1/products/privateca/terraform.yaml index f1564fe8ac6e..23a476ecff38 100644 --- a/mmv1/products/privateca/terraform.yaml +++ b/mmv1/products/privateca/terraform.yaml @@ -15,51 +15,28 @@ overrides: !ruby/object:Overrides::ResourceOverrides CertificateAuthority: !ruby/object:Overrides::Terraform::ResourceOverride autogen_async: true - iam_policy: !ruby/object:Api::Resource::IamPolicy - parent_resource_attribute: certificate_authority - allowed_iam_role: 'roles/privateca.certificateManager' - method_name_separator: ':' - example_config_body: 'templates/terraform/iam/example_config_body/privateca_certificate_authority.tf.erb' - base_url: '{{name}}' - description: | - {{description}} - - ~> **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_id}}"] + import_format: ["projects/{{project}}/locations/{{location}}/caPools/{{pool}}/certificateAuthorities/{{certificate_authority_id}}"] + custom_code: !ruby/object:Provider::Terraform::CustomCode + test_check_destroy: templates/terraform/custom_check_destroy/privateca_certificate_authority.go.erb examples: - !ruby/object:Provider::Terraform::Examples name: "privateca_certificate_authority_basic" - min_version: "beta" - primary_resource_id: "default" - vars: - certificate_authority_id: "my-certificate-authority" - - !ruby/object:Provider::Terraform::Examples - name: "privateca_certificate_authority_full" - min_version: "beta" primary_resource_id: "default" vars: certificate_authority_id: "my-certificate-authority" + test_vars_overrides: + pool: "\"static-ca-pool\"" - !ruby/object:Provider::Terraform::Examples - min_version: beta name: "privateca_certificate_authority_cmek" - min_version: "beta" primary_resource_id: "default" # Multiple IAM bindings on the same key cause non-determinism skip_vcr: true vars: kms_key_name: "projects/keys-project/locations/us-central1/keyRings/key-ring/cryptoKeys/crypto-key" + certificate_authority_id: "my-certificate-authority" test_vars_overrides: kms_key_name: 'BootstrapKMSKeyWithPurposeInLocation(t, "ASYMMETRIC_SIGN", "us-central1").CryptoKey.Name' - virtual_fields: - - !ruby/object:Api::Type::Boolean - name: 'disable_on_delete' - default_value: false - description: | - If set to `true`, the Certificate Authority will be disabled - on delete. If the Certitificate Authorities is not disabled, - it cannot be deleted. Use with care. Defaults to `false`. + pool: "\"static-ca-pool\"" properties: type: !ruby/object:Overrides::Terraform::PropertyOverride description: | @@ -68,17 +45,13 @@ overrides: !ruby/object:Overrides::ResourceOverrides ~> **Note:** For `SUBORDINATE` Certificate Authorities, they need to be manually activated (via Cloud Console of `gcloud`) before they can issue certificates. - config.reusableConfig.reusableConfig: !ruby/object:Overrides::Terraform::PropertyOverride - description: | - {{description}}. Alternatively, one of the short names - found by running `gcloud beta privateca reusable-configs list`. - diff_suppress_func: 'certificateAuthorityReusableConfigDiffSuppress' + config.x509Config: !ruby/object:Overrides::Terraform::PropertyOverride + custom_flatten: 'templates/terraform/custom_flatten/privateca_certificate_509_config.go.erb' custom_code: !ruby/object:Provider::Terraform::CustomCode - constants: templates/terraform/constants/certificate_authority.go.erb - encoder: templates/terraform/encoders/certificate_authority.go.erb - pre_delete: templates/terraform/pre_delete/privateca_certificate_authority.go.erb + decoder: templates/terraform/decoders/treat_deleted_state_as_gone.go.erb + post_create: templates/terraform/post_create/privateca_authority_enable.go.erb + pre_delete: templates/terraform/pre_delete/privateca_authority_disable.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 @@ -88,30 +61,64 @@ overrides: !ruby/object:Overrides::ResourceOverrides ~> **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}}"] + properties: + config.x509Config: !ruby/object:Overrides::Terraform::PropertyOverride + custom_flatten: 'templates/terraform/custom_flatten/privateca_certificate_509_config.go.erb' 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 + test_vars_overrides: + pool: "\"static-ca-pool\"" - !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 + test_vars_overrides: + pool: "\"static-ca-pool\"" + - !ruby/object:Provider::Terraform::Examples + name: "privateca_certificate_no_authority" + primary_resource_id: "default" + vars: + certificate_name: "my-certificate" + certificate_authority_id: "my-authority" + test_env_vars: + project: :PROJECT_NAME + test_vars_overrides: + pool: "\"static-ca-pool\"" custom_code: !ruby/object:Provider::Terraform::CustomCode + pre_create: templates/terraform/pre_create/privateca_certificate.go.erb test_check_destroy: templates/terraform/custom_check_destroy/privateca_certificate.go.erb + CaPool: !ruby/object:Overrides::Terraform::ResourceOverride + properties: + issuancePolicy.baselineValues: !ruby/object:Overrides::Terraform::PropertyOverride + custom_flatten: 'templates/terraform/custom_flatten/privateca_certificate_509_config.go.erb' + iam_policy: !ruby/object:Api::Resource::IamPolicy + allowed_iam_role: 'roles/privateca.certificateManager' + method_name_separator: ':' + parent_resource_attribute: ca_pool + example_config_body: 'templates/terraform/iam/example_config_body/privateca_ca_pool.tf.erb' + autogen_async: true + import_format: ["projects/{{project}}/locations/{{location}}/caPools/{{name}}"] + examples: + - !ruby/object:Provider::Terraform::Examples + name: "privateca_capool_basic" + primary_resource_name: "fmt.Sprintf(\"tf-test-my-pool%s\", context[\"random_suffix\"])" + primary_resource_id: "default" + vars: + name: "my-pool" + - !ruby/object:Provider::Terraform::Examples + name: "privateca_capool_all_fields" + primary_resource_id: "default" + vars: + name: "my-pool" diff --git a/mmv1/templates/terraform/constants/certificate_authority.go.erb b/mmv1/templates/terraform/constants/certificate_authority.go.erb deleted file mode 100644 index f45d73c16c93..000000000000 --- a/mmv1/templates/terraform/constants/certificate_authority.go.erb +++ /dev/null @@ -1,11 +0,0 @@ -func certificateAuthorityReusableConfigDiffSuppress(k, old, new string, d *schema.ResourceData) bool { - if old != "" && new != "" { - newParts := strings.Split(new, "/") - // If the new form is a short version, we just - // check if it matches the suffix of the old version - if len(newParts) == 1 { - return strings.HasSuffix(old, new) - } - } - return old == new -} diff --git a/mmv1/templates/terraform/custom_check_destroy/privateca_certificate.go.erb b/mmv1/templates/terraform/custom_check_destroy/privateca_certificate.go.erb index 9dccc2241b36..6c1572bea6d1 100644 --- a/mmv1/templates/terraform/custom_check_destroy/privateca_certificate.go.erb +++ b/mmv1/templates/terraform/custom_check_destroy/privateca_certificate.go.erb @@ -1,6 +1,6 @@ config := googleProviderConfig(t) -url, err := replaceVarsForTest(config, rs, "{{PrivatecaBasePath}}projects/{{project}}/locations/{{location}}/certificateAuthorities/{{certificate_authority}}/certificates/{{name}}") +url, err := replaceVarsForTest(config, rs, "{{PrivatecaBasePath}}projects/{{project}}/locations/{{location}}/caPools/{{pool}}/certificates/{{name}}") if err != nil { return err diff --git a/mmv1/templates/terraform/custom_check_destroy/privateca_certificate_authority.go.erb b/mmv1/templates/terraform/custom_check_destroy/privateca_certificate_authority.go.erb index 982a9a227735..83555b3d2810 100644 --- a/mmv1/templates/terraform/custom_check_destroy/privateca_certificate_authority.go.erb +++ b/mmv1/templates/terraform/custom_check_destroy/privateca_certificate_authority.go.erb @@ -1,6 +1,6 @@ config := googleProviderConfig(t) -url, err := replaceVarsForTest(config, rs, "{{PrivatecaBasePath}}projects/{{project}}/locations/{{location}}/certificateAuthorities/{{certificate_authority_id}}") +url, err := replaceVarsForTest(config, rs, "{{PrivatecaBasePath}}projects/{{project}}/locations/{{location}}/caPools/{{pool}}/certificateAuthorities/{{certificate_authority_id}}") if err != nil { return err } @@ -10,6 +10,6 @@ if err != nil { return nil } -if s := res["state"]; s != "PENDING_DELETION" { - return fmt.Errorf("CertificateAuthority %s got %s, want PENDING_DELETION", url, s) +if s := res["state"]; s != "DELETED" { + return fmt.Errorf("CertificateAuthority %s got %s, want DELETED", url, s) } \ No newline at end of file diff --git a/mmv1/templates/terraform/custom_flatten/privateca_certificate_509_config.go.erb b/mmv1/templates/terraform/custom_flatten/privateca_certificate_509_config.go.erb new file mode 100644 index 000000000000..81ccb1a33dda --- /dev/null +++ b/mmv1/templates/terraform/custom_flatten/privateca_certificate_509_config.go.erb @@ -0,0 +1,18 @@ +<%# See mmv1/third_party/terraform/utils/privateca_utils.go for the sub-expanders and explanation %> +func flatten<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d *schema.ResourceData, config *Config) interface{} { + if v == nil { + v = make(map[string]interface{}) + } + original := v.(map[string]interface{}) + transformed := make(map[string]interface{}) + transformed["additional_extensions"] = + flattenPrivatecaCertificateConfigX509ConfigAdditionalExtensions(original["additionalExtensions"], d, config) + transformed["policy_ids"] = + flattenPrivatecaCertificateConfigX509ConfigPolicyIds(original["policyIds"], d, config) + transformed["aia_ocsp_servers"] = flattenPrivatecaCertificateConfigX509ConfigAiaOcspServers(original["aiaOcspServers"], d, config) + transformed["ca_options"] = + flattenPrivatecaCertificateConfigX509ConfigCaOptions(original["caOptions"], d, config) + transformed["key_usage"] = + flattenPrivatecaCertificateConfigX509ConfigKeyUsage(original["keyUsage"], d, config) + return []interface{}{transformed} +} diff --git a/mmv1/templates/terraform/encoders/certificate_authority.go.erb b/mmv1/templates/terraform/encoders/certificate_authority.go.erb deleted file mode 100644 index 645012b24fbb..000000000000 --- a/mmv1/templates/terraform/encoders/certificate_authority.go.erb +++ /dev/null @@ -1,13 +0,0 @@ -rc := d.Get("config.0.reusable_config.0.reusable_config").(string) - -parts := strings.Split(rc, "/") - -if len(parts) == 1 { - // If we have a short form: add the full path to the reusable-configs from - // the Google-managed project and the location of the CA. - config := obj["config"].(map[string]interface{}) - configReusableConfig := config["reusableConfig"].(map[string]interface{}) - configReusableConfig["reusableConfig"] = fmt.Sprintf("projects/568668481468/locations/%s/reusableConfigs/%s", d.Get("location"), parts[0]) -} - -return obj, nil diff --git a/mmv1/templates/terraform/examples/privateca_capool_all_fields.tf.erb b/mmv1/templates/terraform/examples/privateca_capool_all_fields.tf.erb new file mode 100644 index 000000000000..25d47c76d6c0 --- /dev/null +++ b/mmv1/templates/terraform/examples/privateca_capool_all_fields.tf.erb @@ -0,0 +1,77 @@ +resource "google_privateca_ca_pool" "<%= ctx[:primary_resource_id] %>" { + name = "<%= ctx[:vars]["name"] %>" + location = "us-central1" + tier = "ENTERPRISE" + publishing_options { + publish_ca_cert = false + publish_crl = true + } + labels = { + foo = "bar" + } + issuance_policy { + allowed_key_types { + elliptic_curve { + signature_algorithm = "ECDSA_P256" + } + } + allowed_key_types { + rsa { + min_modulus_size = 5 + max_modulus_size = 10 + } + } + maximum_lifetime = "50000s" + allowed_issuance_modes { + allow_csr_based_issuance = true + allow_config_based_issuance = true + } + identity_constraints { + allow_subject_passthrough = true + allow_subject_alt_names_passthrough = true + cel_expression { + expression = "subject_alt_names.all(san, san.type == DNS || san.type == EMAIL )" + title = "My title" + } + } + baseline_values { + aia_ocsp_servers = ["example.com"] + additional_extensions { + critical = true + value = "asdf" + object_id { + object_id_path = [123, 899] + } + } + policy_ids { + object_id_path = [123, 888] + } + policy_ids { + object_id_path = [456, 120] + } + ca_options { + is_ca = true + max_issuer_path_length = 10 + } + key_usage { + base_key_usage { + digital_signature = true + content_commitment = true + key_encipherment = false + data_encipherment = true + key_agreement = true + cert_sign = false + crl_sign = true + decipher_only = true + } + extended_key_usage { + server_auth = true + client_auth = false + email_protection = true + code_signing = true + time_stamping = true + } + } + } + } +} diff --git a/mmv1/templates/terraform/examples/privateca_capool_basic.tf.erb b/mmv1/templates/terraform/examples/privateca_capool_basic.tf.erb new file mode 100644 index 000000000000..5c64b66dc306 --- /dev/null +++ b/mmv1/templates/terraform/examples/privateca_capool_basic.tf.erb @@ -0,0 +1,12 @@ +resource "google_privateca_ca_pool" "<%= ctx[:primary_resource_id] %>" { + name = "<%= ctx[:vars]["name"] %>" + location = "us-central1" + tier = "ENTERPRISE" + publishing_options { + publish_ca_cert = true + publish_crl = true + } + labels = { + foo = "bar" + } +} diff --git a/mmv1/templates/terraform/examples/privateca_certificate_authority_basic.tf.erb b/mmv1/templates/terraform/examples/privateca_certificate_authority_basic.tf.erb index 1166f861a5ca..03a2d95eea0e 100644 --- a/mmv1/templates/terraform/examples/privateca_certificate_authority_basic.tf.erb +++ b/mmv1/templates/terraform/examples/privateca_certificate_authority_basic.tf.erb @@ -1,23 +1,47 @@ resource "google_privateca_certificate_authority" "<%= ctx[:primary_resource_id] %>" { - provider = google-beta + // This example assumes this pool already exists. + // Pools cannot be deleted in normal test circumstances, so we depend on static pools + pool = "<%= ctx[:vars]["pool"] %>" certificate_authority_id = "<%= ctx[:vars]["certificate_authority_id"] %>" location = "us-central1" config { subject_config { subject { organization = "HashiCorp" + common_name = "my-certificate-authority" } - common_name = "my-certificate-authority" subject_alt_name { dns_names = ["hashicorp.com"] } } - reusable_config { - reusable_config = "projects/568668481468/locations/us-central1/reusableConfigs/root-unconstrained" + x509_config { + ca_options { + is_ca = true + max_issuer_path_length = 10 + } + key_usage { + base_key_usage { + digital_signature = true + content_commitment = true + key_encipherment = false + data_encipherment = true + key_agreement = true + cert_sign = true + crl_sign = true + decipher_only = true + } + extended_key_usage { + server_auth = true + client_auth = false + email_protection = true + code_signing = true + time_stamping = true + } + } } } + lifetime = "86400s" key_spec { algorithm = "RSA_PKCS1_4096_SHA256" } - disable_on_delete = true } diff --git a/mmv1/templates/terraform/examples/privateca_certificate_authority_cmek.tf.erb b/mmv1/templates/terraform/examples/privateca_certificate_authority_cmek.tf.erb index 5150f06afe93..39ab936ce940 100644 --- a/mmv1/templates/terraform/examples/privateca_certificate_authority_cmek.tf.erb +++ b/mmv1/templates/terraform/examples/privateca_certificate_authority_cmek.tf.erb @@ -1,10 +1,8 @@ resource "google_project_service_identity" "privateca_sa" { - provider = google-beta - service = "privateca.googleapis.com" + service = "privateca.googleapis.com" } resource "google_kms_crypto_key_iam_binding" "privateca_sa_keyuser_signerverifier" { - provider = google-beta crypto_key_id = "<%= ctx[:vars]['kms_key_name'] %>" role = "roles/cloudkms.signerVerifier" @@ -14,7 +12,6 @@ resource "google_kms_crypto_key_iam_binding" "privateca_sa_keyuser_signerverifie } resource "google_kms_crypto_key_iam_binding" "privateca_sa_keyuser_viewer" { - provider = google-beta crypto_key_id = "<%= ctx[:vars]['kms_key_name'] %>" role = "roles/viewer" members = [ @@ -23,24 +20,38 @@ resource "google_kms_crypto_key_iam_binding" "privateca_sa_keyuser_viewer" { } resource "google_privateca_certificate_authority" "<%= ctx[:primary_resource_id] %>" { - provider = google-beta - certificate_authority_id = "tf-test%{random_suffix}" - location = "us-central1" - + // This example assumes this pool already exists. + // Pools cannot be deleted in normal test circumstances, so we depend on static pools + pool = "<%= ctx[:vars]["pool"] %>" + certificate_authority_id = "<%= ctx[:vars]["certificate_authority_id"] %>" + location = "us-central1" key_spec { cloud_kms_key_version = "<%= ctx[:vars]['kms_key_name'] %>/cryptoKeyVersions/1" } config { subject_config { - common_name = "Example Authority" subject { organization = "Example, Org." + common_name = "Example Authority" } } - - reusable_config { - reusable_config= "root-unconstrained" + x509_config { + ca_options { + # is_ca *MUST* be true for certificate authorities + is_ca = true + max_issuer_path_length = 10 + } + key_usage { + base_key_usage { + # cert_sign and crl_sign *MUST* be true for certificate authorities + cert_sign = true + crl_sign = true + } + extended_key_usage { + server_auth = false + } + } } } @@ -48,6 +59,4 @@ resource "google_privateca_certificate_authority" "<%= ctx[:primary_resource_id] google_kms_crypto_key_iam_binding.privateca_sa_keyuser_signerverifier, google_kms_crypto_key_iam_binding.privateca_sa_keyuser_viewer, ] - - disable_on_delete = true } \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/privateca_certificate_authority_full.tf.erb b/mmv1/templates/terraform/examples/privateca_certificate_authority_full.tf.erb deleted file mode 100644 index 64258aa5a42e..000000000000 --- a/mmv1/templates/terraform/examples/privateca_certificate_authority_full.tf.erb +++ /dev/null @@ -1,38 +0,0 @@ -resource "google_privateca_certificate_authority" "<%= ctx[:primary_resource_id] %>" { - provider = google-beta - certificate_authority_id = "<%= ctx[:vars]["certificate_authority_id"] %>" - location = "us-central1" - tier = "DEVOPS" - config { - subject_config { - subject { - country_code = "US" - organization = "HashiCorp" - organizational_unit = "Terraform" - locality = "San Francisco" - province = "CA" - street_address = "101 2nd St #700" - postal_code = "94105" - } - common_name = "my-certificate-authority" - 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"] - } - } - reusable_config { - reusable_config = "projects/568668481468/locations/us-central1/reusableConfigs/root-unconstrained" - } - } - lifetime = "86400s" - issuing_options { - include_ca_cert_url = true - include_crl_access_url = false - } - key_spec { - algorithm = "EC_P256_SHA256" - } - disable_on_delete = true -} diff --git a/mmv1/templates/terraform/examples/privateca_certificate_config.tf.erb b/mmv1/templates/terraform/examples/privateca_certificate_config.tf.erb index 61d128871448..ec5dccb49370 100644 --- a/mmv1/templates/terraform/examples/privateca_certificate_config.tf.erb +++ b/mmv1/templates/terraform/examples/privateca_certificate_config.tf.erb @@ -1,62 +1,79 @@ resource "google_privateca_certificate_authority" "test-ca" { - provider = google-beta certificate_authority_id = "<%= ctx[:vars]["certificate_authority_id"] %>" location = "us-central1" + pool = "<%= ctx[:vars]["pool"] %>" tier = "ENTERPRISE" + ignore_active_certificates = true config { subject_config { subject { organization = "HashiCorp" + common_name = "my-certificate-authority" } - common_name = "my-certificate-authority" subject_alt_name { dns_names = ["hashicorp.com"] } } - reusable_config { - reusable_config = "projects/568668481468/locations/us-central1/reusableConfigs/root-unconstrained" + x509_config { + ca_options { + is_ca = true + } + key_usage { + base_key_usage { + cert_sign = true + crl_sign = true + } + extended_key_usage { + server_auth = true + } + } } } 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'] %>" + pool = "<%= ctx[:vars]["pool"] %>" 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 { + subject_config { + subject { 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"] + country_code = "us" + organization = "google" + organizational_unit = "enterprise" + locality = "mountain view" + province = "california" + street_address = "1600 amphitheatre parkway" + } + subject_alt_name { + email_addresses = ["email@example.com"] + ip_addresses = ["127.0.0.1"] + uris = ["http://www.ietf.org/rfc/rfc3986.txt"] + } + } + x509_config { + ca_options { + is_ca = false + } + key_usage { + base_key_usage { + crl_sign = false + decipher_only = false + } + extended_key_usage { + server_auth = false } } - + } public_key { - type = "PEM_RSA_KEY" + format = "PEM" 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 index 5ce90d5632ad..41c4f572e568 100644 --- a/mmv1/templates/terraform/examples/privateca_certificate_csr.tf.erb +++ b/mmv1/templates/terraform/examples/privateca_certificate_csr.tf.erb @@ -1,5 +1,5 @@ resource "google_privateca_certificate_authority" "test-ca" { - provider = google-beta + pool = "<%= ctx[:vars]["pool"] %>" certificate_authority_id = "<%= ctx[:vars]["certificate_authority_id"] %>" location = "us-central1" tier = "ENTERPRISE" @@ -7,28 +7,37 @@ resource "google_privateca_certificate_authority" "test-ca" { subject_config { subject { organization = "HashiCorp" + common_name = "my-certificate-authority" } - common_name = "my-certificate-authority" subject_alt_name { dns_names = ["hashicorp.com"] } } - reusable_config { - reusable_config = "projects/568668481468/locations/us-central1/reusableConfigs/root-unconstrained" + x509_config { + ca_options { + # is_ca *MUST* be true for certificate authorities + is_ca = true + } + key_usage { + base_key_usage { + # cert_sign and crl_sign *MUST* be true for certificate authorities + cert_sign = true + crl_sign = true + } + extended_key_usage { + server_auth = false + } + } } } 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'] %>" + pool = "<%= ctx[:vars]["pool"] %>" location = "us-central1" certificate_authority = google_privateca_certificate_authority.test-ca.certificate_authority_id lifetime = "860s" diff --git a/mmv1/templates/terraform/examples/privateca_certificate_no_authority.tf.erb b/mmv1/templates/terraform/examples/privateca_certificate_no_authority.tf.erb new file mode 100644 index 000000000000..721825903548 --- /dev/null +++ b/mmv1/templates/terraform/examples/privateca_certificate_no_authority.tf.erb @@ -0,0 +1,79 @@ +resource "google_privateca_certificate_authority" "authority" { + // This example assumes this pool already exists. + // Pools cannot be deleted in normal test circumstances, so we depend on static pools + pool = "<%= ctx[:vars]["pool"] %>" + certificate_authority_id = "<%= ctx[:vars]["certificate_authority_id"] %>" + location = "us-central1" + config { + subject_config { + subject { + organization = "HashiCorp" + common_name = "my-certificate-authority" + } + subject_alt_name { + dns_names = ["hashicorp.com"] + } + } + x509_config { + ca_options { + is_ca = true + } + key_usage { + base_key_usage { + digital_signature = true + cert_sign = true + crl_sign = true + } + extended_key_usage { + server_auth = true + } + } + } + } + lifetime = "86400s" + key_spec { + algorithm = "RSA_PKCS1_4096_SHA256" + } +} + + +resource "google_privateca_certificate" "<%= ctx[:primary_resource_id] %>" { + pool = "<%= ctx[:vars]["pool"] %>" + location = "us-central1" + lifetime = "860s" + name = "<%= ctx[:vars]["certificate_name"] %>" + config { + subject_config { + subject { + common_name = "san1.example.com" + country_code = "us" + organization = "google" + organizational_unit = "enterprise" + locality = "mountain view" + province = "california" + street_address = "1600 amphitheatre parkway" + postal_code = "94109" + } + } + x509_config { + ca_options { + is_ca = false + } + key_usage { + base_key_usage { + crl_sign = true + } + extended_key_usage { + server_auth = true + } + } + } + public_key { + format = "PEM" + key = filebase64("test-fixtures/rsa_public.pem") + } + } + // Certificates require an authority to exist in the pool, though they don't + // need to be explicitly connected to it + depends_on = [google_privateca_certificate_authority.authority] +} \ No newline at end of file diff --git a/mmv1/templates/terraform/iam/example_config_body/privateca_ca_pool.tf.erb b/mmv1/templates/terraform/iam/example_config_body/privateca_ca_pool.tf.erb new file mode 100644 index 000000000000..b83c03358456 --- /dev/null +++ b/mmv1/templates/terraform/iam/example_config_body/privateca_ca_pool.tf.erb @@ -0,0 +1 @@ + ca_pool = google_privateca_ca_pool.default.id diff --git a/mmv1/templates/terraform/iam/example_config_body/privateca_certificate_authority.tf.erb b/mmv1/templates/terraform/iam/example_config_body/privateca_certificate_authority.tf.erb deleted file mode 100644 index 92bc4454e2aa..000000000000 --- a/mmv1/templates/terraform/iam/example_config_body/privateca_certificate_authority.tf.erb +++ /dev/null @@ -1 +0,0 @@ - certificate_authority = google_privateca_certificate_authority.default.id diff --git a/mmv1/templates/terraform/post_create/privateca_authority_enable.go.erb b/mmv1/templates/terraform/post_create/privateca_authority_enable.go.erb new file mode 100644 index 000000000000..cebbc2b39783 --- /dev/null +++ b/mmv1/templates/terraform/post_create/privateca_authority_enable.go.erb @@ -0,0 +1,11 @@ + url, err = replaceVars(d, config, "{{PrivatecaBasePath}}projects/{{project}}/locations/{{location}}/caPools/{{pool}}/certificateAuthorities/{{certificate_authority_id}}:enable") + if err != nil { + return err + } + + log.Printf("[DEBUG] Enabling CertificateAuthority: %#v", obj) + + res, err = sendRequest(config, "POST", billingProject, url, userAgent, nil) + if err != nil { + return fmt.Errorf("Error enabling CertificateAuthority: %s", err) + } \ No newline at end of file diff --git a/mmv1/templates/terraform/pre_create/privateca_certificate.go.erb b/mmv1/templates/terraform/pre_create/privateca_certificate.go.erb new file mode 100644 index 000000000000..d9fa0e3a7db6 --- /dev/null +++ b/mmv1/templates/terraform/pre_create/privateca_certificate.go.erb @@ -0,0 +1,21 @@ +<%# The license inside this block applies to this file. + # Copyright 2020 Google 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. +-%> +// Only include linked certificate authority if the user specified it +if p, ok := d.GetOk("certificate_authority"); ok { + url, err = addQueryParams(url, map[string]string{"issuingCertificateAuthorityId": p.(string)}) + if err != nil { + return err + } +} \ No newline at end of file diff --git a/mmv1/templates/terraform/pre_delete/privateca_authority_disable.go.erb b/mmv1/templates/terraform/pre_delete/privateca_authority_disable.go.erb new file mode 100644 index 000000000000..e7e529213a39 --- /dev/null +++ b/mmv1/templates/terraform/pre_delete/privateca_authority_disable.go.erb @@ -0,0 +1,11 @@ + disableUrl, err := replaceVars(d, config, "{{PrivatecaBasePath}}projects/{{project}}/locations/{{location}}/caPools/{{pool}}/certificateAuthorities/{{certificate_authority_id}}:disable") + if err != nil { + return err + } + + log.Printf("[DEBUG] Enabling CertificateAuthority: %#v", obj) + + _, err = sendRequest(config, "POST", billingProject, disableUrl, userAgent, nil) + if err != nil { + return fmt.Errorf("Error enabling CertificateAuthority: %s", err) + } \ No newline at end of file diff --git a/mmv1/templates/terraform/pre_delete/privateca_certificate_authority.go.erb b/mmv1/templates/terraform/pre_delete/privateca_certificate_authority.go.erb deleted file mode 100644 index ccb01d203f14..000000000000 --- a/mmv1/templates/terraform/pre_delete/privateca_certificate_authority.go.erb +++ /dev/null @@ -1,19 +0,0 @@ -if d.Get("disable_on_delete").(bool) && d.Get("state").(string) == "ENABLED" { - log.Printf("[DEBUG] Disabling CertificateAuthority %q", d.Id()) - - disableURL, err := replaceVars(d, config, "{{PrivatecaBasePath}}{{name}}:disable") - if err != nil { - return err - } - - disableRes, err := sendRequestWithTimeout(config, "POST", billingProject, disableURL, userAgent, obj, d.Timeout(schema.TimeoutDelete)) - if err != nil { - return err - } - - err = privatecaOperationWaitTime(config, disableRes, project, "Disabling CertificateAuthority", userAgent, d.Timeout(schema.TimeoutDelete)) - if err != nil { - return err - } -} - diff --git a/mmv1/third_party/terraform/tests/resource_privateca_ca_pool_test.go b/mmv1/third_party/terraform/tests/resource_privateca_ca_pool_test.go new file mode 100644 index 000000000000..4569e4be9d3f --- /dev/null +++ b/mmv1/third_party/terraform/tests/resource_privateca_ca_pool_test.go @@ -0,0 +1,278 @@ +package google + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func TestAccPrivatecaCaPool_privatecaCapoolUpdate(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": randString(t, 10), + } + + vcrTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckPrivatecaCaPoolDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccPrivatecaCaPool_privatecaCapoolStart(context), + }, + { + ResourceName: "google_privateca_ca_pool.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name", "location"}, + }, + { + Config: testAccPrivatecaCaPool_privatecaCapoolEnd(context), + }, + { + ResourceName: "google_privateca_ca_pool.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name", "location"}, + }, + { + Config: testAccPrivatecaCaPool_privatecaCapoolStart(context), + }, + { + ResourceName: "google_privateca_ca_pool.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name", "location"}, + }, + }, + }) +} + +func testAccPrivatecaCaPool_privatecaCapoolStart(context map[string]interface{}) string { + return Nprintf(` +resource "google_privateca_ca_pool" "default" { + name = "tf-test-my-capool%{random_suffix}" + location = "us-central1" + tier = "ENTERPRISE" + publishing_options { + publish_ca_cert = false + publish_crl = true + } + labels = { + foo = "bar" + } + issuance_policy { + allowed_key_types { + elliptic_curve { + signature_algorithm = "ECDSA_P256" + } + } + allowed_key_types { + rsa { + min_modulus_size = 5 + max_modulus_size = 10 + } + } + maximum_lifetime = "50000s" + allowed_issuance_modes { + allow_csr_based_issuance = true + allow_config_based_issuance = true + } + identity_constraints { + allow_subject_passthrough = true + allow_subject_alt_names_passthrough = true + cel_expression { + expression = "subject_alt_names.all(san, san.type == DNS || san.type == EMAIL )" + title = "My title" + } + } + baseline_values { + aia_ocsp_servers = ["example.com"] + additional_extensions { + critical = true + value = "asdf" + object_id { + object_id_path = [123, 899] + } + } + policy_ids { + object_id_path = [123, 888] + } + policy_ids { + object_id_path = [456, 120] + } + ca_options { + is_ca = true + max_issuer_path_length = 10 + } + key_usage { + base_key_usage { + digital_signature = true + content_commitment = true + key_encipherment = false + data_encipherment = true + key_agreement = true + cert_sign = false + crl_sign = true + decipher_only = true + } + extended_key_usage { + server_auth = true + client_auth = false + email_protection = true + code_signing = true + time_stamping = true + } + } + } + } +} +`, context) +} + +func testAccPrivatecaCaPool_privatecaCapoolEnd(context map[string]interface{}) string { + return Nprintf(` +resource "google_privateca_ca_pool" "default" { + name = "tf-test-my-capool%{random_suffix}" + location = "us-central1" + tier = "ENTERPRISE" + publishing_options { + publish_ca_cert = true + publish_crl = true + } + labels = { + foo = "bar" + baz = "qux" + } + issuance_policy { + allowed_key_types { + elliptic_curve { + signature_algorithm = "ECDSA_P256" + } + } + allowed_key_types { + rsa { + min_modulus_size = 6 + } + } + maximum_lifetime = "3000s" + allowed_issuance_modes { + allow_csr_based_issuance = true + allow_config_based_issuance = true + } + identity_constraints { + allow_subject_passthrough = true + allow_subject_alt_names_passthrough = true + cel_expression { + expression = "subject_alt_names.all(san, san.type == DNS || san.type == EMAIL )" + title = "My title3" + } + } + baseline_values { + aia_ocsp_servers = ["example.com", "hashicorp.com"] + additional_extensions { + critical = true + value = "asdf" + object_id { + object_id_path = [899, 123] + } + } + policy_ids { + object_id_path = [123, 999] + } + policy_ids { + object_id_path = [456, 120, 789] + } + ca_options { + is_ca = true + max_issuer_path_length = 10 + } + key_usage { + base_key_usage { + digital_signature = true + content_commitment = true + key_encipherment = false + data_encipherment = true + key_agreement = false + cert_sign = false + crl_sign = true + decipher_only = false + } + extended_key_usage { + server_auth = false + client_auth = true + email_protection = true + code_signing = true + time_stamping = false + } + } + } + } +} +`, context) +} + +func TestAccPrivatecaCaPool_privatecaCapoolEmptyBaseline(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": randString(t, 10), + } + + vcrTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckPrivatecaCaPoolDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccPrivatecaCaPool_privatecaCapoolEmptyBaseline(context), + }, + { + ResourceName: "google_privateca_ca_pool.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name", "location"}, + }, + }, + }) +} + +func testAccPrivatecaCaPool_privatecaCapoolEmptyBaseline(context map[string]interface{}) string { + return Nprintf(` +resource "google_privateca_ca_pool" "default" { + name = "tf-test-my-capool%{random_suffix}" + location = "us-central1" + tier = "ENTERPRISE" + publishing_options { + publish_ca_cert = false + publish_crl = true + } + labels = { + foo = "bar" + } + issuance_policy { + baseline_values { + additional_extensions { + critical = false + value = "asdf" + object_id { + object_id_path = [123, 899] + } + } + ca_options { + is_ca = false + } + key_usage { + base_key_usage { + digital_signature = false + } + extended_key_usage { + server_auth = false + } + } + } + } +} +`, context) +} diff --git a/mmv1/third_party/terraform/utils/privateca_utils.go b/mmv1/third_party/terraform/utils/privateca_utils.go new file mode 100644 index 000000000000..332af73dacd2 --- /dev/null +++ b/mmv1/third_party/terraform/utils/privateca_utils.go @@ -0,0 +1,267 @@ +package google + +import ( + "strconv" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +// This file contains shared flatteners between PrivateCA Certificate, CaPool and CertificateAuthority. +// These resources share the x509Config (Certificate, CertificateAuthorty)/baselineValues (CaPool) object. +// The API does not return this object if it only contains booleans with the default (false) value. This +// causes problems if a user specifies only default values, as Terraform detects that the object has been +// deleted on the API-side. This flattener creates default objects for sub-objects that match this pattern +// to fix perma-diffs on default-only objects. For this to work all objects that are flattened from nil to +// their default object *MUST* be set in the user's config, so they are all marked as Required in the schema. + +func flattenPrivatecaCertificateConfigX509ConfigAdditionalExtensions(v interface{}, d *schema.ResourceData, config *Config) interface{} { + if v == nil { + return v + } + l := v.([]interface{}) + transformed := make([]interface{}, 0, len(l)) + for _, raw := range l { + original := raw.(map[string]interface{}) + if len(original) < 1 { + // Do not include empty json objects coming back from the api + continue + } + transformed = append(transformed, map[string]interface{}{ + "critical": flattenPrivatecaCertificateConfigX509ConfigAdditionalExtensionsCritical(original["critical"], d, config), + "value": flattenPrivatecaCertificateConfigX509ConfigAdditionalExtensionsValue(original["value"], d, config), + "object_id": flattenPrivatecaCertificateConfigX509ConfigAdditionalExtensionsObjectId(original["objectId"], d, config), + }) + } + return transformed +} +func flattenPrivatecaCertificateConfigX509ConfigAdditionalExtensionsCritical(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenPrivatecaCertificateConfigX509ConfigAdditionalExtensionsValue(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenPrivatecaCertificateConfigX509ConfigAdditionalExtensionsObjectId(v interface{}, d *schema.ResourceData, config *Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["object_id_path"] = + flattenPrivatecaCertificateConfigX509ConfigAdditionalExtensionsObjectIdObjectIdPath(original["objectIdPath"], d, config) + return []interface{}{transformed} +} +func flattenPrivatecaCertificateConfigX509ConfigAdditionalExtensionsObjectIdObjectIdPath(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenPrivatecaCertificateConfigX509ConfigPolicyIds(v interface{}, d *schema.ResourceData, config *Config) interface{} { + if v == nil { + return v + } + l := v.([]interface{}) + transformed := make([]interface{}, 0, len(l)) + for _, raw := range l { + original := raw.(map[string]interface{}) + if len(original) < 1 { + // Do not include empty json objects coming back from the api + continue + } + transformed = append(transformed, map[string]interface{}{ + "object_id_path": flattenPrivatecaCertificateConfigX509ConfigPolicyIdsObjectIdPath(original["objectIdPath"], d, config), + }) + } + return transformed +} +func flattenPrivatecaCertificateConfigX509ConfigPolicyIdsObjectIdPath(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenPrivatecaCertificateConfigX509ConfigAiaOcspServers(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenPrivatecaCertificateConfigX509ConfigCaOptions(v interface{}, d *schema.ResourceData, config *Config) interface{} { + // Special case here as the CaPool API returns an empty object rather than nil unlike the Certificate + // and CertificateAuthority APIs. + if v == nil || len(v.(map[string]interface{})) == 0 { + v = make(map[string]interface{}) + original := v.(map[string]interface{}) + transformed := make(map[string]interface{}) + transformed["is_ca"] = flattenPrivatecaCertificateConfigX509ConfigCaOptionsIsCa(original["isCa"], d, config) + return []interface{}{transformed} + } + original := v.(map[string]interface{}) + transformed := make(map[string]interface{}) + transformed["is_ca"] = + flattenPrivatecaCertificateConfigX509ConfigCaOptionsIsCa(original["isCa"], d, config) + transformed["max_issuer_path_length"] = + flattenPrivatecaCertificateConfigX509ConfigCaOptionsMaxIssuerPathLength(original["maxIssuerPathLength"], d, config) + return []interface{}{transformed} +} +func flattenPrivatecaCertificateConfigX509ConfigCaOptionsIsCa(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenPrivatecaCertificateConfigX509ConfigCaOptionsMaxIssuerPathLength(v interface{}, d *schema.ResourceData, config *Config) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } + } + + // number values are represented as float64 + if floatVal, ok := v.(float64); ok { + intVal := int(floatVal) + return intVal + } + + return v // let terraform core handle it otherwise +} + +func flattenPrivatecaCertificateConfigX509ConfigKeyUsage(v interface{}, d *schema.ResourceData, config *Config) interface{} { + if v == nil { + v = make(map[string]interface{}) + } + original := v.(map[string]interface{}) + transformed := make(map[string]interface{}) + transformed["base_key_usage"] = + flattenPrivatecaCertificateConfigX509ConfigKeyUsageBaseKeyUsage(original["baseKeyUsage"], d, config) + transformed["extended_key_usage"] = + flattenPrivatecaCertificateConfigX509ConfigKeyUsageExtendedKeyUsage(original["extendedKeyUsage"], d, config) + transformed["unknown_extended_key_usages"] = + flattenPrivatecaCertificateConfigX509ConfigKeyUsageUnknownExtendedKeyUsages(original["unknownExtendedKeyUsages"], d, config) + return []interface{}{transformed} +} +func flattenPrivatecaCertificateConfigX509ConfigKeyUsageBaseKeyUsage(v interface{}, d *schema.ResourceData, config *Config) interface{} { + if v == nil { + v = make(map[string]interface{}) + } + original := v.(map[string]interface{}) + transformed := make(map[string]interface{}) + transformed["digital_signature"] = + flattenPrivatecaCertificateConfigX509ConfigKeyUsageBaseKeyUsageDigitalSignature(original["digitalSignature"], d, config) + transformed["content_commitment"] = + flattenPrivatecaCertificateConfigX509ConfigKeyUsageBaseKeyUsageContentCommitment(original["contentCommitment"], d, config) + transformed["key_encipherment"] = + flattenPrivatecaCertificateConfigX509ConfigKeyUsageBaseKeyUsageKeyEncipherment(original["keyEncipherment"], d, config) + transformed["data_encipherment"] = + flattenPrivatecaCertificateConfigX509ConfigKeyUsageBaseKeyUsageDataEncipherment(original["dataEncipherment"], d, config) + transformed["key_agreement"] = + flattenPrivatecaCertificateConfigX509ConfigKeyUsageBaseKeyUsageKeyAgreement(original["keyAgreement"], d, config) + transformed["cert_sign"] = + flattenPrivatecaCertificateConfigX509ConfigKeyUsageBaseKeyUsageCertSign(original["certSign"], d, config) + transformed["crl_sign"] = + flattenPrivatecaCertificateConfigX509ConfigKeyUsageBaseKeyUsageCrlSign(original["crlSign"], d, config) + transformed["encipher_only"] = + flattenPrivatecaCertificateConfigX509ConfigKeyUsageBaseKeyUsageEncipherOnly(original["encipherOnly"], d, config) + transformed["decipher_only"] = + flattenPrivatecaCertificateConfigX509ConfigKeyUsageBaseKeyUsageDecipherOnly(original["decipherOnly"], d, config) + return []interface{}{transformed} +} +func flattenPrivatecaCertificateConfigX509ConfigKeyUsageBaseKeyUsageDigitalSignature(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenPrivatecaCertificateConfigX509ConfigKeyUsageBaseKeyUsageContentCommitment(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenPrivatecaCertificateConfigX509ConfigKeyUsageBaseKeyUsageKeyEncipherment(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenPrivatecaCertificateConfigX509ConfigKeyUsageBaseKeyUsageDataEncipherment(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenPrivatecaCertificateConfigX509ConfigKeyUsageBaseKeyUsageKeyAgreement(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenPrivatecaCertificateConfigX509ConfigKeyUsageBaseKeyUsageCertSign(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenPrivatecaCertificateConfigX509ConfigKeyUsageBaseKeyUsageCrlSign(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenPrivatecaCertificateConfigX509ConfigKeyUsageBaseKeyUsageEncipherOnly(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenPrivatecaCertificateConfigX509ConfigKeyUsageBaseKeyUsageDecipherOnly(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenPrivatecaCertificateConfigX509ConfigKeyUsageExtendedKeyUsage(v interface{}, d *schema.ResourceData, config *Config) interface{} { + if v == nil { + v = make(map[string]interface{}) + } + original := v.(map[string]interface{}) + transformed := make(map[string]interface{}) + transformed["server_auth"] = + flattenPrivatecaCertificateConfigX509ConfigKeyUsageExtendedKeyUsageServerAuth(original["serverAuth"], d, config) + transformed["client_auth"] = + flattenPrivatecaCertificateConfigX509ConfigKeyUsageExtendedKeyUsageClientAuth(original["clientAuth"], d, config) + transformed["code_signing"] = + flattenPrivatecaCertificateConfigX509ConfigKeyUsageExtendedKeyUsageCodeSigning(original["codeSigning"], d, config) + transformed["email_protection"] = + flattenPrivatecaCertificateConfigX509ConfigKeyUsageExtendedKeyUsageEmailProtection(original["emailProtection"], d, config) + transformed["time_stamping"] = + flattenPrivatecaCertificateConfigX509ConfigKeyUsageExtendedKeyUsageTimeStamping(original["timeStamping"], d, config) + transformed["ocsp_signing"] = + flattenPrivatecaCertificateConfigX509ConfigKeyUsageExtendedKeyUsageOcspSigning(original["ocspSigning"], d, config) + return []interface{}{transformed} +} +func flattenPrivatecaCertificateConfigX509ConfigKeyUsageExtendedKeyUsageServerAuth(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenPrivatecaCertificateConfigX509ConfigKeyUsageExtendedKeyUsageClientAuth(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenPrivatecaCertificateConfigX509ConfigKeyUsageExtendedKeyUsageCodeSigning(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenPrivatecaCertificateConfigX509ConfigKeyUsageExtendedKeyUsageEmailProtection(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenPrivatecaCertificateConfigX509ConfigKeyUsageExtendedKeyUsageTimeStamping(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenPrivatecaCertificateConfigX509ConfigKeyUsageExtendedKeyUsageOcspSigning(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenPrivatecaCertificateConfigX509ConfigKeyUsageUnknownExtendedKeyUsages(v interface{}, d *schema.ResourceData, config *Config) interface{} { + if v == nil { + return v + } + l := v.([]interface{}) + transformed := make([]interface{}, 0, len(l)) + for _, raw := range l { + original := raw.(map[string]interface{}) + if len(original) < 1 { + // Do not include empty json objects coming back from the api + continue + } + transformed = append(transformed, map[string]interface{}{ + "object_id_path": flattenPrivatecaCertificateConfigX509ConfigKeyUsageUnknownExtendedKeyUsagesObjectIdPath(original["objectIdPath"], d, config), + }) + } + return transformed +} +func flattenPrivatecaCertificateConfigX509ConfigKeyUsageUnknownExtendedKeyUsagesObjectIdPath(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +}