Skip to content

Commit

Permalink
[bug] fix fastly_tls_subscription resource to properly handle challen…
Browse files Browse the repository at this point in the history
…ges for multi-SAN (#435)

* fix fastly_tls_subscription resource to properly handle DNS challenges for multi-SAN

* doc update

* Update route53 example snippet

* update doc

* leave managed_dns_challenge attribute for backward compatibility

* Update fastly/resource_fastly_tls_subscription.go

* Set Deprecated field instead

* fix message

Co-authored-by: Mark McDonnell <Integralist@users.noreply.github.com>
  • Loading branch information
smaeda-ks and Integralist committed Jul 20, 2021
1 parent a8d4356 commit d810875
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 32 deletions.
28 changes: 20 additions & 8 deletions docs/resources/tls_subscription.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Enables TLS on a domain using a certificate managed by Fastly.

DNS records need to be modified on the domain being secured, in order to respond to the ACME domain ownership challenge.

There are two options for doing this: the `managed_dns_challenge`, which is the default method; and the `managed_http_challenges`, which points production traffic to Fastly.
There are two options for doing this: the `managed_dns_challenges`, which is the default method; and the `managed_http_challenges`, which points production traffic to Fastly.

~> See the [Fastly documentation](https://docs.fastly.com/en/guides/serving-https-traffic-using-fastly-managed-certificates#verifying-domain-ownership) for more information on verifying domain ownership.

Expand Down Expand Up @@ -78,11 +78,12 @@ data "aws_route53_zone" "demo" {
# Set up DNS record for managed DNS domain validation method
resource "aws_route53_record" "domain_validation" {
name = fastly_tls_subscription.example.managed_dns_challenge.record_name
type = fastly_tls_subscription.example.managed_dns_challenge.record_type
for_each = { for domain in fastly_tls_subscription.example.managed_dns_challenges : domain.record_name => domain }
name = each.value.record_name
type = each.value.record_type
zone_id = data.aws_route53_zone.demo.id
allow_overwrite = true
records = [fastly_tls_subscription.example.managed_dns_challenge.record_value]
records = [each.value.record_value]
ttl = 60
}
Expand Down Expand Up @@ -112,14 +113,14 @@ In addition to the arguments listed above, the following attributes are exported
* `created_at` - Timestamp (GMT) when the subscription was created.
* `updated_at` - Timestamp (GMT) when the subscription was last updated.
* `state` - The current state of the subscription. The list of possible states are: `pending`, `processing`, `issued`, and `renewing`.
* `managed_dns_challenge` - The details required to configure DNS to respond to ACME DNS challenge in order to verify domain ownership. See Managed DNS Challenge below for details.
* `managed_dns_challenges` - A list of options for configuring DNS to respond to ACME DNS challenge in order to verify domain ownership. See Managed DNS Challenge below for details.
* `managed_http_challenges` - A list of options for configuring DNS to respond to ACME HTTP challenge in order to verify domain ownership. See Managed HTTP Challenges below for details.

### Managed DNS Challenge

The available attributes in the `managed_dns_challenge` block are:
The available attributes in the `managed_dns_challenges` block are:

* `record_name` - The name of the DNS record to add. For example `_acme-challenge.example.com`. Accessed like this, `fastly_tls_subscription.tls.managed_dns_challenge.record_name`.
* `record_name` - The name of the DNS record to add. For example `_acme-challenge.example.com`. Accessed like this, `fastly_tls_subscription.tls.managed_dns_challenges.record_name`.
* `record_type` - The type of DNS record to add, e.g. `A`, or `CNAME`.
* `record_value` - The value to which the DNS record should point, e.g. `xxxxx.fastly-validations.com`.

Expand Down Expand Up @@ -160,11 +161,22 @@ $ terraform import fastly_tls_subscription.demo xxxxxxxxxxx
### Read-Only

- **created_at** (String) Timestamp (GMT) when the subscription was created.
- **managed_dns_challenge** (Map of String) The details required to configure DNS to respond to ACME DNS challenge in order to verify domain ownership.
- **managed_dns_challenge** (Map of String, Deprecated) The details required to configure DNS to respond to ACME DNS challenge in order to verify domain ownership.
- **managed_dns_challenges** (Set of Object) A list of options for configuring DNS to respond to ACME DNS challenge in order to verify domain ownership. (see [below for nested schema](#nestedatt--managed_dns_challenges))
- **managed_http_challenges** (Set of Object) A list of options for configuring DNS to respond to ACME HTTP challenge in order to verify domain ownership. Best accessed through a `for` expression to filter the relevant record. (see [below for nested schema](#nestedatt--managed_http_challenges))
- **state** (String) The current state of the subscription. The list of possible states are: `pending`, `processing`, `issued`, and `renewing`.
- **updated_at** (String) Timestamp (GMT) when the subscription was updated.

<a id="nestedatt--managed_dns_challenges"></a>
### Nested Schema for `managed_dns_challenges`

Read-Only:

- **record_name** (String)
- **record_type** (String)
- **record_value** (String)


<a id="nestedatt--managed_http_challenges"></a>
### Nested Schema for `managed_http_challenges`

Expand Down
88 changes: 71 additions & 17 deletions fastly/resource_fastly_tls_subscription.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ package fastly

import (
"context"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"time"

"github.com/fastly/go-fastly/v3/fastly"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
Expand Down Expand Up @@ -73,6 +73,31 @@ func resourceFastlyTLSSubscription() *schema.Resource {
Description: "The details required to configure DNS to respond to ACME DNS challenge in order to verify domain ownership.",
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
Deprecated: "Use 'managed_dns_challenges' attribute instead",
},
"managed_dns_challenges": {
Type: schema.TypeSet,
Description: "A list of options for configuring DNS to respond to ACME DNS challenge in order to verify domain ownership.",
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"record_name": {
Type: schema.TypeString,
Description: "The name of the DNS record to add. For example `_acme-challenge.example.com`.",
Computed: true,
},
"record_type": {
Type: schema.TypeString,
Description: "The type of DNS record to add, e.g. `A`, or `CNAME`.",
Computed: true,
},
"record_value": {
Type: schema.TypeString,
Description: "The value to which the DNS record should point, e.g. `xxxxx.fastly-validations.com`.",
Computed: true,
},
},
},
},
"managed_http_challenges": {
Type: schema.TypeSet,
Expand Down Expand Up @@ -172,24 +197,53 @@ func resourceFastlyTLSSubscriptionRead(_ context.Context, d *schema.ResourceData
}

var managedHTTPChallenges []map[string]interface{}
var managedDNSChallenge map[string]string
for _, challenge := range subscription.Authorizations[0].Challenges {
if challenge.Type == "managed-dns" {
if len(challenge.Values) < 1 {
return diag.Errorf("Fastly API returned no record values for Managed DNS Challenge")
var managedDNSChallenges []map[string]interface{}
for _, domain := range subscription.Authorizations {
for _, challenge := range domain.Challenges {
if challenge.Type == "managed-dns" {
if len(challenge.Values) < 1 {
return diag.Errorf("Fastly API returned no record values for Managed DNS Challenges")
}

managedDNSChallenges = append(managedDNSChallenges, map[string]interface{}{
"record_type": challenge.RecordType,
"record_name": challenge.RecordName,
"record_value": challenge.Values[0],
})
} else {
managedHTTPChallenges = append(managedHTTPChallenges, map[string]interface{}{
"record_type": challenge.RecordType,
"record_name": challenge.RecordName,
"record_values": challenge.Values,
})
}
}
}

managedDNSChallenge = map[string]string{
"record_type": challenge.RecordType,
"record_name": challenge.RecordName,
"record_value": challenge.Values[0],
// TODO: This block of code contains a bug where the state file will only include
// the first domain's challenge data in the case of multi-SAN cert subscriptions.
// Users should use the new "managed_dns_challenges" attribute instead.
// We're leaving this for backward compatibility but is planned to be removed in v1.0.0.
// https://github.com/fastly/terraform-provider-fastly/pull/435
{
var managedDNSChallengeOld map[string]string
for _, challenge := range subscription.Authorizations[0].Challenges {
if challenge.Type == "managed-dns" {
if len(challenge.Values) < 1 {
return diag.Errorf("Fastly API returned no record values for Managed DNS Challenge")
}

managedDNSChallengeOld = map[string]string{
"record_type": challenge.RecordType,
"record_name": challenge.RecordName,
"record_value": challenge.Values[0],
}
}
} else {
managedHTTPChallenges = append(managedHTTPChallenges, map[string]interface{}{
"record_type": challenge.RecordType,
"record_name": challenge.RecordName,
"record_values": challenge.Values,
})
}

err = d.Set("managed_dns_challenge", managedDNSChallengeOld)
if err != nil {
return diag.FromErr(err)
}
}

Expand Down Expand Up @@ -221,7 +275,7 @@ func resourceFastlyTLSSubscriptionRead(_ context.Context, d *schema.ResourceData
if err != nil {
return diag.FromErr(err)
}
err = d.Set("managed_dns_challenge", managedDNSChallenge)
err = d.Set("managed_dns_challenges", managedDNSChallenges)
if err != nil {
return diag.FromErr(err)
}
Expand Down
15 changes: 8 additions & 7 deletions templates/resources/tls_subscription.md.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Enables TLS on a domain using a certificate managed by Fastly.

DNS records need to be modified on the domain being secured, in order to respond to the ACME domain ownership challenge.

There are two options for doing this: the `managed_dns_challenge`, which is the default method; and the `managed_http_challenges`, which points production traffic to Fastly.
There are two options for doing this: the `managed_dns_challenges`, which is the default method; and the `managed_http_challenges`, which points production traffic to Fastly.

~> See the [Fastly documentation](https://docs.fastly.com/en/guides/serving-https-traffic-using-fastly-managed-certificates#verifying-domain-ownership) for more information on verifying domain ownership.

Expand Down Expand Up @@ -78,11 +78,12 @@ data "aws_route53_zone" "demo" {

# Set up DNS record for managed DNS domain validation method
resource "aws_route53_record" "domain_validation" {
name = fastly_tls_subscription.example.managed_dns_challenge.record_name
type = fastly_tls_subscription.example.managed_dns_challenge.record_type
for_each = { for domain in fastly_tls_subscription.example.managed_dns_challenges : domain.record_name => domain }
name = each.value.record_name
type = each.value.record_type
zone_id = data.aws_route53_zone.demo.id
allow_overwrite = true
records = [fastly_tls_subscription.example.managed_dns_challenge.record_value]
records = [each.value.record_value]
ttl = 60
}

Expand Down Expand Up @@ -112,14 +113,14 @@ In addition to the arguments listed above, the following attributes are exported
* `created_at` - Timestamp (GMT) when the subscription was created.
* `updated_at` - Timestamp (GMT) when the subscription was last updated.
* `state` - The current state of the subscription. The list of possible states are: `pending`, `processing`, `issued`, and `renewing`.
* `managed_dns_challenge` - The details required to configure DNS to respond to ACME DNS challenge in order to verify domain ownership. See Managed DNS Challenge below for details.
* `managed_dns_challenges` - A list of options for configuring DNS to respond to ACME DNS challenge in order to verify domain ownership. See Managed DNS Challenge below for details.
* `managed_http_challenges` - A list of options for configuring DNS to respond to ACME HTTP challenge in order to verify domain ownership. See Managed HTTP Challenges below for details.

### Managed DNS Challenge

The available attributes in the `managed_dns_challenge` block are:
The available attributes in the `managed_dns_challenges` block are:

* `record_name` - The name of the DNS record to add. For example `_acme-challenge.example.com`. Accessed like this, `fastly_tls_subscription.tls.managed_dns_challenge.record_name`.
* `record_name` - The name of the DNS record to add. For example `_acme-challenge.example.com`. Accessed like this, `fastly_tls_subscription.tls.managed_dns_challenges.record_name`.
* `record_type` - The type of DNS record to add, e.g. `A`, or `CNAME`.
* `record_value` - The value to which the DNS record should point, e.g. `xxxxx.fastly-validations.com`.

Expand Down

0 comments on commit d810875

Please sign in to comment.