aws / aws-cdk

The AWS Cloud Development Kit is a framework for defining cloud infrastructure in code
https://aws.amazon.com/cdk
Apache License 2.0
11.55k stars 3.87k forks source link

aws-cdk-aws-cognito-identitypool-alpha: IdentityPoolProviderUrl.user_pool cant handle imported userpools #30304

Closed SpielerNogard closed 1 week ago

SpielerNogard commented 4 months ago

Describe the bug

Our Userpool and clients are created outside our application. We now want to attach a identity pool to this userpool. Today i updated from version aws-cdk-aws-cognito-identitypool-alpha==2.96.0a0 to aws-cdk-aws-cognito-identitypool-alpha == 2.141.0a0 and changed the role_mappings accordingly. While running cdk synth i get the error: TypeError: type of argument user_pool must be aws_cdk.aws_cognito.UserPool; got jsii._reference_map.InterfaceDynamicProxy instead

Expected Behavior

Since the UserPoolAuthenticationProvider is able to handle imported userpools and clients, the IdentityPoolProviderUrl should also be

Current Behavior

Traceback (most recent call last):
  File "app.py", line 9, in <module>
    pipeline = PipelineStack(
  File "/Users/spielernogard/Documents/Repositories/bestoraged-okean-control-backend/.venv/lib/python3.8/site-packages/jsii/_runtime.py", line 118, in __call__
    inst = super(JSIIMeta, cast(JSIIMeta, cls)).__call__(*args, **kwargs)
  File "/Users/spielernogard/Documents/Repositories/bestoraged-okean-control-backend/pipeline/pipeline_stack.py", line 34, in __init__
    self._add_stages(pipeline=pipeline, id_suffix="Prod", branch=branch)
  File "/Users/spielernogard/Documents/Repositories/bestoraged-okean-control-backend/pipeline/pipeline_stack.py", line 69, in _add_stages
    services = Services(
  File "/Users/spielernogard/Documents/Repositories/bestoraged-okean-control-backend/.venv/lib/python3.8/site-packages/jsii/_runtime.py", line 118, in __call__
    inst = super(JSIIMeta, cast(JSIIMeta, cls)).__call__(*args, **kwargs)
  File "/Users/spielernogard/Documents/Repositories/bestoraged-okean-control-backend/pipeline/deployment.py", line 68, in __init__
    gui_backend = GUIBackendStack(
  File "/Users/spielernogard/Documents/Repositories/bestoraged-okean-control-backend/.venv/lib/python3.8/site-packages/jsii/_runtime.py", line 118, in __call__
    inst = super(JSIIMeta, cast(JSIIMeta, cls)).__call__(*args, **kwargs)
  File "/Users/spielernogard/Documents/Repositories/bestoraged-okean-control-backend/services/gui_backend/stack_gui_backend.py", line 18, in __init__
    ControlUserPool(scope=self, id="UserPool")
  File "/Users/spielernogard/Documents/Repositories/bestoraged-okean-control-backend/.venv/lib/python3.8/site-packages/jsii/_runtime.py", line 118, in __call__
    inst = super(JSIIMeta, cast(JSIIMeta, cls)).__call__(*args, **kwargs)
  File "/Users/spielernogard/Documents/Repositories/bestoraged-okean-control-backend/services/gui_backend/user_pool/infrastructure.py", line 106, in __init__
    provider_url=IdentityPoolProviderUrl.user_pool(
  File "/Users/spielernogard/Documents/Repositories/bestoraged-okean-control-backend/.venv/lib/python3.8/site-packages/aws_cdk/aws_cognito_identitypool_alpha/__init__.py", line 1411, in user_pool
    check_type(argname="argument user_pool", value=user_pool, expected_type=type_hints["user_pool"])
  File "/Users/spielernogard/Documents/Repositories/bestoraged-okean-control-backend/.venv/lib/python3.8/site-packages/typeguard/__init__.py", line 785, in check_type
    raise TypeError(
TypeError: type of argument user_pool must be aws_cdk.aws_cognito.UserPool; got jsii._reference_map.InterfaceDynamicProxy instead

Reproduction Steps

import os  

import aws_cdk as cdk  
import aws_cdk.aws_cognito as cognito  
from aws_cdk import aws_iam as iam  
from aws_cdk.aws_cognito_identitypool_alpha import (  
    IdentityPool,  
    IdentityPoolAuthenticationProviders,  
    IdentityPoolRoleMapping,  
    IdentityPoolProviderUrl,  
    UserPoolAuthenticationProvider,  
)    
from constructs import Construct  

USER_POOL_ARN = 'ARN_HERE'
USER_POOL_CLIENT_ID = "CLIENT_ID_HERE"

class ControlUserPool(Construct):  
    """Construct"""  

    def __init__(self, scope: Construct, id: str):  
        super().__init__(scope, id)   
        this_dir = os.path.dirname(__file__)  

        # import userpool
        self.user_pool = cognito.UserPool.from_user_pool_arn(  
            scope=self, id="CognitoUserPool", user_pool_arn=USER_POOL_ARN  
        )  

        # import userpool client
        self.user_pool_client = cognito.UserPoolClient.from_user_pool_client_id(  
            scope=self,  
            id="UserPoolClientId",  
            user_pool_client_id=USER_POOL_CLIENT_ID,  
        )  

        # create and attach identity pool
        self.identity_pool = IdentityPool(  
            scope=self,  
            id="IdentityPool",  
            identity_pool_name=resource_name(  
                self, name="IdentityPool"  
            ),  
            authentication_providers=IdentityPoolAuthenticationProviders(  
                user_pools=[  
                    UserPoolAuthenticationProvider(  
                        user_pool=self.user_pool,  
                        user_pool_client=self.user_pool_client,  
                    )  
                ]  
            ),  
            role_mappings=[  
                IdentityPoolRoleMapping(  
                    mapping_key="cognito",  
                    provider_url=IdentityPoolProviderUrl.user_pool(  
                        user_pool=self.user_pool,  
                        user_pool_client=self.user_pool_client,  
                    ),  
                    use_token=True,  
                )  
            ],  
            allow_unauthenticated_identities=False,  
        )

Possible Solution

No response

Additional Information/Context

No response

CDK CLI Version

2.142.1 (build ed4e152)

Framework Version

No response

Node.js Version

v21.1.0

OS

Mac OS 14.5 (23F79)

Language

Python

Language Version

3.8.18 3.12.0 3.11.6

Other information

No response

ashishdhingra commented 4 months ago

@SpielerNogard Good morning. I tried to reproduce the issue in TypeScript (even though the issue was reported in Python) to compare the behavior.

import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as cognito from 'aws-cdk-lib/aws-cognito';
import * as cognitoidp from '@aws-cdk/aws-cognito-identitypool-alpha';

export class TypescriptStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const userPool = cognito.UserPool.fromUserPoolArn(this, 'CognitoUserPool', 'arn:aws:cognito-idp:<<REGION>>:<<ACCOUNT-ID>>:userpool/<<REGION>>_<<SOME-ID>>');

    const userPoolClient = cognito.UserPoolClient.fromUserPoolClientId(this, 'UserPoolClientId', '<<APP-CLIENT-ID>>');

    const identityPool = new cognitoidp.IdentityPool(this, 'IdentityPool', {
      identityPoolName: 'IdentityPool',
      authenticationProviders: {
        userPools: [
          new cognitoidp.UserPoolAuthenticationProvider({
            userPool: userPool,
            userPoolClient: userPoolClient
          })
        ]
      },
      roleMappings: [
        {
          mappingKey: 'cognito', 
          providerUrl: cognitoidp.IdentityPoolProviderUrl.userPool(userPool, userPoolClient),
          useToken: true
        }
      ],
      allowUnauthenticatedIdentities: false
    });
  }
}

The Visual Studio Code IDE itself flagged the error Argument of type 'IUserPool' is not assignable to parameter of type 'UserPool'. Type 'IUserPool' is missing the following properties from type 'UserPool': userPoolProviderName, userPoolProviderUrl, triggers, addTrigger, and 17 more.ts(2345) at line providerUrl: cognitoidp.IdentityPoolProviderUrl.userPool(userPool, userPoolClient),.

Upon investigating further:

I will discuss this with the team for any workarounds.

Thanks, Ashish

SpielerNogard commented 4 months ago

Thanks for the answer.

Thats bad, since we cant recreate the userpool in the stack, because we have too much users, and this error interrupts us also with the plan to go to python3.12

Hope its possible to find a workaround 🤞

pahud commented 4 months ago

That's correct!

But if we look at its implementation:

https://github.com/aws/aws-cdk/blob/c3003ab41f0efc763f39eb2cab490c8a005e146b/packages/%40aws-cdk/aws-cognito-identitypool-alpha/lib/identitypool.ts#L160-L163

we just need the userPoolProviderName attribute of the userPool, which is not available in IUserPool. https://github.com/aws/aws-cdk/blob/c3003ab41f0efc763f39eb2cab490c8a005e146b/packages/aws-cdk-lib/aws-cognito/lib/user-pool.ts#L757-L803

To fix this bug:

  1. We need to add userPoolProviderName in IUserPool
  2. We need to add a fromUserPoolAttributes() method that allows user to pass userPoolProviderName for an existing user pool.
  3. After all above, we can change userPool(userPool: UserPool to userPool(userPool: IUserPool
sakurai-ryo commented 4 months ago

I'll take this.

pahud commented 4 months ago

Hi @sakurai-ryo

Please note adding new attributes to IUserPool would be a breaking change and we should avoid that as aws-cognito is a stable module. I am requesting input from our maintainers for this issue so we'll know how to address that.

TheRealAmazonKendra commented 4 months ago

Just one point of clarification: adding attributes is not a breaking change. The proposed change is OK on our end.

github-actions[bot] commented 1 week ago

Comments on closed issues and PRs are hard for our team to see. If you need help, please open a new issue that references this one.

github-actions[bot] commented 1 week ago

Comments on closed issues and PRs are hard for our team to see. If you need help, please open a new issue that references this one.