diff --git a/lib/deploy/stepFunctions/compileIamRole.js b/lib/deploy/stepFunctions/compileIamRole.js index f1d0ba8c..f99c8d2a 100644 --- a/lib/deploy/stepFunctions/compileIamRole.js +++ b/lib/deploy/stepFunctions/compileIamRole.js @@ -35,12 +35,18 @@ function sqsQueueUrlToArn(serverless, queueUrl) { const accountId = match[2]; const queueName = match[3]; return `arn:aws:sqs:${region}:${accountId}:${queueName}`; - } if (isIntrinsic(queueUrl) && queueUrl.Ref) { - // most likely we'll see a { Ref: LogicalId }, which we need to map to - // { Fn::GetAtt: [ LogicalId, Arn ] } to get the ARN - return { - 'Fn::GetAtt': [queueUrl.Ref, 'Arn'], - }; + } + if (isIntrinsic(queueUrl)) { + if (queueUrl.Ref) { + // most likely we'll see a { Ref: LogicalId }, which we need to map to + // { Fn::GetAtt: [ LogicalId, Arn ] } to get the ARN + return { + 'Fn::GetAtt': [queueUrl.Ref, 'Arn'], + }; + } + // in case of for example { Fn::ImportValue: sharedValueToImport } + // we need to use "*" as ARN + return '*'; } serverless.cli.consoleLog(`Unable to parse SQS queue url [${queueUrl}]`); return []; diff --git a/lib/deploy/stepFunctions/compileIamRole.test.js b/lib/deploy/stepFunctions/compileIamRole.test.js index 8276b971..4437d9ab 100644 --- a/lib/deploy/stepFunctions/compileIamRole.test.js +++ b/lib/deploy/stepFunctions/compileIamRole.test.js @@ -362,6 +362,56 @@ describe('#compileIamRole', () => { expect(policy.PolicyDocument.Statement[0].Resource).to.equal('*'); }); + it('should give sqs:SendMessage permission to * whenever QueueUrl is some intrinsic function except Ref', () => { + const helloQueue = 'https://sqs.#{AWS::Region}.amazonaws.com/#{AWS::AccountId}/hello'; + const worldQueue = 'https://sqs.us-east-1.amazonaws.com/#{AWS::AccountId}/world'; + + const genStateMachine = (name, queueUrl) => ({ + name, + definition: { + StartAt: 'A', + States: { + A: { + Type: 'Task', + Resource: 'arn:aws:states:::sqs:sendMessage', + Parameters: { + QueueUrl: queueUrl, + Message: '42', + }, + Next: 'B', + }, + B: { + Type: 'Task', + Resource: 'arn:aws:states:::sqs:sendMessage', + Parameters: { + QueueUrl: { + 'Fn::ImportValue': 'some-shared-value-here', + }, + Message: '42', + }, + End: true, + }, + }, + }, + }); + + serverless.service.stepFunctions = { + stateMachines: { + myStateMachine1: genStateMachine('stateMachineBeta1', helloQueue), + myStateMachine2: genStateMachine('stateMachineBeta2', worldQueue), + }, + }; + + serverlessStepFunctions.compileIamRole(); + const policy = serverlessStepFunctions.serverless.service + .provider.compiledCloudFormationTemplate.Resources.IamRoleStateMachineExecution + .Properties.Policies[0]; + + // when using instrinct functions other than Ref to define QueueUrl + // we can't recontruct ARN from it, so we need to give broad permissions + expect(policy.PolicyDocument.Statement[0].Resource).to.equal('*'); + }); + it('should not give sqs:SendMessage permission if QueueUrl and QueueUrl.$ are missing', () => { const genStateMachine = name => ({ name,