diff --git a/.changelog/20073.txt b/.changelog/20073.txt
new file mode 100644
index 000000000000..f4e6c9021684
--- /dev/null
+++ b/.changelog/20073.txt
@@ -0,0 +1,7 @@
+```release-note:bug
+resource/aws_acm_certificate: Correctly handle SAN entries that match `domain_name`
+```
+
+```release-note:enhancement
+resource/aws_acm_certificate_validation: Increase default resource Create (certificate issuance) timeout to 75 minutes
+```
diff --git a/internal/service/acm/certificate.go b/internal/service/acm/certificate.go
index 1e31986c1444..65ff3826f80e 100644
--- a/internal/service/acm/certificate.go
+++ b/internal/service/acm/certificate.go
@@ -8,6 +8,7 @@ import (
 	"fmt"
 	"log"
 	"regexp"
+	"strconv"
 	"strings"
 	"time"
 
@@ -33,6 +34,8 @@ const (
 	// Maximum amount of time for ACM Certificate asynchronous DNS validation record assignment.
 	// This timeout is unrelated to any creation or validation of those assigned DNS records.
 	AcmCertificateDnsValidationAssignmentTimeout = 5 * time.Minute
+
+	certificateValidationMethodNone = "NONE"
 )
 
 func ResourceCertificate() *schema.Resource {
@@ -41,27 +44,33 @@ func ResourceCertificate() *schema.Resource {
 		Read:   resourceCertificateRead,
 		Update: resourceCertificateUpdate,
 		Delete: resourceCertificateDelete,
+
 		Importer: &schema.ResourceImporter{
 			State: schema.ImportStatePassthrough,
 		},
+
 		Schema: map[string]*schema.Schema{
-			"certificate_body": {
+			"arn": {
 				Type:     schema.TypeString,
-				Optional: true,
+				Computed: true,
 			},
-			"certificate_chain": {
-				Type:     schema.TypeString,
-				Optional: true,
+			"certificate_authority_arn": {
+				Type:          schema.TypeString,
+				Optional:      true,
+				ForceNew:      true,
+				ValidateFunc:  verify.ValidARN,
+				ConflictsWith: []string{"certificate_body", "private_key", "validation_method"},
 			},
-			"private_key": {
-				Type:      schema.TypeString,
-				Optional:  true,
-				Sensitive: true,
+			"certificate_body": {
+				Type:          schema.TypeString,
+				Optional:      true,
+				RequiredWith:  []string{"private_key"},
+				ConflictsWith: []string{"certificate_authority_arn", "domain_name", "validation_method"},
 			},
-			"certificate_authority_arn": {
-				Type:     schema.TypeString,
-				Optional: true,
-				ForceNew: true,
+			"certificate_chain": {
+				Type:          schema.TypeString,
+				Optional:      true,
+				ConflictsWith: []string{"certificate_authority_arn", "domain_name", "validation_method"},
 			},
 			"domain_name": {
 				// AWS Provider 3.0.0 aws_route53_zone references no longer contain a
@@ -71,37 +80,9 @@ func ResourceCertificate() *schema.Resource {
 				Optional:      true,
 				Computed:      true,
 				ForceNew:      true,
-				ConflictsWith: []string{"private_key", "certificate_body", "certificate_chain"},
 				ValidateFunc:  validation.StringDoesNotMatch(regexp.MustCompile(`\.$`), "cannot end with a period"),
-			},
-			"subject_alternative_names": {
-				Type:     schema.TypeSet,
-				Optional: true,
-				Computed: true,
-				ForceNew: true,
-				Elem: &schema.Schema{
-					// AWS Provider 3.0.0 aws_route53_zone references no longer contain a
-					// trailing period, no longer requiring a custom StateFunc
-					// to prevent ACM API error
-					Type: schema.TypeString,
-					ValidateFunc: validation.All(
-						validation.StringLenBetween(1, 253),
-						validation.StringDoesNotMatch(regexp.MustCompile(`\.$`), "cannot end with a period"),
-					),
-				},
-				Set:           schema.HashString,
-				ConflictsWith: []string{"private_key", "certificate_body", "certificate_chain"},
-			},
-			"validation_method": {
-				Type:          schema.TypeString,
-				Optional:      true,
-				Computed:      true,
-				ForceNew:      true,
-				ConflictsWith: []string{"private_key", "certificate_body", "certificate_chain", "certificate_authority_arn"},
-			},
-			"arn": {
-				Type:     schema.TypeString,
-				Computed: true,
+				ExactlyOneOf:  []string{"domain_name", "private_key"},
+				ConflictsWith: []string{"certificate_body", "certificate_chain", "private_key"},
 			},
 			"domain_validation_options": {
 				Type:     schema.TypeSet,
@@ -128,51 +109,80 @@ func ResourceCertificate() *schema.Resource {
 				},
 				Set: acmDomainValidationOptionsHash,
 			},
-			"validation_emails": {
-				Type:     schema.TypeList,
-				Computed: true,
-				Elem:     &schema.Schema{Type: schema.TypeString},
-			},
 			"options": {
 				Type:     schema.TypeList,
 				Optional: true,
 				MaxItems: 1,
-				DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool {
-					if _, ok := d.GetOk("private_key"); ok {
-						// ignore diffs for imported certs; they have a different logging preference
-						// default to requested certs which can't be changed by the ImportCertificate API
-						return true
-					}
-					// behave just like verify.SuppressMissingOptionalConfigurationBlock() for requested certs
-					return old == "1" && new == "0"
-				},
 				Elem: &schema.Resource{
 					Schema: map[string]*schema.Schema{
 						"certificate_transparency_logging_preference": {
 							Type:          schema.TypeString,
 							Optional:      true,
-							Default:       acm.CertificateTransparencyLoggingPreferenceEnabled,
 							ForceNew:      true,
-							ConflictsWith: []string{"private_key", "certificate_body", "certificate_chain"},
-							ValidateFunc: validation.StringInSlice([]string{
-								acm.CertificateTransparencyLoggingPreferenceEnabled,
-								acm.CertificateTransparencyLoggingPreferenceDisabled,
-							}, false),
+							Default:       acm.CertificateTransparencyLoggingPreferenceEnabled,
+							ValidateFunc:  validation.StringInSlice(acm.CertificateTransparencyLoggingPreference_Values(), false),
+							ConflictsWith: []string{"certificate_body", "certificate_chain", "private_key"},
 						},
 					},
 				},
+				DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool {
+					if _, ok := d.GetOk("private_key"); ok {
+						// ignore diffs for imported certs; they have a different logging preference
+						// default to requested certs which can't be changed by the ImportCertificate API
+						return true
+					}
+					// behave just like verify.SuppressMissingOptionalConfigurationBlock() for requested certs
+					return old == "1" && new == "0"
+				},
+			},
+			"private_key": {
+				Type:         schema.TypeString,
+				Optional:     true,
+				Sensitive:    true,
+				ExactlyOneOf: []string{"domain_name", "private_key"},
 			},
 			"status": {
 				Type:     schema.TypeString,
 				Computed: true,
 			},
+			"subject_alternative_names": {
+				Type:     schema.TypeSet,
+				Optional: true,
+				Computed: true,
+				ForceNew: true,
+				Elem: &schema.Schema{
+					// AWS Provider 3.0.0 aws_route53_zone references no longer contain a
+					// trailing period, no longer requiring a custom StateFunc
+					// to prevent ACM API error
+					Type: schema.TypeString,
+					ValidateFunc: validation.All(
+						validation.StringLenBetween(1, 253),
+						validation.StringDoesNotMatch(regexp.MustCompile(`\.$`), "cannot end with a period"),
+					),
+				},
+				ConflictsWith: []string{"certificate_body", "certificate_chain", "private_key"},
+			},
 			"tags":     tftags.TagsSchema(),
 			"tags_all": tftags.TagsSchemaComputed(),
+			"validation_emails": {
+				Type:     schema.TypeList,
+				Computed: true,
+				Elem:     &schema.Schema{Type: schema.TypeString},
+			},
+			"validation_method": {
+				Type:          schema.TypeString,
+				Optional:      true,
+				Computed:      true,
+				ForceNew:      true,
+				ValidateFunc:  validation.StringInSlice(append(acm.ValidationMethod_Values(), certificateValidationMethodNone), false),
+				ConflictsWith: []string{"certificate_authority_arn", "certificate_body", "certificate_chain", "private_key"},
+			},
 		},
+
 		CustomizeDiff: customdiff.Sequence(
 			func(_ context.Context, diff *schema.ResourceDiff, v interface{}) error {
 				// Attempt to calculate the domain validation options based on domains present in domain_name and subject_alternative_names
-				if diff.Get("validation_method").(string) == "DNS" && (diff.HasChange("domain_name") || diff.HasChange("subject_alternative_names")) {
+				if diff.Get("validation_method").(string) == acm.ValidationMethodDns && (diff.HasChange("domain_name") || diff.HasChange("subject_alternative_names")) {
 					domainValidationOptionsList := []interface{}{map[string]interface{}{
 						// AWS Provider 3.0 -- plan-time validation prevents "domain_name"
 						// argument to accept a string with trailing period; thus, trim of trailing period
@@ -204,6 +214,19 @@ func ResourceCertificate() *schema.Resource {
 					}
 				}
 
+				// ACM automatically adds the domain_name value to the list of SANs. Mimic ACM's behavior
+				// so that the user doesn't need to explicitly set it themselves.
+				if diff.HasChange("domain_name") || diff.HasChange("subject_alternative_names") {
+					domain_name := diff.Get("domain_name").(string)
+
+					if sanSet, ok := diff.Get("subject_alternative_names").(*schema.Set); ok {
+						sanSet.Add(domain_name)
+						if err := diff.SetNew("subject_alternative_names", sanSet); err != nil {
+							return fmt.Errorf("error setting new subject_alternative_names diff: %w", err)
+						}
+					}
+				}
+
 				return nil
 			},
 			verify.SetTagsDiff,
@@ -212,92 +235,80 @@ func ResourceCertificate() *schema.Resource {
 }
 
 func resourceCertificateCreate(d *schema.ResourceData, meta interface{}) error {
-	if _, ok := d.GetOk("domain_name"); ok {
-		if _, ok := d.GetOk("certificate_authority_arn"); ok {
-			return resourceCertificateCreateRequested(d, meta)
-		}
-
-		if _, ok := d.GetOk("validation_method"); !ok {
-			return errors.New("validation_method must be set when creating a certificate")
-		}
-		return resourceCertificateCreateRequested(d, meta)
-	} else if _, ok := d.GetOk("private_key"); ok {
-		if _, ok := d.GetOk("certificate_body"); !ok {
-			return errors.New("certificate_body must be set when importing a certificate with private_key")
-		}
-		return resourceCertificateCreateImported(d, meta)
-	}
-	return errors.New("certificate must be imported (private_key) or created (domain_name)")
-}
-
-func resourceCertificateCreateImported(d *schema.ResourceData, meta interface{}) error {
 	conn := meta.(*conns.AWSClient).ACMConn
 	defaultTagsConfig := meta.(*conns.AWSClient).DefaultTagsConfig
 	tags := defaultTagsConfig.MergeTags(tftags.New(d.Get("tags").(map[string]interface{})))
 
-	input := &acm.ImportCertificateInput{
-		Certificate: []byte(d.Get("certificate_body").(string)),
-		PrivateKey:  []byte(d.Get("private_key").(string)),
-	}
+	if _, ok := d.GetOk("domain_name"); ok {
+		_, v1 := d.GetOk("certificate_authority_arn")
+		_, v2 := d.GetOk("validation_method")
 
-	if v, ok := d.GetOk("certificate_chain"); ok {
-		input.CertificateChain = []byte(v.(string))
-	}
+		if !v1 && !v2 {
+			return errors.New("`certificate_authority_arn` or `validation_method` must be set when creating an ACM certificate")
+		}
 
-	if len(tags) > 0 {
-		input.Tags = Tags(tags.IgnoreAWS())
-	}
+		domainName := d.Get("domain_name").(string)
+		input := &acm.RequestCertificateInput{
+			DomainName:       aws.String(domainName),
+			IdempotencyToken: aws.String(resource.PrefixedUniqueId("tf")), // 32 character limit
+		}
 
-	output, err := conn.ImportCertificate(input)
+		if v, ok := d.GetOk("certificate_authority_arn"); ok {
+			input.CertificateAuthorityArn = aws.String(v.(string))
+		}
 
-	if err != nil {
-		return fmt.Errorf("error importing ACM Certificate: %w", err)
-	}
+		if v, ok := d.GetOk("options"); ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil {
+			input.Options = expandCertificateOptions(v.([]interface{})[0].(map[string]interface{}))
+		}
 
-	d.SetId(aws.StringValue(output.CertificateArn))
+		if v, ok := d.GetOk("subject_alternative_names"); ok {
+			for _, v := range v.(*schema.Set).List() {
+				input.SubjectAlternativeNames = append(input.SubjectAlternativeNames, aws.String(v.(string)))
+			}
+		}
 
-	return resourceCertificateRead(d, meta)
-}
+		if v, ok := d.GetOk("validation_method"); ok {
+			input.ValidationMethod = aws.String(v.(string))
+		}
 
-func resourceCertificateCreateRequested(d *schema.ResourceData, meta interface{}) error {
-	conn := meta.(*conns.AWSClient).ACMConn
-	defaultTagsConfig := meta.(*conns.AWSClient).DefaultTagsConfig
-	tags := defaultTagsConfig.MergeTags(tftags.New(d.Get("tags").(map[string]interface{})))
+		if len(tags) > 0 {
+			input.Tags = Tags(tags.IgnoreAWS())
+		}
 
-	params := &acm.RequestCertificateInput{
-		DomainName:       aws.String(d.Get("domain_name").(string)),
-		IdempotencyToken: aws.String(resource.PrefixedUniqueId("tf")), // 32 character limit
-		Options:          expandAcmCertificateOptions(d.Get("options").([]interface{})),
-	}
+		log.Printf("[DEBUG] Requesting ACM Certificate: %s", input)
+		output, err := conn.RequestCertificate(input)
 
-	if len(tags) > 0 {
-		params.Tags = Tags(tags.IgnoreAWS())
-	}
+		if err != nil {
+			return fmt.Errorf("requesting ACM Certificate (%s): %w", domainName, err)
+		}
 
-	if caARN, ok := d.GetOk("certificate_authority_arn"); ok {
-		params.CertificateAuthorityArn = aws.String(caARN.(string))
-	}
+		d.SetId(aws.StringValue(output.CertificateArn))
+	} else {
+		input := &acm.ImportCertificateInput{
+			Certificate: []byte(d.Get("certificate_body").(string)),
+			PrivateKey:  []byte(d.Get("private_key").(string)),
+		}
 
-	if sans, ok := d.GetOk("subject_alternative_names"); ok {
-		subjectAlternativeNames := make([]*string, len(sans.(*schema.Set).List()))
-		for i, sanRaw := range sans.(*schema.Set).List() {
-			subjectAlternativeNames[i] = aws.String(sanRaw.(string))
+		if v, ok := d.GetOk("certificate_chain"); ok {
+			input.CertificateChain = []byte(v.(string))
 		}
-		params.SubjectAlternativeNames = subjectAlternativeNames
-	}
 
-	if v, ok := d.GetOk("validation_method"); ok {
-		params.ValidationMethod = aws.String(v.(string))
-	}
+		if len(tags) > 0 {
+			input.Tags = Tags(tags.IgnoreAWS())
+		}
 
-	log.Printf("[DEBUG] ACM Certificate Request: %#v", params)
-	resp, err := conn.RequestCertificate(params)
+		output, err := conn.ImportCertificate(input)
 
-	if err != nil {
-		return fmt.Errorf("Error requesting certificate: %s", err)
+		if err != nil {
+			return fmt.Errorf("importing ACM Certificate: %w", err)
+		}
+
+		d.SetId(aws.StringValue(output.CertificateArn))
 	}
 
-	d.SetId(aws.StringValue(resp.CertificateArn))
+	if _, err := waitCertificateDomainValidationsAvailable(conn, d.Id(), AcmCertificateDnsValidationAssignmentTimeout); err != nil {
+		return fmt.Errorf("waiting for ACM Certificate (%s) to be issued: %w", d.Id(), err)
+	}
 
 	return resourceCertificateRead(d, meta)
 }
@@ -307,93 +318,56 @@ func resourceCertificateRead(d *schema.ResourceData, meta interface{}) error {
 	defaultTagsConfig := meta.(*conns.AWSClient).DefaultTagsConfig
 	ignoreTagsConfig := meta.(*conns.AWSClient).IgnoreTagsConfig
 
-	params := &acm.DescribeCertificateInput{
-		CertificateArn: aws.String(d.Id()),
-	}
-
-	return resource.Retry(AcmCertificateDnsValidationAssignmentTimeout, func() *resource.RetryError {
-		resp, err := conn.DescribeCertificate(params)
-
-		if !d.IsNewResource() && tfawserr.ErrCodeEquals(err, acm.ErrCodeResourceNotFoundException) {
-			log.Printf("[WARN] ACM Certificate (%s) not found, removing from state", d.Id())
-			d.SetId("")
-			return nil
-		}
-
-		if err != nil {
-			return resource.NonRetryableError(fmt.Errorf("error reading ACM Certificate (%s): %w", d.Id(), err))
-		}
-
-		if resp == nil || resp.Certificate == nil {
-			return resource.NonRetryableError(fmt.Errorf("error reading ACM Certificate (%s): empty response", d.Id()))
-		}
-
-		if !d.IsNewResource() && aws.StringValue(resp.Certificate.Status) == acm.CertificateStatusValidationTimedOut {
-			log.Printf("[WARN] ACM Certificate (%s) validation timed out, removing from state", d.Id())
-			d.SetId("")
-			return nil
-		}
-
-		d.Set("domain_name", resp.Certificate.DomainName)
-		d.Set("arn", resp.Certificate.CertificateArn)
-		d.Set("certificate_authority_arn", resp.Certificate.CertificateAuthorityArn)
-
-		if err := d.Set("subject_alternative_names", cleanUpSubjectAlternativeNames(resp.Certificate)); err != nil {
-			return resource.NonRetryableError(err)
-		}
-
-		domainValidationOptions, emailValidationOptions, err := convertValidationOptions(resp.Certificate)
-
-		if err != nil {
-			return resource.RetryableError(err)
-		}
-
-		if err := d.Set("domain_validation_options", domainValidationOptions); err != nil {
-			return resource.NonRetryableError(err)
-		}
-		if err := d.Set("validation_emails", emailValidationOptions); err != nil {
-			return resource.NonRetryableError(err)
-		}
+	certificate, err := FindCertificateByARN(conn, d.Id())
 
-		d.Set("validation_method", resourceCertificateValidationMethod(resp.Certificate))
-
-		if err := d.Set("options", flattenAcmCertificateOptions(resp.Certificate.Options)); err != nil {
-			return resource.NonRetryableError(fmt.Errorf("error setting certificate options: %s", err))
-		}
+	if !d.IsNewResource() && tfresource.NotFound(err) {
+		log.Printf("[WARN] ACM Certificate %s not found, removing from state", d.Id())
+		d.SetId("")
+		return nil
+	}
 
-		d.Set("status", resp.Certificate.Status)
+	if err != nil {
+		return fmt.Errorf("reading ACM Certificate (%s): %w", d.Id(), err)
+	}
 
-		tags, err := ListTags(conn, d.Id())
+	domainValidationOptions, validationEmails := flattenDomainValidations(certificate.DomainValidationOptions)
 
-		if err != nil {
-			return resource.NonRetryableError(fmt.Errorf("error listing tags for ACM Certificate (%s): %s", d.Id(), err))
+	d.Set("arn", certificate.CertificateArn)
+	d.Set("certificate_authority_arn", certificate.CertificateAuthorityArn)
+	d.Set("domain_name", certificate.DomainName)
+	if err := d.Set("domain_validation_options", domainValidationOptions); err != nil {
+		return fmt.Errorf("error setting domain_validation_options: %w", err)
+	}
+	if certificate.Options != nil {
+		if err := d.Set("options", []interface{}{flattenCertificateOptions(certificate.Options)}); err != nil {
+			return fmt.Errorf("error setting options: %w", err)
 		}
+	} else {
+		d.Set("options", nil)
+	}
+	d.Set("status", certificate.Status)
+	d.Set("subject_alternative_names", aws.StringValueSlice(certificate.SubjectAlternativeNames))
+	d.Set("validation_emails", validationEmails)
+	d.Set("validation_method", certificateValidationMethod(certificate))
 
-		tags = tags.IgnoreAWS().IgnoreConfig(ignoreTagsConfig)
+	tags, err := ListTags(conn, d.Id())
 
-		//lintignore:AWSR002
-		if err := d.Set("tags", tags.RemoveDefaultConfig(defaultTagsConfig).Map()); err != nil {
-			return resource.NonRetryableError(fmt.Errorf("error setting tags: %w", err))
-		}
+	if err != nil {
+		return fmt.Errorf("listing tags for ACM Certificate (%s): %w", d.Id(), err)
+	}
 
-		if err := d.Set("tags_all", tags.Map()); err != nil {
-			return resource.NonRetryableError(fmt.Errorf("error setting tags_all: %w", err))
-		}
+	tags = tags.IgnoreAWS().IgnoreConfig(ignoreTagsConfig)
 
-		return nil
-	})
-}
+	//lintignore:AWSR002
+	if err := d.Set("tags", tags.RemoveDefaultConfig(defaultTagsConfig).Map()); err != nil {
+		return fmt.Errorf("error setting tags: %w", err)
+	}
 
-func resourceCertificateValidationMethod(certificate *acm.CertificateDetail) string {
-	if aws.StringValue(certificate.Type) == acm.CertificateTypeAmazonIssued {
-		for _, domainValidation := range certificate.DomainValidationOptions {
-			if domainValidation.ValidationMethod != nil {
-				return aws.StringValue(domainValidation.ValidationMethod)
-			}
-		}
+	if err := d.Set("tags_all", tags.Map()); err != nil {
+		return fmt.Errorf("error setting tags_all: %w", err)
 	}
 
-	return "NONE"
+	return nil
 }
 
 func resourceCertificateUpdate(d *schema.ResourceData, meta interface{}) error {
@@ -420,108 +394,56 @@ func resourceCertificateUpdate(d *schema.ResourceData, meta interface{}) error {
 			_, err := conn.ImportCertificate(input)
 
 			if err != nil {
-				return fmt.Errorf("error re-importing ACM Certificate (%s): %w", d.Id(), err)
+				return fmt.Errorf("re-importing ACM Certificate (%s): %w", d.Id(), err)
 			}
 		}
 	}
 
 	if d.HasChange("tags_all") {
 		o, n := d.GetChange("tags_all")
-		if err := UpdateTags(conn, d.Id(), o, n); err != nil {
-			return fmt.Errorf("error updating tags: %s", err)
-		}
-	}
-	return resourceCertificateRead(d, meta)
-}
-
-func cleanUpSubjectAlternativeNames(cert *acm.CertificateDetail) []string {
-	sans := cert.SubjectAlternativeNames
-	vs := make([]string, 0)
-	for _, v := range sans {
-		if aws.StringValue(v) != aws.StringValue(cert.DomainName) {
-			vs = append(vs, aws.StringValue(v))
-		}
-	}
-	return vs
-}
 
-func convertValidationOptions(certificate *acm.CertificateDetail) ([]map[string]interface{}, []string, error) {
-	var domainValidationResult []map[string]interface{}
-	var emailValidationResult []string
-
-	switch aws.StringValue(certificate.Type) {
-	case acm.CertificateTypeAmazonIssued:
-		if len(certificate.DomainValidationOptions) == 0 && aws.StringValue(certificate.Status) == acm.DomainStatusPendingValidation {
-			log.Printf("[DEBUG] No validation options need to retry.")
-			return nil, nil, fmt.Errorf("No validation options need to retry.")
-		}
-		for _, o := range certificate.DomainValidationOptions {
-			if o.ResourceRecord != nil {
-				validationOption := map[string]interface{}{
-					"domain_name":           aws.StringValue(o.DomainName),
-					"resource_record_name":  aws.StringValue(o.ResourceRecord.Name),
-					"resource_record_type":  aws.StringValue(o.ResourceRecord.Type),
-					"resource_record_value": aws.StringValue(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 if o.ValidationStatus == nil || aws.StringValue(o.ValidationStatus) == acm.DomainStatusPendingValidation {
-				log.Printf("[DEBUG] Asynchronous ACM service domain validation assignment not complete, need to retry: %#v", o)
-				return nil, nil, fmt.Errorf("asynchronous ACM service domain validation assignment not complete, need to retry: %#v", o)
-			}
-		}
-	case acm.CertificateTypePrivate:
-		// While ACM PRIVATE certificates do not need to be validated, there is a slight delay for
-		// the API to fill in all certificate details, which is during the PENDING_VALIDATION status.
-		if aws.StringValue(certificate.Status) == acm.DomainStatusPendingValidation {
-			return nil, nil, fmt.Errorf("certificate still pending issuance")
+		if err := UpdateTags(conn, d.Id(), o, n); err != nil {
+			return fmt.Errorf("error updating tags: %w", err)
 		}
 	}
 
-	return domainValidationResult, emailValidationResult, nil
+	return resourceCertificateRead(d, meta)
 }
 
 func resourceCertificateDelete(d *schema.ResourceData, meta interface{}) error {
 	conn := meta.(*conns.AWSClient).ACMConn
 
 	log.Printf("[INFO] Deleting ACM Certificate: %s", d.Id())
-
-	params := &acm.DeleteCertificateInput{
-		CertificateArn: aws.String(d.Id()),
-	}
-
-	err := resource.Retry(AcmCertificateCrossServicePropagationTimeout, func() *resource.RetryError {
-		_, err := conn.DeleteCertificate(params)
-
-		if tfawserr.ErrCodeEquals(err, acm.ErrCodeResourceInUseException) {
-			return resource.RetryableError(err)
-		}
-
-		if err != nil {
-			return resource.NonRetryableError(err)
-		}
-
-		return nil
-	})
-
-	if tfresource.TimedOut(err) {
-		_, err = conn.DeleteCertificate(params)
-	}
+	_, err := tfresource.RetryWhenAWSErrCodeEquals(AcmCertificateCrossServicePropagationTimeout,
+		func() (interface{}, error) {
+			return conn.DeleteCertificate(&acm.DeleteCertificateInput{
+				CertificateArn: aws.String(d.Id()),
+			})
+		}, acm.ErrCodeResourceInUseException)
 
 	if tfawserr.ErrCodeEquals(err, acm.ErrCodeResourceNotFoundException) {
 		return nil
 	}
 
 	if err != nil {
-		return fmt.Errorf("error deleting ACM Certificate (%s): %w", d.Id(), err)
+		return fmt.Errorf("deleting ACM Certificate (%s): %w", d.Id(), err)
 	}
 
 	return nil
 }
 
+func certificateValidationMethod(certificate *acm.CertificateDetail) string {
+	if aws.StringValue(certificate.Type) == acm.CertificateTypeAmazonIssued {
+		for _, v := range certificate.DomainValidationOptions {
+			if v.ValidationMethod != nil {
+				return aws.StringValue(v.ValidationMethod)
+			}
+		}
+	}
+
+	return certificateValidationMethodNone
+}
+
 func acmDomainValidationOptionsHash(v interface{}) int {
 	m, ok := v.(map[string]interface{})
 
@@ -536,28 +458,89 @@ func acmDomainValidationOptionsHash(v interface{}) int {
 	return 0
 }
 
-func expandAcmCertificateOptions(l []interface{}) *acm.CertificateOptions {
-	if len(l) == 0 || l[0] == nil {
+func expandCertificateOptions(tfMap map[string]interface{}) *acm.CertificateOptions {
+	if tfMap == nil {
+		return nil
+	}
+
+	apiObject := &acm.CertificateOptions{}
+
+	if v, ok := tfMap["certificate_transparency_logging_preference"].(string); ok && v != "" {
+		apiObject.CertificateTransparencyLoggingPreference = aws.String(v)
+	}
+
+	return apiObject
+}
+
+func flattenCertificateOptions(apiObject *acm.CertificateOptions) map[string]interface{} {
+	if apiObject == nil {
 		return nil
 	}
 
-	m := l[0].(map[string]interface{})
+	tfMap := map[string]interface{}{}
+
+	if v := apiObject.CertificateTransparencyLoggingPreference; v != nil {
+		tfMap["certificate_transparency_logging_preference"] = aws.StringValue(v)
+	}
+
+	return tfMap
+}
+
+func flattenDomainValidation(apiObject *acm.DomainValidation) (map[string]interface{}, []string) {
+	if apiObject == nil {
+		return nil, nil
+	}
+
+	tfMap := map[string]interface{}{}
+	var tfStrings []string
+
+	if v := apiObject.ResourceRecord; v != nil {
+		if v := apiObject.DomainName; v != nil {
+			tfMap["domain_name"] = aws.StringValue(v)
+		}
 
-	options := &acm.CertificateOptions{}
+		if v := v.Name; v != nil {
+			tfMap["resource_record_name"] = aws.StringValue(v)
+		}
 
-	if v, ok := m["certificate_transparency_logging_preference"]; ok {
-		options.CertificateTransparencyLoggingPreference = aws.String(v.(string))
+		if v := v.Type; v != nil {
+			tfMap["resource_record_type"] = aws.StringValue(v)
+		}
+
+		if v := v.Value; v != nil {
+			tfMap["resource_record_value"] = aws.StringValue(v)
+		}
 	}
 
-	return options
+	tfStrings = aws.StringValueSlice(apiObject.ValidationEmails)
+
+	return tfMap, tfStrings
 }
 
-func flattenAcmCertificateOptions(co *acm.CertificateOptions) []interface{} {
-	m := map[string]interface{}{
-		"certificate_transparency_logging_preference": aws.StringValue(co.CertificateTransparencyLoggingPreference),
+func flattenDomainValidations(apiObjects []*acm.DomainValidation) ([]interface{}, []string) {
+	if len(apiObjects) == 0 {
+		return nil, nil
+	}
+
+	var tfList []interface{}
+	var tfStrings []string
+
+	for _, apiObject := range apiObjects {
+		if apiObject == nil {
+			continue
+		}
+
+		v1, v2 := flattenDomainValidation(apiObject)
+
+		if len(v1) > 0 {
+			tfList = append(tfList, v1)
+		}
+		if len(v2) > 0 {
+			tfStrings = append(tfStrings, v2...)
+		}
 	}
 
-	return []interface{}{m}
+	return tfList, tfStrings
 }
 
 func isChangeNormalizeCertRemoval(oldRaw, newRaw interface{}) bool {
@@ -573,20 +556,116 @@ func isChangeNormalizeCertRemoval(oldRaw, newRaw interface{}) bool {
 		return false
 	}
 
+	// strip CRs from raw literals. Lifted from go/scanner/scanner.go
+	// See https://github.com/golang/go/blob/release-branch.go1.6/src/go/scanner/scanner.go#L479
+	stripCR := func(b []byte) []byte {
+		c := make([]byte, len(b))
+		i := 0
+		for _, ch := range b {
+			if ch != '\r' {
+				c[i] = ch
+				i++
+			}
+		}
+		return c[:i]
+	}
+
 	newCleanVal := sha1.Sum(stripCR([]byte(strings.TrimSpace(new))))
 	return hex.EncodeToString(newCleanVal[:]) == old
 }
 
-// strip CRs from raw literals. Lifted from go/scanner/scanner.go
-// See https://github.com/golang/go/blob/release-branch.go1.6/src/go/scanner/scanner.go#L479
-func stripCR(b []byte) []byte {
-	c := make([]byte, len(b))
-	i := 0
-	for _, ch := range b {
-		if ch != '\r' {
-			c[i] = ch
-			i++
+func findCertificate(conn *acm.ACM, input *acm.DescribeCertificateInput) (*acm.CertificateDetail, error) {
+	output, err := conn.DescribeCertificate(input)
+
+	if tfawserr.ErrCodeEquals(err, acm.ErrCodeResourceNotFoundException) {
+		return nil, &resource.NotFoundError{
+			LastError:   err,
+			LastRequest: input,
 		}
 	}
-	return c[:i]
+
+	if err != nil {
+		return nil, err
+	}
+
+	if output == nil || output.Certificate == nil {
+		return nil, tfresource.NewEmptyResultError(input)
+	}
+
+	return output.Certificate, nil
+}
+
+func FindCertificateByARN(conn *acm.ACM, arn string) (*acm.CertificateDetail, error) {
+	input := &acm.DescribeCertificateInput{
+		CertificateArn: aws.String(arn),
+	}
+
+	output, err := findCertificate(conn, input)
+
+	if err != nil {
+		return nil, err
+	}
+
+	if status := aws.StringValue(output.Status); status == acm.CertificateStatusValidationTimedOut {
+		return nil, &resource.NotFoundError{
+			Message:     status,
+			LastRequest: input,
+		}
+	}
+
+	return output, nil
+}
+
+func statusCertificateDomainValidationsAvailable(conn *acm.ACM, arn string) resource.StateRefreshFunc {
+	return func() (interface{}, string, error) {
+		certificate, err := FindCertificateByARN(conn, arn)
+
+		if tfresource.NotFound(err) {
+			return nil, "", nil
+		}
+
+		if err != nil {
+			return nil, "", err
+		}
+
+		domainValidationsAvailable := true
+
+		switch aws.StringValue(certificate.Type) {
+		case acm.CertificateTypeAmazonIssued:
+			domainValidationsAvailable = false
+
+			for _, v := range certificate.DomainValidationOptions {
+				if v.ResourceRecord != nil || len(v.ValidationEmails) > 0 || (aws.StringValue(v.ValidationStatus) == acm.DomainStatusSuccess) {
+					domainValidationsAvailable = true
+
+					break
+				}
+			}
+
+		case acm.CertificateTypePrivate:
+			// While ACM PRIVATE certificates do not need to be validated, there is a slight delay for
+			// the API to fill in all certificate details, which is during the PENDING_VALIDATION status.
+			if aws.StringValue(certificate.Status) == acm.DomainStatusPendingValidation {
+				domainValidationsAvailable = false
+			}
+		}
+
+		return certificate, strconv.FormatBool(domainValidationsAvailable), nil
+	}
+}
+
+func waitCertificateDomainValidationsAvailable(conn *acm.ACM, arn string, timeout time.Duration) (*acm.CertificateDetail, error) {
+	stateConf := &resource.StateChangeConf{
+		Target:  []string{strconv.FormatBool(true)},
+		Refresh: statusCertificateDomainValidationsAvailable(conn, arn),
+		Timeout: timeout,
+	}
+
+	outputRaw, err := stateConf.WaitForState()
+
+	if output, ok := outputRaw.(*acm.CertificateDetail); ok {
+		return output, err
+	}
+
+	return nil, err
 }
diff --git a/internal/service/acm/certificate_data_source_test.go b/internal/service/acm/certificate_data_source_test.go
index 63544ea9a848..f60aa5f8dc0d 100644
--- a/internal/service/acm/certificate_data_source_test.go
+++ b/internal/service/acm/certificate_data_source_test.go
@@ -197,7 +197,7 @@ func TestAccACMCertificateDataSource_keyTypes(t *testing.T) {
 	resourceName := "aws_acm_certificate.test"
 	dataSourceName := "data.aws_acm_certificate.test"
 	key := acctest.TLSRSAPrivateKeyPEM(4096)
-	certificate := acctest.TLSRSAX509SelfSignedCertificatePEM(key, "example.com")
+	certificate := acctest.TLSRSAX509SelfSignedCertificatePEM(key, acctest.RandomDomain().String())
 	rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
 
 	resource.ParallelTest(t, resource.TestCase{
diff --git a/internal/service/acm/certificate_test.go b/internal/service/acm/certificate_test.go
index 9b830f51db33..d78e2317511c 100644
--- a/internal/service/acm/certificate_test.go
+++ b/internal/service/acm/certificate_test.go
@@ -7,19 +7,20 @@ import (
 	"strings"
 	"testing"
 
-	"github.com/aws/aws-sdk-go/aws"
 	"github.com/aws/aws-sdk-go/service/acm"
-	"github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr"
 	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
 	"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
 	"github.com/hashicorp/terraform-provider-aws/internal/acctest"
 	"github.com/hashicorp/terraform-provider-aws/internal/conns"
+	tfacm "github.com/hashicorp/terraform-provider-aws/internal/service/acm"
+	"github.com/hashicorp/terraform-provider-aws/internal/tfresource"
 )
 
 func TestAccACMCertificate_emailValidation(t *testing.T) {
-	resourceName := "aws_acm_certificate.cert"
+	resourceName := "aws_acm_certificate.test"
 	rootDomain := acctest.ACMCertificateDomainFromEnv(t)
 	domain := acctest.ACMCertificateRandomSubDomain(rootDomain)
+	var v acm.CertificateDetail
 
 	resource.ParallelTest(t, resource.TestCase{
 		PreCheck:     func() { acctest.PreCheck(t) },
@@ -29,12 +30,15 @@ func TestAccACMCertificate_emailValidation(t *testing.T) {
 		Steps: []resource.TestStep{
 			{
 				Config: testAccAcmCertificateConfig(domain, acm.ValidationMethodEmail),
-				Check: resource.ComposeTestCheckFunc(
+				Check: resource.ComposeAggregateTestCheckFunc(
+					testAccCheckAcmCertificateExists(resourceName, &v),
 					acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "acm", regexp.MustCompile("certificate/.+$")),
 					resource.TestCheckResourceAttr(resourceName, "domain_name", domain),
 					resource.TestCheckResourceAttr(resourceName, "domain_validation_options.#", "0"),
 					resource.TestCheckResourceAttr(resourceName, "status", acm.CertificateStatusPendingValidation),
-					resource.TestCheckResourceAttr(resourceName, "subject_alternative_names.#", "0"),
+					resource.TestCheckResourceAttr(resourceName, "subject_alternative_names.#", "1"),
+					resource.TestCheckTypeSetElemAttr(resourceName, "subject_alternative_names.*", domain),
+					acctest.CheckResourceAttrGreaterThanValue(resourceName, "validation_emails.#", "0"),
 					resource.TestMatchResourceAttr(resourceName, "validation_emails.0", regexp.MustCompile(`^[^@]+@.+$`)),
 					resource.TestCheckResourceAttr(resourceName, "validation_method", acm.ValidationMethodEmail),
 				),
@@ -49,9 +53,10 @@ func TestAccACMCertificate_emailValidation(t *testing.T) {
 }
 
 func TestAccACMCertificate_dnsValidation(t *testing.T) {
-	resourceName := "aws_acm_certificate.cert"
+	resourceName := "aws_acm_certificate.test"
 	rootDomain := acctest.ACMCertificateDomainFromEnv(t)
 	domain := acctest.ACMCertificateRandomSubDomain(rootDomain)
+	var v acm.CertificateDetail
 
 	resource.ParallelTest(t, resource.TestCase{
 		PreCheck:     func() { acctest.PreCheck(t) },
@@ -62,6 +67,7 @@ func TestAccACMCertificate_dnsValidation(t *testing.T) {
 			{
 				Config: testAccAcmCertificateConfig(domain, acm.ValidationMethodDns),
 				Check: resource.ComposeTestCheckFunc(
+					testAccCheckAcmCertificateExists(resourceName, &v),
 					acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "acm", regexp.MustCompile("certificate/.+$")),
 					resource.TestCheckResourceAttr(resourceName, "domain_name", domain),
 					resource.TestCheckResourceAttr(resourceName, "domain_validation_options.#", "1"),
@@ -70,7 +76,8 @@ func TestAccACMCertificate_dnsValidation(t *testing.T) {
 						"resource_record_type": "CNAME",
 					}),
 					resource.TestCheckResourceAttr(resourceName, "status", acm.CertificateStatusPendingValidation),
-					resource.TestCheckResourceAttr(resourceName, "subject_alternative_names.#", "0"),
+					resource.TestCheckResourceAttr(resourceName, "subject_alternative_names.#", "1"),
+					resource.TestCheckTypeSetElemAttr(resourceName, "subject_alternative_names.*", domain),
 					resource.TestCheckResourceAttr(resourceName, "validation_emails.#", "0"),
 					resource.TestCheckResourceAttr(resourceName, "validation_method", acm.ValidationMethodDns),
 				),
@@ -85,8 +92,9 @@ func TestAccACMCertificate_dnsValidation(t *testing.T) {
 }
 
 func TestAccACMCertificate_root(t *testing.T) {
-	resourceName := "aws_acm_certificate.cert"
+	resourceName := "aws_acm_certificate.test"
 	rootDomain := acctest.ACMCertificateDomainFromEnv(t)
+	var v acm.CertificateDetail
 
 	resource.ParallelTest(t, resource.TestCase{
 		PreCheck:     func() { acctest.PreCheck(t) },
@@ -97,6 +105,7 @@ func TestAccACMCertificate_root(t *testing.T) {
 			{
 				Config: testAccAcmCertificateConfig(rootDomain, acm.ValidationMethodDns),
 				Check: resource.ComposeTestCheckFunc(
+					testAccCheckAcmCertificateExists(resourceName, &v),
 					acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "acm", regexp.MustCompile("certificate/.+$")),
 					resource.TestCheckResourceAttr(resourceName, "domain_name", rootDomain),
 					resource.TestCheckResourceAttr(resourceName, "domain_validation_options.#", "1"),
@@ -105,7 +114,8 @@ func TestAccACMCertificate_root(t *testing.T) {
 						"resource_record_type": "CNAME",
 					}),
 					resource.TestCheckResourceAttr(resourceName, "status", acm.CertificateStatusPendingValidation),
-					resource.TestCheckResourceAttr(resourceName, "subject_alternative_names.#", "0"),
+					resource.TestCheckResourceAttr(resourceName, "subject_alternative_names.#", "1"),
+					resource.TestCheckTypeSetElemAttr(resourceName, "subject_alternative_names.*", rootDomain),
 					resource.TestCheckResourceAttr(resourceName, "validation_emails.#", "0"),
 					resource.TestCheckResourceAttr(resourceName, "validation_method", acm.ValidationMethodDns),
 				),
@@ -121,10 +131,10 @@ func TestAccACMCertificate_root(t *testing.T) {
 
 func TestAccACMCertificate_privateCert(t *testing.T) {
 	certificateAuthorityResourceName := "aws_acmpca_certificate_authority.test"
-	resourceName := "aws_acm_certificate.cert"
-
+	resourceName := "aws_acm_certificate.test"
 	commonName := acctest.RandomDomain()
 	certificateDomainName := commonName.RandomSubdomain().String()
+	var v acm.CertificateDetail
 
 	resource.ParallelTest(t, resource.TestCase{
 		PreCheck:     func() { acctest.PreCheck(t) },
@@ -133,13 +143,15 @@ func TestAccACMCertificate_privateCert(t *testing.T) {
 		CheckDestroy: testAccCheckAcmCertificateDestroy,
 		Steps: []resource.TestStep{
 			{
-				Config: testAccAcmCertificateConfig_privateCert(commonName.String(), certificateDomainName),
+				Config: testAccAcmCertificatePrivateCertConfig(commonName.String(), certificateDomainName),
 				Check: resource.ComposeTestCheckFunc(
+					testAccCheckAcmCertificateExists(resourceName, &v),
 					acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "acm", regexp.MustCompile("certificate/.+$")),
 					resource.TestCheckResourceAttr(resourceName, "domain_name", certificateDomainName),
 					resource.TestCheckResourceAttr(resourceName, "domain_validation_options.#", "0"),
 					resource.TestCheckResourceAttr(resourceName, "status", acm.CertificateStatusFailed), // FailureReason: PCA_INVALID_STATE (PCA State: PENDING_CERTIFICATE)
-					resource.TestCheckResourceAttr(resourceName, "subject_alternative_names.#", "0"),
+					resource.TestCheckResourceAttr(resourceName, "subject_alternative_names.#", "1"),
+					resource.TestCheckTypeSetElemAttr(resourceName, "subject_alternative_names.*", certificateDomainName),
 					resource.TestCheckResourceAttr(resourceName, "validation_emails.#", "0"),
 					resource.TestCheckResourceAttr(resourceName, "validation_method", "NONE"),
 					resource.TestCheckResourceAttrPair(resourceName, "certificate_authority_arn", certificateAuthorityResourceName, "arn"),
@@ -175,9 +187,10 @@ func TestAccACMCertificate_Root_trailingPeriod(t *testing.T) {
 }
 
 func TestAccACMCertificate_rootAndWildcardSan(t *testing.T) {
-	resourceName := "aws_acm_certificate.cert"
+	resourceName := "aws_acm_certificate.test"
 	rootDomain := acctest.ACMCertificateDomainFromEnv(t)
 	wildcardDomain := fmt.Sprintf("*.%s", rootDomain)
+	var v acm.CertificateDetail
 
 	resource.ParallelTest(t, resource.TestCase{
 		PreCheck:     func() { acctest.PreCheck(t) },
@@ -186,8 +199,9 @@ func TestAccACMCertificate_rootAndWildcardSan(t *testing.T) {
 		CheckDestroy: testAccCheckAcmCertificateDestroy,
 		Steps: []resource.TestStep{
 			{
-				Config: testAccAcmCertificateConfig_subjectAlternativeNames(rootDomain, strconv.Quote(wildcardDomain), acm.ValidationMethodDns),
+				Config: testAccAcmCertificateSubjectAlternativeNamesConfig(rootDomain, strconv.Quote(wildcardDomain), acm.ValidationMethodDns),
 				Check: resource.ComposeTestCheckFunc(
+					testAccCheckAcmCertificateExists(resourceName, &v),
 					acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "acm", regexp.MustCompile("certificate/.+$")),
 					resource.TestCheckResourceAttr(resourceName, "domain_name", rootDomain),
 					resource.TestCheckResourceAttr(resourceName, "domain_validation_options.#", "2"),
@@ -200,7 +214,8 @@ func TestAccACMCertificate_rootAndWildcardSan(t *testing.T) {
 						"resource_record_type": "CNAME",
 					}),
 					resource.TestCheckResourceAttr(resourceName, "status", acm.CertificateStatusPendingValidation),
-					resource.TestCheckResourceAttr(resourceName, "subject_alternative_names.#", "1"),
+					resource.TestCheckResourceAttr(resourceName, "subject_alternative_names.#", "2"),
+					resource.TestCheckTypeSetElemAttr(resourceName, "subject_alternative_names.*", rootDomain),
 					resource.TestCheckTypeSetElemAttr(resourceName, "subject_alternative_names.*", wildcardDomain),
 					resource.TestCheckResourceAttr(resourceName, "validation_emails.#", "0"),
 					resource.TestCheckResourceAttr(resourceName, "validation_method", acm.ValidationMethodDns),
@@ -226,7 +241,7 @@ func TestAccACMCertificate_SubjectAlternativeNames_emptyString(t *testing.T) {
 		CheckDestroy: testAccCheckAcmCertificateDestroy,
 		Steps: []resource.TestStep{
 			{
-				Config:      testAccAcmCertificateConfig_subjectAlternativeNames(domain, strconv.Quote(""), acm.ValidationMethodDns),
+				Config:      testAccAcmCertificateSubjectAlternativeNamesConfig(domain, strconv.Quote(""), acm.ValidationMethodDns),
 				ExpectError: regexp.MustCompile(`expected length`),
 			},
 		},
@@ -234,10 +249,11 @@ func TestAccACMCertificate_SubjectAlternativeNames_emptyString(t *testing.T) {
 }
 
 func TestAccACMCertificate_San_single(t *testing.T) {
-	resourceName := "aws_acm_certificate.cert"
+	resourceName := "aws_acm_certificate.test"
 	rootDomain := acctest.ACMCertificateDomainFromEnv(t)
 	domain := acctest.ACMCertificateRandomSubDomain(rootDomain)
 	sanDomain := acctest.ACMCertificateRandomSubDomain(rootDomain)
+	var v acm.CertificateDetail
 
 	resource.ParallelTest(t, resource.TestCase{
 		PreCheck:     func() { acctest.PreCheck(t) },
@@ -246,8 +262,9 @@ func TestAccACMCertificate_San_single(t *testing.T) {
 		CheckDestroy: testAccCheckAcmCertificateDestroy,
 		Steps: []resource.TestStep{
 			{
-				Config: testAccAcmCertificateConfig_subjectAlternativeNames(domain, strconv.Quote(sanDomain), acm.ValidationMethodDns),
+				Config: testAccAcmCertificateSubjectAlternativeNamesConfig(domain, strconv.Quote(sanDomain), acm.ValidationMethodDns),
 				Check: resource.ComposeTestCheckFunc(
+					testAccCheckAcmCertificateExists(resourceName, &v),
 					acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "acm", regexp.MustCompile("certificate/.+$")),
 					resource.TestCheckResourceAttr(resourceName, "domain_name", domain),
 					resource.TestCheckResourceAttr(resourceName, "domain_validation_options.#", "2"),
@@ -260,7 +277,8 @@ func TestAccACMCertificate_San_single(t *testing.T) {
 						"resource_record_type": "CNAME",
 					}),
 					resource.TestCheckResourceAttr(resourceName, "status", acm.CertificateStatusPendingValidation),
-					resource.TestCheckResourceAttr(resourceName, "subject_alternative_names.#", "1"),
+					resource.TestCheckResourceAttr(resourceName, "subject_alternative_names.#", "2"),
+					resource.TestCheckTypeSetElemAttr(resourceName, "subject_alternative_names.*", domain),
 					resource.TestCheckTypeSetElemAttr(resourceName, "subject_alternative_names.*", sanDomain),
 					resource.TestCheckResourceAttr(resourceName, "validation_emails.#", "0"),
 					resource.TestCheckResourceAttr(resourceName, "validation_method", acm.ValidationMethodDns),
@@ -276,11 +294,12 @@ func TestAccACMCertificate_San_single(t *testing.T) {
 }
 
 func TestAccACMCertificate_San_multiple(t *testing.T) {
-	resourceName := "aws_acm_certificate.cert"
+	resourceName := "aws_acm_certificate.test"
 	rootDomain := acctest.ACMCertificateDomainFromEnv(t)
 	domain := acctest.ACMCertificateRandomSubDomain(rootDomain)
 	sanDomain1 := acctest.ACMCertificateRandomSubDomain(rootDomain)
 	sanDomain2 := acctest.ACMCertificateRandomSubDomain(rootDomain)
+	var v acm.CertificateDetail
 
 	resource.ParallelTest(t, resource.TestCase{
 		PreCheck:     func() { acctest.PreCheck(t) },
@@ -289,8 +308,9 @@ func TestAccACMCertificate_San_multiple(t *testing.T) {
 		CheckDestroy: testAccCheckAcmCertificateDestroy,
 		Steps: []resource.TestStep{
 			{
-				Config: testAccAcmCertificateConfig_subjectAlternativeNames(domain, fmt.Sprintf("%q, %q", sanDomain1, sanDomain2), acm.ValidationMethodDns),
+				Config: testAccAcmCertificateSubjectAlternativeNamesConfig(domain, fmt.Sprintf("%q, %q", sanDomain1, sanDomain2), acm.ValidationMethodDns),
 				Check: resource.ComposeTestCheckFunc(
+					testAccCheckAcmCertificateExists(resourceName, &v),
 					acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "acm", regexp.MustCompile("certificate/.+$")),
 					resource.TestCheckResourceAttr(resourceName, "domain_name", domain),
 					resource.TestCheckResourceAttr(resourceName, "domain_validation_options.#", "3"),
@@ -307,7 +327,8 @@ func TestAccACMCertificate_San_multiple(t *testing.T) {
 						"resource_record_type": "CNAME",
 					}),
 					resource.TestCheckResourceAttr(resourceName, "status", acm.CertificateStatusPendingValidation),
-					resource.TestCheckResourceAttr(resourceName, "subject_alternative_names.#", "2"),
+					resource.TestCheckResourceAttr(resourceName, "subject_alternative_names.#", "3"),
+					resource.TestCheckTypeSetElemAttr(resourceName, "subject_alternative_names.*", domain),
 					resource.TestCheckTypeSetElemAttr(resourceName, "subject_alternative_names.*", sanDomain1),
 					resource.TestCheckTypeSetElemAttr(resourceName, "subject_alternative_names.*", sanDomain2),
 					resource.TestCheckResourceAttr(resourceName, "validation_emails.#", "0"),
@@ -327,7 +348,8 @@ func TestAccACMCertificate_San_trailingPeriod(t *testing.T) {
 	rootDomain := acctest.ACMCertificateDomainFromEnv(t)
 	domain := acctest.ACMCertificateRandomSubDomain(rootDomain)
 	sanDomain := acctest.ACMCertificateRandomSubDomain(rootDomain)
-	resourceName := "aws_acm_certificate.cert"
+	resourceName := "aws_acm_certificate.test"
+	var v acm.CertificateDetail
 
 	resource.ParallelTest(t, resource.TestCase{
 		PreCheck:     func() { acctest.PreCheck(t) },
@@ -336,8 +358,9 @@ func TestAccACMCertificate_San_trailingPeriod(t *testing.T) {
 		CheckDestroy: testAccCheckAcmCertificateDestroy,
 		Steps: []resource.TestStep{
 			{
-				Config: testAccAcmCertificateConfig_subjectAlternativeNames(domain, strconv.Quote(sanDomain), acm.ValidationMethodDns),
+				Config: testAccAcmCertificateSubjectAlternativeNamesConfig(domain, strconv.Quote(sanDomain), acm.ValidationMethodDns),
 				Check: resource.ComposeTestCheckFunc(
+					testAccCheckAcmCertificateExists(resourceName, &v),
 					acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "acm", regexp.MustCompile(`certificate/.+`)),
 					resource.TestCheckResourceAttr(resourceName, "domain_name", domain),
 					resource.TestCheckResourceAttr(resourceName, "domain_validation_options.#", "2"),
@@ -350,7 +373,8 @@ func TestAccACMCertificate_San_trailingPeriod(t *testing.T) {
 						"resource_record_type": "CNAME",
 					}),
 					resource.TestCheckResourceAttr(resourceName, "status", acm.CertificateStatusPendingValidation),
-					resource.TestCheckResourceAttr(resourceName, "subject_alternative_names.#", "1"),
+					resource.TestCheckResourceAttr(resourceName, "subject_alternative_names.#", "2"),
+					resource.TestCheckTypeSetElemAttr(resourceName, "subject_alternative_names.*", domain),
 					resource.TestCheckTypeSetElemAttr(resourceName, "subject_alternative_names.*", strings.TrimSuffix(sanDomain, ".")),
 					resource.TestCheckResourceAttr(resourceName, "validation_emails.#", "0"),
 					resource.TestCheckResourceAttr(resourceName, "validation_method", acm.ValidationMethodDns),
@@ -365,10 +389,12 @@ func TestAccACMCertificate_San_trailingPeriod(t *testing.T) {
 	})
 }
 
-func TestAccACMCertificate_wildcard(t *testing.T) {
-	resourceName := "aws_acm_certificate.cert"
+func TestAccACMCertificate_San_matches_domain(t *testing.T) {
+	resourceName := "aws_acm_certificate.test"
 	rootDomain := acctest.ACMCertificateDomainFromEnv(t)
-	wildcardDomain := fmt.Sprintf("*.%s", rootDomain)
+	domain := acctest.ACMCertificateRandomSubDomain(rootDomain)
+	sanDomain := rootDomain
+	var v acm.CertificateDetail
 
 	resource.ParallelTest(t, resource.TestCase{
 		PreCheck:     func() { acctest.PreCheck(t) },
@@ -377,17 +403,24 @@ func TestAccACMCertificate_wildcard(t *testing.T) {
 		CheckDestroy: testAccCheckAcmCertificateDestroy,
 		Steps: []resource.TestStep{
 			{
-				Config: testAccAcmCertificateConfig(wildcardDomain, acm.ValidationMethodDns),
-				Check: resource.ComposeTestCheckFunc(
-					acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "acm", regexp.MustCompile("certificate/.+$")),
-					resource.TestCheckResourceAttr(resourceName, "domain_name", wildcardDomain),
-					resource.TestCheckResourceAttr(resourceName, "domain_validation_options.#", "1"),
+				Config: testAccAcmCertificateSubjectAlternativeNamesConfig(domain, strconv.Quote(sanDomain), acm.ValidationMethodDns),
+				Check: resource.ComposeAggregateTestCheckFunc(
+					testAccCheckAcmCertificateExists(resourceName, &v),
+					acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "acm", regexp.MustCompile(`certificate/.+`)),
+					resource.TestCheckResourceAttr(resourceName, "domain_name", domain),
+					resource.TestCheckResourceAttr(resourceName, "domain_validation_options.#", "2"),
 					resource.TestCheckTypeSetElemNestedAttrs(resourceName, "domain_validation_options.*", map[string]string{
-						"domain_name":          wildcardDomain,
+						"domain_name":          domain,
+						"resource_record_type": "CNAME",
+					}),
+					resource.TestCheckTypeSetElemNestedAttrs(resourceName, "domain_validation_options.*", map[string]string{
+						"domain_name":          sanDomain,
 						"resource_record_type": "CNAME",
 					}),
 					resource.TestCheckResourceAttr(resourceName, "status", acm.CertificateStatusPendingValidation),
-					resource.TestCheckResourceAttr(resourceName, "subject_alternative_names.#", "0"),
+					resource.TestCheckResourceAttr(resourceName, "subject_alternative_names.#", "2"),
+					resource.TestCheckTypeSetElemAttr(resourceName, "subject_alternative_names.*", domain),
+					resource.TestCheckTypeSetElemAttr(resourceName, "subject_alternative_names.*", sanDomain),
 					resource.TestCheckResourceAttr(resourceName, "validation_emails.#", "0"),
 					resource.TestCheckResourceAttr(resourceName, "validation_method", acm.ValidationMethodDns),
 				),
@@ -401,10 +434,11 @@ func TestAccACMCertificate_wildcard(t *testing.T) {
 	})
 }
 
-func TestAccACMCertificate_wildcardAndRootSan(t *testing.T) {
-	resourceName := "aws_acm_certificate.cert"
+func TestAccACMCertificate_wildcard(t *testing.T) {
+	resourceName := "aws_acm_certificate.test"
 	rootDomain := acctest.ACMCertificateDomainFromEnv(t)
 	wildcardDomain := fmt.Sprintf("*.%s", rootDomain)
+	var v acm.CertificateDetail
 
 	resource.ParallelTest(t, resource.TestCase{
 		PreCheck:     func() { acctest.PreCheck(t) },
@@ -413,22 +447,19 @@ func TestAccACMCertificate_wildcardAndRootSan(t *testing.T) {
 		CheckDestroy: testAccCheckAcmCertificateDestroy,
 		Steps: []resource.TestStep{
 			{
-				Config: testAccAcmCertificateConfig_subjectAlternativeNames(wildcardDomain, strconv.Quote(rootDomain), acm.ValidationMethodDns),
+				Config: testAccAcmCertificateConfig(wildcardDomain, acm.ValidationMethodDns),
 				Check: resource.ComposeTestCheckFunc(
+					testAccCheckAcmCertificateExists(resourceName, &v),
 					acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "acm", regexp.MustCompile("certificate/.+$")),
 					resource.TestCheckResourceAttr(resourceName, "domain_name", wildcardDomain),
-					resource.TestCheckResourceAttr(resourceName, "domain_validation_options.#", "2"),
-					resource.TestCheckTypeSetElemNestedAttrs(resourceName, "domain_validation_options.*", map[string]string{
-						"domain_name":          rootDomain,
-						"resource_record_type": "CNAME",
-					}),
+					resource.TestCheckResourceAttr(resourceName, "domain_validation_options.#", "1"),
 					resource.TestCheckTypeSetElemNestedAttrs(resourceName, "domain_validation_options.*", map[string]string{
 						"domain_name":          wildcardDomain,
 						"resource_record_type": "CNAME",
 					}),
 					resource.TestCheckResourceAttr(resourceName, "status", acm.CertificateStatusPendingValidation),
 					resource.TestCheckResourceAttr(resourceName, "subject_alternative_names.#", "1"),
-					resource.TestCheckTypeSetElemAttr(resourceName, "subject_alternative_names.*", rootDomain),
+					resource.TestCheckTypeSetElemAttr(resourceName, "subject_alternative_names.*", wildcardDomain),
 					resource.TestCheckResourceAttr(resourceName, "validation_emails.#", "0"),
 					resource.TestCheckResourceAttr(resourceName, "validation_method", acm.ValidationMethodDns),
 				),
@@ -442,9 +473,11 @@ func TestAccACMCertificate_wildcardAndRootSan(t *testing.T) {
 	})
 }
 
-func TestAccACMCertificate_disableCTLogging(t *testing.T) {
-	resourceName := "aws_acm_certificate.cert"
+func TestAccACMCertificate_wildcardAndRootSan(t *testing.T) {
+	resourceName := "aws_acm_certificate.test"
 	rootDomain := acctest.ACMCertificateDomainFromEnv(t)
+	wildcardDomain := fmt.Sprintf("*.%s", rootDomain)
+	var v acm.CertificateDetail
 
 	resource.ParallelTest(t, resource.TestCase{
 		PreCheck:     func() { acctest.PreCheck(t) },
@@ -453,21 +486,26 @@ func TestAccACMCertificate_disableCTLogging(t *testing.T) {
 		CheckDestroy: testAccCheckAcmCertificateDestroy,
 		Steps: []resource.TestStep{
 			{
-				Config: testAccAcmCertificateConfig_disableCTLogging(rootDomain, acm.ValidationMethodDns),
+				Config: testAccAcmCertificateSubjectAlternativeNamesConfig(wildcardDomain, strconv.Quote(rootDomain), acm.ValidationMethodDns),
 				Check: resource.ComposeTestCheckFunc(
+					testAccCheckAcmCertificateExists(resourceName, &v),
 					acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "acm", regexp.MustCompile("certificate/.+$")),
-					resource.TestCheckResourceAttr(resourceName, "domain_name", rootDomain),
-					resource.TestCheckResourceAttr(resourceName, "domain_validation_options.#", "1"),
+					resource.TestCheckResourceAttr(resourceName, "domain_name", wildcardDomain),
+					resource.TestCheckResourceAttr(resourceName, "domain_validation_options.#", "2"),
 					resource.TestCheckTypeSetElemNestedAttrs(resourceName, "domain_validation_options.*", map[string]string{
 						"domain_name":          rootDomain,
 						"resource_record_type": "CNAME",
 					}),
-					resource.TestCheckResourceAttr(resourceName, "subject_alternative_names.#", "0"),
+					resource.TestCheckTypeSetElemNestedAttrs(resourceName, "domain_validation_options.*", map[string]string{
+						"domain_name":          wildcardDomain,
+						"resource_record_type": "CNAME",
+					}),
 					resource.TestCheckResourceAttr(resourceName, "status", acm.CertificateStatusPendingValidation),
+					resource.TestCheckResourceAttr(resourceName, "subject_alternative_names.#", "2"),
+					resource.TestCheckTypeSetElemAttr(resourceName, "subject_alternative_names.*", rootDomain),
+					resource.TestCheckTypeSetElemAttr(resourceName, "subject_alternative_names.*", wildcardDomain),
 					resource.TestCheckResourceAttr(resourceName, "validation_emails.#", "0"),
 					resource.TestCheckResourceAttr(resourceName, "validation_method", acm.ValidationMethodDns),
-					resource.TestCheckResourceAttr(resourceName, "options.#", "1"),
-					resource.TestCheckResourceAttr(resourceName, "options.0.certificate_transparency_logging_preference", acm.CertificateTransparencyLoggingPreferenceDisabled),
 				),
 			},
 			{
@@ -479,10 +517,10 @@ func TestAccACMCertificate_disableCTLogging(t *testing.T) {
 	})
 }
 
-func TestAccACMCertificate_tags(t *testing.T) {
-	resourceName := "aws_acm_certificate.cert"
+func TestAccACMCertificate_disableCTLogging(t *testing.T) {
+	resourceName := "aws_acm_certificate.test"
 	rootDomain := acctest.ACMCertificateDomainFromEnv(t)
-	domain := acctest.ACMCertificateRandomSubDomain(rootDomain)
+	var v acm.CertificateDetail
 
 	resource.ParallelTest(t, resource.TestCase{
 		PreCheck:     func() { acctest.PreCheck(t) },
@@ -491,32 +529,23 @@ func TestAccACMCertificate_tags(t *testing.T) {
 		CheckDestroy: testAccCheckAcmCertificateDestroy,
 		Steps: []resource.TestStep{
 			{
-				Config: testAccAcmCertificateConfig(domain, acm.ValidationMethodDns),
-				Check: resource.ComposeTestCheckFunc(
-					resource.TestCheckResourceAttr(resourceName, "tags.%", "0"),
-				),
-			},
-			{
-				Config: testAccAcmCertificateConfig_twoTags(domain, acm.ValidationMethodDns, "Hello", "World", "Foo", "Bar"),
-				Check: resource.ComposeTestCheckFunc(
-					resource.TestCheckResourceAttr(resourceName, "tags.%", "2"),
-					resource.TestCheckResourceAttr(resourceName, "tags.Hello", "World"),
-					resource.TestCheckResourceAttr(resourceName, "tags.Foo", "Bar"),
-				),
-			},
-			{
-				Config: testAccAcmCertificateConfig_twoTags(domain, acm.ValidationMethodDns, "Hello", "World", "Foo", "Baz"),
-				Check: resource.ComposeTestCheckFunc(
-					resource.TestCheckResourceAttr(resourceName, "tags.%", "2"),
-					resource.TestCheckResourceAttr(resourceName, "tags.Hello", "World"),
-					resource.TestCheckResourceAttr(resourceName, "tags.Foo", "Baz"),
-				),
-			},
-			{
-				Config: testAccAcmCertificateConfig_oneTag(domain, acm.ValidationMethodDns, "Environment", "Test"),
+				Config: testAccAcmCertificateDisableCTLoggingConfig(rootDomain, acm.ValidationMethodDns),
 				Check: resource.ComposeTestCheckFunc(
-					resource.TestCheckResourceAttr(resourceName, "tags.%", "1"),
-					resource.TestCheckResourceAttr(resourceName, "tags.Environment", "Test"),
+					testAccCheckAcmCertificateExists(resourceName, &v),
+					acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "acm", regexp.MustCompile("certificate/.+$")),
+					resource.TestCheckResourceAttr(resourceName, "domain_name", rootDomain),
+					resource.TestCheckResourceAttr(resourceName, "domain_validation_options.#", "1"),
+					resource.TestCheckTypeSetElemNestedAttrs(resourceName, "domain_validation_options.*", map[string]string{
+						"domain_name":          rootDomain,
+						"resource_record_type": "CNAME",
+					}),
+					resource.TestCheckResourceAttr(resourceName, "subject_alternative_names.#", "1"),
+					resource.TestCheckTypeSetElemAttr(resourceName, "subject_alternative_names.*", rootDomain),
+					resource.TestCheckResourceAttr(resourceName, "status", acm.CertificateStatusPendingValidation),
+					resource.TestCheckResourceAttr(resourceName, "validation_emails.#", "0"),
+					resource.TestCheckResourceAttr(resourceName, "validation_method", acm.ValidationMethodDns),
+					resource.TestCheckResourceAttr(resourceName, "options.#", "1"),
+					resource.TestCheckResourceAttr(resourceName, "options.0.certificate_transparency_logging_preference", acm.CertificateTransparencyLoggingPreferenceDisabled),
 				),
 			},
 			{
@@ -531,18 +560,16 @@ func TestAccACMCertificate_tags(t *testing.T) {
 //lintignore:AT002
 func TestAccACMCertificate_Imported_domainName(t *testing.T) {
 	resourceName := "aws_acm_certificate.test"
-
 	commonName := "example.com"
 	caKey := acctest.TLSRSAPrivateKeyPEM(2048)
 	caCertificate := acctest.TLSRSAX509SelfSignedCACertificatePEM(caKey)
 	key := acctest.TLSRSAPrivateKeyPEM(2048)
 	certificate := acctest.TLSRSAX509LocallySignedCertificatePEM(caKey, caCertificate, key, commonName)
-
 	newCaKey := acctest.TLSRSAPrivateKeyPEM(2048)
 	newCaCertificate := acctest.TLSRSAX509SelfSignedCACertificatePEM(newCaKey)
 	newCertificate := acctest.TLSRSAX509LocallySignedCertificatePEM(newCaKey, newCaCertificate, key, commonName)
-
 	withoutChainDomain := acctest.RandomDomainName()
+	var v acm.CertificateDetail
 
 	resource.ParallelTest(t, resource.TestCase{
 		PreCheck:     func() { acctest.PreCheck(t) },
@@ -551,14 +578,15 @@ func TestAccACMCertificate_Imported_domainName(t *testing.T) {
 		CheckDestroy: testAccCheckAcmCertificateDestroy,
 		Steps: []resource.TestStep{
 			{
-				Config: testAccAcmCertificateConfigPrivateKey(certificate, key, caCertificate),
+				Config: testAccAcmCertificatePrivateKeyConfig(certificate, key, caCertificate),
 				Check: resource.ComposeTestCheckFunc(
+					testAccCheckAcmCertificateExists(resourceName, &v),
 					resource.TestCheckResourceAttr(resourceName, "tags.%", "0"),
 					resource.TestCheckResourceAttr(resourceName, "domain_name", commonName),
 				),
 			},
 			{
-				Config: testAccAcmCertificateConfigPrivateKey(newCertificate, key, newCaCertificate),
+				Config: testAccAcmCertificatePrivateKeyConfig(newCertificate, key, newCaCertificate),
 				Check: resource.ComposeTestCheckFunc(
 					resource.TestCheckResourceAttr(resourceName, "status", acm.CertificateStatusIssued),
 					resource.TestCheckResourceAttr(resourceName, "tags.%", "0"),
@@ -566,7 +594,7 @@ func TestAccACMCertificate_Imported_domainName(t *testing.T) {
 				),
 			},
 			{
-				Config: testAccAcmCertificateConfigPrivateKeyWithoutChain(withoutChainDomain),
+				Config: testAccAcmCertificatePrivateKeyWithoutChainConfig(withoutChainDomain),
 				Check: resource.ComposeTestCheckFunc(
 					resource.TestCheckResourceAttr(resourceName, "status", acm.CertificateStatusIssued),
 					resource.TestCheckResourceAttr(resourceName, "tags.%", "0"),
@@ -587,6 +615,7 @@ func TestAccACMCertificate_Imported_domainName(t *testing.T) {
 //lintignore:AT002
 func TestAccACMCertificate_Imported_ipAddress(t *testing.T) { // Reference: https://github.com/hashicorp/terraform-provider-aws/issues/7103
 	resourceName := "aws_acm_certificate.test"
+	var v acm.CertificateDetail
 
 	resource.ParallelTest(t, resource.TestCase{
 		PreCheck:     func() { acctest.PreCheck(t) },
@@ -595,8 +624,9 @@ func TestAccACMCertificate_Imported_ipAddress(t *testing.T) { // Reference: http
 		CheckDestroy: testAccCheckAcmCertificateDestroy,
 		Steps: []resource.TestStep{
 			{
-				Config: testAccAcmCertificateConfigPrivateKeyWithoutChain("1.2.3.4"),
+				Config: testAccAcmCertificatePrivateKeyWithoutChainConfig("1.2.3.4"),
 				Check: resource.ComposeTestCheckFunc(
+					testAccCheckAcmCertificateExists(resourceName, &v),
 					resource.TestCheckResourceAttr(resourceName, "domain_name", ""),
 					resource.TestCheckResourceAttr(resourceName, "status", acm.CertificateStatusIssued),
 					resource.TestCheckResourceAttr(resourceName, "subject_alternative_names.#", "0"),
@@ -616,6 +646,11 @@ func TestAccACMCertificate_Imported_ipAddress(t *testing.T) { // Reference: http
 // Reference: https://github.com/hashicorp/terraform-provider-aws/issues/15055
 func TestAccACMCertificate_PrivateKey_tags(t *testing.T) {
 	resourceName := "aws_acm_certificate.test"
+	key1 := acctest.TLSRSAPrivateKeyPEM(2048)
+	certificate1 := acctest.TLSRSAX509SelfSignedCertificatePEM(key1, "1.2.3.4")
+	key2 := acctest.TLSRSAPrivateKeyPEM(2048)
+	certificate2 := acctest.TLSRSAX509SelfSignedCertificatePEM(key2, "5.6.7.8")
+	var v acm.CertificateDetail
 
 	resource.ParallelTest(t, resource.TestCase{
 		PreCheck:     func() { acctest.PreCheck(t) },
@@ -624,9 +659,11 @@ func TestAccACMCertificate_PrivateKey_tags(t *testing.T) {
 		CheckDestroy: testAccCheckAcmCertificateDestroy,
 		Steps: []resource.TestStep{
 			{
-				Config: testAccAcmCertificateConfigPrivateKeyTags("1.2.3.4"),
+				Config: testAccAcmCertificateConfigTags1(certificate1, key1, "key1", "value1"),
 				Check: resource.ComposeTestCheckFunc(
+					testAccCheckAcmCertificateExists(resourceName, &v),
 					resource.TestCheckResourceAttr(resourceName, "tags.%", "1"),
+					resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1"),
 				),
 			},
 			{
@@ -636,25 +673,90 @@ func TestAccACMCertificate_PrivateKey_tags(t *testing.T) {
 				ImportStateVerifyIgnore: []string{"private_key", "certificate_body"},
 			},
 			{
-				Config: testAccAcmCertificateConfigPrivateKeyTags("5.6.7.8"),
+				Config: testAccAcmCertificateConfigTags2(certificate1, key1, "key1", "value1updated", "key2", "value2"),
+				Check: resource.ComposeTestCheckFunc(
+					resource.TestCheckResourceAttr(resourceName, "tags.%", "2"),
+					resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1updated"),
+					resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"),
+				),
+			},
+			{
+				Config: testAccAcmCertificateConfigTags1(certificate1, key1, "key2", "value2"),
 				Check: resource.ComposeTestCheckFunc(
 					resource.TestCheckResourceAttr(resourceName, "tags.%", "1"),
+					resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"),
+				),
+			},
+			{
+				Config: testAccAcmCertificateConfigTags1(certificate2, key2, "key1", "value1"),
+				Check: resource.ComposeTestCheckFunc(
+					resource.TestCheckResourceAttr(resourceName, "tags.%", "1"),
+					resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1"),
 				),
 			},
 		},
 	})
 }
 
+func testAccCheckAcmCertificateExists(n string, v *acm.CertificateDetail) resource.TestCheckFunc {
+	return func(s *terraform.State) error {
+		rs, ok := s.RootModule().Resources[n]
+		if !ok {
+			return fmt.Errorf("Not found: %s", n)
+		}
+
+		if rs.Primary.ID == "" {
+			return fmt.Errorf("No ACM Certificate ID is set")
+		}
+
+		conn := acctest.Provider.Meta().(*conns.AWSClient).ACMConn
+
+		output, err := tfacm.FindCertificateByARN(conn, rs.Primary.ID)
+
+		if err != nil {
+			return err
+		}
+
+		*v = *output
+
+		return nil
+	}
+}
+
+func testAccCheckAcmCertificateDestroy(s *terraform.State) error {
+	conn := acctest.Provider.Meta().(*conns.AWSClient).ACMConn
+
+	for _, rs := range s.RootModule().Resources {
+		if rs.Type != "aws_acm_certificate" {
+			continue
+		}
+
+		_, err := tfacm.FindCertificateByARN(conn, rs.Primary.ID)
+
+		if tfresource.NotFound(err) {
+			continue
+		}
+
+		if err != nil {
+			return err
+		}
+
+		return fmt.Errorf("ACM Certificate %s still exists", rs.Primary.ID)
+	}
+
+	return nil
+}
+
 func testAccAcmCertificateConfig(domainName, validationMethod string) string {
 	return fmt.Sprintf(`
-resource "aws_acm_certificate" "cert" {
+resource "aws_acm_certificate" "test" {
   domain_name       = "%s"
   validation_method = "%s"
 }
 `, domainName, validationMethod)
 }
 
-func testAccAcmCertificateConfig_privateCert(commonName, certificateDomainName string) string {
+func testAccAcmCertificatePrivateCertConfig(commonName, certificateDomainName string) string {
 	return fmt.Sprintf(`
 resource "aws_acmpca_certificate_authority" "test" {
   permanent_deletion_time_in_days = 7
@@ -670,51 +772,24 @@ resource "aws_acmpca_certificate_authority" "test" {
   }
 }
 
-resource "aws_acm_certificate" "cert" {
+resource "aws_acm_certificate" "test" {
   domain_name               = %[2]q
   certificate_authority_arn = aws_acmpca_certificate_authority.test.arn
 }
 `, commonName, certificateDomainName)
 }
 
-func testAccAcmCertificateConfig_subjectAlternativeNames(domainName, subjectAlternativeNames, validationMethod string) string {
+func testAccAcmCertificateSubjectAlternativeNamesConfig(domainName, subjectAlternativeNames, validationMethod string) string {
 	return fmt.Sprintf(`
-resource "aws_acm_certificate" "cert" {
-  domain_name               = "%s"
-  subject_alternative_names = [%s]
-  validation_method         = "%s"
+resource "aws_acm_certificate" "test" {
+  domain_name               = %[1]q
+  subject_alternative_names = [%[2]s]
+  validation_method         = %[3]q
 }
 `, domainName, subjectAlternativeNames, validationMethod)
 }
 
-func testAccAcmCertificateConfig_oneTag(domainName, validationMethod, tag1Key, tag1Value string) string {
-	return fmt.Sprintf(`
-resource "aws_acm_certificate" "cert" {
-  domain_name       = "%s"
-  validation_method = "%s"
-
-  tags = {
-    "%s" = "%s"
-  }
-}
-`, domainName, validationMethod, tag1Key, tag1Value)
-}
-
-func testAccAcmCertificateConfig_twoTags(domainName, validationMethod, tag1Key, tag1Value, tag2Key, tag2Value string) string {
-	return fmt.Sprintf(`
-resource "aws_acm_certificate" "cert" {
-  domain_name       = "%s"
-  validation_method = "%s"
-
-  tags = {
-    "%s" = "%s"
-    "%s" = "%s"
-  }
-}
-`, domainName, validationMethod, tag1Key, tag1Value, tag2Key, tag2Value)
-}
-
-func testAccAcmCertificateConfigPrivateKeyWithoutChain(commonName string) string {
+func testAccAcmCertificatePrivateKeyWithoutChainConfig(commonName string) string {
 	key := acctest.TLSRSAPrivateKeyPEM(2048)
 	certificate := acctest.TLSRSAX509SelfSignedCertificatePEM(key, commonName)
 
@@ -726,23 +801,34 @@ resource "aws_acm_certificate" "test" {
 `, acctest.TLSPEMEscapeNewlines(certificate), acctest.TLSPEMEscapeNewlines(key))
 }
 
-func testAccAcmCertificateConfigPrivateKeyTags(commonName string) string {
-	key := acctest.TLSRSAPrivateKeyPEM(2048)
-	certificate := acctest.TLSRSAX509SelfSignedCertificatePEM(key, commonName)
+func testAccAcmCertificateConfigTags1(certificate, key, tagKey1, tagValue1 string) string {
+	return fmt.Sprintf(`
+resource "aws_acm_certificate" "test" {
+  certificate_body = "%[1]s"
+  private_key      = "%[2]s"
 
+  tags = {
+    %[3]q = %[4]q
+  }
+}
+`, acctest.TLSPEMEscapeNewlines(certificate), acctest.TLSPEMEscapeNewlines(key), tagKey1, tagValue1)
+}
+
+func testAccAcmCertificateConfigTags2(certificate, key, tagKey1, tagValue1, tagKey2, tagValue2 string) string {
 	return fmt.Sprintf(`
 resource "aws_acm_certificate" "test" {
   certificate_body = "%[1]s"
   private_key      = "%[2]s"
 
   tags = {
-    key1 = "value1"
+    %[3]q = %[4]q
+    %[5]q = %[6]q
   }
 }
-`, acctest.TLSPEMEscapeNewlines(certificate), acctest.TLSPEMEscapeNewlines(key))
+`, acctest.TLSPEMEscapeNewlines(certificate), acctest.TLSPEMEscapeNewlines(key), tagKey1, tagValue1, tagKey2, tagValue2)
 }
 
-func testAccAcmCertificateConfigPrivateKey(certificate, privateKey, chain string) string {
+func testAccAcmCertificatePrivateKeyConfig(certificate, privateKey, chain string) string {
 	return fmt.Sprintf(`
 resource "aws_acm_certificate" "test" {
   certificate_body  = "%[1]s"
@@ -752,38 +838,15 @@ resource "aws_acm_certificate" "test" {
 `, acctest.TLSPEMEscapeNewlines(certificate), acctest.TLSPEMEscapeNewlines(privateKey), acctest.TLSPEMEscapeNewlines(chain))
 }
 
-func testAccAcmCertificateConfig_disableCTLogging(domainName, validationMethod string) string {
+func testAccAcmCertificateDisableCTLoggingConfig(domainName, validationMethod string) string {
 	return fmt.Sprintf(`
-resource "aws_acm_certificate" "cert" {
-  domain_name       = "%s"
-  validation_method = "%s"
+resource "aws_acm_certificate" "test" {
+  domain_name       = %[1]q
+  validation_method = %[2]q
+
   options {
     certificate_transparency_logging_preference = "DISABLED"
   }
 }
 `, domainName, validationMethod)
 }
-
-func testAccCheckAcmCertificateDestroy(s *terraform.State) error {
-	conn := acctest.Provider.Meta().(*conns.AWSClient).ACMConn
-
-	for _, rs := range s.RootModule().Resources {
-		if rs.Type != "aws_acm_certificate" {
-			continue
-		}
-		_, err := conn.DescribeCertificate(&acm.DescribeCertificateInput{
-			CertificateArn: aws.String(rs.Primary.ID),
-		})
-
-		if err == nil {
-			return fmt.Errorf("Certificate still exists.")
-		}
-
-		// Verify the error is what we want
-		if !tfawserr.ErrCodeEquals(err, acm.ErrCodeResourceNotFoundException) {
-			return err
-		}
-	}
-
-	return nil
-}
diff --git a/internal/service/acm/certificate_validation.go b/internal/service/acm/certificate_validation.go
index e1c9c738e780..c0d772a15e55 100644
--- a/internal/service/acm/certificate_validation.go
+++ b/internal/service/acm/certificate_validation.go
@@ -1,6 +1,7 @@
 package acm
 
 import (
+	"errors"
 	"fmt"
 	"log"
 	"strings"
@@ -8,7 +9,6 @@ import (
 
 	"github.com/aws/aws-sdk-go/aws"
 	"github.com/aws/aws-sdk-go/service/acm"
-	"github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr"
 	multierror "github.com/hashicorp/go-multierror"
 	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
 	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
@@ -20,7 +20,11 @@ func ResourceCertificateValidation() *schema.Resource {
 	return &schema.Resource{
 		Create: resourceCertificateValidationCreate,
 		Read:   resourceCertificateValidationRead,
-		Delete: resourceCertificateValidationDelete,
+		Delete: schema.Noop,
+
+		Timeouts: &schema.ResourceTimeout{
+			Create: schema.DefaultTimeout(75 * time.Minute),
+		},
 
 		Schema: map[string]*schema.Schema{
 			"certificate_arn": {
@@ -33,183 +37,142 @@ func ResourceCertificateValidation() *schema.Resource {
 				Optional: true,
 				ForceNew: true,
 				Elem:     &schema.Schema{Type: schema.TypeString},
-				Set:      schema.HashString,
 			},
 		},
-		Timeouts: &schema.ResourceTimeout{
-			Create: schema.DefaultTimeout(45 * time.Minute),
-		},
 	}
 }
 
 func resourceCertificateValidationCreate(d *schema.ResourceData, meta interface{}) error {
-	certificate_arn := d.Get("certificate_arn").(string)
-
 	conn := meta.(*conns.AWSClient).ACMConn
-	params := &acm.DescribeCertificateInput{
-		CertificateArn: aws.String(certificate_arn),
-	}
 
-	resp, err := conn.DescribeCertificate(params)
+	arn := d.Get("certificate_arn").(string)
+	certificate, err := FindCertificateByARN(conn, arn)
 
 	if err != nil {
-		return fmt.Errorf("Error describing certificate: %w", err)
-	}
-
-	if resp == nil || resp.Certificate == nil {
-		return fmt.Errorf("Error describing certificate: empty output")
+		return fmt.Errorf("reading ACM Certificate (%s): %w", arn, err)
 	}
 
-	if aws.StringValue(resp.Certificate.Type) != acm.CertificateTypeAmazonIssued {
-		return fmt.Errorf("Certificate %s has type %s, no validation necessary", aws.StringValue(resp.Certificate.CertificateArn), aws.StringValue(resp.Certificate.Status))
+	if v := aws.StringValue(certificate.Type); v != acm.CertificateTypeAmazonIssued {
+		return fmt.Errorf("ACM Certificate (%s) has type %s, no validation necessary", arn, v)
 	}
 
-	if validation_record_fqdns, ok := d.GetOk("validation_record_fqdns"); ok {
-		err := resourceCertificateCheckValidationRecords(validation_record_fqdns.(*schema.Set).List(), resp.Certificate, conn)
-		if err != nil {
-			return err
-		}
-	} else {
-		log.Printf("[INFO] No validation_record_fqdns set, skipping check")
-	}
+	if v, ok := d.GetOk("validation_record_fqdns"); ok && v.(*schema.Set).Len() > 0 {
+		fqdns := make(map[string]*acm.DomainValidation)
 
-	err = resource.Retry(d.Timeout(schema.TimeoutCreate), func() *resource.RetryError {
-		resp, err := conn.DescribeCertificate(params)
+		for _, domainValidation := range certificate.DomainValidationOptions {
+			if v := aws.StringValue(domainValidation.ValidationMethod); v != acm.ValidationMethodDns {
+				return fmt.Errorf("validation_record_fqdns is not valid for %s validation", v)
+			}
 
-		if err != nil {
-			return resource.NonRetryableError(fmt.Errorf("Error describing certificate: %w", err))
+			if v := domainValidation.ResourceRecord; v != nil {
+				if v := aws.StringValue(v.Name); v != "" {
+					fqdns[strings.TrimSuffix(v, ".")] = domainValidation
+				}
+			}
 		}
 
-		if aws.StringValue(resp.Certificate.Status) != acm.CertificateStatusIssued {
-			return resource.RetryableError(fmt.Errorf("Expected certificate to be issued but was in state %s", aws.StringValue(resp.Certificate.Status)))
+		for _, v := range v.(*schema.Set).List() {
+			delete(fqdns, strings.TrimSuffix(v.(string), "."))
 		}
 
-		log.Printf("[INFO] ACM Certificate validation for %s done, certificate was issued", certificate_arn)
-		if err := resourceCertificateValidationRead(d, meta); err != nil {
-			return resource.NonRetryableError(err)
-		}
-		return nil
-	})
-	if tfresource.TimedOut(err) {
-		resp, err = conn.DescribeCertificate(params)
-		if aws.StringValue(resp.Certificate.Status) != acm.CertificateStatusIssued {
-			return fmt.Errorf("Expected certificate to be issued but was in state %s", aws.StringValue(resp.Certificate.Status))
-		}
-	}
-	if err != nil {
-		return fmt.Errorf("Error describing created certificate: %w", err)
-	}
-	return nil
-}
+		if len(fqdns) > 0 {
+			var errs *multierror.Error
 
-func resourceCertificateCheckValidationRecords(validationRecordFqdns []interface{}, cert *acm.CertificateDetail, conn *acm.ACM) error {
-	expectedFqdns := make(map[string]*acm.DomainValidation)
-
-	if len(cert.DomainValidationOptions) == 0 {
-		input := &acm.DescribeCertificateInput{
-			CertificateArn: cert.CertificateArn,
-		}
-		var err error
-		var output *acm.DescribeCertificateOutput
-		err = resource.Retry(1*time.Minute, func() *resource.RetryError {
-			log.Printf("[DEBUG] Certificate domain validation options empty for %s, retrying", aws.StringValue(cert.CertificateArn))
-			output, err = conn.DescribeCertificate(input)
-			if err != nil {
-				return resource.NonRetryableError(err)
-			}
-			if len(output.Certificate.DomainValidationOptions) == 0 {
-				return resource.RetryableError(fmt.Errorf("Certificate domain validation options empty for %s", aws.StringValue(cert.CertificateArn)))
+			for fqdn, domainValidation := range fqdns {
+				errs = multierror.Append(errs, fmt.Errorf("missing %s DNS validation record: %s", aws.StringValue(domainValidation.DomainName), fqdn))
 			}
-			cert = output.Certificate
-			return nil
-		})
-		if tfresource.TimedOut(err) {
-			output, err = conn.DescribeCertificate(input)
-			if err != nil {
-				return fmt.Errorf("Error describing ACM certificate: %w", err)
-			}
-			if len(output.Certificate.DomainValidationOptions) == 0 {
-				return fmt.Errorf("Certificate domain validation options empty for %s", aws.StringValue(cert.CertificateArn))
-			}
-		}
-		if err != nil {
-			return fmt.Errorf("Error checking certificate domain validation options: %w", err)
-		}
-		if output == nil || output.Certificate == nil {
-			return fmt.Errorf("Error checking certificate domain validation options: empty output")
-		}
 
-		cert = output.Certificate
-	}
-	for _, v := range cert.DomainValidationOptions {
-		if v.ValidationMethod != nil {
-			if aws.StringValue(v.ValidationMethod) != acm.ValidationMethodDns {
-				return fmt.Errorf("validation_record_fqdns is only valid for DNS validation")
-			}
-			if v.ResourceRecord != nil && aws.StringValue(v.ResourceRecord.Name) != "" {
-				newExpectedFqdn := strings.TrimSuffix(aws.StringValue(v.ResourceRecord.Name), ".")
-				expectedFqdns[newExpectedFqdn] = v
-			}
-		} else if len(v.ValidationEmails) > 0 {
-			// ACM API sometimes is not sending ValidationMethod for EMAIL validation
-			return fmt.Errorf("validation_record_fqdns is only valid for DNS validation")
+			return errs
 		}
 	}
 
-	for _, v := range validationRecordFqdns {
-		delete(expectedFqdns, strings.TrimSuffix(v.(string), "."))
+	if _, err := waitCertificateIssued(conn, arn, d.Timeout(schema.TimeoutCreate)); err != nil {
+		return fmt.Errorf("waiting for ACM Certificate (%s) to be issued: %w", arn, err)
 	}
 
-	if len(expectedFqdns) > 0 {
-		var errors error
-		for expectedFqdn, domainValidation := range expectedFqdns {
-			errors = multierror.Append(errors, fmt.Errorf("missing %s DNS validation record: %s", aws.StringValue(domainValidation.DomainName), expectedFqdn))
-		}
-		return errors
-	}
+	d.SetId(arn)
 
-	return nil
+	return resourceCertificateValidationRead(d, meta)
 }
 
 func resourceCertificateValidationRead(d *schema.ResourceData, meta interface{}) error {
 	conn := meta.(*conns.AWSClient).ACMConn
 
-	params := &acm.DescribeCertificateInput{
-		CertificateArn: aws.String(d.Get("certificate_arn").(string)),
-	}
+	certificate, err := FindCertificateValidationByARN(conn, d.Id())
 
-	resp, err := conn.DescribeCertificate(params)
-
-	if !d.IsNewResource() && tfawserr.ErrCodeEquals(err, acm.ErrCodeResourceNotFoundException) {
-		log.Printf("[WARN] ACM Certificate (%s) not found, removing from state", d.Id())
+	if !d.IsNewResource() && tfresource.NotFound(err) {
+		log.Printf("[WARN] ACM Certificate %s not found, removing from state", d.Id())
 		d.SetId("")
 		return nil
 	}
 
 	if err != nil {
-		return fmt.Errorf("error describing ACM Certificate (%s): %w", d.Id(), err)
+		return fmt.Errorf("reading ACM Certificate (%s): %w", d.Id(), err)
 	}
 
-	if resp == nil || resp.Certificate == nil {
-		return fmt.Errorf("error describing ACM Certificate (%s): empty response", d.Id())
+	d.Set("certificate_arn", certificate.CertificateArn)
+
+	return nil
+}
+
+func FindCertificateValidationByARN(conn *acm.ACM, arn string) (*acm.CertificateDetail, error) {
+	output, err := FindCertificateByARN(conn, arn)
+
+	if err != nil {
+		return nil, err
 	}
 
-	if status := aws.StringValue(resp.Certificate.Status); status != acm.CertificateStatusIssued {
-		if d.IsNewResource() {
-			return fmt.Errorf("ACM Certificate (%s) status not issued: %s", d.Id(), status)
+	if status := aws.StringValue(output.Status); status != acm.CertificateStatusIssued {
+		return nil, &resource.NotFoundError{
+			Message:     status,
+			LastRequest: arn,
 		}
-
-		log.Printf("[WARN] ACM Certificate (%s) status not issued (%s), removing from state", d.Id(), status)
-		d.SetId("")
-		return nil
 	}
 
-	d.SetId(aws.TimeValue(resp.Certificate.IssuedAt).String())
+	return output, nil
+}
 
-	return nil
+func statusCertificate(conn *acm.ACM, arn string) resource.StateRefreshFunc {
+	return func() (interface{}, string, error) {
+		// Don't call FindCertificateByARN as it maps useful status codes to NotFoundError.
+		input := &acm.DescribeCertificateInput{
+			CertificateArn: aws.String(arn),
+		}
+
+		output, err := findCertificate(conn, input)
+
+		if tfresource.NotFound(err) {
+			return nil, "", nil
+		}
+
+		if err != nil {
+			return nil, "", err
+		}
+
+		return output, aws.StringValue(output.Status), nil
+	}
 }
 
-func resourceCertificateValidationDelete(d *schema.ResourceData, meta interface{}) error {
-	// No need to do anything, certificate will be deleted when acm_certificate is deleted
-	return nil
+func waitCertificateIssued(conn *acm.ACM, arn string, timeout time.Duration) (*acm.CertificateDetail, error) {
+	stateConf := &resource.StateChangeConf{
+		Pending: []string{acm.CertificateStatusPendingValidation},
+		Target:  []string{acm.CertificateStatusIssued},
+		Refresh: statusCertificate(conn, arn),
+		Timeout: timeout,
+	}
+
+	outputRaw, err := stateConf.WaitForState()
+
+	if output, ok := outputRaw.(*acm.CertificateDetail); ok {
+		switch aws.StringValue(output.Status) {
+		case acm.CertificateStatusFailed:
+			tfresource.SetLastError(err, errors.New(aws.StringValue(output.FailureReason)))
+		case acm.CertificateStatusRevoked:
+			tfresource.SetLastError(err, errors.New(aws.StringValue(output.RevocationReason)))
+		}
+
+		return output, err
+	}
+
+	return nil, err
 }
diff --git a/internal/service/acm/certificate_validation_test.go b/internal/service/acm/certificate_validation_test.go
index 4a0aa0fe5002..bbac5bf94fc0 100644
--- a/internal/service/acm/certificate_validation_test.go
+++ b/internal/service/acm/certificate_validation_test.go
@@ -8,7 +8,10 @@ import (
 
 	"github.com/aws/aws-sdk-go/service/acm"
 	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
+	"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
 	"github.com/hashicorp/terraform-provider-aws/internal/acctest"
+	"github.com/hashicorp/terraform-provider-aws/internal/conns"
+	tfacm "github.com/hashicorp/terraform-provider-aws/internal/service/acm"
 )
 
 func TestAccACMCertificateValidation_basic(t *testing.T) {
@@ -25,8 +28,9 @@ func TestAccACMCertificateValidation_basic(t *testing.T) {
 		Steps: []resource.TestStep{
 			// Test that validation succeeds
 			{
-				Config: testAccAcmCertificateValidation_basic(rootDomain, domain),
+				Config: testAccAcmCertificateValidationConfig(rootDomain, domain),
 				Check: resource.ComposeTestCheckFunc(
+					testAccCheckAcmCertificateValidationExists(resourceName),
 					resource.TestCheckResourceAttrPair(resourceName, "certificate_arn", certificateResourceName, "arn"),
 				),
 			},
@@ -45,8 +49,8 @@ func TestAccACMCertificateValidation_timeout(t *testing.T) {
 		CheckDestroy: testAccCheckAcmCertificateDestroy,
 		Steps: []resource.TestStep{
 			{
-				Config:      testAccAcmCertificateValidation_timeout(domain),
-				ExpectError: regexp.MustCompile("Expected certificate to be issued but was in state PENDING_VALIDATION"),
+				Config:      testAccAcmCertificateValidationTimeoutConfig(domain),
+				ExpectError: regexp.MustCompile(`timeout while waiting for state to become 'ISSUED' \(last state: 'PENDING_VALIDATION'`),
 			},
 		},
 	})
@@ -66,13 +70,14 @@ func TestAccACMCertificateValidation_validationRecordFQDNS(t *testing.T) {
 		Steps: []resource.TestStep{
 			// Test that validation fails if given validation_fqdns don't match
 			{
-				Config:      testAccAcmCertificateValidation_validationRecordFqdnsWrongFqdn(domain),
+				Config:      testAccAcmCertificateValidationValidationRecordFQDNsWrongFQDNConfig(domain),
 				ExpectError: regexp.MustCompile("missing .+ DNS validation record: .+"),
 			},
 			// Test that validation succeeds with validation
 			{
-				Config: testAccAcmCertificateValidation_validationRecordFqdnsOneRoute53Record(rootDomain, domain),
+				Config: testAccAcmCertificateValidationValidationRecordFQDNsOneRoute53RecordConfig(rootDomain, domain),
 				Check: resource.ComposeTestCheckFunc(
+					testAccCheckAcmCertificateValidationExists(resourceName),
 					resource.TestCheckResourceAttrPair(resourceName, "certificate_arn", certificateResourceName, "arn"),
 				),
 			},
@@ -91,8 +96,8 @@ func TestAccACMCertificateValidation_validationRecordFQDNSEmail(t *testing.T) {
 		CheckDestroy: testAccCheckAcmCertificateDestroy,
 		Steps: []resource.TestStep{
 			{
-				Config:      testAccAcmCertificateValidation_validationRecordFqdnsEmailValidation(domain),
-				ExpectError: regexp.MustCompile("validation_record_fqdns is only valid for DNS validation"),
+				Config:      testAccAcmCertificateValidationValidationRecordFQDNsEmailValidationConfig(domain),
+				ExpectError: regexp.MustCompile("validation_record_fqdns is not valid for EMAIL validation"),
 			},
 		},
 	})
@@ -110,8 +115,9 @@ func TestAccACMCertificateValidation_validationRecordFQDNSRoot(t *testing.T) {
 		CheckDestroy: testAccCheckAcmCertificateDestroy,
 		Steps: []resource.TestStep{
 			{
-				Config: testAccAcmCertificateValidation_validationRecordFqdnsOneRoute53Record(rootDomain, rootDomain),
+				Config: testAccAcmCertificateValidationValidationRecordFQDNsOneRoute53RecordConfig(rootDomain, rootDomain),
 				Check: resource.ComposeTestCheckFunc(
+					testAccCheckAcmCertificateValidationExists(resourceName),
 					resource.TestCheckResourceAttrPair(resourceName, "certificate_arn", certificateResourceName, "arn"),
 				),
 			},
@@ -132,8 +138,9 @@ func TestAccACMCertificateValidation_validationRecordFQDNSRootAndWildcard(t *tes
 		CheckDestroy: testAccCheckAcmCertificateDestroy,
 		Steps: []resource.TestStep{
 			{
-				Config: testAccAcmCertificateValidation_validationRecordFqdnsTwoRoute53Records(rootDomain, rootDomain, strconv.Quote(wildcardDomain)),
+				Config: testAccAcmCertificateValidationValidationRecordFQDNsTwoRoute53RecordsConfig(rootDomain, rootDomain, strconv.Quote(wildcardDomain)),
 				Check: resource.ComposeTestCheckFunc(
+					testAccCheckAcmCertificateValidationExists(resourceName),
 					resource.TestCheckResourceAttrPair(resourceName, "certificate_arn", certificateResourceName, "arn"),
 				),
 			},
@@ -155,8 +162,9 @@ func TestAccACMCertificateValidation_validationRecordFQDNSSan(t *testing.T) {
 		CheckDestroy: testAccCheckAcmCertificateDestroy,
 		Steps: []resource.TestStep{
 			{
-				Config: testAccAcmCertificateValidation_validationRecordFqdnsTwoRoute53Records(rootDomain, domain, strconv.Quote(sanDomain)),
+				Config: testAccAcmCertificateValidationValidationRecordFQDNsTwoRoute53RecordsConfig(rootDomain, domain, strconv.Quote(sanDomain)),
 				Check: resource.ComposeTestCheckFunc(
+					testAccCheckAcmCertificateValidationExists(resourceName),
 					resource.TestCheckResourceAttrPair(resourceName, "certificate_arn", certificateResourceName, "arn"),
 				),
 			},
@@ -177,10 +185,12 @@ func TestAccACMCertificateValidation_validationRecordFQDNSWildcard(t *testing.T)
 		CheckDestroy: testAccCheckAcmCertificateDestroy,
 		Steps: []resource.TestStep{
 			{
-				Config: testAccAcmCertificateValidation_validationRecordFqdnsOneRoute53Record(rootDomain, wildcardDomain),
+				Config: testAccAcmCertificateValidationValidationRecordFQDNsOneRoute53RecordConfig(rootDomain, wildcardDomain),
 				Check: resource.ComposeTestCheckFunc(
+					testAccCheckAcmCertificateValidationExists(resourceName),
 					resource.TestCheckResourceAttrPair(resourceName, "certificate_arn", certificateResourceName, "arn"),
 				),
+				// ExpectNonEmptyPlan: true, // https://github.com/hashicorp/terraform-provider-aws/issues/16913
 			},
 		},
 	})
@@ -199,16 +209,41 @@ func TestAccACMCertificateValidation_validationRecordFQDNSWildcardAndRoot(t *tes
 		CheckDestroy: testAccCheckAcmCertificateDestroy,
 		Steps: []resource.TestStep{
 			{
-				Config: testAccAcmCertificateValidation_validationRecordFqdnsTwoRoute53Records(rootDomain, wildcardDomain, strconv.Quote(rootDomain)),
+				Config: testAccAcmCertificateValidationValidationRecordFQDNsTwoRoute53RecordsConfig(rootDomain, wildcardDomain, strconv.Quote(rootDomain)),
 				Check: resource.ComposeTestCheckFunc(
+					testAccCheckAcmCertificateValidationExists(resourceName),
 					resource.TestCheckResourceAttrPair(resourceName, "certificate_arn", certificateResourceName, "arn"),
 				),
+				// ExpectNonEmptyPlan: true, // https://github.com/hashicorp/terraform-provider-aws/issues/16913
 			},
 		},
 	})
 }
 
-func testAccAcmCertificateValidation_basic(rootZoneDomain, domainName string) string {
+func testAccCheckAcmCertificateValidationExists(n string) resource.TestCheckFunc {
+	return func(s *terraform.State) error {
+		rs, ok := s.RootModule().Resources[n]
+		if !ok {
+			return fmt.Errorf("Not found: %s", n)
+		}
+
+		if rs.Primary.ID == "" {
+			return fmt.Errorf("No ACM Certificate Validation ID is set")
+		}
+
+		conn := acctest.Provider.Meta().(*conns.AWSClient).ACMConn
+
+		_, err := tfacm.FindCertificateValidationByARN(conn, rs.Primary.ID)
+
+		if err != nil {
+			return err
+		}
+
+		return nil
+	}
+}
+
+func testAccAcmCertificateValidationConfig(rootZoneDomain, domainName string) string {
 	return fmt.Sprintf(`
 resource "aws_acm_certificate" "test" {
   domain_name       = %[1]q
@@ -257,7 +292,7 @@ resource "aws_acm_certificate_validation" "test" {
 `, domainName, rootZoneDomain)
 }
 
-func testAccAcmCertificateValidation_timeout(domainName string) string {
+func testAccAcmCertificateValidationTimeoutConfig(domainName string) string {
 	return fmt.Sprintf(`
 resource "aws_acm_certificate" "test" {
   domain_name       = %[1]q
@@ -274,7 +309,7 @@ resource "aws_acm_certificate_validation" "test" {
 `, domainName)
 }
 
-func testAccAcmCertificateValidation_validationRecordFqdnsEmailValidation(domainName string) string {
+func testAccAcmCertificateValidationValidationRecordFQDNsEmailValidationConfig(domainName string) string {
 	return fmt.Sprintf(`
 resource "aws_acm_certificate" "test" {
   domain_name       = %[1]q
@@ -288,7 +323,7 @@ resource "aws_acm_certificate_validation" "test" {
 `, domainName)
 }
 
-func testAccAcmCertificateValidation_validationRecordFqdnsOneRoute53Record(rootZoneDomain, domainName string) string {
+func testAccAcmCertificateValidationValidationRecordFQDNsOneRoute53RecordConfig(rootZoneDomain, domainName string) string {
 	return fmt.Sprintf(`
 resource "aws_acm_certificate" "test" {
   domain_name       = %[1]q
@@ -341,7 +376,7 @@ resource "aws_acm_certificate_validation" "test" {
 `, domainName, rootZoneDomain)
 }
 
-func testAccAcmCertificateValidation_validationRecordFqdnsTwoRoute53Records(rootZoneDomain, domainName, subjectAlternativeNames string) string {
+func testAccAcmCertificateValidationValidationRecordFQDNsTwoRoute53RecordsConfig(rootZoneDomain, domainName, subjectAlternativeNames string) string {
 	return fmt.Sprintf(`
 resource "aws_acm_certificate" "test" {
   domain_name               = %[1]q
@@ -404,7 +439,7 @@ resource "aws_acm_certificate_validation" "test" {
 `, domainName, subjectAlternativeNames, rootZoneDomain)
 }
 
-func testAccAcmCertificateValidation_validationRecordFqdnsWrongFqdn(domainName string) string {
+func testAccAcmCertificateValidationValidationRecordFQDNsWrongFQDNConfig(domainName string) string {
 	return fmt.Sprintf(`
 resource "aws_acm_certificate" "test" {
   domain_name       = %[1]q
diff --git a/website/docs/r/acm_certificate_validation.html.markdown b/website/docs/r/acm_certificate_validation.html.markdown
index 5d68e0a8e34a..d9602205d6b0 100644
--- a/website/docs/r/acm_certificate_validation.html.markdown
+++ b/website/docs/r/acm_certificate_validation.html.markdown
@@ -144,4 +144,4 @@ In addition to all arguments above, the following attributes are exported:
 `acm_certificate_validation` provides the following [Timeouts](https://www.terraform.io/docs/configuration/blocks/resources/syntax.html#operation-timeouts)
 configuration options:
 
-- `create` - (Default `45m`) How long to wait for a certificate to be issued.
+- `create` - (Default `75m`) How long to wait for a certificate to be issued.