diff --git a/docs/data-sources/tls_subscription.md b/docs/data-sources/tls_subscription.md index 50cf91943..af426399e 100644 --- a/docs/data-sources/tls_subscription.md +++ b/docs/data-sources/tls_subscription.md @@ -30,6 +30,7 @@ data "fastly_tls_subscription" "example" { ### Read-Only +- `certificate_ids` (Set of String) List of certificate IDs associated with the Subscription. - `common_name` (String) The common name associated with the subscription generated by Fastly TLS. - `created_at` (String) Timestamp (GMT) when subscription was created. - `state` (String) The current state of the subscription. The list of possible states are: `pending`, `processing`, `issued`, and `renewing`. diff --git a/docs/resources/tls_mutual_authentication.md b/docs/resources/tls_mutual_authentication.md index 60a11fa66..f941030c5 100644 --- a/docs/resources/tls_mutual_authentication.md +++ b/docs/resources/tls_mutual_authentication.md @@ -1,16 +1,227 @@ --- -# generated by https://github.com/hashicorp/terraform-plugin-docs -page_title: "fastly_tls_mutual_authentication Resource - terraform-provider-fastly" -subcategory: "" +layout: "fastly" +page_title: "Fastly: tls_mutual_authentication" +sidebar_current: "docs-fastly-resource-tls_mutual_authentication" description: |- - +Allows for client-to-server authentication using client-side X.509 authentication. --- -# fastly_tls_mutual_authentication (Resource) +# fastly_tls_mutual_authentication +The Mutual TLS API allows for client-to-server authentication using client-side X.509 authentication. +The main Mutual Authentication object represents the certificate bundle and other configurations which support Mutual TLS for your domains. +Mutual TLS can be added to existing TLS activations to allow for client-to-server authentication. In order to use mutual TLS, you must already have active server-side TLS using either custom certificates or an enabled Fastly-managed subscription. +The examples below demonstrate how to use Mutual Authentication along with a TLS Subscription. Refer to the `fastly_tls_subscription` resource documentation for a deeper explanation of that code. + +## Example: Single Activation + +The following example sets up a TLS Subscription for `www.example.com` and then adds Mutual Authentication. + +```terraform +terraform { + required_providers { + dnsimple = { + source = "dnsimple/dnsimple" + version = "1.5.0" + } + fastly = { + source = "fastly/fastly" + version = "5.7.2" + } + } +} + +variable "dnsimple_token" { + type = string +} + +variable "dnsimple_account" { + type = string +} + +provider "dnsimple" { + account = var.dnsimple_account + token = var.dnsimple_token +} + +variable "zone" { + type = string + default = "example.com" +} + +resource "fastly_service_vcl" "example" { + name = "example" + domain { + name = "www.${var.zone}" + } + backend { + address = "httpbin.org" + name = "httpbin" + } + force_destroy = true +} + +resource "fastly_tls_subscription" "www" { + domains = [for domain in fastly_service_vcl.example.domain : domain.name if domain.name == "www.${var.zone}"] + certificate_authority = "certainly" +} + +resource "dnsimple_zone_record" "www_acme_challenge" { + name = "_acme-challenge.www" + ttl = "60" + type = "CNAME" + value = one([for obj in fastly_tls_subscription.www.managed_dns_challenges : obj.record_value if obj.record_name == "_acme-challenge.www.${var.zone}"]) + zone_name = var.zone +} + +resource "fastly_tls_subscription_validation" "www" { + subscription_id = fastly_tls_subscription.www.id + depends_on = [dnsimple_zone_record.www_acme_challenge] +} + +data "fastly_tls_configuration" "default" { + default = true + depends_on = [fastly_tls_subscription_validation.www] +} + +resource "dnsimple_zone_record" "www" { + name = "www" + ttl = "60" + type = "CNAME" + value = one([for record in data.fastly_tls_configuration.default.dns_records : record.record_value if record.record_type == "CNAME"]) + zone_name = var.zone +} + +data "fastly_tls_activation" "www" { + domain = "www.example.com" + depends_on = [dnsimple_zone_record.www] +} + +resource "fastly_tls_mutual_authentication" "www" { + activation_ids = [data.fastly_tls_activation.www.id] + cert_bundle = "-----BEGIN CERTIFICATE-----\n\n-----END CERTIFICATE-----" + enforced = true +} +``` + +## Example: Multiple Activations + +The following example sets up a TLS Subscription for `foo.example.com` and `bar.example.com` and then adds Mutual Authentication to each TLS Activation. + +```terraform +terraform { + required_providers { + dnsimple = { + source = "dnsimple/dnsimple" + version = "1.5.0" + } + fastly = { + source = "fastly/fastly" + version = "5.7.2" + } + } +} + +variable "dnsimple_token" { + type = string +} + +variable "dnsimple_account" { + type = string +} + +provider "dnsimple" { + account = var.dnsimple_account + token = var.dnsimple_token +} + +variable "zone" { + type = string + default = "example.com" +} + +resource "fastly_service_vcl" "example" { + name = "example" + domain { + name = "foo.${var.zone}" + } + domain { + name = "bar.${var.zone}" + } + backend { + address = "httpbin.org" + name = "httpbin" + } + force_destroy = true +} + +resource "fastly_tls_subscription" "example" { + domains = [for domain in fastly_service_vcl.example.domain : domain.name] + certificate_authority = "certainly" +} + +resource "dnsimple_zone_record" "example_acme_challenge" { + for_each = { + for domain in fastly_tls_subscription.example.domains : domain => one([ + for obj in fastly_tls_subscription.example.managed_dns_challenges : obj if obj.record_name == "_acme-challenge.${domain}" + ]) + } + name = each.value.record_name + ttl = "60" + type = each.value.record_type + value = each.value.record_value + zone_name = var.zone +} + +resource "fastly_tls_subscription_validation" "example" { + subscription_id = fastly_tls_subscription.example.id + depends_on = [dnsimple_zone_record.example_acme_challenge] +} + +data "fastly_tls_configuration" "default" { + default = true + depends_on = [fastly_tls_subscription_validation.example] +} + +resource "dnsimple_zone_record" "foo" { + name = "foo" + ttl = "60" + type = "CNAME" + value = one([for record in data.fastly_tls_configuration.default.dns_records : record.record_value if record.record_type == "CNAME"]) + zone_name = var.zone +} + +resource "dnsimple_zone_record" "bar" { + name = "bar" + ttl = "60" + type = "CNAME" + value = one([for record in data.fastly_tls_configuration.default.dns_records : record.record_value if record.record_type == "CNAME"]) + zone_name = var.zone +} + +# IMPORTANT: The subscription's certificate_id attribute is initially empty. +# So we can't reference the certificate_id attribute directly (not until a state refresh). +# This means we need to use the subscription data source instead. +# We need this data source to wait for the subscription process to complete. +# Once complete we'll have a Certificate ID we can reference as input to the `fastly_tls_activation_ids` data source. +data "fastly_tls_subscription" "example" { + id = fastly_tls_subscription.example.id + depends_on = [fastly_tls_subscription_validation.example] +} + +data "fastly_tls_activation_ids" "example" { + certificate_id = one(data.fastly_tls_subscription.example.certificate_ids) +} + +resource "fastly_tls_mutual_authentication" "example" { + activation_ids = data.fastly_tls_activation_ids.example.ids + cert_bundle = "-----BEGIN CERTIFICATE-----\n\n-----END CERTIFICATE-----" + enforced = true +} +``` ## Schema @@ -21,8 +232,9 @@ description: |- ### Optional +- `activation_ids` (Set of String) List of TLS Activation IDs - `enforced` (Boolean) Determines whether Mutual TLS will fail closed (enforced) or fail open. A true value will require a successful Mutual TLS handshake for the connection to continue and will fail closed if unsuccessful. A false value will fail open and allow the connection to proceed (if this attribute is not set we default to `false`). -- `include` (String) Comma-separated list of related objects to include (e.g. `tls_activations` will provide you with the TLS domain names that are related to your Mutual TLS authentication). +- `include` (String) A comma-separated list used by the Terraform provider during a state refresh to return more data related to your mutual authentication from the Fastly API (permitted values: `tls_activations`). - `name` (String) A custom name for your mutual authentication. If name is not supplied we will auto-generate one. ### Read-Only diff --git a/examples/resources/tls_mutual_authentication_basic_usage.tf b/examples/resources/tls_mutual_authentication_basic_usage.tf new file mode 100644 index 000000000..7ac89e36a --- /dev/null +++ b/examples/resources/tls_mutual_authentication_basic_usage.tf @@ -0,0 +1,84 @@ +terraform { + required_providers { + dnsimple = { + source = "dnsimple/dnsimple" + version = "1.5.0" + } + fastly = { + source = "fastly/fastly" + version = "5.7.2" + } + } +} + +variable "dnsimple_token" { + type = string +} + +variable "dnsimple_account" { + type = string +} + +provider "dnsimple" { + account = var.dnsimple_account + token = var.dnsimple_token +} + +variable "zone" { + type = string + default = "example.com" +} + +resource "fastly_service_vcl" "example" { + name = "example" + domain { + name = "www.${var.zone}" + } + backend { + address = "httpbin.org" + name = "httpbin" + } + force_destroy = true +} + +resource "fastly_tls_subscription" "www" { + domains = [for domain in fastly_service_vcl.example.domain : domain.name if domain.name == "www.${var.zone}"] + certificate_authority = "certainly" +} + +resource "dnsimple_zone_record" "www_acme_challenge" { + name = "_acme-challenge.www" + ttl = "60" + type = "CNAME" + value = one([for obj in fastly_tls_subscription.www.managed_dns_challenges : obj.record_value if obj.record_name == "_acme-challenge.www.${var.zone}"]) + zone_name = var.zone +} + +resource "fastly_tls_subscription_validation" "www" { + subscription_id = fastly_tls_subscription.www.id + depends_on = [dnsimple_zone_record.www_acme_challenge] +} + +data "fastly_tls_configuration" "default" { + default = true + depends_on = [fastly_tls_subscription_validation.www] +} + +resource "dnsimple_zone_record" "www" { + name = "www" + ttl = "60" + type = "CNAME" + value = one([for record in data.fastly_tls_configuration.default.dns_records : record.record_value if record.record_type == "CNAME"]) + zone_name = var.zone +} + +data "fastly_tls_activation" "www" { + domain = "www.example.com" + depends_on = [dnsimple_zone_record.www] +} + +resource "fastly_tls_mutual_authentication" "www" { + activation_ids = [data.fastly_tls_activation.www.id] + cert_bundle = "-----BEGIN CERTIFICATE-----\n\n-----END CERTIFICATE-----" + enforced = true +} diff --git a/examples/resources/tls_mutual_authentication_multiple_activations.tf b/examples/resources/tls_mutual_authentication_multiple_activations.tf new file mode 100644 index 000000000..c83fe99bf --- /dev/null +++ b/examples/resources/tls_mutual_authentication_multiple_activations.tf @@ -0,0 +1,109 @@ +terraform { + required_providers { + dnsimple = { + source = "dnsimple/dnsimple" + version = "1.5.0" + } + fastly = { + source = "fastly/fastly" + version = "5.7.2" + } + } +} + +variable "dnsimple_token" { + type = string +} + +variable "dnsimple_account" { + type = string +} + +provider "dnsimple" { + account = var.dnsimple_account + token = var.dnsimple_token +} + +variable "zone" { + type = string + default = "example.com" +} + +resource "fastly_service_vcl" "example" { + name = "example" + domain { + name = "foo.${var.zone}" + } + domain { + name = "bar.${var.zone}" + } + backend { + address = "httpbin.org" + name = "httpbin" + } + force_destroy = true +} + +resource "fastly_tls_subscription" "example" { + domains = [for domain in fastly_service_vcl.example.domain : domain.name] + certificate_authority = "certainly" +} + +resource "dnsimple_zone_record" "example_acme_challenge" { + for_each = { + for domain in fastly_tls_subscription.example.domains : domain => one([ + for obj in fastly_tls_subscription.example.managed_dns_challenges : obj if obj.record_name == "_acme-challenge.${domain}" + ]) + } + name = each.value.record_name + ttl = "60" + type = each.value.record_type + value = each.value.record_value + zone_name = var.zone +} + +resource "fastly_tls_subscription_validation" "example" { + subscription_id = fastly_tls_subscription.example.id + depends_on = [dnsimple_zone_record.example_acme_challenge] +} + +data "fastly_tls_configuration" "default" { + default = true + depends_on = [fastly_tls_subscription_validation.example] +} + +resource "dnsimple_zone_record" "foo" { + name = "foo" + ttl = "60" + type = "CNAME" + value = one([for record in data.fastly_tls_configuration.default.dns_records : record.record_value if record.record_type == "CNAME"]) + zone_name = var.zone +} + +resource "dnsimple_zone_record" "bar" { + name = "bar" + ttl = "60" + type = "CNAME" + value = one([for record in data.fastly_tls_configuration.default.dns_records : record.record_value if record.record_type == "CNAME"]) + zone_name = var.zone +} + +# IMPORTANT: The subscription's certificate_id attribute is initially empty. +# So we can't reference the certificate_id attribute directly (not until a state refresh). +# This means we need to use the subscription data source instead. +# We need this data source to wait for the subscription process to complete. +# Once complete we'll have a Certificate ID we can reference as input to the `fastly_tls_activation_ids` data source. +data "fastly_tls_subscription" "example" { + id = fastly_tls_subscription.example.id + depends_on = [fastly_tls_subscription_validation.example] +} + +data "fastly_tls_activation_ids" "example" { + certificate_id = one(data.fastly_tls_subscription.example.certificate_ids) +} + +resource "fastly_tls_mutual_authentication" "example" { + activation_ids = data.fastly_tls_activation_ids.example.ids + cert_bundle = "-----BEGIN CERTIFICATE-----\n\n-----END CERTIFICATE-----" + enforced = true +} diff --git a/fastly/data_source_fastly_tls_activation_ids.go b/fastly/data_source_fastly_tls_activation_ids.go index 1cc5c8499..53b536a07 100644 --- a/fastly/data_source_fastly_tls_activation_ids.go +++ b/fastly/data_source_fastly_tls_activation_ids.go @@ -5,9 +5,10 @@ import ( "fmt" "github.com/fastly/go-fastly/v9/fastly" - "github.com/fastly/terraform-provider-fastly/fastly/hashcode" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/fastly/terraform-provider-fastly/fastly/hashcode" ) func dataSourceFastlyTLSActivationIds() *schema.Resource { diff --git a/fastly/data_source_fastly_tls_subscription.go b/fastly/data_source_fastly_tls_subscription.go index e914680c9..d6c4526e8 100644 --- a/fastly/data_source_fastly_tls_subscription.go +++ b/fastly/data_source_fastly_tls_subscription.go @@ -4,9 +4,8 @@ import ( "context" "time" - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" - "github.com/fastly/go-fastly/v9/fastly" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) @@ -21,6 +20,12 @@ func dataSourceFastlyTLSSubscription() *schema.Resource { Description: "The entity that issues and certifies the TLS certificates for the subscription.", ConflictsWith: []string{"id"}, }, + "certificate_ids": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: "List of certificate IDs associated with the Subscription.", + }, "common_name": { Type: schema.TypeString, Computed: true, @@ -167,12 +172,21 @@ func listTLSSubscriptions(conn *fastly.Client, filters ...TLSSubscriptionPredica func dataSourceFastlyTLSSubscriptionSetAttributes(subscription *fastly.TLSSubscription, d *schema.ResourceData) error { d.SetId(subscription.ID) + var certIDs []string + for _, cert := range subscription.Certificates { + certIDs = append(certIDs, cert.ID) + } + var domains []string for _, domain := range subscription.Domains { domains = append(domains, domain.ID) } - err := d.Set("configuration_id", subscription.Configuration.ID) + err := d.Set("certificate_ids", certIDs) + if err != nil { + return err + } + err = d.Set("configuration_id", subscription.Configuration.ID) if err != nil { return err } diff --git a/fastly/resource_fastly_tls_mutual_authentication.go b/fastly/resource_fastly_tls_mutual_authentication.go index 138431a2f..8354d97a1 100644 --- a/fastly/resource_fastly_tls_mutual_authentication.go +++ b/fastly/resource_fastly_tls_mutual_authentication.go @@ -22,6 +22,14 @@ func resourceFastlyTLSMutualAuthentication() *schema.Resource { StateContext: schema.ImportStatePassthroughContext, }, Schema: map[string]*schema.Schema{ + "activation_ids": { + Type: schema.TypeSet, + Description: "List of TLS Activation IDs", + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, "cert_bundle": { Type: schema.TypeString, Description: "One or more certificates. Enter each individual certificate blob on a new line. Must be PEM-formatted.", @@ -40,7 +48,7 @@ func resourceFastlyTLSMutualAuthentication() *schema.Resource { }, "include": { Type: schema.TypeString, - Description: "Comma-separated list of related objects to include (e.g. `tls_activations` will provide you with the TLS domain names that are related to your Mutual TLS authentication).", + Description: "A comma-separated list used by the Terraform provider during a state refresh to return more data related to your mutual authentication from the Fastly API (permitted values: `tls_activations`).", Optional: true, }, "name": { @@ -69,25 +77,40 @@ func resourceFastlyTLSMutualAuthentication() *schema.Resource { func resourceFastlyTLSMutualAuthenticationCreate(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { conn := meta.(*APIClient).conn - input := &gofastly.CreateTLSMutualAuthenticationInput{ + inputCreate := &gofastly.CreateTLSMutualAuthenticationInput{ CertBundle: d.Get("cert_bundle").(string), } if v, ok := d.GetOk("enforced"); ok { - input.Enforced = v.(bool) + inputCreate.Enforced = v.(bool) } if v, ok := d.GetOk("name"); ok { - input.Name = v.(string) + inputCreate.Name = v.(string) } - log.Printf("[DEBUG] CREATE: TLS Mutual Authentication input: %#v", input) + log.Printf("[DEBUG] CREATE: TLS Mutual Authentication input: %#v", inputCreate) - output, err := conn.CreateTLSMutualAuthentication(input) + mTLS, err := conn.CreateTLSMutualAuthentication(inputCreate) if err != nil { return diag.FromErr(err) } - d.SetId(output.ID) + d.SetId(mTLS.ID) + + if v, ok := d.GetOk("activation_ids"); ok { + activationIDs := v.(*schema.Set).List() + for _, id := range activationIDs { + inputUpdate := &gofastly.UpdateTLSActivationInput{ + ID: id.(string), + MutualAuthentication: &gofastly.TLSMutualAuthentication{ID: mTLS.ID}, + } + log.Printf("[DEBUG] CREATE: Update TLS Activation input: %#v", inputUpdate) + _, err = conn.UpdateTLSActivation(inputUpdate) + if err != nil { + return diag.FromErr(err) + } + } + } return resourceFastlyTLSMutualAuthenticationRead(ctx, d, meta) } @@ -169,12 +192,55 @@ func resourceFastlyTLSMutualAuthenticationUpdate(_ context.Context, d *schema.Re if err != nil { return diag.FromErr(err) } + + if d.HasChange("activation_ids") { + // First unset mTLS from the old TLS Activations. + old, _ := d.GetChange("activation_ids") + for _, id := range old.(*schema.Set).List() { + input := &gofastly.UpdateTLSActivationInput{ + ID: id.(string), + MutualAuthentication: &gofastly.TLSMutualAuthentication{ID: ""}, + } + log.Printf("[DEBUG] UPDATE: TLS Activation input: %#v", input) + _, _ = conn.UpdateTLSActivation(input) + } + + // Once old Activations have mTLS unset, set mTLS on the new Activations. + for _, id := range d.Get("activation_ids").(*schema.Set).List() { + inputUpdate := &gofastly.UpdateTLSActivationInput{ + ID: id.(string), + MutualAuthentication: &gofastly.TLSMutualAuthentication{ID: d.Id()}, + } + log.Printf("[DEBUG] UPDATE: Update TLS Activation input: %#v", inputUpdate) + _, err = conn.UpdateTLSActivation(inputUpdate) + if err != nil { + return diag.FromErr(err) + } + } + } + return nil } func resourceFastlyTLSMutualAuthenticationDelete(_ context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { conn := meta.(*APIClient).conn + // IMPORTANT: You can't delete mTLS with active domains. + // You must first disable the active domains. + // To do that, you can set "" for the mTLS ID on each TLS Activation. + activationIDs := d.Get("activation_ids").(*schema.Set).List() + for _, id := range activationIDs { + input := &gofastly.UpdateTLSActivationInput{ + ID: id.(string), + MutualAuthentication: &gofastly.TLSMutualAuthentication{ID: ""}, + } + log.Printf("[DEBUG] DELETE: TLS Activation input: %#v", input) + _, err := conn.UpdateTLSActivation(input) + if err != nil { + return diag.FromErr(err) + } + } + input := &gofastly.DeleteTLSMutualAuthenticationInput{ ID: d.Id(), } diff --git a/fastly/resource_fastly_tls_mutual_authentication_test.go b/fastly/resource_fastly_tls_mutual_authentication_test.go index c74e1d6b5..581549b23 100644 --- a/fastly/resource_fastly_tls_mutual_authentication_test.go +++ b/fastly/resource_fastly_tls_mutual_authentication_test.go @@ -2,6 +2,7 @@ package fastly import ( "fmt" + "strings" "testing" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" @@ -9,54 +10,104 @@ import ( "github.com/stretchr/testify/require" ) -func TestAccFastlyMTLS_validate(t *testing.T) { - name := acctest.RandomWithPrefix(testResourcePrefix) - domain := fmt.Sprintf("%s.example.com", name) - - _, cert, err := generateKeyAndCert(domain) +func TestAccFastlyMTLS_basic(t *testing.T) { + domain := fmt.Sprintf("%s.com", acctest.RandomWithPrefix(testResourcePrefix)) + key, cert, cert2, err := generateKeyAndMultipleCerts(domain) + require.NoError(t, err) + _, mtlsCert, err := generateKeyAndCert(domain) require.NoError(t, err) + key = strings.ReplaceAll(key, "\n", `\n`) + cert = strings.ReplaceAll(cert, "\n", `\n`) + cert2 = strings.ReplaceAll(cert2, "\n", `\n`) - resourceName := "fastly_tls_mutual_authentication.test" + name := acctest.RandomWithPrefix(testResourcePrefix) + updatedName := acctest.RandomWithPrefix(testResourcePrefix) + resourceTLSActivationName := "fastly_tls_activation.test" + resourceMTLSName := "fastly_tls_mutual_authentication.test" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, ProviderFactories: testAccProviders, - CheckDestroy: testAccCheckServiceVCLDestroy, + CheckDestroy: testAccFastlyTLSActivationCheckDestroy, Steps: []resource.TestStep{ { - Config: testAccMTLSConfig(cert, name), + Config: testAccFastlyMTLSConfig(name, name, key, name, cert, domain, mtlsCert), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "name", name), - resource.TestCheckResourceAttr(resourceName, "enforced", "false"), + resource.TestCheckResourceAttrSet(resourceTLSActivationName, "certificate_id"), + resource.TestCheckResourceAttrSet(resourceTLSActivationName, "configuration_id"), + resource.TestCheckResourceAttr(resourceTLSActivationName, "domain", domain), + resource.TestCheckResourceAttrSet(resourceTLSActivationName, "created_at"), + testAccFastlyTLSActivationCheckExists(resourceTLSActivationName), + resource.TestCheckResourceAttr(resourceMTLSName, "name", "example_mtls"), + resource.TestCheckResourceAttr(resourceMTLSName, "enforced", "false"), ), }, { - Config: testAccMTLSConfig(cert, name+"updated"), + Config: testAccFastlyMTLSConfig(name, name, key, updatedName, cert2, domain, mtlsCert), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "name", name+"updated"), - resource.TestCheckResourceAttr(resourceName, "enforced", "false"), + testAccFastlyTLSActivationCheckExists(resourceTLSActivationName), + resource.TestCheckResourceAttr(resourceMTLSName, "name", "example_mtls"), + resource.TestCheckResourceAttr(resourceMTLSName, "enforced", "false"), ), }, { - ResourceName: "fastly_tls_mutual_authentication.test", + ResourceName: resourceTLSActivationName, + ImportState: true, + ImportStateVerify: true, + }, + { + ResourceName: resourceMTLSName, ImportState: true, ImportStateVerify: true, // These attributes are not stored on the Fastly API and must be ignored. - ImportStateVerifyIgnore: []string{"cert_bundle"}, + ImportStateVerifyIgnore: []string{"cert_bundle", "activation_id"}, }, }, }) } -func testAccMTLSConfig(cert, name string) string { +func testAccFastlyMTLSConfig(serviceName, keyName, key, certName, cert, domain, certBundle string) string { return fmt.Sprintf(` +resource "fastly_service_vcl" "test" { + name = "%s" + + domain { + name = "%s" + } + + backend { + address = "127.0.0.1" + name = "localhost" + } + + force_destroy = true +} + +resource "fastly_tls_private_key" "test" { + key_pem = "%s" + name = "%s" +} + +resource "fastly_tls_certificate" "test" { + certificate_body = "%s" + name = "%s" + depends_on = [fastly_tls_private_key.test] +} + +resource "fastly_tls_activation" "test" { + certificate_id = fastly_tls_certificate.test.id + domain = "%s" + depends_on = [fastly_service_vcl.test] +} + resource "fastly_tls_mutual_authentication" "test" { + activation_ids = [fastly_tls_activation.test.id] cert_bundle = <