From e7ed12f15b2bc6c1879ece16b1b871ab8d06c6f6 Mon Sep 17 00:00:00 2001 From: Ninir Date: Wed, 14 Jun 2017 19:06:52 +0200 Subject: [PATCH 1/2] Cognito: Added Identity Pool Roles Attachment --- aws/provider.go | 1 + ..._cognito_identity_pool_roles_attachment.go | 285 ++++++++++++ ...ito_identity_pool_roles_attachment_test.go | 431 ++++++++++++++++++ aws/structure.go | 111 +++++ aws/validators.go | 116 +++++ aws/validators_test.go | 130 ++++++ website/aws.erb | 3 + ...to_identity_pool_roles_attachment.markdown | 127 ++++++ 8 files changed, 1204 insertions(+) create mode 100644 aws/resource_aws_cognito_identity_pool_roles_attachment.go create mode 100644 aws/resource_aws_cognito_identity_pool_roles_attachment_test.go create mode 100644 website/docs/r/cognito_identity_pool_roles_attachment.markdown diff --git a/aws/provider.go b/aws/provider.go index b0dab0f5576..8042471da47 100644 --- a/aws/provider.go +++ b/aws/provider.go @@ -278,6 +278,7 @@ func Provider() terraform.ResourceProvider { "aws_config_configuration_recorder_status": resourceAwsConfigConfigurationRecorderStatus(), "aws_config_delivery_channel": resourceAwsConfigDeliveryChannel(), "aws_cognito_identity_pool": resourceAwsCognitoIdentityPool(), + "aws_cognito_identity_pool_roles_attachment": resourceAwsCognitoIdentityPoolRolesAttachment(), "aws_autoscaling_lifecycle_hook": resourceAwsAutoscalingLifecycleHook(), "aws_cloudwatch_metric_alarm": resourceAwsCloudWatchMetricAlarm(), "aws_cloudwatch_dashboard": resourceAwsCloudWatchDashboard(), diff --git a/aws/resource_aws_cognito_identity_pool_roles_attachment.go b/aws/resource_aws_cognito_identity_pool_roles_attachment.go new file mode 100644 index 00000000000..6007515517c --- /dev/null +++ b/aws/resource_aws_cognito_identity_pool_roles_attachment.go @@ -0,0 +1,285 @@ +package aws + +import ( + "fmt" + "log" + "time" + + "bytes" + + "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/hashcode" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/helper/schema" +) + +func resourceAwsCognitoIdentityPoolRolesAttachment() *schema.Resource { + return &schema.Resource{ + Create: resourceAwsCognitoIdentityPoolRolesAttachmentCreate, + Read: resourceAwsCognitoIdentityPoolRolesAttachmentRead, + Update: resourceAwsCognitoIdentityPoolRolesAttachmentUpdate, + Delete: resourceAwsCognitoIdentityPoolRolesAttachmentDelete, + + Schema: map[string]*schema.Schema{ + "identity_pool_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "role_mapping": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "identity_provider": { + Type: schema.TypeString, + Required: true, + }, + "ambiguous_role_resolution": { + Type: schema.TypeString, + ValidateFunc: validateCognitoRoleMappingsAmbiguousRoleResolution, + Optional: true, // Required if Type equals Token or Rules. + }, + "mapping_rule": { + Type: schema.TypeList, + Optional: true, + MaxItems: 25, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "claim": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validateCognitoRoleMappingsRulesClaim, + }, + "match_type": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validateCognitoRoleMappingsRulesMatchType, + }, + "role_arn": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validateArn, + }, + "value": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validateCognitoRoleMappingsRulesValue, + }, + }, + }, + }, + "type": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validateCognitoRoleMappingsType, + }, + }, + }, + }, + + "roles": { + Type: schema.TypeMap, + Required: true, + ForceNew: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "authenticated": { + Type: schema.TypeString, + ValidateFunc: validateArn, + Optional: true, // Required if unauthenticated isn't defined. + }, + "unauthenticated": { + Type: schema.TypeString, + ValidateFunc: validateArn, + Optional: true, // Required if authenticated isn't defined. + }, + }, + }, + }, + }, + } +} + +func resourceAwsCognitoIdentityPoolRolesAttachmentCreate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).cognitoconn + + // Validates role keys to be either authenticated or unauthenticated, + // since ValidateFunc validates only the value not the key. + if errors := validateCognitoRoles(d.Get("roles").(map[string]interface{}), "roles"); len(errors) > 0 { + return fmt.Errorf("Error validating Roles: %v", errors) + } + + params := &cognitoidentity.SetIdentityPoolRolesInput{ + IdentityPoolId: aws.String(d.Get("identity_pool_id").(string)), + Roles: expandCognitoIdentityPoolRoles(d.Get("roles").(map[string]interface{})), + } + + if v, ok := d.GetOk("role_mapping"); ok { + errors := validateRoleMappings(v.(*schema.Set).List()) + + if len(errors) > 0 { + return fmt.Errorf("Error validating ambiguous role resolution: %v", errors) + } + + params.RoleMappings = expandCognitoIdentityPoolRoleMappingsAttachment(v.([]interface{})) + } + + log.Sprintf("[DEBUG] Creating Cognito Identity Pool Roles Association: %#v", params) + _, err := conn.SetIdentityPoolRoles(params) + if err != nil { + return fmt.Errorf("Error creating Cognito Identity Pool Roles Association: %s", err) + } + + d.SetId(d.Get("identity_pool_id").(string)) + + return resourceAwsCognitoIdentityPoolRolesAttachmentRead(d, meta) +} + +func resourceAwsCognitoIdentityPoolRolesAttachmentRead(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).cognitoconn + log.Printf("[DEBUG] Reading Cognito Identity Pool Roles Association: %s", d.Id()) + + ip, err := conn.GetIdentityPoolRoles(&cognitoidentity.GetIdentityPoolRolesInput{ + IdentityPoolId: aws.String(d.Get("identity_pool_id").(string)), + }) + if err != nil { + if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == "ResourceNotFoundException" { + log.Printf("[WARN] Cognito Identity Pool Roles Association %s not found, removing from state", d.Id()) + d.SetId("") + return nil + } + return err + } + + if err := d.Set("roles", flattenCognitoIdentityPoolRoles(ip.Roles)); err != nil { + return fmt.Errorf("[DEBUG] Error setting roles error: %#v", err) + } + + if err := d.Set("role_mapping", flattenCognitoIdentityPoolRoleMappingsAttachment(ip.RoleMappings)); err != nil { + return fmt.Errorf("[DEBUG] Error setting role mappings error: %#v", err) + } + + return nil +} + +func resourceAwsCognitoIdentityPoolRolesAttachmentUpdate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).cognitoconn + + // Validates role keys to be either authenticated or unauthenticated, + // since ValidateFunc validates only the value not the key. + if errors := validateCognitoRoles(d.Get("roles").(map[string]interface{}), "roles"); len(errors) > 0 { + return fmt.Errorf("Error validating Roles: %v", errors) + } + + params := &cognitoidentity.SetIdentityPoolRolesInput{ + IdentityPoolId: aws.String(d.Get("identity_pool_id").(string)), + Roles: expandCognitoIdentityPoolRoles(d.Get("roles").(map[string]interface{})), + } + + if d.HasChange("role_mapping") { + v, ok := d.GetOk("role_mapping") + var mappings []interface{} + + if ok { + errors := validateRoleMappings(v.(*schema.Set).List()) + + if len(errors) > 0 { + return fmt.Errorf("Error validating ambiguous role resolution: %v", errors) + } + mappings = v.(*schema.Set).List() + } else { + mappings = []interface{}{} + } + + params.RoleMappings = expandCognitoIdentityPoolRoleMappingsAttachment(mappings) + } + + log.Sprintf("[DEBUG] Updating Cognito Identity Pool Roles Association: %#v", params) + _, err := conn.SetIdentityPoolRoles(params) + if err != nil { + return fmt.Errorf("Error updating Cognito Identity Pool Roles Association: %s", err) + } + + d.SetId(d.Get("identity_pool_id").(string)) + + return resourceAwsCognitoIdentityPoolRolesAttachmentRead(d, meta) +} + +func resourceAwsCognitoIdentityPoolRolesAttachmentDelete(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).cognitoconn + log.Printf("[DEBUG] Deleting Cognito Identity Pool Roles Association: %s", d.Id()) + + return resource.Retry(5*time.Minute, func() *resource.RetryError { + _, err := conn.SetIdentityPoolRoles(&cognitoidentity.SetIdentityPoolRolesInput{ + IdentityPoolId: aws.String(d.Get("identity_pool_id").(string)), + Roles: expandCognitoIdentityPoolRoles(make(map[string]interface{})), + RoleMappings: expandCognitoIdentityPoolRoleMappingsAttachment([]interface{}{}), + }) + + if err == nil { + return nil + } + + return resource.NonRetryableError(err) + }) +} + +// Validating that each role_mapping ambiguous_role_resolution +// is defined when "type" equals Token or Rules. +func validateRoleMappings(roleMappings []interface{}) []error { + errors := make([]error, 0) + + for _, r := range roleMappings { + rm := r.(map[string]interface{}) + + // If Type equals "Token" or "Rules", ambiguous_role_resolution must be defined. + // This should be removed as soon as we can have a ValidateFuncAgainst callable on the schema. + if err := validateCognitoRoleMappingsAmbiguousRoleResolutionAgainstType(rm); len(err) > 0 { + errors = append(errors, fmt.Errorf("Role Mapping %q: %v", rm["identity_provider"].(string), err)) + } + + // Validating that Rules Configuration is defined when Type equals Rules + // but not defined when Type equals Token. + if err := validateCognitoRoleMappingsRulesConfiguration(rm); len(err) > 0 { + errors = append(errors, fmt.Errorf("Role Mapping %q: %v", rm["identity_provider"].(string), err)) + } + } + + return errors +} + +func cognitoRoleMappingHash(v interface{}) int { + var buf bytes.Buffer + m := v.(map[string]interface{}) + buf.WriteString(fmt.Sprintf("%s-", m["identity_provider"].(string))) + + return hashcode.String(buf.String()) +} + +func cognitoRoleMappingValueHash(v interface{}) int { + var buf bytes.Buffer + m := v.(map[string]interface{}) + buf.WriteString(fmt.Sprintf("%s-", m["type"].(string))) + if d, ok := m["ambiguous_role_resolution"]; ok { + buf.WriteString(fmt.Sprintf("%s-", d.(string))) + } + + return hashcode.String(buf.String()) +} + +func cognitoRoleMappingRulesConfigurationHash(v interface{}) int { + var buf bytes.Buffer + for _, rule := range v.([]interface{}) { + r := rule.(map[string]interface{}) + buf.WriteString(fmt.Sprintf("%s-", r["claim"].(string))) + buf.WriteString(fmt.Sprintf("%s-", r["match_type"].(string))) + buf.WriteString(fmt.Sprintf("%s-", r["role_arn"].(string))) + buf.WriteString(fmt.Sprintf("%s-", r["value"].(string))) + } + + return hashcode.String(buf.String()) +} diff --git a/aws/resource_aws_cognito_identity_pool_roles_attachment_test.go b/aws/resource_aws_cognito_identity_pool_roles_attachment_test.go new file mode 100644 index 00000000000..df1776b7df4 --- /dev/null +++ b/aws/resource_aws_cognito_identity_pool_roles_attachment_test.go @@ -0,0 +1,431 @@ +package aws + +import ( + "errors" + "fmt" + "regexp" + "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 TestAccAWSCognitoIdentityPoolRolesAttachment_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: testAccCheckAWSCognitoIdentityPoolRolesAttachmentDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSCognitoIdentityPoolRolesAttachmentConfig_basic(name), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSCognitoIdentityPoolRolesAttachmentExists("aws_cognito_identity_pool_roles_attachment.main"), + resource.TestCheckResourceAttrSet("aws_cognito_identity_pool_roles_attachment.main", "identity_pool_id"), + resource.TestCheckResourceAttrSet("aws_cognito_identity_pool_roles_attachment.main", "roles.authenticated"), + ), + }, + { + Config: testAccAWSCognitoIdentityPoolRolesAttachmentConfig_basic(updatedName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSCognitoIdentityPoolRolesAttachmentExists("aws_cognito_identity_pool_roles_attachment.main"), + resource.TestCheckResourceAttrSet("aws_cognito_identity_pool_roles_attachment.main", "identity_pool_id"), + resource.TestCheckResourceAttrSet("aws_cognito_identity_pool_roles_attachment.main", "roles.authenticated"), + ), + }, + }, + }) +} + +func TestAccAWSCognitoIdentityPoolRolesAttachment_roleMappings(t *testing.T) { + name := fmt.Sprintf("%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSCognitoIdentityPoolRolesAttachmentDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSCognitoIdentityPoolRolesAttachmentConfig_basic(name), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSCognitoIdentityPoolRolesAttachmentExists("aws_cognito_identity_pool_roles_attachment.main"), + resource.TestCheckResourceAttrSet("aws_cognito_identity_pool_roles_attachment.main", "identity_pool_id"), + resource.TestCheckResourceAttr("aws_cognito_identity_pool_roles_attachment.main", "role_mapping.#", "0"), + resource.TestCheckResourceAttrSet("aws_cognito_identity_pool_roles_attachment.main", "roles.authenticated"), + ), + }, + { + Config: testAccAWSCognitoIdentityPoolRolesAttachmentConfig_roleMappings(name), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSCognitoIdentityPoolRolesAttachmentExists("aws_cognito_identity_pool_roles_attachment.main"), + resource.TestCheckResourceAttrSet("aws_cognito_identity_pool_roles_attachment.main", "identity_pool_id"), + resource.TestCheckResourceAttr("aws_cognito_identity_pool_roles_attachment.main", "role_mapping.#", "1"), + resource.TestCheckResourceAttrSet("aws_cognito_identity_pool_roles_attachment.main", "roles.authenticated"), + ), + }, + { + Config: testAccAWSCognitoIdentityPoolRolesAttachmentConfig_roleMappingsUpdated(name), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSCognitoIdentityPoolRolesAttachmentExists("aws_cognito_identity_pool_roles_attachment.main"), + resource.TestCheckResourceAttrSet("aws_cognito_identity_pool_roles_attachment.main", "identity_pool_id"), + resource.TestCheckResourceAttr("aws_cognito_identity_pool_roles_attachment.main", "role_mapping.#", "1"), + resource.TestCheckResourceAttrSet("aws_cognito_identity_pool_roles_attachment.main", "roles.authenticated"), + ), + }, + { + Config: testAccAWSCognitoIdentityPoolRolesAttachmentConfig_basic(name), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSCognitoIdentityPoolRolesAttachmentExists("aws_cognito_identity_pool_roles_attachment.main"), + resource.TestCheckResourceAttrSet("aws_cognito_identity_pool_roles_attachment.main", "identity_pool_id"), + resource.TestCheckResourceAttr("aws_cognito_identity_pool_roles_attachment.main", "role_mapping.#", "0"), + resource.TestCheckResourceAttrSet("aws_cognito_identity_pool_roles_attachment.main", "roles.authenticated"), + ), + }, + }, + }) +} + +func TestAccAWSCognitoIdentityPoolRolesAttachment_roleMappingsWithAmbiguousRoleResolutionError(t *testing.T) { + name := fmt.Sprintf("%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSCognitoIdentityPoolRolesAttachmentDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSCognitoIdentityPoolRolesAttachmentConfig_roleMappingsWithAmbiguousRoleResolutionError(name), + ExpectError: regexp.MustCompile(`Error validating ambiguous role resolution`), + }, + }, + }) +} + +func TestAccAWSCognitoIdentityPoolRolesAttachment_roleMappingsWithRulesTypeError(t *testing.T) { + name := fmt.Sprintf("%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSCognitoIdentityPoolRolesAttachmentDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSCognitoIdentityPoolRolesAttachmentConfig_roleMappingsWithRulesTypeError(name), + ExpectError: regexp.MustCompile(`mapping_rule is required for Rules`), + }, + }, + }) +} + +func TestAccAWSCognitoIdentityPoolRolesAttachment_roleMappingsWithTokenTypeError(t *testing.T) { + name := fmt.Sprintf("%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSCognitoIdentityPoolRolesAttachmentDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSCognitoIdentityPoolRolesAttachmentConfig_roleMappingsWithTokenTypeError(name), + ExpectError: regexp.MustCompile(`mapping_rule must not be set for Token based role mapping`), + }, + }, + }) +} + +func testAccCheckAWSCognitoIdentityPoolRolesAttachmentExists(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 Roles Attachment ID is set") + } + + conn := testAccProvider.Meta().(*AWSClient).cognitoconn + + _, err := conn.GetIdentityPoolRoles(&cognitoidentity.GetIdentityPoolRolesInput{ + IdentityPoolId: aws.String(rs.Primary.Attributes["identity_pool_id"]), + }) + + if err != nil { + return err + } + + return nil + } +} + +func testAccCheckAWSCognitoIdentityPoolRolesAttachmentDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*AWSClient).cognitoconn + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_cognito_identity_pool_roles_attachment" { + continue + } + + _, err := conn.GetIdentityPoolRoles(&cognitoidentity.GetIdentityPoolRolesInput{ + IdentityPoolId: aws.String(rs.Primary.Attributes["identity_pool_id"]), + }) + + if err != nil { + if wserr, ok := err.(awserr.Error); ok && wserr.Code() == "ResourceNotFoundException" { + return nil + } + return err + } + } + + return nil +} + +const baseAWSCognitoIdentityPoolRolesAttachmentConfig = ` +resource "aws_cognito_identity_pool" "main" { + identity_pool_name = "identity pool %s" + allow_unauthenticated_identities = false + + supported_login_providers { + "graph.facebook.com" = "7346241598935555" + } +} + +# Unauthenticated Role +resource "aws_iam_role" "unauthenticated" { + name = "cognito_unauthenticated_%s" + + assume_role_policy = < 0 { + rct := &cognitoidentity.RulesConfigurationType{} + mappingRules := make([]*cognitoidentity.MappingRule, 0) + + for _, r := range mr { + rule := r.(map[string]interface{}) + mr := &cognitoidentity.MappingRule{ + Claim: aws.String(rule["claim"].(string)), + MatchType: aws.String(rule["match_type"].(string)), + RoleARN: aws.String(rule["role_arn"].(string)), + Value: aws.String(rule["value"].(string)), + } + + mappingRules = append(mappingRules, mr) + } + + rct.Rules = mappingRules + roleMapping.RulesConfiguration = rct + } + + values[key] = roleMapping + } + + return values +} + +func flattenCognitoIdentityPoolRoleMappingsAttachment(rms map[string]*cognitoidentity.RoleMapping) []map[string]interface{} { + roleMappings := make([]map[string]interface{}, 0) + + if rms == nil { + return roleMappings + } + + for k, v := range rms { + m := make(map[string]interface{}) + + if v == nil { + return nil + } + + if v.Type != nil { + m["type"] = *v.Type + } + + if v.AmbiguousRoleResolution != nil { + m["ambiguous_role_resolution"] = *v.AmbiguousRoleResolution + } + + if v.RulesConfiguration != nil && v.RulesConfiguration.Rules != nil { + m["mapping_rule"] = flattenCognitoIdentityPoolRolesAttachmentMappingRules(v.RulesConfiguration.Rules) + } + + m["identity_provider"] = k + roleMappings = append(roleMappings, m) + } + + return roleMappings +} + +func flattenCognitoIdentityPoolRolesAttachmentMappingRules(d []*cognitoidentity.MappingRule) []interface{} { + rules := make([]interface{}, 0) + + for _, rule := range d { + r := make(map[string]interface{}) + r["claim"] = *rule.Claim + r["match_type"] = *rule.MatchType + r["role_arn"] = *rule.RoleARN + r["value"] = *rule.Value + + rules = append(rules, r) + } + + return rules +} diff --git a/aws/validators.go b/aws/validators.go index 2a3b2c16360..44acd2cf1a6 100644 --- a/aws/validators.go +++ b/aws/validators.go @@ -9,6 +9,7 @@ import ( "time" "github.com/aws/aws-sdk-go/service/apigateway" + "github.com/aws/aws-sdk-go/service/cognitoidentity" "github.com/aws/aws-sdk-go/service/s3" "github.com/hashicorp/terraform/helper/schema" ) @@ -1535,3 +1536,118 @@ func validateServiceCatalogPortfolioProviderName(v interface{}, k string) (ws [] } return } + +func validateCognitoRoleMappingsAmbiguousRoleResolutionAgainstType(v map[string]interface{}) (errors []error) { + t := v["type"].(string) + isRequired := t == cognitoidentity.RoleMappingTypeToken || t == cognitoidentity.RoleMappingTypeRules + + if value, ok := v["ambiguous_role_resolution"]; (!ok || value == "") && isRequired { + errors = append(errors, fmt.Errorf("Ambiguous Role Resolution must be defined when \"type\" equals \"Token\" or \"Rules\"")) + } + + return +} + +func validateCognitoRoleMappingsRulesConfiguration(v map[string]interface{}) (errors []error) { + t := v["type"].(string) + value, ok := v["mapping_rule"] + valLength := len(value.([]interface{})) + + if (!ok || valLength == 0) && t == cognitoidentity.RoleMappingTypeRules { + errors = append(errors, fmt.Errorf("mapping_rule is required for Rules")) + } + + if (ok || valLength > 0) && t == cognitoidentity.RoleMappingTypeToken { + errors = append(errors, fmt.Errorf("mapping_rule must not be set for Token based role mapping")) + } + + return +} + +func validateCognitoRoleMappingsAmbiguousRoleResolution(v interface{}, k string) (ws []string, errors []error) { + validValues := []string{ + cognitoidentity.AmbiguousRoleResolutionTypeAuthenticatedRole, + cognitoidentity.AmbiguousRoleResolutionTypeDeny, + } + value := v.(string) + for _, s := range validValues { + if value == s { + return + } + } + errors = append(errors, fmt.Errorf( + "%q contains an invalid value %q. Valid values are %q.", + k, value, validValues)) + return +} + +func validateCognitoRoleMappingsRulesClaim(v interface{}, k string) (ws []string, errors []error) { + value := v.(string) + + if !regexp.MustCompile("^[\\p{L}\\p{M}\\p{S}\\p{N}\\p{P}]+$").MatchString(value) { + errors = append(errors, fmt.Errorf("%q must contain only alphanumeric caracters, dots, underscores, colons, slashes and hyphens", k)) + } + + return +} + +func validateCognitoRoleMappingsRulesMatchType(v interface{}, k string) (ws []string, errors []error) { + validValues := []string{ + cognitoidentity.MappingRuleMatchTypeEquals, + cognitoidentity.MappingRuleMatchTypeContains, + cognitoidentity.MappingRuleMatchTypeStartsWith, + cognitoidentity.MappingRuleMatchTypeNotEqual, + } + value := v.(string) + for _, s := range validValues { + if value == s { + return + } + } + errors = append(errors, fmt.Errorf( + "%q contains an invalid value %q. Valid values are %q.", + k, value, validValues)) + return +} + +func validateCognitoRoleMappingsRulesValue(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 caracter", k)) + } + + if len(value) > 128 { + errors = append(errors, fmt.Errorf("%q cannot be longer than 1 caracters", k)) + } + + return +} + +func validateCognitoRoleMappingsType(v interface{}, k string) (ws []string, errors []error) { + validValues := []string{ + cognitoidentity.RoleMappingTypeToken, + cognitoidentity.RoleMappingTypeRules, + } + value := v.(string) + for _, s := range validValues { + if value == s { + return + } + } + errors = append(errors, fmt.Errorf( + "%q contains an invalid value %q. Valid values are %q.", + k, value, validValues)) + return +} + +// Validates that either authenticated or unauthenticated is defined +func validateCognitoRoles(v map[string]interface{}, k string) (errors []error) { + _, hasAuthenticated := v["authenticated"].(string) + _, hasUnauthenticated := v["authenticated"].(string) + + if !hasAuthenticated && !hasUnauthenticated { + errors = append(errors, fmt.Errorf("%q: Either \"authenticated\" or \"unauthenticated\" must be defined", k)) + } + + return +} diff --git a/aws/validators_test.go b/aws/validators_test.go index 451414b9afd..2e9dae246b9 100644 --- a/aws/validators_test.go +++ b/aws/validators_test.go @@ -5,6 +5,7 @@ import ( "strings" "testing" + "github.com/aws/aws-sdk-go/service/cognitoidentity" "github.com/aws/aws-sdk-go/service/s3" ) @@ -2448,6 +2449,107 @@ func TestValidateBatchName(t *testing.T) { } } +func TestValidateCognitoRoleMappingsAmbiguousRoleResolutionAgainstType(t *testing.T) { + cases := []struct { + AmbiguousRoleResolution interface{} + Type string + ErrCount int + }{ + { + AmbiguousRoleResolution: nil, + Type: cognitoidentity.RoleMappingTypeToken, + ErrCount: 1, + }, + { + AmbiguousRoleResolution: "foo", + Type: cognitoidentity.RoleMappingTypeToken, + ErrCount: 0, // 0 as it should be defined, the value isn't validated here + }, + { + AmbiguousRoleResolution: cognitoidentity.AmbiguousRoleResolutionTypeAuthenticatedRole, + Type: cognitoidentity.RoleMappingTypeToken, + ErrCount: 0, + }, + { + AmbiguousRoleResolution: cognitoidentity.AmbiguousRoleResolutionTypeDeny, + Type: cognitoidentity.RoleMappingTypeToken, + ErrCount: 0, + }, + } + + for _, tc := range cases { + m := make(map[string]interface{}) + // Reproducing the undefined ambiguous_role_resolution + if tc.AmbiguousRoleResolution != nil { + m["ambiguous_role_resolution"] = tc.AmbiguousRoleResolution + } + m["type"] = tc.Type + + errors := validateCognitoRoleMappingsAmbiguousRoleResolutionAgainstType(m) + if len(errors) != tc.ErrCount { + t.Fatalf("Cognito Role Mappings validation failed: %v, expected err count %d, got %d, for config %#v", errors, tc.ErrCount, len(errors), m) + } + } +} + +func TestValidateCognitoRoleMappingsAmbiguousRoleResolution(t *testing.T) { + validValues := []string{ + cognitoidentity.AmbiguousRoleResolutionTypeAuthenticatedRole, + cognitoidentity.AmbiguousRoleResolutionTypeDeny, + } + + for _, s := range validValues { + _, errors := validateCognitoRoleMappingsAmbiguousRoleResolution(s, "ambiguous_role_resolution") + if len(errors) > 0 { + t.Fatalf("%q should be a valid Cognito Ambiguous Role Resolution type: %v", s, errors) + } + } + + invalidValues := []string{ + "foo", + "123", + "foo-bar", + "foo_bar123", + } + + for _, s := range invalidValues { + _, errors := validateCognitoRoleMappingsAmbiguousRoleResolution(s, "ambiguous_role_resolution") + if len(errors) == 0 { + t.Fatalf("%q should not be a valid Cognito Ambiguous Role Resolution type: %v", s, errors) + } + } +} + +func TestValidateCognitoRoleMappingsRulesMatchType(t *testing.T) { + validValues := []string{ + cognitoidentity.MappingRuleMatchTypeEquals, + cognitoidentity.MappingRuleMatchTypeContains, + cognitoidentity.MappingRuleMatchTypeStartsWith, + cognitoidentity.MappingRuleMatchTypeNotEqual, + } + + for _, s := range validValues { + _, errors := validateCognitoRoleMappingsRulesMatchType(s, "match_type") + if len(errors) > 0 { + t.Fatalf("%q should be a valid Cognito Role Mappings Rules Match Type: %v", s, errors) + } + } + + invalidValues := []string{ + "foo", + "123", + "foo-bar", + "foo_bar123", + } + + for _, s := range invalidValues { + _, errors := validateCognitoRoleMappingsRulesMatchType(s, "match_type") + if len(errors) == 0 { + t.Fatalf("%q should not be a valid Cognito Role Mappings Rules Match Type: %v", s, errors) + } + } +} + func TestValidateSecurityGroupRuleDescription(t *testing.T) { validDescriptions := []string{ "testrule", @@ -2473,3 +2575,31 @@ func TestValidateSecurityGroupRuleDescription(t *testing.T) { } } } + +func TestValidateCognitoRoleMappingsType(t *testing.T) { + validValues := []string{ + cognitoidentity.RoleMappingTypeToken, + cognitoidentity.RoleMappingTypeRules, + } + + for _, s := range validValues { + _, errors := validateCognitoRoleMappingsType(s, "match_type") + if len(errors) > 0 { + t.Fatalf("%q should be a valid Cognito Role Mappings Type: %v", s, errors) + } + } + + invalidValues := []string{ + "foo", + "123", + "foo-bar", + "foo_bar123", + } + + for _, s := range invalidValues { + _, errors := validateCognitoRoleMappingsType(s, "match_type") + if len(errors) == 0 { + t.Fatalf("%q should not be a valid Cognito Role Mappings Type: %v", s, errors) + } + } +} diff --git a/website/aws.erb b/website/aws.erb index d2cbf0efe19..af3c20a7627 100644 --- a/website/aws.erb +++ b/website/aws.erb @@ -439,6 +439,9 @@ > aws_cognito_identity_pool + > + aws_cognito_identity_pool_roles_attachment + diff --git a/website/docs/r/cognito_identity_pool_roles_attachment.markdown b/website/docs/r/cognito_identity_pool_roles_attachment.markdown new file mode 100644 index 00000000000..2be8da7f0be --- /dev/null +++ b/website/docs/r/cognito_identity_pool_roles_attachment.markdown @@ -0,0 +1,127 @@ +--- +layout: "aws" +page_title: "AWS: aws_cognito_identity_pool_roles_attachment" +sidebar_current: "docs-aws-resource-cognito-identity-pool-roles-attachment" +description: |- + Provides an AWS Cognito Identity Pool Roles Attachment. +--- + +# aws_cognito_identity_pool_roles_attachment + +Provides an AWS Cognito Identity Pool Roles Attachment. + +## Example Usage + +``` +resource "aws_cognito_identity_pool" "main" { + identity_pool_name = "identity pool" + allow_unauthenticated_identities = false + + supported_login_providers { + "graph.facebook.com" = "7346241598935555" + } +} + +resource "aws_iam_role" "authenticated" { + name = "cognito_authenticated" + + assume_role_policy = < Date: Mon, 23 Oct 2017 18:53:28 +0200 Subject: [PATCH 2/2] Cognito Roles Attachment: Fixed cast issue, updated test logic --- ..._cognito_identity_pool_roles_attachment.go | 6 +-- ...ito_identity_pool_roles_attachment_test.go | 47 +++++++++++-------- 2 files changed, 31 insertions(+), 22 deletions(-) diff --git a/aws/resource_aws_cognito_identity_pool_roles_attachment.go b/aws/resource_aws_cognito_identity_pool_roles_attachment.go index 6007515517c..5030331b961 100644 --- a/aws/resource_aws_cognito_identity_pool_roles_attachment.go +++ b/aws/resource_aws_cognito_identity_pool_roles_attachment.go @@ -125,10 +125,10 @@ func resourceAwsCognitoIdentityPoolRolesAttachmentCreate(d *schema.ResourceData, return fmt.Errorf("Error validating ambiguous role resolution: %v", errors) } - params.RoleMappings = expandCognitoIdentityPoolRoleMappingsAttachment(v.([]interface{})) + params.RoleMappings = expandCognitoIdentityPoolRoleMappingsAttachment(v.(*schema.Set).List()) } - log.Sprintf("[DEBUG] Creating Cognito Identity Pool Roles Association: %#v", params) + log.Printf("[DEBUG] Creating Cognito Identity Pool Roles Association: %#v", params) _, err := conn.SetIdentityPoolRoles(params) if err != nil { return fmt.Errorf("Error creating Cognito Identity Pool Roles Association: %s", err) @@ -198,7 +198,7 @@ func resourceAwsCognitoIdentityPoolRolesAttachmentUpdate(d *schema.ResourceData, params.RoleMappings = expandCognitoIdentityPoolRoleMappingsAttachment(mappings) } - log.Sprintf("[DEBUG] Updating Cognito Identity Pool Roles Association: %#v", params) + log.Printf("[DEBUG] Updating Cognito Identity Pool Roles Association: %#v", params) _, err := conn.SetIdentityPoolRoles(params) if err != nil { return fmt.Errorf("Error updating Cognito Identity Pool Roles Association: %s", err) diff --git a/aws/resource_aws_cognito_identity_pool_roles_attachment_test.go b/aws/resource_aws_cognito_identity_pool_roles_attachment_test.go index df1776b7df4..8d0a9ba5fee 100644 --- a/aws/resource_aws_cognito_identity_pool_roles_attachment_test.go +++ b/aws/resource_aws_cognito_identity_pool_roles_attachment_test.go @@ -187,9 +187,10 @@ func testAccCheckAWSCognitoIdentityPoolRolesAttachmentDestroy(s *terraform.State return nil } -const baseAWSCognitoIdentityPoolRolesAttachmentConfig = ` +func baseAWSCognitoIdentityPoolRolesAttachmentConfig(name string) string { + return fmt.Sprintf(` resource "aws_cognito_identity_pool" "main" { - identity_pool_name = "identity pool %s" + identity_pool_name = "identity pool %[1]s" allow_unauthenticated_identities = false supported_login_providers { @@ -199,7 +200,7 @@ resource "aws_cognito_identity_pool" "main" { # Unauthenticated Role resource "aws_iam_role" "unauthenticated" { - name = "cognito_unauthenticated_%s" + name = "cognito_unauthenticated_%[1]s" assume_role_policy = <