Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions lib/deploy/stepFunctions/compileIamRole.js
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,7 @@ function getStateMachineArn(state) {
function getStepFunctionsPermissions(state) {
let stateMachineArn = state.Mode === 'DISTRIBUTED' ? {
'Fn::Sub': [
`arn:aws:states:\${AWS::Region}:\${AWS::AccountId}:stateMachine:${state.StateMachineName}`,
`arn:\${AWS::Partition}:states:\${AWS::Region}:\${AWS::AccountId}:stateMachine:${state.StateMachineName}`,
{},
],
} : null;
Expand Down Expand Up @@ -496,7 +496,7 @@ function getStepFunctionsPermissions(state) {
function getStepFunctionsSDKPermissions(state) {
let stateMachineArn = state.Mode === 'DISTRIBUTED' ? {
'Fn::Sub': [
`arn:aws:states:\${AWS::Region}:\${AWS::AccountId}:stateMachine:${state.StateMachineName}`,
`arn:\${AWS::Partition}:states:\${AWS::Region}:\${AWS::AccountId}:stateMachine:${state.StateMachineName}`,
{},
],
} : null;
Expand Down Expand Up @@ -736,7 +736,12 @@ function consolidatePermissionsByResource(permissions) {

function getIamPermissions(taskStates) {
return _.flatMap(taskStates, (state) => {
const resourceName = typeof state.Resource === 'string' ? state.Resource.replace(/^arn:aws(-[a-z]+)*:/, 'arn:aws:') : state.Resource;
// Normalize resource ARN to handle different partition formats:
// - arn:aws:, arn:aws-cn:, arn:aws-us-gov: (literal partitions)
// - arn:${AWS::Partition}: (CloudFormation intrinsic)
const resourceName = typeof state.Resource === 'string'
? state.Resource.replace(/^arn:(aws(-[a-z]+)*|\$\{AWS::Partition\}):/, 'arn:aws:')
: state.Resource;
switch (resourceName) {
case 'arn:aws:states:::sqs:sendMessage':
case 'arn:aws:states:::sqs:sendMessage.waitForTaskToken':
Expand Down
62 changes: 60 additions & 2 deletions lib/deploy/stepFunctions/compileIamRole.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3274,6 +3274,64 @@ describe('#compileIamRole', () => {
],
}]);
});

it('should handle ${AWS::Partition} in resource ARN', () => {
const stateMachineArn = 'arn:aws:states:us-east-1:123456789:stateMachine:HelloStateMachine';
const genStateMachine = id => ({
id,
definition: {
StartAt: 'A',
States: {
A: {
Type: 'Task',
Resource: 'arn:${AWS::Partition}:states:::states:startExecution',
Parameters: {
StateMachineArn: stateMachineArn,
Input: {},
},
Next: 'B',
},
B: {
Type: 'Task',
Resource: 'arn:${AWS::Partition}:states:::states:startExecution.sync',
Parameters: {
StateMachineArn: stateMachineArn,
Input: {},
},
End: true,
},
},
},
});

serverless.service.stepFunctions = {
stateMachines: {
myStateMachine1: genStateMachine('StateMachine1'),
},
};

serverlessStepFunctions.compileIamRole();
const statements = serverlessStepFunctions.serverless.service
.provider.compiledCloudFormationTemplate.Resources.StateMachine1Role
.Properties.Policies[0].PolicyDocument.Statement;

const stateMachinePermissions = statements.filter(s => _.isEqual(s.Action, ['states:StartExecution']));
expect(stateMachinePermissions).to.have.lengthOf(1);
expect(stateMachinePermissions[0].Resource).to.deep.eq([stateMachineArn]);

const executionPermissions = statements.filter(s => _.isEqual(s.Action, ['states:DescribeExecution', 'states:StopExecution']));
expect(executionPermissions).to.have.lengthOf(1);
expect(executionPermissions[0].Resource).to.equal('*');

const eventPermissions = statements.filter(s => _.isEqual(s.Action, ['events:PutTargets', 'events:PutRule', 'events:DescribeRule']));
expect(eventPermissions).to.have.lengthOf(1);
expect(eventPermissions[0].Resource).to.deep.eq([{
'Fn::Sub': [
'arn:${AWS::Partition}:events:${AWS::Region}:${AWS::AccountId}:rule/StepFunctionsGetEventsForStepFunctionsExecutionRule',
{},
],
}]);
});
});

describe('should give step functions using sdk permissions (too permissive, but mirrors console behavior)', () => {
Expand Down Expand Up @@ -3660,7 +3718,7 @@ describe('#compileIamRole', () => {
expect(stepFunctionPermission).to.have.lengthOf(1);
expect(stepFunctionPermission[0].Resource).to.deep.eq([{
'Fn::Sub': [
'arn:aws:states:${AWS::Region}:${AWS::AccountId}:stateMachine:myStateMachine',
'arn:${AWS::Partition}:states:${AWS::Region}:${AWS::AccountId}:stateMachine:myStateMachine',
{},
],
},
Expand Down Expand Up @@ -3711,7 +3769,7 @@ describe('#compileIamRole', () => {
expect(stepFunctionPermission).to.have.lengthOf(1);
expect(stepFunctionPermission[0].Resource).to.deep.eq([{
'Fn::Sub': [
'arn:aws:states:${AWS::Region}:${AWS::AccountId}:stateMachine:DistributedMapper',
'arn:${AWS::Partition}:states:${AWS::Region}:${AWS::AccountId}:stateMachine:DistributedMapper',
{},
],
},
Expand Down
Loading