aws-amplify / amplify-category-api

The AWS Amplify CLI is a toolchain for simplifying serverless web and mobile development. This plugin provides functionality for the API category, allowing for the creation and management of GraphQL and REST based backends for your amplify project.
https://docs.amplify.aws/
Apache License 2.0
89 stars 77 forks source link

Function access to API not applied #679

Closed johnf closed 8 months ago

johnf commented 2 years ago

Before opening, please confirm:

How did you install the Amplify CLI?

yarn

If applicable, what version of Node.js are you using?

v16.15.0

Amplify CLI Version

8.2.0

What operating system are you using?

Ubuntu

Did you make any manual changes to the cloud resources managed by Amplify? Please describe the changes made.

No

Amplify Categories

function, api

Amplify Commands

add, push

Describe the bug

The VTL is updated locally but not remotely to give the function access.

You can see this during the pus in that there is "No Change" to the API Modifying the schema and then pushing fixes it.

See below for detailed steps to reproduce and you can follow along at

See below for detailed steps to reproduce and you can follow along at https://github.com/johnf/amplify-api-lambda-perms-bug

To me it looks like the permission change on the function isn't triggering that the API also needs to be updated.

Expected behavior

Permissions are correctly applied to appsync

Reproduction steps

See https://github.com/johnf/amplify-api-lambda-perms-bug#readme

GraphQL schema(s)

https://github.com/johnf/amplify-api-lambda-perms-bug/blob/main/amplify/backend/api/amplifyapivtl/schema.graphql

Log output

``` # Put your logs below this line ```

Additional information

No response

ykethan commented 2 years ago

hello @johnf, Thank you for reporting this. I was able to replicate the behavior in my amplify application.

Note: On creating a Lambda function and giving access to the API in advanced options the vtl gets updated with the following snippet.

#if( $util.authType() == "IAM Authorization" )
  #set( $adminRoles = ["customauhtfunc7aed174a-dev"] )
  #foreach( $adminRole in $adminRoles )
    #if( $ctx.identity.userArn.contains($adminRole) && $ctx.identity.userArn != $ctx.stash.authRole && $ctx.identity.userArn != $ctx.stash.unauthRole )
      #return($util.toJson({}))
    #end
  #end
  #if( !$isAuthorized )
    #if( $ctx.identity.userArn == $ctx.stash.authRole )
      #set( $isAuthorized = true )
    #end
  #end
#end

on performing a amplify push the CLI only recognizes the function following.

image

in order to mitigate the issue, adding a empty line in the AppSync schema and pushing it uploads the VTL. I was able to successfully perform queries using my Lambda function.

Additionally, I wanted to mention the docs for AppSync queries using IAM auth have been updated at https://docs.amplify.aws/lib/graphqlapi/graphql-from-nodejs/q/platform/js/#iam-authorization with newer example.

Marking this as bug.

KevinSnyderCodes commented 2 years ago

Alternatively, you can run:

amplify push --force api

Which will rebuild and push the VTL resolvers, without having to make any changes (e.g. blank space) to the schema to trigger a change.

joekiller commented 1 year ago

force push didn't work for me. only changes to the schema

alex-griffiths commented 1 year ago

I'll add to this to keep some record of the trouble shooting I've been doing. Changing the schema as suggested @ykethan was one solution. Another problem I have found that is related to the VTL resolvers not getting updated properly was caused by the mock api resolvers preventing changes to the API schema from updating the deployed resolvers. Deleting these allowed the remote VTL resolvers to update and allowed my lambda to perform queries/mutations.

josefaidt commented 1 year ago

related https://github.com/aws-amplify/amplify-category-api/issues/100

jeff-accountably commented 1 year ago

This is such an annoying bug, when developing I keep forgetting about it. Making minor changes to the schema just force the resolvers to update is not a good work around.

jeff-accountably commented 1 year ago

Alternatively, you can run:

amplify push --force api

Which will rebuild and push the VTL resolvers, without having to make any changes (e.g. blank space) to the schema to trigger a change.

This does not fix the issue for me.

defish1962 commented 1 year ago

Perhaps this issue should be called out in the Amplify documents since it has been open for over a year without resolution. I just spent several hours pulling my hair out trying to make IAM authorization work with my previously created Lambda functions and having no idea why it wasn't working. After adding a comment to the schema.graphql file and doing an amplify push the problem they immediately started working.

ethan021021 commented 1 year ago

Any updates on fixing this? Just had to do the same empty line trick to our schema.graphql and everything started working as expected.. Definitely an odd workaround.

metuuu commented 1 year ago

I had this issue also. It was really frustrating to find out it was just another amplify bug...

qwikag commented 1 year ago

here is my experience. I was getting this body.error.message, adding to this thread (if not relevant I can remove!):

body: { data: { listLogins: null }, errors: [ { path: [Array], data: null, errorType: 'Unauthorized', errorInfo: null, locations: [Array], message: 'Not Authorized to access listLogins on type Query' } ] }

The process I took. I stood up a whole new App from amplify init. Installing backend (except my problematic function): API(Cognito, IAM), Auth(userpools, groups), adding only the PostConfirmTrigger (Add-to-Group function) Then setup my GraphQL tables, Added : @auth(rules: [{allow: private, provider: iam},... I ran > amplify api gql-compile and > amplify codegen I ran > amplify push --force api Added my custom PostAuth trigger (custom function) Updated my custom PostAuth trigger (with api access) added the SDK v3, used the node-fetch library, and pretty much duplicated the guide code: https://docs.amplify.aws/guides/functions/graphql-from-lambda/q/platform/js/#iam-authorization

The guide code was pretty good, but it still gave me the same error. After a complete re-build from blank app and following all guides step by step to still have the same error was super frustrating.

Last ditch effort: I needed to remove a table from the schema.graphql ran >amplify push --force api made sure it processed the mutations and queries again

And it worked! But I do not know what was the piece that worked. Nor what is going to happen when I add my next @Auth IAM table.

kylekirkby commented 11 months ago

What's the recommended fix for this? Everything was working fine and now its not etc...

## [Start] Field Authorization Steps. **
#set( $isAuthorized = false )
#if( $util.authType() == "IAM Authorization" )
  #foreach( $adminRole in $ctx.stash.adminRoles )
    #if( $ctx.identity.userArn.contains($adminRole) && $ctx.identity.userArn != $ctx.stash.authRole && $ctx.identity.userArn != $ctx.stash.unauthRole )
      #return($context.source.sendEmail)
    #end
  #end
  #if( !$isAuthorized )
    #if( ($ctx.identity.userArn == $ctx.stash.authRole) || ($ctx.identity.cognitoIdentityPoolId == $ctx.stash.identityPoolId && $ctx.identity.cognitoIdentityAuthType == "authenticated") )
      #set( $isAuthorized = true )
    #end
  #end
#end
#if( $util.authType() == "User Pool Authorization" )
  #set( $isAuthorized = true )
#end
#if( !$isAuthorized )
$util.unauthorized()
#end
$util.toJson({"version":"2018-05-29","payload":{}})
## [End] Field Authorization Steps. **

This is what my Mutation.sendEmail.auth.req.vtl mutation resolve looks like in the broken state. Do I need to add a custom-roles.json file and add these lambda roles manually?

kylekirkby commented 11 months ago

It looks like the FunctionDirectiveStack.json file is not updating the context stash as with the generated resolvers. What's weird is that I'm sure this has been working. Not matter what I do, I cannot get the custom mutation resolvers to respect the IAM role auth rules...

E.g custom mutation with @auth rules

type Mutation {
    editConnectedAccount(input: EditConnectedAccountInput!): ConnectedAccount
        @function(name: "manageConnectedAccounts-${env}")
        @auth(rules: [{ allow: private }, { allow: private, provider: iam }])

I'm on the latest version of the amplify cli. This looks like a massive oversight to me.

defish1962 commented 11 months ago

It looks like the FunctionDirectiveStack.json file is not updating the context stash as with the generated resolvers. What's weird is that I'm sure this has been working. Not matter what I do, I cannot get the custom mutation resolvers to respect the IAM role auth rules...

E.g custom mutation with @auth rules

type Mutation {
  editConnectedAccount(input: EditConnectedAccountInput!): ConnectedAccount
      @function(name: "manageConnectedAccounts-${env}")
      @auth(rules: [{ allow: private }, { allow: private, provider: iam }])

I'm on the latest version of the amplify cli. This looks like a massive oversight to me.

Did you modify the schema.graphql file and do an amplify push? Just add a comment or modify a comment, save and then push. That action seems to update the IAM permissions, whether set in a custom-roles.json file or added through amplify add/update function.

kylekirkby commented 11 months ago

So I've rolled back to 12.3.0 and the inline adminRoles are successfully being written to the auth resolvers...

@josefaidt - Hey! Can you take a look at this bug since this has broken in the latest release. Custom queries / mutations are not correctly having their RequestMappingTemplates updated in the FunctionDirectiveStack.json files. The adminRoles used to be inlined and have since been moved to VTL mapping.

kylekirkby commented 11 months ago

Also, adding a test to make sure all VTL resolvers have the correct adminRoles added would be great to prevent this happening going forward.

kylekirkby commented 11 months ago

It looks like the FunctionDirectiveStack.json file is not updating the context stash as with the generated resolvers. What's weird is that I'm sure this has been working. Not matter what I do, I cannot get the custom mutation resolvers to respect the IAM role auth rules... E.g custom mutation with @auth rules

type Mutation {
    editConnectedAccount(input: EditConnectedAccountInput!): ConnectedAccount
        @function(name: "manageConnectedAccounts-${env}")
        @auth(rules: [{ allow: private }, { allow: private, provider: iam }])

I'm on the latest version of the amplify cli. This looks like a massive oversight to me.

Did you modify the schema.graphql file and do an amplify push? Just add a comment or modify a comment, save and then push. That action seems to update the IAM permissions, whether set in a custom-roles.json file or added through amplify add/update function.

Yes I had done that multiple times with and without the force flag. This is a bug since moving the adminRoles out of the VTL resolvers source code.

rafaelfaria commented 11 months ago

+1 for having this working and now i keep getting Not Authorized to access MY_GRAPHQL_CUSTOM_FUNCTION on type Mutation

johndebord commented 11 months ago

Is there a amplify CLI command that just re-pushes/rebuilds everything? I'd rather do that than deal with blank lines

Etep15 commented 10 months ago

amplify push --force api I believe will do that @johndebord

joekiller commented 10 months ago

I remember fiddling with this quite a bit and finally it occurred to me that actions like a force doesn't works because the problem is that the app sync resolvers that are updating don't get applied to the endpoint without a schema change. Because the resolver to app sync endpoint is a little disjointed

johndebord commented 10 months ago

I encounter this issue approximately once a week.

In the latest occurrence, I implemented a flow where I create a user in a Cognito Pool, and subsequently, albeit not immediately, create a user in another database. After a period, when I perform a comparison between the Cognito Pool user and the database user, it fails. The error isn't immediately apparent, leading me to investigate various potential causes. However, the root cause turned out to be this particular issue, which I find myself running into frequently.

johndebord commented 8 months ago

Any progress or clarification on this? It'd be valuable to have something documented here about the ins-and-outs of this situation by an experienced team member.

dpilch commented 8 months ago

Here are the updated docs: https://docs.amplify.aws/react/build-a-backend/graphqlapi/customize-authorization-rules/#grant-lambda-function-access-to-graphql-api

Once you grant a function access to the GraphQL API, it is required to redeploy the API to apply the permissions. To do so, run the command amplify api gql-compile --force before deployment via amplify push.

joekiller commented 8 months ago

For those curious this is the codepath triggered via the force:

https://github.com/aws-amplify/amplify-category-api/blob/30a297217e2cad518d42c23665d2208431845f14/packages/amplify-category-api/src/force-updates/force-refresh-schema.ts#L10

BTW, good on y'all to provide a workaround and this fix is the luls