From 80d940d154c8e468e41adad77feaff957382b24b Mon Sep 17 00:00:00 2001 From: Gauthier Wallet Date: Fri, 21 Apr 2017 05:53:48 -0400 Subject: [PATCH] provider/aws: Added Cognito Identity Pool (#13783) --- builtin/providers/aws/config.go | 3 + .../import_aws_cognito_identity_pool_test.go | 30 ++ builtin/providers/aws/provider.go | 1 + .../aws/resource_aws_cognito_identity_pool.go | 238 +++++++++++ ...resource_aws_cognito_identity_pool_test.go | 371 ++++++++++++++++++ builtin/providers/aws/structure.go | 72 ++++ builtin/providers/aws/validators.go | 73 ++++ builtin/providers/aws/validators_test.go | 167 +++++++- .../aws/r/cognito_identity_pool.markdown | 78 ++++ website/source/layouts/aws.erb | 32 +- 10 files changed, 1052 insertions(+), 13 deletions(-) create mode 100644 builtin/providers/aws/import_aws_cognito_identity_pool_test.go create mode 100644 builtin/providers/aws/resource_aws_cognito_identity_pool.go create mode 100644 builtin/providers/aws/resource_aws_cognito_identity_pool_test.go create mode 100644 website/source/docs/providers/aws/r/cognito_identity_pool.markdown diff --git a/builtin/providers/aws/config.go b/builtin/providers/aws/config.go index 17105d259..78fa93deb 100644 --- a/builtin/providers/aws/config.go +++ b/builtin/providers/aws/config.go @@ -28,6 +28,7 @@ import ( "github.com/aws/aws-sdk-go/service/codecommit" "github.com/aws/aws-sdk-go/service/codedeploy" "github.com/aws/aws-sdk-go/service/codepipeline" + "github.com/aws/aws-sdk-go/service/cognitoidentity" "github.com/aws/aws-sdk-go/service/configservice" "github.com/aws/aws-sdk-go/service/databasemigrationservice" "github.com/aws/aws-sdk-go/service/directoryservice" @@ -111,6 +112,7 @@ type AWSClient struct { cloudwatchconn *cloudwatch.CloudWatch cloudwatchlogsconn *cloudwatchlogs.CloudWatchLogs cloudwatcheventsconn *cloudwatchevents.CloudWatchEvents + cognitoconn *cognitoidentity.CognitoIdentity configconn *configservice.ConfigService dmsconn *databasemigrationservice.DatabaseMigrationService dsconn *directoryservice.DirectoryService @@ -306,6 +308,7 @@ func (c *Config) Client() (interface{}, error) { client.codebuildconn = codebuild.New(sess) client.codedeployconn = codedeploy.New(sess) client.configconn = configservice.New(sess) + client.cognitoconn = cognitoidentity.New(sess) client.dmsconn = databasemigrationservice.New(sess) client.codepipelineconn = codepipeline.New(sess) client.dsconn = directoryservice.New(sess) diff --git a/builtin/providers/aws/import_aws_cognito_identity_pool_test.go b/builtin/providers/aws/import_aws_cognito_identity_pool_test.go new file mode 100644 index 000000000..bdd2caec8 --- /dev/null +++ b/builtin/providers/aws/import_aws_cognito_identity_pool_test.go @@ -0,0 +1,30 @@ +package aws + +import ( + "testing" + + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" +) + +func TestAccAWSCognitoIdentityPool_importBasic(t *testing.T) { + resourceName := "aws_cognito_identity_pool.main" + rName := acctest.RandString(10) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSAPIGatewayAccountDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSCognitoIdentityPoolConfig_basic(rName), + }, + + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} diff --git a/builtin/providers/aws/provider.go b/builtin/providers/aws/provider.go index 889d9afcf..a353d5eb3 100644 --- a/builtin/providers/aws/provider.go +++ b/builtin/providers/aws/provider.go @@ -258,6 +258,7 @@ func Provider() terraform.ResourceProvider { "aws_config_configuration_recorder": resourceAwsConfigConfigurationRecorder(), "aws_config_configuration_recorder_status": resourceAwsConfigConfigurationRecorderStatus(), "aws_config_delivery_channel": resourceAwsConfigDeliveryChannel(), + "aws_cognito_identity_pool": resourceAwsCognitoIdentityPool(), "aws_autoscaling_lifecycle_hook": resourceAwsAutoscalingLifecycleHook(), "aws_cloudwatch_metric_alarm": resourceAwsCloudWatchMetricAlarm(), "aws_codedeploy_app": resourceAwsCodeDeployApp(), diff --git a/builtin/providers/aws/resource_aws_cognito_identity_pool.go b/builtin/providers/aws/resource_aws_cognito_identity_pool.go new file mode 100644 index 000000000..b85472cf9 --- /dev/null +++ b/builtin/providers/aws/resource_aws_cognito_identity_pool.go @@ -0,0 +1,238 @@ +package aws + +import ( + "fmt" + "log" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/service/cognitoidentity" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/helper/schema" +) + +func resourceAwsCognitoIdentityPool() *schema.Resource { + return &schema.Resource{ + Create: resourceAwsCognitoIdentityPoolCreate, + Read: resourceAwsCognitoIdentityPoolRead, + Update: resourceAwsCognitoIdentityPoolUpdate, + Delete: resourceAwsCognitoIdentityPoolDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Schema: map[string]*schema.Schema{ + "identity_pool_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validateCognitoIdentityPoolName, + }, + + "cognito_identity_providers": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "client_id": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validateCognitoIdentityProvidersClientId, + }, + "provider_name": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validateCognitoIdentityProvidersProviderName, + }, + "server_side_token_check": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + }, + }, + }, + + "developer_provider_name": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, // Forcing a new resource since it cannot be edited afterwards + ValidateFunc: validateCognitoProviderDeveloperName, + }, + + "allow_unauthenticated_identities": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + + "openid_connect_provider_arns": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: validateArn, + }, + }, + + "saml_provider_arns": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: validateArn, + }, + }, + + "supported_login_providers": { + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: validateCognitoSupportedLoginProviders, + }, + }, + }, + } +} + +func resourceAwsCognitoIdentityPoolCreate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).cognitoconn + log.Print("[DEBUG] Creating Cognito Identity Pool") + + params := &cognitoidentity.CreateIdentityPoolInput{ + IdentityPoolName: aws.String(d.Get("identity_pool_name").(string)), + AllowUnauthenticatedIdentities: aws.Bool(d.Get("allow_unauthenticated_identities").(bool)), + } + + if v, ok := d.GetOk("developer_provider_name"); ok { + params.DeveloperProviderName = aws.String(v.(string)) + } + + if v, ok := d.GetOk("supported_login_providers"); ok { + params.SupportedLoginProviders = expandCognitoSupportedLoginProviders(v.(map[string]interface{})) + } + + if v, ok := d.GetOk("cognito_identity_providers"); ok { + params.CognitoIdentityProviders = expandCognitoIdentityProviders(v.(*schema.Set)) + } + + if v, ok := d.GetOk("saml_provider_arns"); ok { + params.SamlProviderARNs = expandStringList(v.([]interface{})) + } + + if v, ok := d.GetOk("openid_connect_provider_arns"); ok { + params.OpenIdConnectProviderARNs = expandStringList(v.([]interface{})) + } + + entity, err := conn.CreateIdentityPool(params) + if err != nil { + return fmt.Errorf("Error creating Cognito Identity Pool: %s", err) + } + + d.SetId(*entity.IdentityPoolId) + + return resourceAwsCognitoIdentityPoolRead(d, meta) +} + +func resourceAwsCognitoIdentityPoolRead(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).cognitoconn + log.Printf("[DEBUG] Reading Cognito Identity Pool: %s", d.Id()) + + ip, err := conn.DescribeIdentityPool(&cognitoidentity.DescribeIdentityPoolInput{ + IdentityPoolId: aws.String(d.Id()), + }) + if err != nil { + if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == "ResourceNotFoundException" { + d.SetId("") + return nil + } + return err + } + + d.Set("identity_pool_name", ip.IdentityPoolName) + d.Set("allow_unauthenticated_identities", ip.AllowUnauthenticatedIdentities) + d.Set("developer_provider_name", ip.DeveloperProviderName) + + if ip.CognitoIdentityProviders != nil { + if err := d.Set("cognito_identity_providers", flattenCognitoIdentityProviders(ip.CognitoIdentityProviders)); err != nil { + return fmt.Errorf("[DEBUG] Error setting cognito_identity_providers error: %#v", err) + } + } + + if ip.OpenIdConnectProviderARNs != nil { + if err := d.Set("openid_connect_provider_arns", flattenStringList(ip.OpenIdConnectProviderARNs)); err != nil { + return fmt.Errorf("[DEBUG] Error setting openid_connect_provider_arns error: %#v", err) + } + } + + if ip.SamlProviderARNs != nil { + if err := d.Set("saml_provider_arns", flattenStringList(ip.SamlProviderARNs)); err != nil { + return fmt.Errorf("[DEBUG] Error setting saml_provider_arns error: %#v", err) + } + } + + if ip.SupportedLoginProviders != nil { + if err := d.Set("supported_login_providers", flattenCognitoSupportedLoginProviders(ip.SupportedLoginProviders)); err != nil { + return fmt.Errorf("[DEBUG] Error setting supported_login_providers error: %#v", err) + } + } + + return nil +} + +func resourceAwsCognitoIdentityPoolUpdate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).cognitoconn + log.Print("[DEBUG] Updating Cognito Identity Pool") + + params := &cognitoidentity.IdentityPool{ + IdentityPoolId: aws.String(d.Id()), + AllowUnauthenticatedIdentities: aws.Bool(d.Get("allow_unauthenticated_identities").(bool)), + IdentityPoolName: aws.String(d.Get("identity_pool_name").(string)), + } + + if d.HasChange("developer_provider_name") { + params.DeveloperProviderName = aws.String(d.Get("developer_provider_name").(string)) + } + + if d.HasChange("cognito_identity_providers") { + params.CognitoIdentityProviders = expandCognitoIdentityProviders(d.Get("cognito_identity_providers").(*schema.Set)) + } + + if d.HasChange("supported_login_providers") { + params.SupportedLoginProviders = expandCognitoSupportedLoginProviders(d.Get("supported_login_providers").(map[string]interface{})) + } + + if d.HasChange("openid_connect_provider_arns") { + params.OpenIdConnectProviderARNs = expandStringList(d.Get("openid_connect_provider_arns").([]interface{})) + } + + if d.HasChange("saml_provider_arns") { + params.SamlProviderARNs = expandStringList(d.Get("saml_provider_arns").([]interface{})) + } + + _, err := conn.UpdateIdentityPool(params) + if err != nil { + return fmt.Errorf("Error creating Cognito Identity Pool: %s", err) + } + + return resourceAwsCognitoIdentityPoolRead(d, meta) +} + +func resourceAwsCognitoIdentityPoolDelete(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).cognitoconn + log.Printf("[DEBUG] Deleting Cognito Identity Pool: %s", d.Id()) + + return resource.Retry(5*time.Minute, func() *resource.RetryError { + _, err := conn.DeleteIdentityPool(&cognitoidentity.DeleteIdentityPoolInput{ + IdentityPoolId: aws.String(d.Id()), + }) + + if err == nil { + return nil + } + + return resource.NonRetryableError(err) + }) +} diff --git a/builtin/providers/aws/resource_aws_cognito_identity_pool_test.go b/builtin/providers/aws/resource_aws_cognito_identity_pool_test.go new file mode 100644 index 000000000..6ee0b1955 --- /dev/null +++ b/builtin/providers/aws/resource_aws_cognito_identity_pool_test.go @@ -0,0 +1,371 @@ +package aws + +import ( + "errors" + "fmt" + "testing" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/service/cognitoidentity" + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +func TestAccAWSCognitoIdentityPool_basic(t *testing.T) { + name := fmt.Sprintf("%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) + updatedName := fmt.Sprintf("%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSCognitoIdentityPoolDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSCognitoIdentityPoolConfig_basic(name), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSCognitoIdentityPoolExists("aws_cognito_identity_pool.main"), + resource.TestCheckResourceAttr("aws_cognito_identity_pool.main", "identity_pool_name", fmt.Sprintf("identity pool %s", name)), + resource.TestCheckResourceAttr("aws_cognito_identity_pool.main", "allow_unauthenticated_identities", "false"), + ), + }, + { + Config: testAccAWSCognitoIdentityPoolConfig_basic(updatedName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSCognitoIdentityPoolExists("aws_cognito_identity_pool.main"), + resource.TestCheckResourceAttr("aws_cognito_identity_pool.main", "identity_pool_name", fmt.Sprintf("identity pool %s", updatedName)), + ), + }, + }, + }) +} + +func TestAccAWSCognitoIdentityPool_supportedLoginProviders(t *testing.T) { + name := fmt.Sprintf("%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSCognitoIdentityPoolDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSCognitoIdentityPoolConfig_supportedLoginProviders(name), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSCognitoIdentityPoolExists("aws_cognito_identity_pool.main"), + resource.TestCheckResourceAttr("aws_cognito_identity_pool.main", "identity_pool_name", fmt.Sprintf("identity pool %s", name)), + resource.TestCheckResourceAttr("aws_cognito_identity_pool.main", "supported_login_providers.graph.facebook.com", "7346241598935555"), + ), + }, + { + Config: testAccAWSCognitoIdentityPoolConfig_supportedLoginProvidersModified(name), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSCognitoIdentityPoolExists("aws_cognito_identity_pool.main"), + resource.TestCheckResourceAttr("aws_cognito_identity_pool.main", "identity_pool_name", fmt.Sprintf("identity pool %s", name)), + resource.TestCheckResourceAttr("aws_cognito_identity_pool.main", "supported_login_providers.graph.facebook.com", "7346241598935552"), + resource.TestCheckResourceAttr("aws_cognito_identity_pool.main", "supported_login_providers.accounts.google.com", "123456789012.apps.googleusercontent.com"), + ), + }, + { + Config: testAccAWSCognitoIdentityPoolConfig_basic(name), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSCognitoIdentityPoolExists("aws_cognito_identity_pool.main"), + resource.TestCheckResourceAttr("aws_cognito_identity_pool.main", "identity_pool_name", fmt.Sprintf("identity pool %s", name)), + ), + }, + }, + }) +} + +func TestAccAWSCognitoIdentityPool_openidConnectProviderArns(t *testing.T) { + name := fmt.Sprintf("%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSCognitoIdentityPoolDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSCognitoIdentityPoolConfig_openidConnectProviderArns(name), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSCognitoIdentityPoolExists("aws_cognito_identity_pool.main"), + resource.TestCheckResourceAttr("aws_cognito_identity_pool.main", "identity_pool_name", fmt.Sprintf("identity pool %s", name)), + resource.TestCheckResourceAttr("aws_cognito_identity_pool.main", "openid_connect_provider_arns.#", "1"), + ), + }, + { + Config: testAccAWSCognitoIdentityPoolConfig_openidConnectProviderArnsModified(name), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSCognitoIdentityPoolExists("aws_cognito_identity_pool.main"), + resource.TestCheckResourceAttr("aws_cognito_identity_pool.main", "identity_pool_name", fmt.Sprintf("identity pool %s", name)), + resource.TestCheckResourceAttr("aws_cognito_identity_pool.main", "openid_connect_provider_arns.#", "2"), + ), + }, + { + Config: testAccAWSCognitoIdentityPoolConfig_basic(name), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSCognitoIdentityPoolExists("aws_cognito_identity_pool.main"), + resource.TestCheckResourceAttr("aws_cognito_identity_pool.main", "identity_pool_name", fmt.Sprintf("identity pool %s", name)), + ), + }, + }, + }) +} + +func TestAccAWSCognitoIdentityPool_samlProviderArns(t *testing.T) { + name := fmt.Sprintf("%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSCognitoIdentityPoolDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSCognitoIdentityPoolConfig_samlProviderArns(name), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSCognitoIdentityPoolExists("aws_cognito_identity_pool.main"), + resource.TestCheckResourceAttr("aws_cognito_identity_pool.main", "identity_pool_name", fmt.Sprintf("identity pool %s", name)), + resource.TestCheckResourceAttr("aws_cognito_identity_pool.main", "saml_provider_arns.#", "1"), + ), + }, + { + Config: testAccAWSCognitoIdentityPoolConfig_samlProviderArnsModified(name), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSCognitoIdentityPoolExists("aws_cognito_identity_pool.main"), + resource.TestCheckResourceAttr("aws_cognito_identity_pool.main", "identity_pool_name", fmt.Sprintf("identity pool %s", name)), + resource.TestCheckResourceAttr("aws_cognito_identity_pool.main", "saml_provider_arns.#", "1"), + ), + }, + { + Config: testAccAWSCognitoIdentityPoolConfig_basic(name), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSCognitoIdentityPoolExists("aws_cognito_identity_pool.main"), + resource.TestCheckResourceAttr("aws_cognito_identity_pool.main", "identity_pool_name", fmt.Sprintf("identity pool %s", name)), + resource.TestCheckNoResourceAttr("aws_cognito_identity_pool.main", "saml_provider_arns.#"), + ), + }, + }, + }) +} + +func TestAccAWSCognitoIdentityPool_cognitoIdentityProviders(t *testing.T) { + name := fmt.Sprintf("%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSCognitoIdentityPoolDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSCognitoIdentityPoolConfig_cognitoIdentityProviders(name), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSCognitoIdentityPoolExists("aws_cognito_identity_pool.main"), + resource.TestCheckResourceAttr("aws_cognito_identity_pool.main", "identity_pool_name", fmt.Sprintf("identity pool %s", name)), + resource.TestCheckResourceAttr("aws_cognito_identity_pool.main", "cognito_identity_providers.66456389.client_id", "7lhlkkfbfb4q5kpp90urffao"), + resource.TestCheckResourceAttr("aws_cognito_identity_pool.main", "cognito_identity_providers.66456389.provider_name", "cognito-idp.us-east-1.amazonaws.com/us-east-1_Zr231apJu"), + resource.TestCheckResourceAttr("aws_cognito_identity_pool.main", "cognito_identity_providers.66456389.server_side_token_check", "false"), + resource.TestCheckResourceAttr("aws_cognito_identity_pool.main", "cognito_identity_providers.3571192419.client_id", "7lhlkkfbfb4q5kpp90urffao"), + resource.TestCheckResourceAttr("aws_cognito_identity_pool.main", "cognito_identity_providers.3571192419.provider_name", "cognito-idp.us-east-1.amazonaws.com/us-east-1_Ab129faBb"), + resource.TestCheckResourceAttr("aws_cognito_identity_pool.main", "cognito_identity_providers.3571192419.server_side_token_check", "false"), + ), + }, + { + Config: testAccAWSCognitoIdentityPoolConfig_cognitoIdentityProvidersModified(name), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSCognitoIdentityPoolExists("aws_cognito_identity_pool.main"), + resource.TestCheckResourceAttr("aws_cognito_identity_pool.main", "identity_pool_name", fmt.Sprintf("identity pool %s", name)), + resource.TestCheckResourceAttr("aws_cognito_identity_pool.main", "cognito_identity_providers.3661724441.client_id", "6lhlkkfbfb4q5kpp90urffae"), + resource.TestCheckResourceAttr("aws_cognito_identity_pool.main", "cognito_identity_providers.3661724441.provider_name", "cognito-idp.us-east-1.amazonaws.com/us-east-1_Zr231apJu"), + resource.TestCheckResourceAttr("aws_cognito_identity_pool.main", "cognito_identity_providers.3661724441.server_side_token_check", "false"), + ), + }, + { + Config: testAccAWSCognitoIdentityPoolConfig_basic(name), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSCognitoIdentityPoolExists("aws_cognito_identity_pool.main"), + resource.TestCheckResourceAttr("aws_cognito_identity_pool.main", "identity_pool_name", fmt.Sprintf("identity pool %s", name)), + ), + }, + }, + }) +} + +func testAccCheckAWSCognitoIdentityPoolExists(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 errors.New("No Cognito Identity Pool ID is set") + } + + conn := testAccProvider.Meta().(*AWSClient).cognitoconn + + _, err := conn.DescribeIdentityPool(&cognitoidentity.DescribeIdentityPoolInput{ + IdentityPoolId: aws.String(rs.Primary.ID), + }) + + if err != nil { + return err + } + + return nil + } +} + +func testAccCheckAWSCognitoIdentityPoolDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*AWSClient).cognitoconn + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_cognito_identity_pool" { + continue + } + + _, err := conn.DescribeIdentityPool(&cognitoidentity.DescribeIdentityPoolInput{ + IdentityPoolId: aws.String(rs.Primary.ID), + }) + + if err != nil { + if wserr, ok := err.(awserr.Error); ok && wserr.Code() == "ResourceNotFoundException" { + return nil + } + return err + } + } + + return nil +} + +func testAccAWSCognitoIdentityPoolConfig_basic(name string) string { + return fmt.Sprintf(` +resource "aws_cognito_identity_pool" "main" { + identity_pool_name = "identity pool %s" + allow_unauthenticated_identities = false + developer_provider_name = "my.developer" +} +`, name) +} + +func testAccAWSCognitoIdentityPoolConfig_supportedLoginProviders(name string) string { + return fmt.Sprintf(` +resource "aws_cognito_identity_pool" "main" { + identity_pool_name = "identity pool %s" + allow_unauthenticated_identities = false + + supported_login_providers { + "graph.facebook.com" = "7346241598935555" + } +} +`, name) +} + +func testAccAWSCognitoIdentityPoolConfig_supportedLoginProvidersModified(name string) string { + return fmt.Sprintf(` +resource "aws_cognito_identity_pool" "main" { + identity_pool_name = "identity pool %s" + allow_unauthenticated_identities = false + + supported_login_providers { + "graph.facebook.com" = "7346241598935552" + "accounts.google.com" = "123456789012.apps.googleusercontent.com" + } +} +`, name) +} + +func testAccAWSCognitoIdentityPoolConfig_openidConnectProviderArns(name string) string { + return fmt.Sprintf(` +resource "aws_cognito_identity_pool" "main" { + identity_pool_name = "identity pool %s" + allow_unauthenticated_identities = false + + openid_connect_provider_arns = ["arn:aws:iam::123456789012:oidc-provider/server.example.com"] +} +`, name) +} + +func testAccAWSCognitoIdentityPoolConfig_openidConnectProviderArnsModified(name string) string { + return fmt.Sprintf(` +resource "aws_cognito_identity_pool" "main" { + identity_pool_name = "identity pool %s" + allow_unauthenticated_identities = false + + openid_connect_provider_arns = ["arn:aws:iam::123456789012:oidc-provider/foo.example.com", "arn:aws:iam::123456789012:oidc-provider/bar.example.com"] +} +`, name) +} + +func testAccAWSCognitoIdentityPoolConfig_samlProviderArns(name string) string { + return fmt.Sprintf(` +resource "aws_iam_saml_provider" "default" { + name = "myprovider-%s" + saml_metadata_document = "${file("./test-fixtures/saml-metadata.xml")}" +} + +resource "aws_cognito_identity_pool" "main" { + identity_pool_name = "identity pool %s" + allow_unauthenticated_identities = false + + saml_provider_arns = ["${aws_iam_saml_provider.default.arn}"] +} +`, name, name) +} + +func testAccAWSCognitoIdentityPoolConfig_samlProviderArnsModified(name string) string { + return fmt.Sprintf(` +resource "aws_iam_saml_provider" "default" { + name = "default-%s" + saml_metadata_document = "${file("./test-fixtures/saml-metadata.xml")}" +} + +resource "aws_iam_saml_provider" "secondary" { + name = "secondary-%s" + saml_metadata_document = "${file("./test-fixtures/saml-metadata.xml")}" +} + +resource "aws_cognito_identity_pool" "main" { + identity_pool_name = "identity pool %s" + allow_unauthenticated_identities = false + + saml_provider_arns = ["${aws_iam_saml_provider.secondary.arn}"] +} +`, name, name, name) +} + +func testAccAWSCognitoIdentityPoolConfig_cognitoIdentityProviders(name string) string { + return fmt.Sprintf(` +resource "aws_cognito_identity_pool" "main" { + identity_pool_name = "identity pool %s" + allow_unauthenticated_identities = false + + cognito_identity_providers { + client_id = "7lhlkkfbfb4q5kpp90urffao" + provider_name = "cognito-idp.us-east-1.amazonaws.com/us-east-1_Ab129faBb" + server_side_token_check = false + } + + cognito_identity_providers { + client_id = "7lhlkkfbfb4q5kpp90urffao" + provider_name = "cognito-idp.us-east-1.amazonaws.com/us-east-1_Zr231apJu" + server_side_token_check = false + } +} +`, name) +} + +func testAccAWSCognitoIdentityPoolConfig_cognitoIdentityProvidersModified(name string) string { + return fmt.Sprintf(` +resource "aws_cognito_identity_pool" "main" { + identity_pool_name = "identity pool %s" + allow_unauthenticated_identities = false + + cognito_identity_providers { + client_id = "6lhlkkfbfb4q5kpp90urffae" + provider_name = "cognito-idp.us-east-1.amazonaws.com/us-east-1_Zr231apJu" + server_side_token_check = false + } +} +`, name) +} diff --git a/builtin/providers/aws/structure.go b/builtin/providers/aws/structure.go index dfe053b9a..d6dd6e358 100644 --- a/builtin/providers/aws/structure.go +++ b/builtin/providers/aws/structure.go @@ -14,6 +14,7 @@ import ( "github.com/aws/aws-sdk-go/service/autoscaling" "github.com/aws/aws-sdk-go/service/cloudformation" "github.com/aws/aws-sdk-go/service/cloudwatchlogs" + "github.com/aws/aws-sdk-go/service/cognitoidentity" "github.com/aws/aws-sdk-go/service/configservice" "github.com/aws/aws-sdk-go/service/directoryservice" "github.com/aws/aws-sdk-go/service/ec2" @@ -1925,3 +1926,74 @@ func flattenApiGatewayUsagePlanQuota(s *apigateway.QuotaSettings) []map[string]i return []map[string]interface{}{settings} } + +func expandCognitoSupportedLoginProviders(config map[string]interface{}) map[string]*string { + m := map[string]*string{} + for k, v := range config { + s := v.(string) + m[k] = &s + } + return m +} + +func flattenCognitoSupportedLoginProviders(config map[string]*string) map[string]string { + m := map[string]string{} + for k, v := range config { + m[k] = *v + } + return m +} + +func expandCognitoIdentityProviders(s *schema.Set) []*cognitoidentity.Provider { + ips := make([]*cognitoidentity.Provider, 0) + + for _, v := range s.List() { + s := v.(map[string]interface{}) + + ip := &cognitoidentity.Provider{} + + if sv, ok := s["client_id"].(string); ok { + ip.ClientId = aws.String(sv) + } + + if sv, ok := s["provider_name"].(string); ok { + ip.ProviderName = aws.String(sv) + } + + if sv, ok := s["server_side_token_check"].(bool); ok { + ip.ServerSideTokenCheck = aws.Bool(sv) + } + + ips = append(ips, ip) + } + + return ips +} + +func flattenCognitoIdentityProviders(ips []*cognitoidentity.Provider) []map[string]interface{} { + values := make([]map[string]interface{}, 0) + + for _, v := range ips { + ip := make(map[string]interface{}) + + if v == nil { + return nil + } + + if v.ClientId != nil { + ip["client_id"] = *v.ClientId + } + + if v.ProviderName != nil { + ip["provider_name"] = *v.ProviderName + } + + if v.ServerSideTokenCheck != nil { + ip["server_side_token_check"] = *v.ServerSideTokenCheck + } + + values = append(values, ip) + } + + return values +} diff --git a/builtin/providers/aws/validators.go b/builtin/providers/aws/validators.go index 9a7bf0e0a..c6a4edb03 100644 --- a/builtin/providers/aws/validators.go +++ b/builtin/providers/aws/validators.go @@ -1218,3 +1218,76 @@ func validateAwsKmsName(v interface{}, k string) (ws []string, es []error) { } return } + +func validateCognitoIdentityPoolName(v interface{}, k string) (ws []string, errors []error) { + val := v.(string) + if !regexp.MustCompile("^[\\w _]+$").MatchString(val) { + errors = append(errors, fmt.Errorf("%q must contain only alphanumeric caracters and spaces", k)) + } + + return +} + +func validateCognitoProviderDeveloperName(v interface{}, k string) (ws []string, errors []error) { + value := v.(string) + if len(value) > 100 { + errors = append(errors, fmt.Errorf("%q cannot be longer than 100 caracters", k)) + } + + if !regexp.MustCompile("^[\\w._-]+$").MatchString(value) { + errors = append(errors, fmt.Errorf("%q must contain only alphanumeric caracters, dots, underscores and hyphens", k)) + } + + return +} + +func validateCognitoSupportedLoginProviders(v interface{}, k string) (ws []string, errors []error) { + value := v.(string) + if len(value) < 1 { + errors = append(errors, fmt.Errorf("%q cannot be less than 1 character", k)) + } + + if len(value) > 128 { + errors = append(errors, fmt.Errorf("%q cannot be longer than 128 caracters", k)) + } + + if !regexp.MustCompile("^[\\w.;_/-]+$").MatchString(value) { + errors = append(errors, fmt.Errorf("%q must contain only alphanumeric caracters, dots, semicolons, underscores, slashes and hyphens", k)) + } + + return +} + +func validateCognitoIdentityProvidersClientId(v interface{}, k string) (ws []string, errors []error) { + value := v.(string) + if len(value) < 1 { + errors = append(errors, fmt.Errorf("%q cannot be less than 1 character", k)) + } + + if len(value) > 128 { + errors = append(errors, fmt.Errorf("%q cannot be longer than 128 caracters", k)) + } + + if !regexp.MustCompile("^[\\w_]+$").MatchString(value) { + errors = append(errors, fmt.Errorf("%q must contain only alphanumeric caracters and underscores", k)) + } + + return +} + +func validateCognitoIdentityProvidersProviderName(v interface{}, k string) (ws []string, errors []error) { + value := v.(string) + if len(value) < 1 { + errors = append(errors, fmt.Errorf("%q cannot be less than 1 character", k)) + } + + if len(value) > 128 { + errors = append(errors, fmt.Errorf("%q cannot be longer than 128 caracters", k)) + } + + if !regexp.MustCompile("^[\\w._:/-]+$").MatchString(value) { + errors = append(errors, fmt.Errorf("%q must contain only alphanumeric caracters, dots, underscores, colons, slashes and hyphens", k)) + } + + return +} diff --git a/builtin/providers/aws/validators_test.go b/builtin/providers/aws/validators_test.go index 4638f0ba0..26b14a484 100644 --- a/builtin/providers/aws/validators_test.go +++ b/builtin/providers/aws/validators_test.go @@ -2011,5 +2011,170 @@ func TestValidateAwsKmsName(t *testing.T) { t.Fatalf("AWS KMS Alias Name validation failed: %v", errors) } } - +} + +func TestValidateCognitoIdentityPoolName(t *testing.T) { + validValues := []string{ + "123", + "1 2 3", + "foo", + "foo bar", + "foo_bar", + "1foo 2bar 3", + } + + for _, s := range validValues { + _, errors := validateCognitoIdentityPoolName(s, "identity_pool_name") + if len(errors) > 0 { + t.Fatalf("%q should be a valid Cognito Identity Pool Name: %v", s, errors) + } + } + + invalidValues := []string{ + "1-2-3", + "foo!", + "foo-bar", + "foo-bar", + "foo1-bar2", + } + + for _, s := range invalidValues { + _, errors := validateCognitoIdentityPoolName(s, "identity_pool_name") + if len(errors) == 0 { + t.Fatalf("%q should not be a valid Cognito Identity Pool Name: %v", s, errors) + } + } +} + +func TestValidateCognitoProviderDeveloperName(t *testing.T) { + validValues := []string{ + "1", + "foo", + "1.2", + "foo1-bar2-baz3", + "foo_bar", + } + + for _, s := range validValues { + _, errors := validateCognitoProviderDeveloperName(s, "developer_provider_name") + if len(errors) > 0 { + t.Fatalf("%q should be a valid Cognito Provider Developer Name: %v", s, errors) + } + } + + invalidValues := []string{ + "foo!", + "foo:bar", + "foo/bar", + "foo;bar", + } + + for _, s := range invalidValues { + _, errors := validateCognitoProviderDeveloperName(s, "developer_provider_name") + if len(errors) == 0 { + t.Fatalf("%q should not be a valid Cognito Provider Developer Name: %v", s, errors) + } + } +} + +func TestValidateCognitoSupportedLoginProviders(t *testing.T) { + validValues := []string{ + "foo", + "7346241598935552", + "123456789012.apps.googleusercontent.com", + "foo_bar", + "foo;bar", + "foo/bar", + "foo-bar", + "xvz1evFS4wEEPTGEFPHBog;kAcSOqF21Fu85e7zjz7ZN2U4ZRhfV3WpwPAoE3Z7kBw", + strings.Repeat("W", 128), + } + + for _, s := range validValues { + _, errors := validateCognitoSupportedLoginProviders(s, "supported_login_providers") + if len(errors) > 0 { + t.Fatalf("%q should be a valid Cognito Supported Login Providers: %v", s, errors) + } + } + + invalidValues := []string{ + "", + strings.Repeat("W", 129), // > 128 + "foo:bar_baz", + "foobar,foobaz", + "foobar=foobaz", + } + + for _, s := range invalidValues { + _, errors := validateCognitoSupportedLoginProviders(s, "supported_login_providers") + if len(errors) == 0 { + t.Fatalf("%q should not be a valid Cognito Supported Login Providers: %v", s, errors) + } + } +} + +func TestValidateCognitoIdentityProvidersClientId(t *testing.T) { + validValues := []string{ + "7lhlkkfbfb4q5kpp90urffao", + "12345678", + "foo_123", + strings.Repeat("W", 128), + } + + for _, s := range validValues { + _, errors := validateCognitoIdentityProvidersClientId(s, "client_id") + if len(errors) > 0 { + t.Fatalf("%q should be a valid Cognito Identity Provider Client ID: %v", s, errors) + } + } + + invalidValues := []string{ + "", + strings.Repeat("W", 129), // > 128 + "foo-bar", + "foo:bar", + "foo;bar", + } + + for _, s := range invalidValues { + _, errors := validateCognitoIdentityProvidersClientId(s, "client_id") + if len(errors) == 0 { + t.Fatalf("%q should not be a valid Cognito Identity Provider Client ID: %v", s, errors) + } + } +} + +func TestValidateCognitoIdentityProvidersProviderName(t *testing.T) { + validValues := []string{ + "foo", + "7346241598935552", + "foo_bar", + "foo:bar", + "foo/bar", + "foo-bar", + "cognito-idp.us-east-1.amazonaws.com/us-east-1_Zr231apJu", + strings.Repeat("W", 128), + } + + for _, s := range validValues { + _, errors := validateCognitoIdentityProvidersProviderName(s, "provider_name") + if len(errors) > 0 { + t.Fatalf("%q should be a valid Cognito Identity Provider Name: %v", s, errors) + } + } + + invalidValues := []string{ + "", + strings.Repeat("W", 129), // > 128 + "foo;bar_baz", + "foobar,foobaz", + "foobar=foobaz", + } + + for _, s := range invalidValues { + _, errors := validateCognitoIdentityProvidersProviderName(s, "provider_name") + if len(errors) == 0 { + t.Fatalf("%q should not be a valid Cognito Identity Provider Name: %v", s, errors) + } + } } diff --git a/website/source/docs/providers/aws/r/cognito_identity_pool.markdown b/website/source/docs/providers/aws/r/cognito_identity_pool.markdown new file mode 100644 index 000000000..5dfe696b6 --- /dev/null +++ b/website/source/docs/providers/aws/r/cognito_identity_pool.markdown @@ -0,0 +1,78 @@ +--- +layout: "aws" +page_title: "AWS: aws_cognito_identity_pool" +sidebar_current: "docs-aws-resource-cognito-identity-pool" +description: |- + Provides an AWS Cognito Identity Pool. +--- + +# aws\_cognito\_identity\_pool + +Provides an AWS Cognito Identity Pool. + +## Example Usage + +``` +resource "aws_iam_saml_provider" "default" { + name = "my-saml-provider" + saml_metadata_document = "${file("saml-metadata.xml")}" +} + +resource "aws_cognito_identity_pool" "main" { + identity_pool_name = "identity pool" + allow_unauthenticated_identities = false + + cognito_identity_providers { + client_id = "6lhlkkfbfb4q5kpp90urffae" + provider_name = "cognito-idp.us-east-1.amazonaws.com/us-east-1_Tv0493apJ" + server_side_token_check = false + } + + cognito_identity_providers { + client_id = "7kodkvfqfb4qfkp39eurffae" + provider_name = "cognito-idp.us-east-1.amazonaws.com/eu-west-1_Zr231apJu" + server_side_token_check = false + } + + supported_login_providers { + "graph.facebook.com" = "7346241598935552" + "accounts.google.com" = "123456789012.apps.googleusercontent.com" + } + + saml_provider_arns = ["${aws_iam_saml_provider.default.arn}"] + openid_connect_provider_arns = ["arn:aws:iam::123456789012:oidc-provider/foo.example.com"] +} +``` + +## Argument Reference + +The Cognito Identity Pool argument layout is a structure composed of several sub-resources - these resources are laid out below. + +* `identity_pool_name` (Required) - The Cognito Identity Pool name. +* `allow_unauthenticated_identities` (Required) - Whether the identity pool supports unauthenticated logins or not. +* `developer_provider_name` (Optional) - The "domain" by which Cognito will refer to your users. This name acts as a placeholder that allows your +backend and the Cognito service to communicate about the developer provider. +* `cognito_identity_providers` (Optional) - An array of [Amazon Cognito Identity user pools](#cognito-identity-providers) and their client IDs. +* `openid_connect_provider_arns` (Optional) - A list of OpendID Connect provider ARNs. +* `saml_provider_arns` (Optional) - An array of Amazon Resource Names (ARNs) of the SAML provider for your identity. +* `supported_login_providers` (Optional) - Key-Value pairs mapping provider names to provider app IDs. + +#### Cognito Identity Providers + + * `client_id` (Optional) - The client ID for the Amazon Cognito Identity User Pool. + * `provider_name` (Optional) - The provider name for an Amazon Cognito Identity User Pool. + * `server_side_token_check` (Optional) - Whether server-side token validation is enabled for the identity provider’s token or not. + +## Attributes Reference + +In addition to the arguments, which are exported, the following attributes are exported: + +* `id` - An identity pool ID in the format REGION:GUID. + +## Import + +Cognito Identity Pool can be imported using the name, e.g. + +``` +$ terraform import aws_cognito_identity_pool.mypool +``` diff --git a/website/source/layouts/aws.erb b/website/source/layouts/aws.erb index 28ff4dfc1..6cbb731b8 100644 --- a/website/source/layouts/aws.erb +++ b/website/source/layouts/aws.erb @@ -203,19 +203,18 @@ - > - App Autoscaling Resources - + > CloudFormation Resources @@ -346,6 +345,15 @@ + > + Cognito Resources + + + > Config Resources