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.67k stars 3.92k forks source link

appsync: the ARN needed to grant access to the API has to contain 'v1' #26746

Open baartch opened 1 year ago

baartch commented 1 year ago

Describe the bug

I want to grant a Lambda function to rotate the API_KEY of the AppSync API. If I provide the ARN of the AppSync API to the PolicyStatement of the Lambda, I get the following error.

    // Creates the AppSync API
    const api = new aws_appsync.GraphqlApi(this, 'Api', {...});
    //Lambda function to rotate API key
    const funcAPIKeyRotate = new PythonFunction(this, 'funcAPIKeyRotate', {...});
    //Grant the Lambda permission to create a new API key
    funcAPIKeyRotate.addToRolePolicy(
      new aws_iam.PolicyStatement({
        actions: ['appsync:CreateApiKey'],
        resources: [api.arn + '/apikeys'],
      }),
    );
... is not authorized to perform: appsync:CreateApiKey on resource:arn:aws:appsync:eu-central-1:<<accountId>>:/v1/apis/<<myApiId>>/apikeys

Please note the v1 before apis

Oh, and just for completeness. There is the same behaviour when I try to grant via the API object:

api.grant(funcAPIKeyRotate, aws_appsync.IamResource.all(), 'appsync:CreateApiKey');

Expected Behavior

I expect the ARN coming from the API constructor being the same as the one needed to grant permission to.

Current Behavior

The ARN coming from the API constructor is without v1, and the one needed to grant a Lambda permission to the API has to contain a v1.

Coming from API Constructor:

arn:aws:appsync:eu-central-1:<<accountId>>:apis/<<myApiId>>

Needed to grant a Lambda:

arn:aws:appsync:eu-central-1:<<accountId>>:/v1/apis/<<myApiId>>

Reproduction Steps

To reproduce, see my bug description.

Possible Solution

My workaround is to concat the strings manually. I don't know if there is any better solution.

    const splittedApiArn = Fn.split('apis', api.arn);
    const joinedArn = Fn.join('', [Fn.select(0, splittedApiArn), '/v1/apis/', api.apiId, '/apikeys']);
    funcAPIKeyRotate.addToRolePolicy(
      new aws_iam.PolicyStatement({
        actions: ['appsync:CreateApiKey'],
        resources: [joinedArn], 
      }),
    );

Additional Information/Context

No response

CDK CLI Version

2.91.0 (build eea12ea)

Framework Version

No response

Node.js Version

Node.js v18.17.0

OS

Ubuntu 22.04 - Linux version 5.15.90.1-microsoft-standard-WSL2

Language

Typescript

Language Version

typescript@5.0.4

Other information

No response

pahud commented 1 year ago

The api.arn is actually from the cloudformation returned values:

https://github.com/aws/aws-cdk/blob/e4e08320412cd6cc999fb9eef0cd93b0445abceb/packages/aws-cdk-lib/aws-appsync/lib/graphqlapi.ts#L527

Arn The Amazon Resource Name (ARN) of the API key, such as arn:aws:appsync:us-east-1:123456789012:apis/graphqlapiid.

If the createApiKey does expected versioned arn, maybe we should return a versioned arn attribute from the constructor but I am not sure if this is a good idea.

cm-dyoshikawa commented 1 year ago

@pahud It may be more convenient for users. So, could we add new propety .versionedArn to GraphqlApi class? if it seems ok, I'll take it.