hashicorp / terraform-provider-aws

The AWS Provider enables Terraform to manage AWS resources.
https://registry.terraform.io/providers/hashicorp/aws
Mozilla Public License 2.0
9.88k stars 9.22k forks source link

Unable to Set Authenticated and Unauthenticated Role at the Same Time in Cognito Identity Pool #25330

Open przemeklach opened 2 years ago

przemeklach commented 2 years ago

Community Note

Terraform CLI and Terraform AWS Provider Version

Terraform v1.2.2 on darwin_arm64

Affected Resource(s)

Terraform Configuration Files

resource "aws_cognito_user_pool" "users" {
  name                = local.pool_name
  username_attributes = ["email"]

  account_recovery_setting {
    recovery_mechanism {
      name     = "verified_email"
      priority = 1
    }
  }

  auto_verified_attributes = ["email"]

  verification_message_template {
    default_email_option = "CONFIRM_WITH_LINK"
  }

  lambda_config {
    pre_sign_up       = var.lambda_pr_sign_up_trigger_arn
    post_confirmation = var.lambda_post_confirmation_trigger_arn
  }

  schema {
    attribute_data_type      = "String"
    name                     = "account_identifier"
    developer_only_attribute = false
    mutable                  = false
    required                 = false
    string_attribute_constraints {
      min_length = 36
      max_length = 36
    }
  }
}

resource "aws_cognito_identity_pool" "main" {
  identity_pool_name               = local.pool_name
  allow_unauthenticated_identities = false

  cognito_identity_providers {
    client_id               = aws_cognito_user_pool_client.website.id
    provider_name           = aws_cognito_user_pool.users.endpoint
    server_side_token_check = true
  }
}

resource "aws_iam_role" "authenticated" {
  name               = "${local.name_prefix}AuthenticatedAssumeRole"
  assume_role_policy = data.aws_iam_policy_document.assume_authenticated_role.json
}

resource "aws_cognito_identity_pool_roles_attachment" "authenticated_users" {
  identity_pool_id = aws_cognito_identity_pool.main.id
  roles            = {
    "authenticated" : aws_iam_role.authenticated.arn
  }
}

resource "aws_iam_role" "unauthenticated" {
  name               = "${local.name_prefix}UnauthenticatedAssumeRole"
  assume_role_policy = data.aws_iam_policy_document.assume_unauthenticated_role.json
}

resource "aws_cognito_identity_pool_roles_attachment" "unauthenticated_users" {
  identity_pool_id = aws_cognito_identity_pool.main.id
  roles            = {
    "unauthenticated" : aws_iam_role.unauthenticated.arn
  }
}

data "aws_iam_policy_document" "assume_unauthenticated_role" {
  version = "2012-10-17"
  statement {
    actions = ["sts:AssumeRoleWithWebIdentity"]
    effect  = "Allow"
    sid     = ""
    principals {
      identifiers = ["cognito-identity.amazonaws.com"]
      type        = "Federated"
    }
    condition {
      test     = "StringEquals"
      values   = [aws_cognito_identity_pool.main.id]
      variable = "cognito-identity.amazonaws.com:aud"
    }
    condition {
      test     = "ForAnyValue:StringLike"
      values   = ["unauthenticated"]
      variable = "cognito-identity.amazonaws.com:amr"
    }
  }
}

data "aws_iam_policy_document" "assume_authenticated_role" {
  version = "2012-10-17"
  statement {
    actions = ["sts:AssumeRoleWithWebIdentity"]
    effect  = "Allow"
    sid     = ""
    principals {
      identifiers = ["cognito-identity.amazonaws.com"]
      type        = "Federated"
    }
    condition {
      test     = "StringEquals"
      values   = [aws_cognito_identity_pool.main.id]
      variable = "cognito-identity.amazonaws.com:aud"
    }
    condition {
      test     = "ForAnyValue:StringLike"
      values   = ["authenticated"]
      variable = "cognito-identity.amazonaws.com:amr"
    }
  }
}

Debug Output

First Run Error: https://gist.github.com/przemeklach/d98cf6270a678a4f71b32828395444e8

Expected Behavior

Both the authenticated and unauthenticated roles are set to the roles I defined in the Identity Pool.

Actual Behavior

Only one of the roles gets set.

Steps to Reproduce

On the first run, or any run where I manually set the roles in aws console to empty or to the desired roles, on a subsequent terraform apply run I get an error "Error creating Cognito Identity Pool Roles Association: ConcurrentModificationException: Only one request to update resource type Identity Pool can be processed at a time". Full output linked in Debug Output section".

This leaves the pool in bad state where only one of the two roles is selected. On subsequent terraform apply it will just cause a flip e.g: if authenticated role was set and unauthenticated was unset it will unset the authenticated role and set the authenticated role. From this point forward if you keep running terraform apply it will just keep flipping back and forth.

aleksandarbos commented 1 year ago

same here, when i try to attach roles to cognito identity:

resource "aws_cognito_identity_pool_roles_attachment" "authenticated_attachment" {
  identity_pool_id = aws_cognito_identity_pool.identity_pool.id
  roles = {
    "authenticated" = aws_iam_role.cognito_authenticated.arn
  }
}

resource "aws_cognito_identity_pool_roles_attachment" "unauthenticated_attachment" {
  identity_pool_id = aws_cognito_identity_pool.identity_pool.id
  roles = {
    "unauthenticated" = aws_iam_role.cognito_unauthenticated.arn
  }
}

i keep getting

│ Error: Error deleting Cognito identity pool roles association: ConcurrentModificationException: Only one request to update resource type Identity Pool can be processed at a time

if you apply that multiple times for some reason it will add auth role and remove unauth and vice versa.

osiro commented 1 year ago

I had the same issue with an old version of the AWS provider (4.67.0). I've just updated to the latest (5.4) and it did work as expected.

Also, try putting multiple roles together on the same resource, see example below:

resource "aws_cognito_identity_pool_roles_attachment" "roles_attachment" {
  identity_pool_id = aws_cognito_identity_pool.identity_pool.id
  roles = {
    "authenticated"   = aws_iam_role.authenticated_role.arn
    "unauthenticated" = aws_iam_role.unauthenticated_role.arn
  }
}

:point_up: that works well for me.

aleksandarbos commented 1 year ago

I had the same issue with an old version of the AWS provider (4.67.0). I've just updated to the latest (5.4) and it did work as expected.

Also, try putting multiple roles together on the same resource, see example below:

resource "aws_cognito_identity_pool_roles_attachment" "roles_attachment" {
  identity_pool_id = aws_cognito_identity_pool.identity_pool.id
  roles = {
    "authenticated"   = aws_iam_role.authenticated_role.arn
    "unauthenticated" = aws_iam_role.unauthenticated_role.arn
  }
}

☝️ that works well for me.

awesome, confirming it works after the update!