10
votes

I have a SNS topic in account "A", which is a trigger of a Lambda function in that same account. This Lambda function sends a message to a private Slack channel.

This works fine, as long as the CloudWatch alarm is in the same account (Account A).

But I also want to do this from "Account B", but there I get:

{
  "error": "Resource: arn:aws:cloudwatch:REGION:ACCOUNT_B:alarm:ALARM is not authorized to perform: SNS:Publish on resource: arn:aws:sns:REGION:ACCOUNT_A:TOPIC",
  "actionState": "Failed",
  "notificationResource": "arn:aws:sns:REGION:ACCOUNT_A:TOPIC",
  "stateUpdateTimestamp": 1495732611020,
  "publishedMessage": null
}

So how do I allow the CloudWatch Alarm ARN access to publish to the topic?

Trying to add the policy fails with:

Invalid parameter: Policy Error: PrincipalNotFound (Service: AmazonSNS; Status Code: 400; Error Code: InvalidParameter; Request ID: 7f5c202e-4784-5386-8dc5-718f5cc55725)

I see that someone else have/had the same problem (years ago!) at https://forums.aws.amazon.com/thread.jspa?threadID=143607, but it was never answered.

Update:

Trying to solve this, I'm now trying to use a local SNS topic, which then sends this to the remove account. However, I'm still getting:

"error": "Resource: arn:aws:cloudwatch:REGION:LOCAL_ACCOUNT:alarm:ALARM is not authorized to perform: SNS:Publish on resource: arn:aws:sns:REGION:LOCAL_ACCOUNT:TOPIC"

This, with this SNS policy:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowLambdaAccountToSubscribe",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::REMOTE_ACCOUNT:root"
      },
      "Action": [
        "sns:Subscribe",
        "sns:Receive"
      ],
      "Resource": "arn:aws:sns:REGION:LOCAL_ACCOUNT:TOPIC"
    },
    {
      "Sid": "AllowLocalAccountToPublish",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "sns:Publish",
      "Resource": "arn:aws:sns:REGION:LOCAL_ACCOUNT:TOPIC",
      "Condition": {
        "StringEquals": {
          "AWS:SourceAccount": "LOCAL_ACCOUNT"
        }
      }
    }
  ]
}

If I manually send a message to the topic with the Publish to topic, I can see that it reaches the Lambda function, so everything except the CloudWatch access rights.

1

1 Answers

12
votes

By means of trial-and-error, I discovered it was the Condition that didn't work. For some reason. Not sure why it didn't see the source account...

A more extensive policy made it work:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowLambdaAccountToSubscribe",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::REMOTE_ACCOUNT:root"
      },
      "Action": [
        "sns:Subscribe",
        "sns:Receive"
      ],
      "Resource": "arn:aws:sns:REGION:LOCAL_ACCOUNT:TOPIC"
    },
    {
      "Sid": "AllowLocalAccountToPublish",
      "Effect": "Allow",
      "Principal": {
        "AWS": "*"
      },
      "Action": "sns:Publish",
      "Resource": "arn:aws:sns:REGION:LOCAL_ACCOUNT:TOPIC",
      "Condition": {
        "StringEquals": {
          "AWS:SourceAccount": "LOCAL_ACCOUNT"
        }
      }
    },
    {
      "Sid": "AllowCloudWatchAlarmsToPublish",
      "Effect": "Allow",
      "Principal": {
        "AWS": "*"
      },
      "Action": "sns:Publish",
      "Resource": "arn:aws:sns:REGION:LOCAL_ACCOUNT:TOPIC",
      "Condition": {
        "ArnLike": {
          "AWS:SourceArn": "arn:aws:cloudwatch:REGION:LOCAL_ACCOUNT:alarm:*"
        }
      }
    }
  ]
}