aws-cdk icon indicating copy to clipboard operation
aws-cdk copied to clipboard

(aws-appsync): Need an option for passing a Service Role to AppSync GraphQL Lambda Data Source

Open DevoKun opened this issue 4 years ago • 9 comments

I have a GraphQL AppSync and a Lambda Function data source.

I want to use existing IAM Roles as the data source Service Role.

Currently, there appears to be no way to specify the service role.

I have this Typescript CDK Code:


    const figaroLambda = new NodejsFunction(this, 'FigaroLambda', {
      memorySize: 1024,
      timeout: cdk.Duration.seconds(5),
      runtime: lambda.Runtime.NODEJS_14_X,
      handler: 'handler',
      role: figaroLambdaRole,
      entry: path.join(__dirname, `figaro/index.ts`),
      vpc,
      vpcSubnets,
      securityGroups: [figaroLambdaSecurityGroup],
    });


    // https://docs.aws.amazon.com/cdk/api/latest/typescript/api/aws-appsync/graphqlapi.html#aws_appsync_GraphqlApi
    // https://docs.aws.amazon.com/cdk/api/latest/typescript/api/aws-appsync/graphqlapiprops.html#aws_appsync_GraphqlApiProps
    const api = new appsync.GraphqlApi(this, 'NeptuneGraphQLApi', {
      schema: appsync.Schema.fromAsset('schema.graphql'),
      authorizationConfig: {
        defaultAuthorization: {
          authorizationType: appsync.AuthorizationType.USER_POOL,
          userPoolConfig: {
            userPool: userPool,
          },
        }
      },
    })


    // https://docs.aws.amazon.com/cdk/api/latest/typescript/api/aws-appsync/graphqlapibase.html#aws_appsync_GraphqlApiBase_addLambdaDataSource
    api.addLambdaDataSource('LambdaDatasourceFigaro', figaroLambda);

Which creates:

  NeptuneGraphQLApiLambdaDatasourceFigaroServiceRoleCCBC152B:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Action: sts:AssumeRole
            Effect: Allow
            Principal:
              Service: appsync.amazonaws.com
        Version: "2012-10-17"

  NeptuneGraphQLApiLambdaDatasourceFigaroServiceRoleDefaultPolicyB39D9AB9:
    Type: AWS::IAM::Policy
    Properties:
      PolicyDocument:
        Statement:
          - Action: lambda:InvokeFunction
            Effect: Allow
            Resource:
              Fn::GetAtt:
                - FigaroLambdaA18864CC
                - Arn
        Version: "2012-10-17"
      PolicyName: NeptuneGraphQLApiLambdaDatasourceFigaroServiceRoleDefaultPolicyB39D9AB9
      Roles:
        - Ref: NeptuneGraphQLApiLambdaDatasourceFigaroServiceRoleCCBC152B

  NeptuneGraphQLApiLambdaDatasourceFigaro8722E995:
    Type: AWS::AppSync::DataSource
    Properties:
      ApiId:
        Fn::GetAtt:
          - NeptuneGraphQLApi8AAC1DF5
          - ApiId
      Name: LambdaDatasourceFigaro
      Type: AWS_LAMBDA
      LambdaConfig:
        LambdaFunctionArn:
          Fn::GetAtt:
            - FigaroLambdaA18864CC
            - Arn
      ServiceRoleArn:
        Fn::GetAtt:
          - NeptuneGraphQLApiLambdaDatasourceFigaroServiceRoleCCBC152B
          - Arn

Need an option for passing a ServiceRole to addLambdaDataSource

Please consider this a feature request to update either addLambdaDataSource(id, lambdaFunction, options) or DataSourceOptions to include an option for specifying a service role:


addLambdaDataSource(
  id: string, 
  lambdaFunction: IFunction, 
  serviceRole: IRole, 
  options?: DataSourceOptions
): LambdaDataSource;


This is a :rocket: Feature Request

DevoKun avatar Aug 25 '21 15:08 DevoKun

I don't know your use case, but can't you assign a custom role to the Lambda function itself?

otaviomacedo avatar Aug 26 '21 09:08 otaviomacedo

Hello, @otaviomacedo . Thank you for looking at this issue. Your comment makes me wonder if this issue would be more appropriate as a bug, rather than a feature request.

My use case is only that I need to use an existing role. My CDK/CloudFormation can not have any IAM::Role creations.

You will note that in my sample code, the Lambda Function is using a pre-made IAM Role:

    const figaroLambda = new NodejsFunction(this, 'FigaroLambda', {
      memorySize: 1024,
      timeout: cdk.Duration.seconds(5),
      runtime: lambda.Runtime.NODEJS_14_X,
      handler: 'handler',
      role: figaroLambdaRole,
      entry: path.join(__dirname, `figaro/index.ts`),
      vpc,
      vpcSubnets,
      securityGroups: [figaroLambdaSecurityGroup],
    });

As you have pointed out, I would expect that a new role NOT be created in the synthesized CloudFormation. However, a new Role for the Data Source is created:

  NeptuneGraphQLApiLambdaDatasourceFigaroServiceRoleCCBC152B:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Action: sts:AssumeRole
            Effect: Allow
            Principal:
              Service: appsync.amazonaws.com
        Version: "2012-10-17"

  NeptuneGraphQLApiLambdaDatasourceFigaroServiceRoleDefaultPolicyB39D9AB9:
    Type: AWS::IAM::Policy
    Properties:
      PolicyDocument:
        Statement:
          - Action: lambda:InvokeFunction
            Effect: Allow
            Resource:
              Fn::GetAtt:
                - FigaroLambdaA18864CC
                - Arn
        Version: "2012-10-17"
      PolicyName: NeptuneGraphQLApiLambdaDatasourceFigaroServiceRoleDefaultPolicyB39D9AB9
      Roles:
        - Ref: NeptuneGraphQLApiLambdaDatasourceFigaroServiceRoleCCBC152B

It would appear that the Role is intended to allow AppSync to invoke the Lambda function, which does seam reasonable.

Looking at the Cloudformation for the Data Source, it appears that the created Role is a Service Role:

  NeptuneGraphQLApiLambdaDatasourceFigaro8722E995:
    Type: AWS::AppSync::DataSource
    Properties:
      ApiId:
        Fn::GetAtt:
          - NeptuneGraphQLApi8AAC1DF5
          - ApiId
      Name: LambdaDatasourceFigaro
      Type: AWS_LAMBDA
      LambdaConfig:
        LambdaFunctionArn:
          Fn::GetAtt:
            - FigaroLambdaA18864CC
            - Arn
      ServiceRoleArn:
        Fn::GetAtt:
          - NeptuneGraphQLApiLambdaDatasourceFigaroServiceRoleCCBC152B
          - Arn

From my point of view, it would appear that the ability to specify an existing IAM Role for a ServiceRole is missing from the AppSyncDataSource. Hence my suggestion of this modification:

addLambdaDataSource(
  id: string, 
  lambdaFunction: IFunction, 
  serviceRole: IRole, 
  options?: DataSourceOptions
): LambdaDataSource;

DevoKun avatar Aug 26 '21 12:08 DevoKun

Yes, you're right. They are different roles. And having some way to specify a custom service role would be useful. I'm just not sure about the best API for this. An alternative signature would be having serviceRole inside DataSourceOptions, for example.

As you know, we welcome community contributions! If you are able, we encourage you to contribute a new feature to the CDK. I'd be happy to review your PR.

otaviomacedo avatar Sep 10 '21 08:09 otaviomacedo

This issue has not received any attention in 1 year. If you want to keep this issue open, please leave a comment below and auto-close will be canceled.

github-actions[bot] avatar Sep 10 '22 12:09 github-actions[bot]

Please keep open

DevoKun avatar Sep 10 '22 12:09 DevoKun

The same with addHttpDataSource. If you connect for example to API Gateway which is using IAM authentication. Vanilla CloudFormation has it on "root level": https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-appsync-datasource.html

I used now CfnDataSource: https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync.CfnDataSource.html

teemuniiranen avatar Oct 20 '22 12:10 teemuniiranen

Please keep open, this is something we would like to also see implemented to improve our integration with AWS

estrudels avatar Jun 14 '23 12:06 estrudels

Any progress on this?

IlliaVern avatar Nov 08 '23 16:11 IlliaVern

I faced the same issue and instead of using "CfnDataSource" or "add*DataSource()" method i went with *DataSource class

const dynamodbDS = new DynamoDbDataSource(this, "DynamoDbDataSource", {
        api: api, // Graphql api 
        table: dynamotable, 
        serviceRole: iamrole // Existing Role
    })

RohitJagdale avatar May 08 '24 19:05 RohitJagdale