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.5k stars 3.84k forks source link

aws-cdk-lib/aws-stepfunctions-tasks: Issue with incorrectly generated IAM policy. #30862

Closed msaphire closed 1 month ago

msaphire commented 1 month ago

Describe the bug

I am working on writing a CDK based step function with a task to call 'tagresources' on an EFS access point:

const tagAccessPoint = new CallAwsService(this, 'TagAccessPoint', {
            stateName: 'Tag access point',
            service: 'efs',
            action: 'tagResource',
            iamResources: ['*'],
            parameters: {
                ResourceId: JsonPath.stringAt('$.pathToArn'),
                Tags: [
                    {
                        Key: "MYTAGNAME",
                        Value: JsonPath.stringAt('$.pathToId')
                    }
                ]
            },
            resultPath: JsonPath.DISCARD
        })

Produces an incorrect a IAM policy snippet.

Expected Behavior

It should be (ref):

{
    "Action": "elasticfilesystem:tagResource",
    "Resource": "*",
    "Effect": "Allow"
}

Current Behavior

Produces:

{
    "Action": "efs:tagResource",
    "Resource": "*",
    "Effect": "Allow"
}

Which is incorrect, it should be (ref):

Reproduction Steps

Create the following task as part of a CDK defined state machine:

const tagAccessPoint = new CallAwsService(this, 'TagAccessPoint', {
            stateName: 'Tag access point',
            service: 'efs',
            action: 'tagResource',
            iamResources: ['*'],
            parameters: {
                ResourceId: JsonPath.stringAt('$.pathToArn'),
                Tags: [
                    {
                        Key: "MYTAGNAME",
                        Value: JsonPath.stringAt('$.pathToId')
                    }
                ]
            },
            resultPath: JsonPath.DISCARD
        })

Possible Solution

No response

Additional Information/Context

No response

CDK CLI Version

2.147.2

Framework Version

No response

Node.js Version

20

OS

macOS

Language

TypeScript

Language Version

TypeScript (5.4.2)

Other information

No response

ashishdhingra commented 1 month ago

Reproducible using below code:

import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as sfn from 'aws-cdk-lib/aws-stepfunctions';
import * as tasks from 'aws-cdk-lib/aws-stepfunctions-tasks';

export class Issue30862Stack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const callAwsServiceTask = new tasks.CallAwsService(this, 'TagEfsAccessPoint', {
      stateName: 'Tag access point',
      service: 'efs',
      action: 'tagResource',
      iamResources: ['*'],
      parameters: {
        ResourceId: sfn.JsonPath.stringAt('$.pathToArn'),
        Tags: [
            {
                Key: "MYTAGNAME",
                Value: sfn.JsonPath.stringAt('$.pathToId')
            }
        ]
      },
      resultPath: sfn.JsonPath.DISCARD
    });

    const stateMachine = new sfn.StateMachine(this, 'MyStateMachine', {
      definition: callAwsServiceTask.next(new sfn.Succeed(this, "GreetedWorld"))
    });
  }
}

Running cdk synth generates the following CloudFormation template:

Resources:
  MyStateMachineRoleD59FFEBC:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Action: sts:AssumeRole
            Effect: Allow
            Principal:
              Service: states.amazonaws.com
        Version: "2012-10-17"
    Metadata:
      aws:cdk:path: Issue30862Stack/MyStateMachine/Role/Resource
  MyStateMachineRoleDefaultPolicyE468EB18:
    Type: AWS::IAM::Policy
    Properties:
      PolicyDocument:
        Statement:
          - Action: efs:tagResource
            Effect: Allow
            Resource: "*"
        Version: "2012-10-17"
      PolicyName: MyStateMachineRoleDefaultPolicyE468EB18
      Roles:
        - Ref: MyStateMachineRoleD59FFEBC
    Metadata:
      aws:cdk:path: Issue30862Stack/MyStateMachine/Role/DefaultPolicy/Resource
  MyStateMachine6C968CA5:
    Type: AWS::StepFunctions::StateMachine
    Properties:
      DefinitionString:
        Fn::Join:
          - ""
          - - '{"StartAt":"Tag access point","States":{"Tag access point":{"Next":"GreetedWorld","Type":"Task","ResultPath":null,"Resource":"arn:'
            - Ref: AWS::Partition
            - :states:::aws-sdk:efs:tagResource","Parameters":{"ResourceId.$":"$.pathToArn","Tags":[{"Key":"MYTAGNAME","Value.$":"$.pathToId"}]}},"GreetedWorld":{"Type":"Succeed"}}}
      RoleArn:
        Fn::GetAtt:
          - MyStateMachineRoleD59FFEBC
          - Arn
    DependsOn:
      - MyStateMachineRoleDefaultPolicyE468EB18
      - MyStateMachineRoleD59FFEBC
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
    Metadata:
      aws:cdk:path: Issue30862Stack/MyStateMachine/Resource
...

Per TagResource, the operation requires permissions for the elasticfilesystem:TagResource action.

Possible root cause:

Possible fix: Possible fix is to add mapping efs: 'elasticfilesystem' to iamServiceMap here.

WorkAround: Explicitly specify CallAwsServiceProps.iamAction as elasticfilesystem:TagResource. Verifies using code below:

const callAwsServiceTask = new tasks.CallAwsService(this, 'TagEfsAccessPoint', {
      stateName: 'Tag access point',
      service: 'efs',
      action: 'tagResource',
      iamResources: ['*'],
      iamAction: 'elasticfilesystem:TagResource',
      parameters: {
        ResourceId: sfn.JsonPath.stringAt('$.pathToArn'),
        Tags: [
            {
                Key: "MYTAGNAME",
                Value: sfn.JsonPath.stringAt('$.pathToId')
            }
        ]
      },
      resultPath: sfn.JsonPath.DISCARD
    });

and it works:

...
  MyStateMachineRoleDefaultPolicyE468EB18:
    Type: AWS::IAM::Policy
    Properties:
      PolicyDocument:
        Statement:
          - Action: elasticfilesystem:TagResource
            Effect: Allow
            Resource: "*"
        Version: "2012-10-17"
      PolicyName: MyStateMachineRoleDefaultPolicyE468EB18
      Roles:
        - Ref: MyStateMachineRoleD59FFEBC
    Metadata:
      aws:cdk:path: Issue30862Stack/MyStateMachine/Role/DefaultPolicy/Resource
...
ishon19 commented 1 month ago

Hi @ashishdhingra, I would like to work on this issue!

ashishdhingra commented 1 month ago

Hi @ashishdhingra, I would like to work on this issue!

@ishon19 Thanks for your reply. I will most likely submit PR for this issue soon. :)

ishon19 commented 1 month ago

@ishon19 Thanks for your reply. I will most likely submit PR for this issue soon. :)

Yeah, sure! =)

github-actions[bot] commented 1 month ago

Comments on closed issues and PRs are hard for our team to see. If you need help, please open a new issue that references this one.

github-actions[bot] commented 1 month ago

Comments on closed issues and PRs are hard for our team to see. If you need help, please open a new issue that references this one.