Skip to content

Commit

Permalink
provider/aws: Added Cognito Identity Pool Roles Association
Browse files Browse the repository at this point in the history
  • Loading branch information
Ninir committed Apr 24, 2017
1 parent d721240 commit 4cea061
Show file tree
Hide file tree
Showing 8 changed files with 1,195 additions and 3 deletions.
1 change: 1 addition & 0 deletions builtin/providers/aws/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,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_codedeploy_app": resourceAwsCodeDeployApp(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,307 @@
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_mappings": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"role_mapping": {
Type: schema.TypeSet,
Required: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"key": {
Type: schema.TypeString,
Required: true,
},
"value": {
Type: schema.TypeSet,
MaxItems: 1,
Required: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"ambiguous_role_resolution": {
Type: schema.TypeString,
ValidateFunc: validateCognitoRoleMappingsAmbiguousRoleResolution,
Optional: true, // Required if Type equals Token or Rules.
},
"rules_configuration": {
Type: schema.TypeSet,
MaxItems: 1,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"rules": {
Type: schema.TypeList,
Required: 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
log.Print("[DEBUG] Creating Cognito Identity Pool Roles Association")

// 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_mappings"); ok {
rms := v.([]interface{})[0].(map[string]interface{})
errors := validateRoleMappings(rms["role_mapping"].(*schema.Set).List())

if len(errors) > 0 {
return fmt.Errorf("Error validating ambiguous role resolution: %v", errors)
}

params.RoleMappings = expandCognitoIdentityPoolRoleMappingsAttachment(v.([]interface{}))
}

_, 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" {
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_mappings", 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
log.Printf("[DEBUG] Updating Cognito Identity Pool Roles Association: %s", d.Id())

// 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_mappings") {
v, ok := d.GetOk("role_mappings")
var mappings []interface{}

if ok {
rms := v.([]interface{})[0].(map[string]interface{})
errors := validateRoleMappings(rms["role_mapping"].(*schema.Set).List())

if len(errors) > 0 {
return fmt.Errorf("Error validating ambiguous role resolution: %v", errors)
}
mappings = v.([]interface{})
} else {
mappings = []interface{}{}
}

params.RoleMappings = expandCognitoIdentityPoolRoleMappingsAttachment(mappings)
}

_, 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{})
roleMapping := rm["value"].(*schema.Set).List()

if err := validateCognitoRoleMappingsAmbiguousRoleResolutionAgainstType(roleMapping[0].(map[string]interface{})); len(err) > 0 {
errors = append(errors, fmt.Errorf("Role Mapping %q: %v", rm["key"].(string), err))
}
}

return errors
}

func cognitoRoleMappingHash(v interface{}) int {
var buf bytes.Buffer
m := v.(map[string]interface{})
buf.WriteString(fmt.Sprintf("%s-", m["key"].(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
m := v.(map[string]interface{})
for _, rule := range m["rules"].([]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())
}
Loading

0 comments on commit 4cea061

Please sign in to comment.