Skip to content

cognito-identity-pool: Can't attach IdentityPoolRoleAttachment even if not present #23449

@wz2b

Description

@wz2b

Describe the bug

If you create an identity pool like this, without specifying an authenticated and unauthenticated role, it generates default roles rather than just leaving them blank.

const idPool = new IdentityPool(stack, "xxx-cognito-id-pool", {
    identityPoolName: "xxx-id-pool",
    allowUnauthenticatedIdentities: true,
    authenticationProviders: {
        userPools: [new UserPoolAuthenticationProvider({userPool: userPool})]
    }
})

Then, later, when you try to attach your own roles, like this:

const roleAttachment = new IdentityPoolRoleAttachment(stack,
    "xxx-id-pool-attachment",
    {
        identityPool: idPool,
        authenticatedRole: authenticatedRole,
        unauthenticatedRole: unauthenticatedRole
    })

it fails with this error:

CREATE_FAILED
AWS::Cognito::IdentityPoolRoleAttachment
xxx-stack/xxx-id-pool-attachment (xxxidpoolattachmentE8645D23) us-east-1:bc70b990-d038-43b8-8501-e7cd3dda6ae7 already exists in stack

Its beef seems to be that even though I created the identity pool without roles attached, it created default ones on its own. Then later when I go to 'attach' my own, it won't let me because it thinks there is already an attachment.

Expected Behavior

I expected that when I create an identity pool with no roles, it would not generate default roles.

Current Behavior

Testing this with only this code and a brand new stack:

    const idPool = new IdentityPool(stack, "my-cognito-id-pool", {
        identityPoolName: "my-id-pool",
        allowUnauthenticatedIdentities: true,
        authenticationProviders: {
            userPools: [new UserPoolAuthenticationProvider({userPool: userPool})]
        }
    })

it created default IAM roles for authenticated and unauthenticated users. This caused a conflict when I then tried to create my own IdentityPoolRoleAttachment, because it says there was already an attachment.

Reproduction Steps

const idPool = new IdentityPool(stack, "my-cognito-id-pool", {
    identityPoolName: "my-id-pool",
    allowUnauthenticatedIdentities: true,
    authenticationProviders: { userPools: [new UserPoolAuthenticationProvider({userPool: userPool})] }
})


const authenticatedRole = new Role(stack, "my-cognito-authenticated-role", {
    roleName: "my-cognito-authenticated-role",
    assumedBy: new WebIdentityPrincipal('cognito-identity.amazonaws.com',
        {
            StringEquals: {
                'cognito-identity.amazonaws.com:aud': `${stack.region}:${idPool.identityPoolId}`,
            },
            'ForAnyValue:StringLike': {
                'cognito-identity.amazonaws.com:amr': 'unauthenticated',
            },
        })
});

const unauthenticatedRole = new Role(stack, "my-cognito-unauthenticated-role", {
    roleName: "my-cognito-unauthenticated-role",
    assumedBy: new WebIdentityPrincipal('cognito-identity.amazonaws.com',
        {
            StringEquals: {
                'cognito-identity.amazonaws.com:aud': `${stack.region}:${idPool.identityPoolId}`,
            },
            'ForAnyValue:StringLike': {
                'cognito-identity.amazonaws.com:amr': 'authenticated',
            },
        })
});

const roleAttachment = new IdentityPoolRoleAttachment(stack,
    "my-id-pool-attachment",
    {
        identityPool: idPool,
        authenticatedRole: authenticatedRole,
        unauthenticatedRole: unauthenticatedRole
    })

Possible Solution

I think the way to fix this is that if you create an identity pool without specifying roles it actually leaves them empty rather than generating default roles. This document tells me this should be possible as the attachment is something completely separate.

Why this is important is that I want to add constraints to my roles that only allow those role to be assumed by this specific identity pool. To do that, I need a reference to the identity pool. So for this to work you have to do things in this order:

  1. Create the identity pool with no attached roles
  2. Create the authorized and unauthorized roles with a trust policy constrained to that identity pool
  3. Attach these roles to the identity pool

Additional Information/Context

My versions of the pieces I am using from packages.json are:

    "@aws-cdk/aws-apigatewayv2-alpha": "^2.56.0-alpha.0",
    "@aws-cdk/aws-apigatewayv2-authorizers-alpha": "^2.56.0-alpha.0",
    "@aws-cdk/aws-apigatewayv2-integrations-alpha": "^2.56.0-alpha.0",
    "@aws-cdk/aws-cognito-identitypool-alpha": "^2.56.0-alpha.0",
    "aws-cdk": "2.56.0",
    "aws-cdk-lib": "2.56.0",

CDK CLI Version

2.56.0 (build 1485f48)

Framework Version

2.56.0-alpha.0

Node.js Version

v16.18.0

OS

Windows 10

Language

Typescript

Language Version

4.9.3

Other information

    "aws-cdk": "2.56.0",
    "aws-cdk-lib": "2.56.0",

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions