diff --git a/packages/aws-cdk-lib/aws-stepfunctions-tasks/lib/aws-sdk/call-aws-service.ts b/packages/aws-cdk-lib/aws-stepfunctions-tasks/lib/aws-sdk/call-aws-service.ts index 556c0becdac08..16d37f7fb1aec 100644 --- a/packages/aws-cdk-lib/aws-stepfunctions-tasks/lib/aws-sdk/call-aws-service.ts +++ b/packages/aws-cdk-lib/aws-stepfunctions-tasks/lib/aws-sdk/call-aws-service.ts @@ -79,6 +79,15 @@ export class CallAwsService extends sfn.TaskStateBase { if (this.props.integrationPattern === sfn.IntegrationPattern.RUN_JOB) { throw new Error('The RUN_JOB integration pattern is not supported for CallAwsService'); } + if (!Token.isUnresolved(this.props.action) && !this.props.action.startsWith(this.props.action[0]?.toLowerCase())) { + throw new Error(`action must be camelCase, got: ${this.props.action}`); + } + if (this.props.parameters) { + const invalidKeys = Object.keys(this.props.parameters).filter(key => !key.startsWith(key[0]?.toUpperCase())); + if (invalidKeys.length) { + throw new Error(`parameter names must be PascalCase, got: ${invalidKeys.join(', ')}`); + } + } const iamServiceMap: Record = { sfn: 'states', diff --git a/packages/aws-cdk-lib/aws-stepfunctions-tasks/test/aws-sdk/call-aws-service.test.ts b/packages/aws-cdk-lib/aws-stepfunctions-tasks/test/aws-sdk/call-aws-service.test.ts index cd5ac68818c15..3eceee2639073 100644 --- a/packages/aws-cdk-lib/aws-stepfunctions-tasks/test/aws-sdk/call-aws-service.test.ts +++ b/packages/aws-cdk-lib/aws-stepfunctions-tasks/test/aws-sdk/call-aws-service.test.ts @@ -161,6 +161,30 @@ test('throws with invalid integration pattern', () => { })).toThrow(/The RUN_JOB integration pattern is not supported for CallAwsService/); }); +test('throws if action is not camelCase', () => { + expect(() => new tasks.CallAwsService(stack, 'GetObject', { + service: 's3', + action: 'GetObject', + parameters: { + Bucket: 'my-bucket', + Key: sfn.JsonPath.stringAt('$.key'), + }, + iamResources: ['*'], + })).toThrow(/action must be camelCase, got: GetObject/); +}); + +test('throws if parameters has keys as not PascalCase', () => { + expect(() => new tasks.CallAwsService(stack, 'GetObject', { + service: 's3', + action: 'getObject', + parameters: { + bucket: 'my-bucket', + key: sfn.JsonPath.stringAt('$.key'), + }, + iamResources: ['*'], + })).toThrow(/parameter names must be PascalCase, got: bucket, key/); +}); + test('can pass additional IAM statements', () => { // WHEN const task = new tasks.CallAwsService(stack, 'DetectLabels', {