Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add validation_domain parameter to aws_acm_certificate #3853

Merged
merged 14 commits into from
Apr 26, 2022
150 changes: 108 additions & 42 deletions aws/resource_aws_acm_certificate.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,45 @@ func resourceAwsAcmCertificate() *schema.Resource {
Required: true,
ForceNew: true,
},
"domain_validation_options": {
Type: schema.TypeList,
Optional: true,
ForceNew: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"domain_name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"validation_domain": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"resource_record_name": {
Type: schema.TypeString,
Computed: true,
Deprecated: "Use `certificate_details[0].resource_record_name` instead",
},
"resource_record_type": {
Type: schema.TypeString,
Computed: true,
Deprecated: "Use `certificate_details[0].resource_record_type` instead",
},
"resource_record_value": {
Type: schema.TypeString,
Computed: true,
Deprecated: "Use `certificate_details[0].resource_record_value` instead",
},
},
},
},
"arn": {
Type: schema.TypeString,
Computed: true,
},
"domain_validation_options": {
ewbankkit marked this conversation as resolved.
Show resolved Hide resolved
"certificate_details": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Expand All @@ -63,23 +97,38 @@ func resourceAwsAcmCertificate() *schema.Resource {
Type: schema.TypeString,
Computed: true,
},
"validation_domain": {
Type: schema.TypeString,
Computed: true,
},
"validation_method": {
Type: schema.TypeString,
Computed: true,
},
"validation_emails": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
},
},
},
"tags": tagsSchema(),
"validation_emails": {
ewbankkit marked this conversation as resolved.
Show resolved Hide resolved
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
Deprecated: "Use `certificate_details[0].validation_emails` instead",
},
"tags": tagsSchema(),
},
}
}

func resourceAwsAcmCertificateCreate(d *schema.ResourceData, meta interface{}) error {
acmconn := meta.(*AWSClient).acmconn
domainName := d.Get("domain_name").(string)
params := &acm.RequestCertificateInput{
DomainName: aws.String(d.Get("domain_name").(string)),
DomainName: aws.String(domainName),
ValidationMethod: aws.String(d.Get("validation_method").(string)),
}

Expand All @@ -89,6 +138,23 @@ func resourceAwsAcmCertificateCreate(d *schema.ResourceData, meta interface{}) e
params.SubjectAlternativeNames = expandStringList(sanStrings)
}

domainValidationOptionsInput, ok := d.GetOk("domain_validation_options")

if ok {
var domainValidationOptions []*acm.DomainValidationOption
for _, o := range domainValidationOptionsInput.([]interface{}) {
x := o.(map[string]interface{})
dn := x["domain_name"].(string)
vd := x["validation_domain"].(string)
domainValidationOption := &acm.DomainValidationOption{
DomainName: &dn,
ValidationDomain: &vd,
}
domainValidationOptions = append(domainValidationOptions, domainValidationOption)
}
params.SetDomainValidationOptions(domainValidationOptions)
}

log.Printf("[DEBUG] ACM Certificate Request: %#v", params)
resp, err := acmconn.RequestCertificate(params)

Expand Down Expand Up @@ -137,19 +203,21 @@ func resourceAwsAcmCertificateRead(d *schema.ResourceData, meta interface{}) err
return resource.NonRetryableError(err)
}

domainValidationOptions, emailValidationOptions, err := convertValidationOptions(resp.Certificate)
certificateDetails, err := convertCertificateDetails(resp.Certificate)

if len(certificateDetails) < 1 {
return resource.NonRetryableError(fmt.Errorf("Error getting certificate details"))
}

if err != nil {
return resource.RetryableError(err)
}

if err := d.Set("domain_validation_options", domainValidationOptions); err != nil {
ewbankkit marked this conversation as resolved.
Show resolved Hide resolved
if err := d.Set("certificate_details", certificateDetails); err != nil {
return resource.NonRetryableError(err)
}
if err := d.Set("validation_emails", emailValidationOptions); err != nil {
ewbankkit marked this conversation as resolved.
Show resolved Hide resolved
return resource.NonRetryableError(err)
}
d.Set("validation_method", resourceAwsAcmCertificateGuessValidationMethod(domainValidationOptions, emailValidationOptions))

d.Set("validation_method", certificateDetails[0]["validation_method"])

params := &acm.ListTagsForCertificateInput{
CertificateArn: aws.String(d.Id()),
Expand All @@ -163,17 +231,6 @@ func resourceAwsAcmCertificateRead(d *schema.ResourceData, meta interface{}) err
return nil
})
}
func resourceAwsAcmCertificateGuessValidationMethod(domainValidationOptions []map[string]interface{}, emailValidationOptions []string) string {
// The DescribeCertificate Response doesn't have information on what validation method was used
// so we need to guess from the validation options we see...
if len(domainValidationOptions) > 0 {
return acm.ValidationMethodDns
} else if len(emailValidationOptions) > 0 {
return acm.ValidationMethodEmail
} else {
return "NONE"
}
}

func resourceAwsAcmCertificateUpdate(d *schema.ResourceData, meta interface{}) error {
if d.HasChange("tags") {
Expand All @@ -198,32 +255,41 @@ func cleanUpSubjectAlternativeNames(cert *acm.CertificateDetail) []string {

}

func convertValidationOptions(certificate *acm.CertificateDetail) ([]map[string]interface{}, []string, error) {
var domainValidationResult []map[string]interface{}
var emailValidationResult []string
func convertCertificateDetails(certificate *acm.CertificateDetail) ([]map[string]interface{}, error) {
var certificateDetails []map[string]interface{}

if *certificate.Type == acm.CertificateTypeAmazonIssued {
for _, o := range certificate.DomainValidationOptions {
var resourceRecordName interface{}
var resourceRecordType interface{}
var resourceRecordValue interface{}
var validationMethod interface{}
if o.ResourceRecord != nil {
validationOption := map[string]interface{}{
"domain_name": *o.DomainName,
"resource_record_name": *o.ResourceRecord.Name,
"resource_record_type": *o.ResourceRecord.Type,
"resource_record_value": *o.ResourceRecord.Value,
}
domainValidationResult = append(domainValidationResult, validationOption)
} else if o.ValidationEmails != nil && len(o.ValidationEmails) > 0 {
for _, validationEmail := range o.ValidationEmails {
emailValidationResult = append(emailValidationResult, *validationEmail)
}
} else {
log.Printf("[DEBUG] No validation options need to retry: %#v", o)
return nil, nil, fmt.Errorf("No validation options need to retry: %#v", o)
resourceRecordName = *o.ResourceRecord.Name
resourceRecordType = *o.ResourceRecord.Type
resourceRecordValue = *o.ResourceRecord.Value
}
if o.ValidationMethod != nil {
validationMethod = *o.ValidationMethod
}

var validationEmails []string
for _, email := range o.ValidationEmails {
validationEmails = append(validationEmails, *email)
}
validationOption := map[string]interface{}{
"domain_name": *o.DomainName,
"validation_domain": *o.ValidationDomain,
"resource_record_name": resourceRecordName,
"resource_record_type": resourceRecordType,
"resource_record_value": resourceRecordValue,
"validation_emails": validationEmails,
"validation_method": validationMethod,
}
certificateDetails = append(certificateDetails, validationOption)
}
}

return domainValidationResult, emailValidationResult, nil
return certificateDetails, nil
}

func resourceAwsAcmCertificateDelete(d *schema.ResourceData, meta interface{}) error {
Expand Down