はじめに
最近、巷でマルチアカウント構成が流行ってるということで、マルチアカウント環境を前提とした SNS のクロスアカウントパブリッシュを試します。
前提条件
マルチアカウント環境を前提とします。本記事では便宜上、各アカウントを以下呼称とします。
- MasterAccount
- MemberAccount
SNS クロスアカウントパブリッシュの仕組み
SNS に対する操作権限は以下2つのポリシーで制御します。
- パブリッシャ―の IAM ポリシー
- SNS アクセスコントロールポリシー
両方でアクションが許可されている時に、SNSのクロスアカウント操作が可能となります。 図で表すと以下です。
今回は、 SNS でパブリッシュを行うので、2つのポリシーで "SNS:Publish" アクションを許可する必要があります。
トピックへの AWS アカウント アクセスの付与 [中略] これは、Amazon SNS API アクション AddPermission を使用して実行できます。 引用元: https://docs.aws.amazon.com/ja_jp/sns/latest/dg/sns-access-policy-use-cases.html
検証の構成
上記の仕組みを検証するために、以下の構成でクロスアカウントパブリッシュを試します。
①Cfnテンプレートを使用して、SNSトピックを作成します。
②CloudshellからCLIをたたいて、SNSトピックへメッセージのパブリッシュを行います。このとき、CloudShell実行IAMユーザが SNS:Publish API コールをできる必要があります。
③SNS が、あらかじめ設定された Eメールエンドポイントへメッセージをサブスクライブします。
このとき、SNS AccessControl Policy がCloudShell実行IAMユーザのSNS:Publish API コールを許可する必要があります。
セットアップ
①SNSトピック作成
本記事の "付録" > "SNS Topic用 Cfnテンプレート" の Cfn テンプレートを使用して、MasterAccount に SNS トピックを作成します。
Cfnコンソールでは、下記テンプレートパラメータを更新してください。
- CrossAccountAccessID: SNSトピックのパブリッシュを許可する AWS アカウントのカンマ区切りのリスト
- EndpointEmailAddress: サブスクライブする E メールアドレス
なお、今回作成される SNS AccessControl Policy は、"CrossAccountAccessID" アカウント内の全ての IAM オブジェクトに対して、テンプレート内で作成される SNS トピックをパブリッシュ可能です。
②サブスクリプション有効化
サブスクリプションに登録したメールアドレスでサブスクリプションを有効化にします。
"EndpointEmailAddress" で入力したメールアドレスに SNS からサブスクリプション確認メールが来るので、"Confirm subscription" を押して、サブスクリプションを有効にします。
- 件名: AWS Notification - Subscription Confirmation
有効になると、SNS コンソール > サブスクリプションタブ > サブスクリプションステータスが "確認済み" になります。
③(オプション)CloudShell用IAMユーザ作成
必要に応じて、以下条件の IAM ユーザを、MemberAccount に作成します。
- SNS:Publish 権限がある
- CloudShell の操作権限がある
- コンソールログイン可能
細かい手順は割愛します。
動作確認
MemberAccount の CloudShell を使って、クロスアカウントパブリッシュのテストを行います。
① SNS:Publish API コールをできる IAM ユーザにより、MemberAccount の CloudSell へログインします。
②ログイン後、以下コマンドを実行します。
{{SNS_TOPIC_ARN}} は、
"Cfn Stack" > "出力タブ" > "OutputsArnforVerifyCrossAccontPublishTopic" から取得した SNS Topic の ARNに置き換えます。
$ aws sns publish --target-arn {{SNS_TOPIC_ARN}} --message "こんにちは、世界!"
参考: https://docs.aws.amazon.com/cli/latest/reference/sns/publish.html
IAM ユーザの権限が足りない場合は、 "Tips" > "パブリッシャー IAM ポリシーの権限不足エラー" のエラーが出ます。
③"EndpointEmailAddress" で入力したメールアドレスにメールが来ていれば完了です。
メールが届かない場合は、本記事の "Tips" > "メール通知のトラシュ" を参考にしてください。
Tips
メール通知のトラシュ
①CW Metrics により、メール通知メトリクスを確認できます。メールが来ない時に確認してください。
- NumberOfMessagesPublished
- NumberOfNotificationsFailed など
参考: https://docs.aws.amazon.com/ja_jp/sns/latest/dg/sns-monitoring-using-cloudwatch.html
②CloudTrail を使ったデバックも可能です
https://docs.aws.amazon.com/ja_jp/sns/latest/dg/sns-logging-using-cloudtrail.html
パブリッシャー IAM ポリシーの権限不足エラー
パブリッシャーにIAM が設定されていない場合、以下エラーが表示されます。
An error occurred (AuthorizationError) when calling the Publish operation: User: arn:aws:iam::xxxx is not authorized to perform: SNS:Publish on resource: arn:aws:sns:xxx because no resource-based policy allows the SNS:Publish action
付録
SNS Topic用 Cfnテンプレート
作成されるリソース:
- SNS Topic
- SNS AccessControl Policy
Parameters: EndpointEmailAddress: Description: Input distination email address. Type: String CrossAccountAccessID: Description: Input AWS Account ID you want to allow access to. e.g. 12345678xxxx, 23456789xxxx Type: CommaDelimitedList Resources: VerifyCrossAccontPublishTopic: Type: AWS::SNS::Topic Properties: Subscription: - Endpoint: !Ref EndpointEmailAddress Protocol: EMAIL TopicName: !Sub topic-verify-crossaccount-publish-${AWS::AccountId} Tags: - Key: Use Value: Verify - Key: CfnStackName Value: !Ref AWS::StackName VerifyCrossAccontPublishTopicPolicy: Type: AWS::SNS::TopicPolicy Properties: PolicyDocument: Statement: - Sid: crossAccountAccess Effect: Allow Principal: AWS: !Ref CrossAccountAccessID Action: - sns:Publish Resource: !Ref VerifyCrossAccontPublishTopic Topics: - !Ref VerifyCrossAccontPublishTopic Outputs: OutputsNameforVerifyCrossAccontPublishTopic: Value: !GetAtt VerifyCrossAccontPublishTopic.TopicName OutputsArnforVerifyCrossAccontPublishTopic: Value: !Ref VerifyCrossAccontPublishTopic
参考:
AWS::SNS::Topic - AWS CloudFormation
AWS::SNS::TopicPolicy - AWS CloudFormation
菅谷 歩 (記事一覧)