Open 0xdevalias opened 4 years ago
@0xdevalias -
I want to be able to easily give my lambda functions access to call AWS API/SDK methods against my UserPool.
Can you give more details on your use case? What do these lambda functions do?
I am looking to see how we can organize these grant methods, and it looks like Cognito Identity Provider has quite a number of APIs. As an example, we have a number of grant methods organized by use case for S3 buckets, similar for Lambda functions and DynamoDB tables.
As per the example code in my original post, they’re needing to use the API calls, in this case for a number of the ‘admin*’ methods in Cognito User Pools.
Even if it was just a single grant method that had types that made it easy to add any of the valid methods (eg, array of enum type thing)
Can you give more details on your use case? What do these lambda functions do?
I just figured this out too and got an answer from Gitter before finding this.
My use case is "a user wants to grant another user permission to do something". In order to do that the other user has to be found using Cognito API calls in a lambda function. Once the user is found, update dynamodb with the relevant permission and ID of the other user.
I think this explains why I've been getting a permission error on my lambda while trying to use AdminResetUserPassword. I'm setting a policy in CDK like this:
const poolPolicyAddendum = new PolicyStatement({
resources: [pool.userPoolArn],
effect: Effect.ALLOW,
actions: [
'cognito-idp:List*',
'cognito-idp:Write*',
'cognito-idp:AdminResetUserPassword',
],
});
I'm still getting an access denied error though. Is this the same issue? Has there been any progress on this or other solutions? I tried posting in stackoverflow, but nothing yet. Glad I found this. Thanks!
Here is my use case.
I have a Lambda Function that is the handler for a serverless web backend.
When the backend Lambda Function is invoked, I want it to be able to call cognito-idp:DescribeUserPoolClient
to get the User Pool's client secret, so that it can POST to the TOKEN endpoint to exchange the authorization code issued by Cognito for JWT tokens.
Without the required permission, my Lambda Function is logging:
AccessDeniedException: User: arn:aws:sts::<ACCOUNT ID>:assumed-role/<REST OF THE ROLE ID> is not authorized to perform: cognito-idp:DescribeUserPoolClient on resource: arn:aws:cognito-idp:<REGION>:<ACCOUNT ID>:userpool/<USER POOL ID>
Yep, our use-case is a fairly obvious one really. When we create a lambda to execute off the PreSignUp
Lambda Trigger we'd like it to be able to access the UserPool to validate things. You can see people working around this by manually adding to Role Policies here and even your own documentation explains how to work around it here. Many thanks for looking into this.
Why this feature has not been added yet :/ Even after paying people to write code seems like lot of work.
Now I will have to create a new IAM policy and pass it to lambda so that it can access my user pool.
It really sad @aws that these important features are not getting added even after years
Thanks for the workaround @0xdevalias, this was an incredibly frustrating issue to try and work through. After 2 years could this maybe get actioned?
Not sure if this ticket is outdated or if it has been implemented in the meantime, but this works for me:
userPool.grant(fnHandler, 'cognito-idp:AdminGetUser', 'cognito-idp:AdminEnableUser', 'cognito-idp:AdminDisableUser');
Not sure if this ticket is outdated or if it has been implemented in the meantime
In CDK v1.202.0
, I'm doing the following, which returns an IUserPool
, which doesn't have any grant
methods defined on it:
const userPool = UserPool.fromUserPoolId(this, 'UserPool', userPoolId)
I can see that the UserPool
construct does have a grant
method though:
This issue has received a significant amount of attention so we are automatically upgrading its priority. A member of the community will see the re-prioritization and provide an update on the issue.
In CDK
v1.202.0
, I'm doing the following, which returns anIUserPool
, which doesn't have anygrant
methods defined on it
It seems like CDK 2.x has a grant
method on the IUserPool
, at least according to these docs:
Hi.
Does anyone have any use cases where the grant method is needed, along with supporting documentation? I was thinking of addressing this issue, but I'm not quite sure what methods and permissions are required.
I've just looked up the codebase that I originally raised this for:
class CustomNodeLambdaEventHandler extends Construct
(wraps NodejsFunction
)FooEventStack
In FooEventStack
we have some EventBridge
EventBus
Rule
s that trigger NodejsFunction
lambda handlers to process Stripe events. We need to give these lambda handlers access to administer a Cognito
UserPool
that's created in another stack, and loaded here with UserPool.fromUserPoolId
, which returns IUserPool
.
These are the relevant snippets of code from the above that are granting the permissions:
fnStripeCustomerEventsHandler.fnHandler.addToRolePolicy(
new PolicyStatement({
effect: Effect.ALLOW,
actions: [
'cognito-idp:AdminGetUser',
'cognito-idp:AdminCreateUser',
'cognito-idp:AdminAddUserToGroup',
'cognito-idp:AdminEnableUser',
],
resources: [
`arn:aws:cognito-idp:${userPool.stack.region}:${userPool.stack.account}:userpool/${userPool.userPoolId}`,
],
})
)
fnStripeCustomerSubscriptionEventsHandler.fnHandler.addToRolePolicy(
new PolicyStatement({
effect: Effect.ALLOW,
actions: [
'cognito-idp:AdminGetUser',
'cognito-idp:AdminCreateUser',
'cognito-idp:AdminAddUserToGroup',
'cognito-idp:AdminEnableUser',
'cognito-idp:AdminDisableUser',
],
resources: [
`arn:aws:cognito-idp:${userPool.stack.region}:${userPool.stack.account}:userpool/${userPool.userPoolId}`,
],
})
)
Edit: From a quick skim of the docs, it looks like instead of manually constructing the UserPool
ARN like I did there (in the resources
section), I probably could have just used userPool.userPoolArn
fnStripeCustomerEventsHandler
/ fnStripeCustomerSubscriptionEventsHandler
are instances of my CustomNodeLambdaEventHandler
, and the .fnHandler
accesses the underlying NodejsFunction
instance.
This code was written in AWS CDK 1.x
days, where the IUserPool
had no grant
method:
Which has changed in 2.x
, and is now available:
public grant(grantee: IGrantable, ...actions: string[]): Grant
Looking at NodeJsFunction
, we can see that it implements IGrantable
:
Therefore in CDK 2.x
, I believe we should be able to simplify my above code to the following (though I haven't tested this to be certain):
const userPool = UserPool.fromUserPoolId(this, 'UserPool', userPoolId)
// ..snip..
- fnStripeCustomerEventsHandler.fnHandler.addToRolePolicy(
- new PolicyStatement({
- effect: Effect.ALLOW,
- actions: [
+ userPool.grant(fnStripeCustomerEventsHandler.fnHandler, [
'cognito-idp:AdminGetUser',
'cognito-idp:AdminCreateUser',
'cognito-idp:AdminAddUserToGroup',
'cognito-idp:AdminEnableUser',
+ ])
- ],
- resources: [
- `arn:aws:cognito-idp:${userPool.stack.region}:${userPool.stack.account}:userpool/${userPool.userPoolId}`,
- ],
- })
- )
// ..snip..
- fnStripeCustomerSubscriptionEventsHandler.fnHandler.addToRolePolicy(
- new PolicyStatement({
- effect: Effect.ALLOW,
- actions: [
+ userPool.grant(fnStripeCustomerSubscriptionEventsHandler.fnHandler, [
'cognito-idp:AdminGetUser',
'cognito-idp:AdminCreateUser',
'cognito-idp:AdminAddUserToGroup',
'cognito-idp:AdminEnableUser',
'cognito-idp:AdminDisableUser',
+ ])
- ],
- resources: [
- `arn:aws:cognito-idp:${userPool.stack.region}:${userPool.stack.account}:userpool/${userPool.userPoolId}`,
- ],
- })
- )
I'm not sure if there is as succinct a method of doing it in reverse, if you wanted to start with the NodeJsFunction
and call functions directly on it to grant access to the UserPool
; but perhaps that isn't the mental model CDK would follow anyway. The closest functions I could see for doing it that way (from a quick skim of the docs) seem to be:
public addPermission(id: string, permission: Permission): void
: Adds a permission to the Lambda resource policy.public addToRolePolicy(statement: PolicyStatement): void
Adds a statement to the IAM role assumed by the instance.
So, at least for my original issue that I raised this for, I think CDK 2.x
already implements what I would have needed/been asking for.
Does anyone have any use cases where the grant method is needed, along with supporting documentation?
So, at least for my original issue that I raised this for, I think CDK
2.x
already implements what I would have needed/been asking for.
Unless the question is more related to this earlier question:
Can you give more details on your use case? What do these lambda functions do?
I am looking to see how we can organize these grant methods, and it looks like Cognito Identity Provider has quite a number of APIs. As an example, we have a number of grant methods organized by use case for S3 buckets, similar for Lambda functions and DynamoDB tables.
If we look at the CDK 2.x
version of those linked examples, we can see that they have a number of grant*
functions for specific pre-defined 'sets' of permissions, rather than just the completely generic grant
function we see on IUserPool
currently:
It's been quite a while since I've worked on this code/with UserPool
in general, so I'm not sure off the top of my head if/what 'pre-defined sets' of permissions might be useful from the 'total list', but if we look at my example above, the permissions used were:
cognito-idp:AdminGetUser
cognito-idp:AdminCreateUser
cognito-idp:AdminAddUserToGroup
cognito-idp:AdminEnableUser
cognito-idp:AdminDisableUser
And the high level goal was to, based on events sent from Stripe, be able to:
If I was to generalise that into a 'higher level category' that a grant*
method could be made for, then I guess I would probably say something like 'UserPool user management' or similar (though for a category like that, there may be some additional permissions worth adding to it as well)
As per https://github.com/aws/aws-cdk/issues/6765#issuecomment-607050027, the
UserPool
construct should havegrant*
methods on it to give other resources (eg. lambda functions) access to various API/SDK methods.Use Case
I want to be able to easily give my lambda functions access to call AWS API/SDK methods against my
UserPool
.Proposed Solution
References
### CDK - https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-cognito.UserPool.html - https://docs.aws.amazon.com/cdk/api/latest/docs/aws-iam-readme.html - https://docs.aws.amazon.com/cdk/latest/guide/permissions.html ### Cognito - https://docs.aws.amazon.com/cognito/latest/developerguide/resource-permissions.html - https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/Welcome.html - eg. https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminGetUser.html - https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/CognitoIdentityServiceProvider.html - eg. https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/CognitoIdentityServiceProvider.html#adminGetUser-propertyBased on:
eg.
Workaround:
Other
This is a :rocket: Feature Request