diff --git a/lib/deploy/stepFunctions/compileIamRole.js b/lib/deploy/stepFunctions/compileIamRole.js index ea9ed374..30a5f470 100644 --- a/lib/deploy/stepFunctions/compileIamRole.js +++ b/lib/deploy/stepFunctions/compileIamRole.js @@ -245,25 +245,82 @@ function getBatchDynamoDBPermissions(action, state) { } function getRedshiftDataPermissions(action, state) { + const permissions = []; + if (['redshift-data:ExecuteStatement', 'redshift-data:BatchExecuteStatement'].includes(action)) { - const clusterName = _.has(state, 'Parameters.ClusterIdentifier') ? state.Parameters.ClusterIdentifier : '*'; - const dbName = _.has(state, 'Parameters.Database') ? state.Parameters.Database : '*'; - const dbUser = _.has(state, 'Parameters.DbUser') ? state.Parameters.DbUser : '*'; - return [{ + const dbName = _.has(state, ['Parameters', 'Database']) ? state.Parameters.Database : '*'; + + let workgroupArn; + let clusterName; + if (_.has(state, ['Parameters', 'WorkgroupName'])) { + if (state.Parameters.WorkgroupName.startsWith('arn:')) { + workgroupArn = state.Parameters.WorkgroupName; + } else { + workgroupArn = { 'Fn::Sub': 'arn:${AWS::Partition}:redshift-serverless:${AWS::Region}:${AWS::AccountId}:workgroup/*' }; + } + } else if (_.has(state, ['Parameters', 'WorkgroupName.$'])) { + workgroupArn = { 'Fn::Sub': 'arn:${AWS::Partition}:redshift-serverless:${AWS::Region}:${AWS::AccountId}:workgroup/*' }; + } else if (_.has(state, ['Parameters', 'ClusterIdentifier'])) { + clusterName = state.Parameters.ClusterIdentifier; + } else { + clusterName = '*'; + } + + let secretArn; + let dbUser; + if (_.has(state, ['Parameters', 'SecretArn'])) { + if (state.Parameters.SecretArn.startsWith('arn:')) { + secretArn = state.Parameters.SecretArn; + } else { + secretArn = { 'Fn::Sub': `arn:\${AWS::Partition}:secretsmanager:\${AWS::Region}:\${AWS::AccountId}:secret:${state.Parameters.SecretArn}*` }; + } + } else if (_.has(state, ['Parameters', 'SecretArn.$'])) { + secretArn = { 'Fn::Sub': 'arn:${AWS::Partition}:secretsmanager:${AWS::Region}:${AWS::AccountId}:secret:*' }; + } else if (_.has(state, ['Parameters', 'DbUser'])) { + dbUser = state.Parameters.DbUser; + } else if (_.has(state, ['Parameters', 'DbUser.$'])) { + dbUser = '*'; + } + + permissions.push({ action, - resource: { 'Fn::Sub': `arn:\${AWS::Partition}:redshift:\${AWS::Region}:\${AWS::AccountId}:cluster:${clusterName}` }, - }, { - action: 'redshift:GetClusterCredentials', - resource: [ - { 'Fn::Sub': `arn:\${AWS::Partition}:redshift:\${AWS::Region}:\${AWS::AccountId}:dbname:${clusterName}/${dbName}` }, - { 'Fn::Sub': `arn:\${AWS::Partition}:redshift:\${AWS::Region}:\${AWS::AccountId}:dbuser:${clusterName}/${dbUser}` }, - ], - }]; + resource: workgroupArn || { 'Fn::Sub': `arn:\${AWS::Partition}:redshift:\${AWS::Region}:\${AWS::AccountId}:cluster:${clusterName}` }, + }); + + if (secretArn) { + permissions.push({ + action: 'secretsmanager:GetSecretValue', + resource: secretArn, + }); + } else if (dbUser) { + permissions.push({ + action: 'redshift:GetClusterCredentials', + resource: [ + { 'Fn::Sub': `arn:\${AWS::Partition}:redshift:\${AWS::Region}:\${AWS::AccountId}:dbuser:${clusterName}/${dbUser}` }, + { 'Fn::Sub': `arn:\${AWS::Partition}:redshift:\${AWS::Region}:\${AWS::AccountId}:dbname:${clusterName}/${dbName}` }, + ], + }); + } else { + if (workgroupArn) { // eslint-disable-line no-lonely-if + permissions.push({ + action: 'redshift-serverless:GetCredentials', + resource: workgroupArn, + }); + } else { + permissions.push({ + action: 'redshift:GetClusterCredentialsWithIAM', + resource: { 'Fn::Sub': `arn:\${AWS::Partition}:redshift:\${AWS::Region}:\${AWS::AccountId}:dbname:${clusterName}/${dbName}` }, + }); + } + } + } else { + permissions.push({ + action, + resource: '*', + }); } - return [{ - action, - resource: '*', - }]; + + return permissions; } function getLambdaPermissions(state) { diff --git a/lib/deploy/stepFunctions/compileIamRole.test.js b/lib/deploy/stepFunctions/compileIamRole.test.js index b0a04df3..21329ce2 100644 --- a/lib/deploy/stepFunctions/compileIamRole.test.js +++ b/lib/deploy/stepFunctions/compileIamRole.test.js @@ -1024,7 +1024,7 @@ describe('#compileIamRole', () => { expect(policy.PolicyDocument.Statement[0].Resource).to.equal('*'); }); - it('should give Redshift Data permissions to * for safe actions', () => { + it('should give Redshift Data permissions for safe actions', () => { serverless.service.stepFunctions = { stateMachines: { myStateMachine: { @@ -1034,23 +1034,23 @@ describe('#compileIamRole', () => { States: { A: { Type: 'Task', - Next: 'B', Resource: 'arn:aws:states:::aws-sdk:redshiftdata:listStatements', + Next: 'B', }, B: { Type: 'Task', - Next: 'C', Resource: 'arn:aws:states:::aws-sdk:redshiftdata:describeStatement', + Next: 'C', }, C: { Type: 'Task', - Next: 'D', Resource: 'arn:aws:states:::aws-sdk:redshiftdata:getStatementResult', + Next: 'D', }, D: { Type: 'Task', - End: true, Resource: 'arn:aws:states:::aws-sdk:redshiftdata:cancelStatement', + End: true, }, }, }, @@ -1058,9 +1058,9 @@ describe('#compileIamRole', () => { }, }; serverlessStepFunctions.compileIamRole(); - const statement = serverlessStepFunctions.serverless.service.provider - .compiledCloudFormationTemplate.Resources.StateMachine1Role.Properties.Policies[0] - .PolicyDocument.Statement[0]; + const statement = serverlessStepFunctions.serverless.service + .provider.compiledCloudFormationTemplate.Resources.StateMachine1Role + .Properties.Policies[0].PolicyDocument.Statement[0]; expect(statement.Action).to.include('redshift-data:ListStatements'); expect(statement.Action).to.include('redshift-data:DescribeStatement'); expect(statement.Action).to.include('redshift-data:GetStatementResult'); @@ -1068,7 +1068,8 @@ describe('#compileIamRole', () => { expect(statement.Resource).to.equal('*'); }); - it('should give Redshift Data permissions to clusters for unsafe actions', () => { + it('should give Redshift Data permissions for unsafe actions on a workgroup, given its ARN', () => { + const workgroupName = 'arn:aws:redshift-serverless:us-east-1:012345678901:workgroup/01234567-89ab-cdef-0123-456789abcdef'; serverless.service.stepFunctions = { stateMachines: { myStateMachine: { @@ -1078,13 +1079,60 @@ describe('#compileIamRole', () => { States: { A: { Type: 'Task', - Next: 'B', Resource: 'arn:aws:states:::aws-sdk:redshiftdata:executeStatement', + Parameters: { + WorkgroupName: workgroupName, + }, + Next: 'B', }, B: { Type: 'Task', + Resource: 'arn:aws:states:::aws-sdk:redshiftdata:batchExecuteStatement', + Parameters: { + WorkgroupName: workgroupName, + }, End: true, + }, + }, + }, + }, + }, + }; + serverlessStepFunctions.compileIamRole(); + const statement = serverlessStepFunctions.serverless.service + .provider.compiledCloudFormationTemplate.Resources.StateMachine1Role + .Properties.Policies[0].PolicyDocument.Statement[0]; + expect(statement.Action).to.include('redshift-data:ExecuteStatement'); + expect(statement.Action).to.include('redshift-data:BatchExecuteStatement'); + expect(statement.Resource).to.have.deep.members([ + workgroupName, + ]); + }); + + it('should give Redshift Data permissions for unsafe actions on all workgroups, given a name', () => { + const workgroupName = 'myWorkgroup'; + serverless.service.stepFunctions = { + stateMachines: { + myStateMachine: { + id: 'StateMachine1', + definition: { + StartAt: 'A', + States: { + A: { + Type: 'Task', + Resource: 'arn:aws:states:::aws-sdk:redshiftdata:executeStatement', + Parameters: { + WorkgroupName: workgroupName, + }, + Next: 'B', + }, + B: { + Type: 'Task', Resource: 'arn:aws:states:::aws-sdk:redshiftdata:batchExecuteStatement', + Parameters: { + WorkgroupName: workgroupName, + }, + End: true, }, }, }, @@ -1092,18 +1140,17 @@ describe('#compileIamRole', () => { }, }; serverlessStepFunctions.compileIamRole(); - const statement = serverlessStepFunctions.serverless.service.provider - .compiledCloudFormationTemplate.Resources.StateMachine1Role.Properties.Policies[0] - .PolicyDocument.Statement[0]; + const statement = serverlessStepFunctions.serverless.service + .provider.compiledCloudFormationTemplate.Resources.StateMachine1Role + .Properties.Policies[0].PolicyDocument.Statement[0]; expect(statement.Action).to.include('redshift-data:ExecuteStatement'); expect(statement.Action).to.include('redshift-data:BatchExecuteStatement'); expect(statement.Resource).to.have.deep.members([{ - 'Fn::Sub': 'arn:${AWS::Partition}:redshift:${AWS::Region}:${AWS::AccountId}:cluster:*', + 'Fn::Sub': 'arn:${AWS::Partition}:redshift-serverless:${AWS::Region}:${AWS::AccountId}:workgroup/*', }]); }); - it('should give Redshift Data permissions to a specified cluster for unsafe actions', () => { - const clusterName = 'myCluster'; + it('should give Redshift Data permissions for unsafe actions on all workgroups, promised a name', () => { serverless.service.stepFunctions = { stateMachines: { myStateMachine: { @@ -1113,19 +1160,100 @@ describe('#compileIamRole', () => { States: { A: { Type: 'Task', + Resource: 'arn:aws:states:::aws-sdk:redshiftdata:executeStatement', + Parameters: { + 'WorkgroupName.$': '$', + }, Next: 'B', + }, + B: { + Type: 'Task', + Resource: 'arn:aws:states:::aws-sdk:redshiftdata:batchExecuteStatement', + Parameters: { + 'WorkgroupName.$': '$', + }, + End: true, + }, + }, + }, + }, + }, + }; + serverlessStepFunctions.compileIamRole(); + const statement = serverlessStepFunctions.serverless.service + .provider.compiledCloudFormationTemplate.Resources.StateMachine1Role + .Properties.Policies[0].PolicyDocument.Statement[0]; + expect(statement.Action).to.include('redshift-data:ExecuteStatement'); + expect(statement.Action).to.include('redshift-data:BatchExecuteStatement'); + expect(statement.Resource).to.have.deep.members([{ + 'Fn::Sub': 'arn:${AWS::Partition}:redshift-serverless:${AWS::Region}:${AWS::AccountId}:workgroup/*', + }]); + }); + + it('should give Redshift Data permissions for unsafe actions on a cluster, given its identifier', () => { + const clusterIdentifier = 'myCluster'; + serverless.service.stepFunctions = { + stateMachines: { + myStateMachine: { + id: 'StateMachine1', + definition: { + StartAt: 'A', + States: { + A: { + Type: 'Task', Resource: 'arn:aws:states:::aws-sdk:redshiftdata:executeStatement', Parameters: { - ClusterIdentifier: clusterName, + ClusterIdentifier: clusterIdentifier, }, + Next: 'B', }, B: { Type: 'Task', + Resource: 'arn:aws:states:::aws-sdk:redshiftdata:batchExecuteStatement', + Parameters: { + ClusterIdentifier: clusterIdentifier, + }, End: true, + }, + }, + }, + }, + }, + }; + serverlessStepFunctions.compileIamRole(); + const statement = serverlessStepFunctions.serverless.service + .provider.compiledCloudFormationTemplate.Resources.StateMachine1Role + .Properties.Policies[0].PolicyDocument.Statement[0]; + expect(statement.Action).to.include('redshift-data:ExecuteStatement'); + expect(statement.Action).to.include('redshift-data:BatchExecuteStatement'); + expect(statement.Resource).to.have.deep.members([{ + 'Fn::Sub': `arn:\${AWS::Partition}:redshift:\${AWS::Region}:\${AWS::AccountId}:cluster:${clusterIdentifier}`, + }]); + }); + + it('should give Redshift Data permissions for unsafe actions on all clusters, promised an identifier', () => { + serverless.service.stepFunctions = { + stateMachines: { + myStateMachine: { + id: 'StateMachine1', + definition: { + StartAt: 'A', + States: { + A: { + Type: 'Task', + Resource: 'arn:aws:states:::aws-sdk:redshiftdata:executeStatement', + Parameters: { + 'ClusterIdentifier.$': '$', + }, + Next: 'B', + }, + B: { + Type: 'Task', Resource: 'arn:aws:states:::aws-sdk:redshiftdata:batchExecuteStatement', Parameters: { - ClusterIdentifier: clusterName, + 'ClusterIdentifier.$': '$', }, + End: true, }, }, }, @@ -1133,17 +1261,18 @@ describe('#compileIamRole', () => { }, }; serverlessStepFunctions.compileIamRole(); - const statement = serverlessStepFunctions.serverless.service.provider - .compiledCloudFormationTemplate.Resources.StateMachine1Role.Properties.Policies[0] - .PolicyDocument.Statement[0]; + const statement = serverlessStepFunctions.serverless.service + .provider.compiledCloudFormationTemplate.Resources.StateMachine1Role + .Properties.Policies[0].PolicyDocument.Statement[0]; expect(statement.Action).to.include('redshift-data:ExecuteStatement'); expect(statement.Action).to.include('redshift-data:BatchExecuteStatement'); expect(statement.Resource).to.have.deep.members([{ - 'Fn::Sub': `arn:\${AWS::Partition}:redshift:\${AWS::Region}:\${AWS::AccountId}:cluster:${clusterName}`, + 'Fn::Sub': 'arn:${AWS::Partition}:redshift:${AWS::Region}:${AWS::AccountId}:cluster:*', }]); }); - it('should give redshift:GetClusterCredentials permission to databases and database users for unsafe actions', () => { + it('should give permissions for unsafe Redshift Data actions to get the value of a secret, given its ARN', () => { + const secretArn = 'arn:aws:secretsmanager:us-east-1:012345678901:secret:mySecret-ABab01'; serverless.service.stepFunctions = { stateMachines: { myStateMachine: { @@ -1153,13 +1282,98 @@ describe('#compileIamRole', () => { States: { A: { Type: 'Task', + Resource: 'arn:aws:states:::aws-sdk:redshiftdata:executeStatement', + Parameters: { + SecretArn: secretArn, + }, Next: 'B', + }, + B: { + Type: 'Task', + Resource: 'arn:aws:states:::aws-sdk:redshiftdata:batchExecuteStatement', + Parameters: { + SecretArn: secretArn, + }, + End: true, + }, + }, + }, + }, + }, + }; + serverlessStepFunctions.compileIamRole(); + const statement = serverlessStepFunctions.serverless.service + .provider.compiledCloudFormationTemplate.Resources.StateMachine1Role + .Properties.Policies[0].PolicyDocument.Statement[1]; + expect(statement.Action).to.include('secretsmanager:GetSecretValue'); + expect(statement.Resource).to.have.deep.members([ + secretArn, + ]); + }); + + it('should give permissions for unsafe Redshift Data actions to get the values of some secrets, given a name', () => { + const secretArn = 'mySecret'; + serverless.service.stepFunctions = { + stateMachines: { + myStateMachine: { + id: 'StateMachine1', + definition: { + StartAt: 'A', + States: { + A: { + Type: 'Task', Resource: 'arn:aws:states:::aws-sdk:redshiftdata:executeStatement', + Parameters: { + SecretArn: secretArn, + }, + Next: 'B', }, B: { Type: 'Task', + Resource: 'arn:aws:states:::aws-sdk:redshiftdata:batchExecuteStatement', + Parameters: { + SecretArn: secretArn, + }, End: true, + }, + }, + }, + }, + }, + }; + serverlessStepFunctions.compileIamRole(); + const statement = serverlessStepFunctions.serverless.service + .provider.compiledCloudFormationTemplate.Resources.StateMachine1Role + .Properties.Policies[0].PolicyDocument.Statement[1]; + expect(statement.Action).to.include('secretsmanager:GetSecretValue'); + expect(statement.Resource).to.have.deep.members([{ + 'Fn::Sub': 'arn:${AWS::Partition}:secretsmanager:${AWS::Region}:${AWS::AccountId}:secret:mySecret*', + }]); + }); + + it('should give permissions for unsafe Redshift Data actions to get the values of all secrets, promised an ARN', () => { + serverless.service.stepFunctions = { + stateMachines: { + myStateMachine: { + id: 'StateMachine1', + definition: { + StartAt: 'A', + States: { + A: { + Type: 'Task', + Resource: 'arn:aws:states:::aws-sdk:redshiftdata:executeStatement', + Parameters: { + 'SecretArn.$': '$', + }, + Next: 'B', + }, + B: { + Type: 'Task', Resource: 'arn:aws:states:::aws-sdk:redshiftdata:batchExecuteStatement', + Parameters: { + 'SecretArn.$': '$', + }, + End: true, }, }, }, @@ -1167,19 +1381,64 @@ describe('#compileIamRole', () => { }, }; serverlessStepFunctions.compileIamRole(); - const statement = serverlessStepFunctions.serverless.service.provider - .compiledCloudFormationTemplate.Resources.StateMachine1Role.Properties.Policies[0] - .PolicyDocument.Statement[1]; + const statement = serverlessStepFunctions.serverless.service + .provider.compiledCloudFormationTemplate.Resources.StateMachine1Role + .Properties.Policies[0].PolicyDocument.Statement[1]; + expect(statement.Action).to.include('secretsmanager:GetSecretValue'); + expect(statement.Resource).to.have.deep.members([{ + 'Fn::Sub': 'arn:${AWS::Partition}:secretsmanager:${AWS::Region}:${AWS::AccountId}:secret:*', + }]); + }); + + it('should give permissions for unsafe Redshift Data actions to get temporary credentials for a database user, given its name', () => { + const dbUser = 'myUser'; + const clusterIdentifier = 'myCluster'; + const database = 'myDatabase'; + serverless.service.stepFunctions = { + stateMachines: { + myStateMachine: { + id: 'StateMachine1', + definition: { + StartAt: 'A', + States: { + A: { + Type: 'Task', + Resource: 'arn:aws:states:::aws-sdk:redshiftdata:executeStatement', + Parameters: { + DbUser: dbUser, + ClusterIdentifier: clusterIdentifier, + Database: database, + }, + Next: 'B', + }, + B: { + Type: 'Task', + Resource: 'arn:aws:states:::aws-sdk:redshiftdata:batchExecuteStatement', + Parameters: { + DbUser: dbUser, + ClusterIdentifier: clusterIdentifier, + Database: database, + }, + End: true, + }, + }, + }, + }, + }, + }; + serverlessStepFunctions.compileIamRole(); + const statement = serverlessStepFunctions.serverless.service + .provider.compiledCloudFormationTemplate.Resources.StateMachine1Role + .Properties.Policies[0].PolicyDocument.Statement[1]; expect(statement.Action).to.include('redshift:GetClusterCredentials'); expect(statement.Resource).to.have.deep.members([{ - 'Fn::Sub': 'arn:${AWS::Partition}:redshift:${AWS::Region}:${AWS::AccountId}:dbname:*/*', + 'Fn::Sub': `arn:\${AWS::Partition}:redshift:\${AWS::Region}:\${AWS::AccountId}:dbuser:${clusterIdentifier}/${dbUser}`, }, { - 'Fn::Sub': 'arn:${AWS::Partition}:redshift:${AWS::Region}:${AWS::AccountId}:dbuser:*/*', + 'Fn::Sub': `arn:\${AWS::Partition}:redshift:\${AWS::Region}:\${AWS::AccountId}:dbname:${clusterIdentifier}/${database}`, }]); }); - it('should give redshift:GetClusterCredentials permission to specified databases for unsafe actions', () => { - const dbName = 'myDatabase'; + it('should give permissions for unsafe Redshift Data actions to get temporary credentials for all database users, promised a name', () => { serverless.service.stepFunctions = { stateMachines: { myStateMachine: { @@ -1189,19 +1448,23 @@ describe('#compileIamRole', () => { States: { A: { Type: 'Task', - Next: 'B', Resource: 'arn:aws:states:::aws-sdk:redshiftdata:executeStatement', Parameters: { - Database: dbName, + 'DbUser.$': '$', + 'ClusterIdentifier.$': '$', + 'Database.$': '$', }, + Next: 'B', }, B: { Type: 'Task', - End: true, Resource: 'arn:aws:states:::aws-sdk:redshiftdata:batchExecuteStatement', Parameters: { - Database: dbName, + 'DbUser.$': '$', + 'ClusterIdentifier.$': '$', + 'Database.$': '$', }, + End: true, }, }, }, @@ -1209,19 +1472,18 @@ describe('#compileIamRole', () => { }, }; serverlessStepFunctions.compileIamRole(); - const statement = serverlessStepFunctions.serverless.service.provider - .compiledCloudFormationTemplate.Resources.StateMachine1Role.Properties.Policies[0] - .PolicyDocument.Statement[1]; + const statement = serverlessStepFunctions.serverless.service + .provider.compiledCloudFormationTemplate.Resources.StateMachine1Role + .Properties.Policies[0].PolicyDocument.Statement[1]; expect(statement.Action).to.include('redshift:GetClusterCredentials'); expect(statement.Resource).to.have.deep.members([{ - 'Fn::Sub': `arn:\${AWS::Partition}:redshift:\${AWS::Region}:\${AWS::AccountId}:dbname:*/${dbName}`, - }, { 'Fn::Sub': 'arn:${AWS::Partition}:redshift:${AWS::Region}:${AWS::AccountId}:dbuser:*/*', + }, { + 'Fn::Sub': 'arn:${AWS::Partition}:redshift:${AWS::Region}:${AWS::AccountId}:dbname:*/*', }]); }); - it('should give redshift:GetClusterCredentials permission to specified database users for unsafe actions', () => { - const dbUser = 'myDatabaseUser'; + it('should give permissions for unsafe Redshift Data actions to get temporary credentials for the current role from workgroups', () => { serverless.service.stepFunctions = { stateMachines: { myStateMachine: { @@ -1231,19 +1493,60 @@ describe('#compileIamRole', () => { States: { A: { Type: 'Task', - Next: 'B', Resource: 'arn:aws:states:::aws-sdk:redshiftdata:executeStatement', Parameters: { - DbUser: dbUser, + 'WorkgroupName.$': '$', }, + Next: 'B', }, B: { Type: 'Task', + Resource: 'arn:aws:states:::aws-sdk:redshiftdata:batchExecuteStatement', + Parameters: { + 'WorkgroupName.$': '$', + }, End: true, + }, + }, + }, + }, + }, + }; + serverlessStepFunctions.compileIamRole(); + const statement = serverlessStepFunctions.serverless.service + .provider.compiledCloudFormationTemplate.Resources.StateMachine1Role + .Properties.Policies[0].PolicyDocument.Statement[0]; + expect(statement.Action).to.include('redshift-serverless:GetCredentials'); + expect(statement.Resource).to.have.deep.members([{ + 'Fn::Sub': 'arn:${AWS::Partition}:redshift-serverless:${AWS::Region}:${AWS::AccountId}:workgroup/*', + }]); + }); + + it('should give permissions for unsafe Redshift Data actions to get temporary credentials for the current role from clusters', () => { + serverless.service.stepFunctions = { + stateMachines: { + myStateMachine: { + id: 'StateMachine1', + definition: { + StartAt: 'A', + States: { + A: { + Type: 'Task', + Resource: 'arn:aws:states:::aws-sdk:redshiftdata:executeStatement', + Parameters: { + 'ClusterIdentifier.$': '$', + 'Database.$': '$', + }, + Next: 'B', + }, + B: { + Type: 'Task', Resource: 'arn:aws:states:::aws-sdk:redshiftdata:batchExecuteStatement', Parameters: { - DbUser: dbUser, + 'ClusterIdentifier.$': '$', + 'Database.$': '$', }, + End: true, }, }, }, @@ -1251,14 +1554,12 @@ describe('#compileIamRole', () => { }, }; serverlessStepFunctions.compileIamRole(); - const statement = serverlessStepFunctions.serverless.service.provider - .compiledCloudFormationTemplate.Resources.StateMachine1Role.Properties.Policies[0] - .PolicyDocument.Statement[1]; - expect(statement.Action).to.include('redshift:GetClusterCredentials'); + const statement = serverlessStepFunctions.serverless.service + .provider.compiledCloudFormationTemplate.Resources.StateMachine1Role + .Properties.Policies[0].PolicyDocument.Statement[1]; + expect(statement.Action).to.include('redshift:GetClusterCredentialsWithIAM'); expect(statement.Resource).to.have.deep.members([{ 'Fn::Sub': 'arn:${AWS::Partition}:redshift:${AWS::Region}:${AWS::AccountId}:dbname:*/*', - }, { - 'Fn::Sub': `arn:\${AWS::Partition}:redshift:\${AWS::Region}:\${AWS::AccountId}:dbuser:*/${dbUser}`, }]); });