简体   繁体   中英

Is it possible to create a rule in a different account?

Using CDK I am trying to create an event bus rule in a different account:

// Getting source bus ARN
const sourceBusArn = Stack.of(this).formatArn({
  region: this.region,
  service: 'events',
  account: Config.sourceAccount,
  resource: 'event-bus',
  resourceName: Config.sourceBusName,
});

// Retrieving source bus
const sourceBus = EventBus.fromEventBusArn(this, 'SourceBus', sourceBusArn);

// creating rule to forward source bus events to target buses
new Rule(this, 'CrossAccountSourceRule', {
  eventPattern: Config.eventPattern,
  eventBus: sourceBus,
  targets: [new EventBusTarget(targetBus)],
});

Here Config.sourceAccount is an external account, different from the one CDK is being executed in. The Config.sourceBusName bus exists in that account, and has policy allowing to create rules from external accounts in the same organization.

But attempt to create the rule throws exception Event bus <bus-in-external-account> does not exist. Status Code: 400 Event bus <bus-in-external-account> does not exist. Status Code: 400 . Is it possible to create a rule in a different account like this or any other way?

Found the solution. When importing bus from the source account instead of EventBus.fromEventBusArn use EventBus.fromEventBusAttributes - but with one twist: pass source bus ARN as both bus name and bus ARN:

// Getting source bus ARN
const sourceBusArn = Stack.of(this).formatArn({
  region: this.region,
  service: 'events',
  account: Config.sourceAccount,
  resource: 'event-bus',
  resourceName: Config.sourceBusName,
});

// Retrieving source bus. Pass ARN both as name and Arn props.
const sourceCoreBus = EventBus.fromEventBusAttributes(this, 'SourceCoreBus', {
  eventBusName: sourceBusArn,
  eventBusArn: sourceBusArn,
  eventBusPolicy: '',
});

// creating rule to forward source bus events to target buses
new Rule(this, 'CrossAccountSourceRule', {
  eventPattern: Config.eventPattern,
  eventBus: sourceBus,
  targets: [new EventBusTarget(targetBus)],
});

This will create rule in the external account. Don't forget that the bus you're trying to access has to have required permission policy in place, eg

{
   "Version":"2012-10-17",
   "Statement":[
      {
         "Effect":"Allow",
         "Principal":{
            "AWS":"<id-of-account-that-creates-rules>"
         },
         "Action":[
            "events:DescribeEventBus",
            "events:PutRule",
            "events:PutTargets",
            "events:DeleteRule",
            "events:RemoveTargets",
            "events:DisableRule",
            "events:EnableRule",
            "events:TagResource",
            "events:UntagResource",
            "events:DescribeRule",
            "events:ListTargetsByRule",
            "events:ListTagsForResource"
         ],
         "Resource":[
            "arn:aws:events:us-west-2:<id-of-source-account>:rule/<bus-name>",
            "arn:aws:events:us-west-2:<id-of-source-account>:rule/<bus-name>/*"
         ]
      }
   ]
}

UPDATE: A bit of explanation. The above solution works because under the hood Rule construct uses Level 1 CfnRule construct. And one of its props EventBusName can be either bus name or ARN . So when ARN is passed instead of name - it is used as such. And generated CloudFormation template looks like this (relevant fragment):

  "CrossAccountSourceRuleAF67328": {
   "Type": "AWS::Events::Rule",
   "Properties": {
    "EventBusName": {
     "Fn::Join": [
      "",
      [
       "arn:",
       {
        "Ref": "AWS::Partition"
       },
       ":events:",
       {
        "Ref": "AWS::Region"
       },
       ":1234567890:event-bus/bus-name"
      ]
     ]
    },

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM