diff --git a/.changelog/8276.txt b/.changelog/8276.txt new file mode 100644 index 00000000000..bec984512df --- /dev/null +++ b/.changelog/8276.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +certificatemanager: added `issuance_config` field to `google_certificate_manager_certificate` resource +``` diff --git a/google/resource_certificate_manager_certificate_generated_test.go b/google/resource_certificate_manager_certificate_generated_test.go index b75d8ff0cb6..49e7268a0f6 100644 --- a/google/resource_certificate_manager_certificate_generated_test.go +++ b/google/resource_certificate_manager_certificate_generated_test.go @@ -30,7 +30,7 @@ import ( transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" ) -func TestAccCertificateManagerCertificate_certificateManagerGoogleManagedCertificateExample(t *testing.T) { +func TestAccCertificateManagerCertificate_certificateManagerGoogleManagedCertificateDnsExample(t *testing.T) { t.Parallel() context := map[string]interface{}{ @@ -43,7 +43,7 @@ func TestAccCertificateManagerCertificate_certificateManagerGoogleManagedCertifi CheckDestroy: testAccCheckCertificateManagerCertificateDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testAccCertificateManagerCertificate_certificateManagerGoogleManagedCertificateExample(context), + Config: testAccCertificateManagerCertificate_certificateManagerGoogleManagedCertificateDnsExample(context), }, { ResourceName: "google_certificate_manager_certificate.default", @@ -55,7 +55,7 @@ func TestAccCertificateManagerCertificate_certificateManagerGoogleManagedCertifi }) } -func testAccCertificateManagerCertificate_certificateManagerGoogleManagedCertificateExample(context map[string]interface{}) string { +func testAccCertificateManagerCertificate_certificateManagerGoogleManagedCertificateDnsExample(context map[string]interface{}) string { return acctest.Nprintf(` resource "google_certificate_manager_certificate" "default" { name = "tf-test-dns-cert%{random_suffix}" @@ -88,6 +88,109 @@ resource "google_certificate_manager_dns_authorization" "instance2" { `, context) } +func TestAccCertificateManagerCertificate_certificateManagerGoogleManagedCertificateIssuanceConfigExample(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckCertificateManagerCertificateDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccCertificateManagerCertificate_certificateManagerGoogleManagedCertificateIssuanceConfigExample(context), + }, + { + ResourceName: "google_certificate_manager_certificate.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"self_managed", "name", "location"}, + }, + }, + }) +} + +func testAccCertificateManagerCertificate_certificateManagerGoogleManagedCertificateIssuanceConfigExample(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_certificate_manager_certificate" "default" { + name = "tf-test-issuance-config-cert%{random_suffix}" + description = "The default cert" + scope = "EDGE_CACHE" + managed { + domains = [ + "terraform.subdomain1.com" + ] + issuance_config = google_certificate_manager_certificate_issuance_config.issuanceconfig.id + } +} + + + +# creating certificate_issuance_config to use it in the managed certificate +resource "google_certificate_manager_certificate_issuance_config" "issuanceconfig" { + name = "issuanceconfigtestterraform" + description = "sample description for the certificate issuanceConfigs" + certificate_authority_config { + certificate_authority_service_config { + ca_pool = google_privateca_ca_pool.pool.id + } + } + lifetime = "1814400s" + rotation_window_percentage = 34 + key_algorithm = "ECDSA_P256" + depends_on=[google_privateca_certificate_authority.ca_authority] +} + +resource "google_privateca_ca_pool" "pool" { + name = "tf-test-my-ca-pool%{random_suffix}" + location = "us-central1" + tier = "ENTERPRISE" +} + +resource "google_privateca_certificate_authority" "ca_authority" { + location = "us-central1" + pool = google_privateca_ca_pool.pool.name + certificate_authority_id = "tf-test-my-ca%{random_suffix}" + 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 { + cert_sign = true + crl_sign = true + } + extended_key_usage { + server_auth = true + } + } + } + } + key_spec { + algorithm = "RSA_PKCS1_4096_SHA256" + } + + // Disable CA deletion related safe checks for easier cleanup. + deletion_protection = false + skip_grace_period = true + ignore_active_certificates_on_deletion = true +} +`, context) +} + func TestAccCertificateManagerCertificate_certificateManagerSelfManagedCertificateExample(t *testing.T) { t.Parallel() diff --git a/google/services/certificatemanager/resource_certificate_manager_certificate.go b/google/services/certificatemanager/resource_certificate_manager_certificate.go index 69bb4787837..668bdbf301c 100644 --- a/google/services/certificatemanager/resource_certificate_manager_certificate.go +++ b/google/services/certificatemanager/resource_certificate_manager_certificate.go @@ -106,7 +106,7 @@ automatically, for as long as it's authorized to do so.`, Optional: true, ForceNew: true, DiffSuppressFunc: tpgresource.ProjectNumberDiffSuppress, - Description: `Authorizations that will be used for performing domain authorization`, + Description: `Authorizations that will be used for performing domain authorization. Either issuanceConfig or dnsAuthorizations should be specificed, but not both.`, Elem: &schema.Schema{ Type: schema.TypeString, }, @@ -121,6 +121,15 @@ Wildcard domains are only supported with DNS challenge resolution`, Type: schema.TypeString, }, }, + "issuance_config": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + DiffSuppressFunc: tpgresource.CompareResourceNames, + Description: `The resource name for a CertificateIssuanceConfig used to configure private PKI certificates in the format projects/*/locations/*/certificateIssuanceConfigs/*. +If this field is not set, the certificates will instead be publicly signed as documented at https://cloud.google.com/load-balancing/docs/ssl-certificates/google-managed-certs#caa. +Either issuanceConfig or dnsAuthorizations should be specificed, but not both.`, + }, "authorization_attempt_info": { Type: schema.TypeList, Computed: true, @@ -590,6 +599,8 @@ func flattenCertificateManagerCertificateManaged(v interface{}, d *schema.Resour flattenCertificateManagerCertificateManagedDomains(original["domains"], d, config) transformed["dns_authorizations"] = flattenCertificateManagerCertificateManagedDnsAuthorizations(original["dnsAuthorizations"], d, config) + transformed["issuance_config"] = + flattenCertificateManagerCertificateManagedIssuanceConfig(original["issuanceConfig"], d, config) transformed["state"] = flattenCertificateManagerCertificateManagedState(original["state"], d, config) transformed["provisioning_issue"] = @@ -606,6 +617,10 @@ func flattenCertificateManagerCertificateManagedDnsAuthorizations(v interface{}, return v } +func flattenCertificateManagerCertificateManagedIssuanceConfig(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + func flattenCertificateManagerCertificateManagedState(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { return v } @@ -768,6 +783,13 @@ func expandCertificateManagerCertificateManaged(v interface{}, d tpgresource.Ter transformed["dnsAuthorizations"] = transformedDnsAuthorizations } + transformedIssuanceConfig, err := expandCertificateManagerCertificateManagedIssuanceConfig(original["issuance_config"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedIssuanceConfig); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["issuanceConfig"] = transformedIssuanceConfig + } + transformedState, err := expandCertificateManagerCertificateManagedState(original["state"], d, config) if err != nil { return nil, err @@ -800,6 +822,10 @@ func expandCertificateManagerCertificateManagedDnsAuthorizations(v interface{}, return v, nil } +func expandCertificateManagerCertificateManagedIssuanceConfig(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + func expandCertificateManagerCertificateManagedState(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { return v, nil } diff --git a/website/docs/r/certificate_manager_certificate.html.markdown b/website/docs/r/certificate_manager_certificate.html.markdown index 2559f6fe570..79c17ae0295 100644 --- a/website/docs/r/certificate_manager_certificate.html.markdown +++ b/website/docs/r/certificate_manager_certificate.html.markdown @@ -28,11 +28,11 @@ values will be stored in the raw state as plain text: `self_managed.certificate_ [Read more about sensitive data in state](https://www.terraform.io/language/state/sensitive-data).
-## Example Usage - Certificate Manager Google Managed Certificate +## Example Usage - Certificate Manager Google Managed Certificate Dns ```hcl @@ -65,6 +65,89 @@ resource "google_certificate_manager_dns_authorization" "instance2" { domain = "subdomain2.hashicorptest.com" } ``` + +## Example Usage - Certificate Manager Google Managed Certificate Issuance Config + + +```hcl +resource "google_certificate_manager_certificate" "default" { + name = "issuance-config-cert" + description = "The default cert" + scope = "EDGE_CACHE" + managed { + domains = [ + "terraform.subdomain1.com" + ] + issuance_config = google_certificate_manager_certificate_issuance_config.issuanceconfig.id + } +} + + + +# creating certificate_issuance_config to use it in the managed certificate +resource "google_certificate_manager_certificate_issuance_config" "issuanceconfig" { + name = "issuanceconfigtestterraform" + description = "sample description for the certificate issuanceConfigs" + certificate_authority_config { + certificate_authority_service_config { + ca_pool = google_privateca_ca_pool.pool.id + } + } + lifetime = "1814400s" + rotation_window_percentage = 34 + key_algorithm = "ECDSA_P256" + depends_on=[google_privateca_certificate_authority.ca_authority] +} + +resource "google_privateca_ca_pool" "pool" { + name = "my-ca-pool" + location = "us-central1" + tier = "ENTERPRISE" +} + +resource "google_privateca_certificate_authority" "ca_authority" { + location = "us-central1" + pool = google_privateca_ca_pool.pool.name + certificate_authority_id = "my-ca" + 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 { + cert_sign = true + crl_sign = true + } + extended_key_usage { + server_auth = true + } + } + } + } + key_spec { + algorithm = "RSA_PKCS1_4096_SHA256" + } + + // Disable CA deletion related safe checks for easier cleanup. + deletion_protection = false + skip_grace_period = true + ignore_active_certificates_on_deletion = true +} +```