Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

tests/resource/aws_cognito_user_pool_domain: Remove hardcoded region handling and create public ACM Certificate #16140

Merged
merged 1 commit into from
Nov 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions aws/cognito_user_pool_domain_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package aws

import (
"context"
"sync"
"testing"

"github.com/aws/aws-sdk-go/aws/endpoints"
"github.com/aws/aws-sdk-go/service/cognitoidentityprovider"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
)

// Cognito User Pool Custom Domains can only be created with ACM Certificates in specific regions.

// testAccCognitoUserPoolCustomDomainRegion is the chosen Cognito User Pool Custom Domains testing region
//
// Cached to prevent issues should multiple regions become available.
var testAccCognitoUserPoolCustomDomainRegion string

// testAccProviderCognitoUserPoolCustomDomain is the Cognito User Pool Custom Domains provider instance
//
// This Provider can be used in testing code for API calls without requiring
// the use of saving and referencing specific ProviderFactories instances.
//
// testAccPreCheckCognitoUserPoolCustomDomain(t) must be called before using this provider instance.
var testAccProviderCognitoUserPoolCustomDomain *schema.Provider

// testAccProviderCognitoUserPoolCustomDomainConfigure ensures the provider is only configured once
var testAccProviderCognitoUserPoolCustomDomainConfigure sync.Once

// testAccPreCheckCognitoUserPoolCustomDomain verifies AWS credentials and that Cognito User Pool Custom Domains is supported
func testAccPreCheckCognitoUserPoolCustomDomain(t *testing.T) {
testAccPartitionHasServicePreCheck(cognitoidentityprovider.EndpointsID, t)

// Since we are outside the scope of the Terraform configuration we must
// call Configure() to properly initialize the provider configuration.
testAccProviderCognitoUserPoolCustomDomainConfigure.Do(func() {
testAccProviderCognitoUserPoolCustomDomain = Provider()

region := testAccGetCognitoUserPoolCustomDomainRegion()

if region == "" {
t.Skip("Cognito User Pool Custom Domains not available in this AWS Partition")
}

config := map[string]interface{}{
"region": region,
}

diags := testAccProviderCognitoUserPoolCustomDomain.Configure(context.Background(), terraform.NewResourceConfigRaw(config))

if diags != nil && diags.HasError() {
for _, d := range diags {
if d.Severity == diag.Error {
t.Fatalf("error configuring Cognito User Pool Custom Domains provider: %s", d.Summary)
}
}
}
})
}

// testAccCognitoUserPoolCustomDomainRegionProviderConfig is the Terraform provider configuration for Cognito User Pool Custom Domains region testing
//
// Testing Cognito User Pool Custom Domains assumes no other provider configurations
// are necessary and overwrites the "aws" provider configuration.
func testAccCognitoUserPoolCustomDomainRegionProviderConfig() string {
return testAccRegionalProviderConfig(testAccGetCognitoUserPoolCustomDomainRegion())
}

// testAccGetCognitoUserPoolCustomDomainRegion returns the Cognito User Pool Custom Domains region for testing
func testAccGetCognitoUserPoolCustomDomainRegion() string {
if testAccCognitoUserPoolCustomDomainRegion != "" {
return testAccCognitoUserPoolCustomDomainRegion
}

// AWS Commercial: https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-add-custom-domain.html
// AWS GovCloud (US) - not supported: https://docs.aws.amazon.com/govcloud-us/latest/UserGuide/govcloud-cog.html
// AWS China - not supported: https://docs.amazonaws.cn/en_us/aws/latest/userguide/cognito.html
switch testAccGetPartition() {
case endpoints.AwsPartitionID:
testAccCognitoUserPoolCustomDomainRegion = endpoints.UsEast1RegionID
}

return testAccCognitoUserPoolCustomDomainRegion
}
5 changes: 3 additions & 2 deletions aws/resource_aws_acm_certificate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,13 @@ func testAccAwsAcmCertificateDomainFromEnv(t *testing.T) string {
}

// ACM domain names cannot be longer than 64 characters
// Other resources, e.g. Cognito User Pool Domains, limit this to 63
func testAccAwsAcmCertificateRandomSubDomain(rootDomain string) string {
// Max length (64)
// Max length (63)
// Subtract "tf-acc-" prefix (7)
// Subtract "." between prefix and root domain (1)
// Subtract length of root domain
return fmt.Sprintf("tf-acc-%s.%s", acctest.RandString(56-len(rootDomain)), rootDomain)
return fmt.Sprintf("tf-acc-%s.%s", acctest.RandString(55-len(rootDomain)), rootDomain)
}

func TestAccAWSAcmCertificate_emailValidation(t *testing.T) {
Expand Down
124 changes: 80 additions & 44 deletions aws/resource_aws_cognito_user_pool_domain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"errors"
"fmt"
"log"
"os"
"regexp"
"testing"

"github.com/aws/aws-sdk-go/aws"
Expand Down Expand Up @@ -104,49 +104,38 @@ func TestAccAWSCognitoUserPoolDomain_basic(t *testing.T) {
}

func TestAccAWSCognitoUserPoolDomain_custom(t *testing.T) {
rootDomain := testAccAwsAcmCertificateDomainFromEnv(t)
domain := testAccAwsAcmCertificateRandomSubDomain(rootDomain)
poolName := fmt.Sprintf("tf-acc-test-pool-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum))
// This test must always run in us-east-1
// BadRequestException: Invalid certificate ARN: arn:aws:acm:us-west-2:123456789012:certificate/xxxxx. Certificate must be in 'us-east-1'.
oldvar := os.Getenv("AWS_DEFAULT_REGION")
os.Setenv("AWS_DEFAULT_REGION", "us-east-1")
defer os.Setenv("AWS_DEFAULT_REGION", oldvar)

customDomainName := os.Getenv("AWS_COGNITO_USER_POOL_DOMAIN_ROOT_DOMAIN")
if customDomainName == "" {
t.Skip(
"Environment variable AWS_COGNITO_USER_POOL_DOMAIN_ROOT_DOMAIN is not set. " +
"This environment variable must be set to the fqdn of " +
"an ISSUED ACM certificate in us-east-1 to enable this test.")
}

customSubDomainName := fmt.Sprintf("%s.%s", fmt.Sprintf("tf-acc-test-domain-%d", acctest.RandInt()), customDomainName)
// For now, use an environment variable to limit running this test
certificateArn := os.Getenv("AWS_COGNITO_USER_POOL_DOMAIN_CERTIFICATE_ARN")
if certificateArn == "" {
t.Skip(
"Environment variable AWS_COGNITO_USER_POOL_DOMAIN_CERTIFICATE_ARN is not set. " +
"This environment variable must be set to the ARN of " +
"an ISSUED ACM certificate in us-east-1 to enable this test.")
}
acmCertificateResourceName := "aws_acm_certificate.test"
cognitoUserPoolResourceName := "aws_cognito_user_pool.test"
resourceName := "aws_cognito_user_pool_domain.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSCognitoIdentityProvider(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSCognitoUserPoolDomainDestroy,
PreCheck: func() { testAccPreCheck(t); testAccPreCheckCognitoUserPoolCustomDomain(t) },
ProviderFactories: testAccProviderFactories,
CheckDestroy: testAccCheckAWSCognitoUserPoolDomainDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSCognitoUserPoolDomainConfig_custom(customSubDomainName, poolName, certificateArn),
Config: testAccAWSCognitoUserPoolDomainConfig_custom(rootDomain, domain, poolName),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckAWSCognitoUserPoolDomainExists("aws_cognito_user_pool_domain.main"),
resource.TestCheckResourceAttr("aws_cognito_user_pool_domain.main", "domain", customSubDomainName),
resource.TestCheckResourceAttr("aws_cognito_user_pool_domain.main", "certificate_arn", certificateArn),
resource.TestCheckResourceAttr("aws_cognito_user_pool.main", "name", poolName),
resource.TestCheckResourceAttrSet("aws_cognito_user_pool_domain.main", "aws_account_id"),
resource.TestCheckResourceAttrSet("aws_cognito_user_pool_domain.main", "cloudfront_distribution_arn"),
resource.TestCheckResourceAttrSet("aws_cognito_user_pool_domain.main", "s3_bucket"),
resource.TestCheckResourceAttrSet("aws_cognito_user_pool_domain.main", "version"),
testAccCheckAWSCognitoUserPoolDomainExists(resourceName),
testAccCheckResourceAttrAccountID(resourceName, "aws_account_id"),
resource.TestCheckResourceAttrPair(resourceName, "certificate_arn", acmCertificateResourceName, "arn"),
//lintignore:AWSAT001 // Reference: https://github.com/hashicorp/terraform-provider-aws/issues/11666
resource.TestMatchResourceAttr(resourceName, "cloudfront_distribution_arn", regexp.MustCompile(`[a-z0-9]+.cloudfront.net$`)),
resource.TestCheckResourceAttrPair(resourceName, "domain", acmCertificateResourceName, "domain_name"),
resource.TestMatchResourceAttr(resourceName, "s3_bucket", regexp.MustCompile(`^.+$`)),
resource.TestCheckResourceAttrPair(resourceName, "user_pool_id", cognitoUserPoolResourceName, "id"),
resource.TestMatchResourceAttr(resourceName, "version", regexp.MustCompile(`^.+$`)),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}
Expand Down Expand Up @@ -230,16 +219,63 @@ resource "aws_cognito_user_pool" "main" {
`, domainName, poolName)
}

func testAccAWSCognitoUserPoolDomainConfig_custom(customSubDomainName, poolName, certificateArn string) string {
return fmt.Sprintf(`
resource "aws_cognito_user_pool_domain" "main" {
domain = "%s"
user_pool_id = aws_cognito_user_pool.main.id
certificate_arn = "%s"
func testAccAWSCognitoUserPoolDomainConfig_custom(rootDomain string, domain string, poolName string) string {
return composeConfig(
testAccCognitoUserPoolCustomDomainRegionProviderConfig(),
fmt.Sprintf(`
data "aws_route53_zone" "test" {
name = %[1]q
private_zone = false
}

resource "aws_cognito_user_pool" "main" {
name = "%s"
resource "aws_acm_certificate" "test" {
domain_name = %[2]q
validation_method = "DNS"
}

#
# for_each acceptance testing requires:
# https://github.com/hashicorp/terraform-plugin-sdk/issues/536
#
# resource "aws_route53_record" "test" {
# for_each = {
# for dvo in aws_acm_certificate.test.domain_validation_options: dvo.domain_name => {
# name = dvo.resource_record_name
# record = dvo.resource_record_value
# type = dvo.resource_record_type
# }
# }

# allow_overwrite = true
# name = each.value.name
# records = [each.value.record]
# ttl = 60
# type = each.value.type
# zone_id = data.aws_route53_zone.test.zone_id
# }

resource "aws_route53_record" "test" {
allow_overwrite = true
name = tolist(aws_acm_certificate.test.domain_validation_options)[0].resource_record_name
records = [tolist(aws_acm_certificate.test.domain_validation_options)[0].resource_record_value]
ttl = 60
type = tolist(aws_acm_certificate.test.domain_validation_options)[0].resource_record_type
zone_id = data.aws_route53_zone.test.zone_id
}

resource "aws_acm_certificate_validation" "test" {
certificate_arn = aws_acm_certificate.test.arn
validation_record_fqdns = [aws_route53_record.test.fqdn]
}

resource "aws_cognito_user_pool" "test" {
name = %[3]q
}

resource "aws_cognito_user_pool_domain" "test" {
certificate_arn = aws_acm_certificate_validation.test.certificate_arn
domain = aws_acm_certificate.test.domain_name
user_pool_id = aws_cognito_user_pool.test.id
}
`, customSubDomainName, certificateArn, poolName)
`, rootDomain, domain, poolName))
}
2 changes: 0 additions & 2 deletions docs/MAINTAINING.md
Original file line number Diff line number Diff line change
Expand Up @@ -400,8 +400,6 @@ Environment variables (beyond standard AWS Go SDK ones) used by acceptance testi
| `AWS_API_GATEWAY_DOMAIN_NAME_REGIONAL_CERTIFICATE_NAME_ENABLED` | Flag to enable API Gateway Domain Name regional certificate upload testing. |
| `AWS_CODEBUILD_BITBUCKET_SOURCE_LOCATION` | BitBucket source URL for CodeBuild testing. CodeBuild must have access to this repository via OAuth or Source Credentials. Defaults to `https://terraform@bitbucket.org/terraform/aws-test.git`. |
| `AWS_CODEBUILD_GITHUB_SOURCE_LOCATION` | GitHub source URL for CodeBuild testing. CodeBuild must have access to this repository via OAuth or Source Credentials. Defaults to `https://github.com/hashibot-test/aws-test.git`. |
| `AWS_COGNITO_USER_POOL_DOMAIN_CERTIFICATE_ARN` | Amazon Resource Name of ACM Certificate in `us-east-1` for Cognito User Pool Domain Name testing. |
| `AWS_COGNITO_USER_POOL_DOMAIN_ROOT_DOMAIN` | Root domain name to use with Cognito User Pool Domain testing. |
| `AWS_DEFAULT_REGION` | Primary AWS region for tests. Defaults to `us-west-2`. |
| `AWS_EC2_CLASSIC_REGION` | AWS region for EC2-Classic testing. Defaults to `us-east-1` in AWS Commercial and `AWS_DEFAULT_REGION` otherwise. |
| `AWS_EC2_CLIENT_VPN_LIMIT` | Concurrency limit for Client VPN acceptance tests. [Default is 5](https://docs.aws.amazon.com/vpn/latest/clientvpn-admin/limits.html) if not specified. |
Expand Down