Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot give postConfirmation trigger access to auth #2303

Closed
Jkap7788 opened this issue Sep 16, 2019 · 28 comments
Closed

Cannot give postConfirmation trigger access to auth #2303

Jkap7788 opened this issue Sep 16, 2019 · 28 comments
Labels
feature-request Request a new feature pending-review Pending review from core-team platform Issues tied to the general CLI platform

Comments

@Jkap7788
Copy link

Jkap7788 commented Sep 16, 2019

Describe the bug
I have created a post confirmation trigger using amplify update auth.

I would like to give the postConfirmation trigger access to the user pool in order to get user information and perform other operations that affect the user pool.

I then used amplify update function in order to give the post confirmation function access to the user pool.

However, an error occurs saying: "Error: Cannot add [functionName] due to a cyclic dependency" where [functionName] is the name of my function.

The postConfirmation cloudformation template file is updated with the appropriate permissions but the user pool id is not passed down as a parameter from nested-cloudformation-stack.yml

Desktop (please complete the following information):

  • OS: windows 10

Additional context
Invoking amplify update auth and then adding add-to-group functionality works fine but invoking amplify update function and then giving permissions to auth throws the error stated above.

I have tried this with @aws-amplify/cli 3.0.0 and 3.2.0, both result in the same error.

Thanks a lot!

@attilah
Copy link
Contributor

attilah commented Sep 17, 2019

@Jkap7788 it is a cyclic dependency as the CLI says. I'm not sure that we've a CLI supported way for this scenario, because the possibility that comes to my mind is adding a custom policy resource which depend on both resources, your user pool and the function, but the CustomResources are getting deployed within the GraphQL API scope.

@attilah attilah added enhancement platform Issues tied to the general CLI platform pending-review Pending review from core-team labels Sep 17, 2019
@thedgbrt
Copy link

it seems related to #1874 and #2076

@attilah , do you have any idea how it can be setup manually, by editing the CloudFormation template files for example?

@Jkap7788
Copy link
Author

@attilah Thanks for the reply!

I'm currently using a manual workaround for this.

Using amplify update function to add auth permissions to cognito triggers will result in a cyclic dependency error message.
However, the correct IAM policy is added to the function's cloud formation template.
The cognito user pool id is NOT passed down as a parameter so to fix this, I manually modify the IAM policy to include the user pool id in the iam resource arn

@thedgbrt A quick and easy fix is just to manually add the user pool id into the iam policy. Not ideal but gets you unstuck quickly.

@attilah Out of curiosity, how come adding add-to-group functionality to a post confirmation trigger does not register as a cyclic dependency where as adding auth permissions via amplify update function does cause a cyclic dependency?

@davekiss
Copy link

davekiss commented Oct 7, 2019

@attilah I'm also running into a similar issue and would benefit from seeing an example of the setup for a custom policy you're referencing

@davidsteed
Copy link

Same problem - permission appear to be fine bu the environment variable is not set properly. What do I edit to set the environment variable to the correct userpool

@WhiteAbeLincoln
Copy link

I had the same issue. I ended up editing the auth's cloudformation template, rather than the function's.

Look for the comment # Updating lambda role with permissions to Cognito. There will be a policy document section with permissions granted for group creation and adding users to groups. Add the additional policies that you want to the list.

  myAuthPostConfirmationAddToGroupCognito:
    Type: AWS::IAM::Policy
    Properties:
      PolicyName: myAuthPostConfirmationAddToGroupCognito
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Action:
            
              - cognito-idp:AdminAddUserToGroup
            
              - cognito-idp:GetGroup
            
              - cognito-idp:CreateGroup

             # Add your other permissions here
            
            
            
            Resource: !GetAtt
            
              - UserPool
            
              - Arn
            
            
            

      Roles:
        - !Join ['',["myAuthPostConfirmation", '-', !Ref env]]
  

Ideally the cli would allow us to select which permissions to grant when setting up a trigger instead of assuming these defaults

@rowanu
Copy link
Contributor

rowanu commented Nov 28, 2019

I have a non-manual way to do this: I create a custom category/resource (i.e. CloudFormation stack) that depends on the function AND the user pool. The custom stack then adds policies to the function after both it and the pool are deployed. If this is interesting to people I'll publish it.

Is there any plan or way the CLI might change to support this function in the future?

@Jkap7788
Copy link
Author

@rowanu Awesome! Yes please, would love to see how you implemented it.

@rowanu
Copy link
Contributor

rowanu commented Dec 1, 2019

Turns out I was relying on a function created directly via the function category (which exports LambdaExecutionRole) in my development environment 🙃 I have submitted a PR to export the role for all the trigger functions, so that I can demo the functionality I mentioned.

kaustavghosh06 pushed a commit that referenced this issue Dec 11, 2019
…2894)

* feat(amplify-category-auth): export lambda trigger roles in template

Expore execution role so that policies can be associated later. This
brings them in line with function category provider.

re #2303

* feat: fix copypasta
@dabit3
Copy link
Contributor

dabit3 commented Dec 15, 2019

Running into this issue as well, but with S3 and Lambda. The workflow looks like this:

  1. Create storage with Amazon S3 and enable and add a Lambda trigger
  2. Would like to give permission to Lambda to write to S3, so we update the Lambda:
$ amplify update function? Please select the Lambda Function you would want to update S3Trigger45ce5c61
? Do you want to update permissions granted to this Lambda function to perform on other resources in your project? Yes
? Select the category storage
> Storage category has a resource called s3cebd22bc
? Select the operations you want to permit for s3cebd22bc create, read, update, delete

Output:

You can access the following resource attributes as environment variables from your Lambda function
var environment = process.env.ENV
var region = process.env.REGION
var storageS3cebd22bcBucketName = process.env.STORAGE_S3CEBD22BC_BUCKETNAME

Error: Cannot add S3Trigger45ce5c61 due to a cyclic dependency
    at checkForCyclicDependencies (/Users/dabit/.nvm/versions/node/v10.16.3/lib/node_modules/@aws-amplify/cli/lib/extensions/amplify-helpers/update-amplify-meta.js:188:15)
    at AmplifyToolkit.updateamplifyMetaAfterResourceUpdate [as _updateamplifyMetaAfterResourceUpdate] (/Users/dabit/.nvm/versions/node/v10.16.3/lib/node_modules/@aws-amplify/cli/lib/extensions/amplify-helpers/update-amplify-meta.js:101:9)
    at Object.updateResource (/Users/dabit/.nvm/versions/node/v10.16.3/lib/node_modules/@aws-amplify/cli/node_modules/amplify-category-function/provider-utils/awscloudformation/index.js:242:21)
    at process._tickCallback (internal/process/next_tick.js:68:7)

The use case here is resizing an image and writing back to S3

cc @kaustavghosh06

@kaustavghosh06
Copy link
Contributor

@dabit3 The Lambda trigger should already have the permissions to read write to the S3 bucket. So you don’t need to explicitly run ‘amplify update function’

@dabit3
Copy link
Contributor

dabit3 commented Dec 15, 2019

Ah interesting, from my initial test it dit not. Will give it another shot and report back.

@dabit3
Copy link
Contributor

dabit3 commented Dec 15, 2019

Based on my testing, the issue actually has to do with this flow only:

  1. Create storage
  2. Add a new function separately. In the following steps, allow the function to have access to storage create, read, update, delete (this seems like a logical thing to do)
  3. When I update storage to add a trigger, I get a cyclic dependency error

This is probably not a high priority error since most people will probably be instead adding a lambda trigger by configuring storage (amplify update storage) and adding the function from there.

Another way around this is, when adding a new function, not to add permissions for storage and then in the storage walkthrough allow the permissions to be set there.

@paulsson
Copy link

@rowanu

I have a non-manual way to do this: I create a custom category/resource (i.e. CloudFormation stack) that depends on the function AND the user pool. The custom stack then adds policies to the function after both it and the pool are deployed. If this is interesting to people I'll publish it.

Any chance you can share how you are accomplishing this? It looks like your PR was merged.
This seems to be a very common problem with circular dependencies that many people are having.
I commented on this ticket asking for Amplify docs that sounds like what you are describing:
#1874 (comment)

Thanks for any knowledge sharing!
Erik

@royalaid
Copy link

I am also running into this issue and it appears my postConfirmation lambda is just using the default value provided for my UserPoolId output because that function never receives the output from the User Pool.

@danielblignaut
Copy link

Hi @royalaid @paulsson ,

not sure if this is the correct approach? But basically my solution involves the following:

  • editing my existing post confirmation trigger lambda business logic to make use of cognito (figure 1)
  • editing the post confirmation trigger lambda's cloudformation template, adding the LambdaExecutionRole resource's name as an output (figure 2)
  • adding a custom resource which depends on the cognito user pool id value and the post confirmation trigger lambda's Lambda execution Role name output value and this custom resource will create the IAM policy to access the given cognito user pool (using the user pool id reference) and attach it to the lambda's role based on the LambdaExecutionRole name reference (figure 3)

Doing the above whilst reading this section of the docs on deploying custom resources made sense to me: https://aws-amplify.github.io/docs/cli-toolchain/quickstart#custom-cloudformation-stacks

figure 1:

const cognitoIdentityServiceProvider = new CognitoIdentityServiceProvider()

figure 2:

{
  ....,
  "Outputs": {
    ....,
    "LambdaExecutionRole": {
      "Value": {
        "Ref": "LambdaExecutionRole"		
      }
    }
  }
}

figure 3:
backend-config.json

{
  ...,
"cognitoLambdaTriggerPermissions": {
		"postConfirmationPermissions": {
			"service": "Cognito-Lambda-Trigger-Permissions",
			"providerPlugin": "awscloudformation",
			"dependsOn": [
				{
                    "category": "auth",
                    "resourceName": "customerAppCognito",
                    "attributes": [
                        "UserPoolId"
                    ]
				},
				{
                    "category": "function",
                    "resourceName": "customerAppCognitoPostConfirmation",
                    "attributes": [
                        "LambdaExecutionRole"
                    ]
                }
			]
		}
	}
}

cognitoLambdaTriggerPeromissions/postConfirmationPermissions/template.json

{
	"AWSTemplateFormatVersion": "2010-09-09",
	"Description": "Resource stack to apply cognito permissions to circular dependency lambda",
	"Parameters": {
		"env": {
			"Type": "String"
		},
		"authcustomerAppCognitoUserPoolId": {
			"Type": "String"		
		},
		"functioncustomerAppCognitoPostConfirmationLambdaExecutionRole": {
			"Type": "String"		
		}
	},
	"Conditions": {
		
	},
	"Resources": {
		"PostConfirmationCognitoResourcesPolicy": {
			"Type": "AWS::IAM::Policy",
			"Properties": {
				"PolicyName": "post-confirmation-cognito-execution-policy",
				"Roles": [
					{
						"Ref": "functioncustomerAppCognitoPostConfirmationLambdaExecutionRole"
					}
				],
				"PolicyDocument": {
					"Version": "2012-10-17",
					"Statement": [
						{
							"Effect": "Allow",
							"Action": [
								"cognito-identity:Describe*",
								"cognito-identity:Get*",
								"cognito-identity:List*",
								"cognito-idp:Describe*",
								"cognito-idp:AdminGetDevice",
								"cognito-idp:AdminGetUser",
								"cognito-idp:AdminList*",
								"cognito-idp:List*",
								"cognito-sync:Describe*",
								"cognito-sync:Get*",
								"cognito-sync:List*",
								"iam:ListOpenIdConnectProviders",
								"iam:ListRoles",
								"sns:ListPlatformApplications",
								"cognito-idp:ForgotPassword",
								"cognito-idp:UpdateAuthEventFeedback",
								"cognito-idp:UpdateResourceServer",
								"cognito-idp:UpdateUserPoolClient",
								"cognito-idp:AdminUpdateUserAttributes",
								"cognito-idp:UpdateUserAttributes",
								"cognito-idp:UpdateUserPoolDomain",
								"cognito-idp:UpdateIdentityProvider",
								"cognito-idp:UpdateGroup",
								"cognito-idp:AdminUpdateAuthEventFeedback",
								"cognito-idp:UpdateDeviceStatus",
								"cognito-idp:UpdateUserPool"
							],
							"Resource": [
								{
									"Fn::Join": [
										"",
										[
											"arn:aws:cognito-idp:",
											{
												"Ref": "AWS::Region"
											},
											":",
											{
												"Ref": "AWS::AccountId"
											},
											":userpool/",
											{
												"Ref": "authcustomerAppCognitoUserPoolId"
											}
										]
									]
								}
							]
						}
					]
				}
			}
		}
	},
	"Outputs": {
		
	}
}

cognitoLambdaTriggerPeromissions/postConfirmationPermissions/parameters.json

{
	"authcustomerAppCognitoUserPoolId": {  
	   "Fn::GetAtt": [
		  "customerAppCognito", 
		  "Outputs.UserPoolId"
	   ]
	},
	"functioncustomerAppCognitoPostConfirmationLambdaExecutionRole": {
		"Fn::GetAtt": [
			"customerAppCognitoPostConfirmation", 
			"Outputs.LambdaExecutionRole"
		 ]
	}
}

@kylekirkby
Copy link
Contributor

Any update on this issue folks? I'm trying to update my post-confirmation lambda trigger to run some business logic when the users sign up. What's the best approach currently to implement this?
Best regards,
Kyle

@kaustavghosh06
Copy link
Contributor

@kylekirkby For your use-case, did you try adding and testing the post-confirmation auth trigger? What's the error that you're getting? The Trigger should already be populated with Cognito user-pool information which is what you're looking for out here?

@kylekirkby
Copy link
Contributor

kylekirkby commented Jun 1, 2020

Hi @kaustavghosh06 ,

Thanks for your reply! I've already got the post Confirmation Trigger added. This successfully adds the users to the "free" cognito user group - works a treat! However, I need to generate an API key for the users upon signup. For the life of me I cannot give the postConfirmation trigger lambda function permission to access my GraphQL API - I'm getting a circular dependency issue (I'm also version 4.21.0 for the CLI if that helps). Any ideas how I can achieve this? I've currently got users clicking a button to trigger a lambda function that generates the keys but would like this to be done automatically on sign up.

I did also comment on this issue: #1874 (comment)

Best regards,

Kyle

@kaustavghosh06
Copy link
Contributor

@kylekirkby Yes, we're aware of this circular dependency issue and it's explained more in detail out here - #1874 (comment)
Did you try out the workaround mentioned here - #1874 (comment)
While we work in resolving this - can't promise an ETA at this point - you can give the workaround a try since it seems to have worked for other customers as well. Thank you!

@kylekirkby
Copy link
Contributor

Hi @kaustavghosh06 ,

I did try the work arounds that other users have tried but to no avail. This may work in allowing the post confirmation function to have permission to access my graphql api but I don’t get the variables added to the process. How do I go about accessing the graphql api output from the post confirmation function?

@kkrao2301
Copy link

Running into the same on S3 triggers to resize.

Approaches tried:
1)Added trigger as part of S3 creation.
2)Also tried adding a function, and then adding as a trigger.
Both the cases "Access Denied" when writing back to s3.

Tried adding permissions and ran into cyclic dependency.

cc:
@kaustavghosh06
@dabit3

@houmark
Copy link

houmark commented Jul 1, 2020

I have the same problem and tried the same as @kkrao2301 — no solution.

@ianmartorell
Copy link

ianmartorell commented Jul 27, 2020

I was having this same issue and @danielblignaut's solution here worked wonders. As a matter of fact, it was simpler than that because I only needed to edit backend-config.json and create the CloudFormation template for that resource. The Outputs key in his figure 2 was already added to my lambda template and the parameters.json wasn't needed because the CLI created them for me automatically in nested-cloudformation-stack.yml.

I did have to amplify env checkout {your-env} for the CLI to pick up the changes to backend-config.json.

@WillDent
Copy link

WillDent commented Oct 4, 2020

I was having this issue. And just added the permission like noted here and then did amplify push and all is well.

@chris7716
Copy link

Few had proposed the solution and @danielblignaut straigh forward answer helped me to solve the issue. xoxo

@attilah
Copy link
Contributor

attilah commented Jan 12, 2021

Closing in favor of: #4568

@attilah attilah closed this as completed Jan 12, 2021
@github-actions
Copy link

This issue has been automatically locked since there hasn't been any recent activity after it was closed. Please open a new issue for related bugs.

Looking for a help forum? We recommend joining the Amplify Community Discord server *-help channels for those types of questions.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 25, 2021
@josefaidt josefaidt added feature-request Request a new feature and removed enhancement labels Sep 3, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
feature-request Request a new feature pending-review Pending review from core-team platform Issues tied to the general CLI platform
Projects
None yet
Development

No branches or pull requests