fix(AWS EventBridge): Ensure no duplicate event bus IAM policies (#7644)

This commit is contained in:
Thomas Aribart 2020-05-04 12:50:02 +02:00 committed by GitHub
parent 03ad56b8e1
commit a1fde35db4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 221 additions and 5 deletions

View File

@ -20,6 +20,7 @@ class AwsCompileEventBridgeEvents {
const { provider } = service;
const { compiledCloudFormationTemplate } = provider;
const iamRoleStatements = [];
const eventBusIamRoleStatements = new Map();
service.getAllFunctions().forEach(functionName => {
let funcUsesEventBridge = false;
@ -159,11 +160,14 @@ class AwsCompileEventBridgeEvents {
],
],
};
iamRoleStatements.push({
Effect: 'Allow',
Resource: eventBusResource,
Action: ['events:CreateEventBus', 'events:DeleteEventBus'],
});
if (!eventBusIamRoleStatements.has(eventBusName)) {
eventBusIamRoleStatements.set(eventBusName, {
Effect: 'Allow',
Resource: eventBusResource,
Action: ['events:CreateEventBus', 'events:DeleteEventBus'],
});
}
}
iamRoleStatements.push({
@ -209,6 +213,8 @@ class AwsCompileEventBridgeEvents {
}
});
iamRoleStatements.unshift(...eventBusIamRoleStatements.values());
if (iamRoleStatements.length) {
return addCustomResourceToService(this.provider, 'eventBridge', iamRoleStatements);
}

View File

@ -395,6 +395,216 @@ describe('AwsCompileEventBridgeEvents', () => {
);
});
it('should create the necessary resources with only one create/delete event bus policy', () => {
awsCompileEventBridgeEvents.serverless.service.functions = {
first: {
name: 'first',
events: [
{
eventBridge: {
eventBus: 'some-event-bus',
schedule: 'rate(10 minutes)',
pattern: {
'source': ['aws.cloudformation'],
'detail-type': ['AWS API Call via CloudTrail'],
'detail': {
eventSource: ['cloudformation.amazonaws.com'],
},
},
},
},
],
},
second: {
name: 'second',
events: [
{
eventBridge: {
eventBus: 'some-event-bus',
schedule: 'rate(10 minutes)',
pattern: {
'source': ['aws.cloudformation'],
'detail-type': ['AWS API Call via CloudTrail'],
'detail': {
eventSource: ['cloudformation.amazonaws.com'],
},
},
},
},
],
},
};
return expect(awsCompileEventBridgeEvents.compileEventBridgeEvents()).to.be.fulfilled.then(
() => {
const {
Resources,
} = awsCompileEventBridgeEvents.serverless.service.provider.compiledCloudFormationTemplate;
expect(addCustomResourceToServiceStub).to.have.been.calledOnce;
expect(addCustomResourceToServiceStub.args[0][1]).to.equal('eventBridge');
expect(addCustomResourceToServiceStub.args[0][2]).to.deep.equal([
{
Action: ['events:CreateEventBus', 'events:DeleteEventBus'],
Effect: 'Allow',
Resource: {
'Fn::Join': [
':',
[
'arn',
{
Ref: 'AWS::Partition',
},
'events',
{
Ref: 'AWS::Region',
},
{
Ref: 'AWS::AccountId',
},
'event-bus/some-event-bus',
],
],
},
},
{
Action: [
'events:PutRule',
'events:RemoveTargets',
'events:PutTargets',
'events:DeleteRule',
],
Effect: 'Allow',
Resource: {
'Fn::Join': [
':',
[
'arn',
{
Ref: 'AWS::Partition',
},
'events',
{
Ref: 'AWS::Region',
},
{
Ref: 'AWS::AccountId',
},
'rule/some-event-bus/first-rule-1',
],
],
},
},
{
Action: ['lambda:AddPermission', 'lambda:RemovePermission'],
Effect: 'Allow',
Resource: {
'Fn::Join': [
':',
[
'arn',
{
Ref: 'AWS::Partition',
},
'lambda',
{
Ref: 'AWS::Region',
},
{
Ref: 'AWS::AccountId',
},
'function',
'first',
],
],
},
},
{
Action: [
'events:PutRule',
'events:RemoveTargets',
'events:PutTargets',
'events:DeleteRule',
],
Effect: 'Allow',
Resource: {
'Fn::Join': [
':',
[
'arn',
{
Ref: 'AWS::Partition',
},
'events',
{
Ref: 'AWS::Region',
},
{
Ref: 'AWS::AccountId',
},
'rule/some-event-bus/second-rule-1',
],
],
},
},
{
Action: ['lambda:AddPermission', 'lambda:RemovePermission'],
Effect: 'Allow',
Resource: {
'Fn::Join': [
':',
[
'arn',
{
Ref: 'AWS::Partition',
},
'lambda',
{
Ref: 'AWS::Region',
},
{
Ref: 'AWS::AccountId',
},
'function',
'second',
],
],
},
},
]);
expect(Resources.FirstCustomEventBridge1).to.deep.equal({
Type: 'Custom::EventBridge',
Version: 1,
DependsOn: [
'FirstLambdaFunction',
'CustomDashresourceDasheventDashbridgeLambdaFunction',
],
Properties: {
ServiceToken: {
'Fn::GetAtt': ['CustomDashresourceDasheventDashbridgeLambdaFunction', 'Arn'],
},
FunctionName: 'first',
EventBridgeConfig: {
EventBus: 'some-event-bus',
Input: undefined,
InputPath: undefined,
InputTransformer: undefined,
Pattern: {
'detail': {
eventSource: ['cloudformation.amazonaws.com'],
},
'detail-type': ['AWS API Call via CloudTrail'],
'source': ['aws.cloudformation'],
},
RuleName: 'first-rule-1',
Schedule: 'rate(10 minutes)',
},
},
});
}
);
});
it('should create the necessary resources when using an own event bus arn', () => {
awsCompileEventBridgeEvents.serverless.service.functions = {
first: {