はじめに
CloudWatch cross-account observabilityは、複数のアカウントのCloudWatchのデータを、一つのアカウントで集約して閲覧可能になる機能です。
単に集約するというだけでなく、本番環境に直接入ることなくメトリクスやログなどを確認するという用途にも使えます。
https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-Unified-Cross-Account.html
複数アカウント環境において監視する際にとても便利な機能なのですが、各リージョンごとに設定しないといけないという点が大きな手間です。
複数リージョンと複数アカウントといえばCloudFormationのStackSetということで、StackSetでまとめて展開していきます。
手順
最終的にできあがる全体図はこちらです。
CloudWatchのデータを提供する側をソースアカウント(222222222222
)、そのデータの監視を行う側をモニタリングアカウント(111111111111
)として、以降進めます。
1. IAM Roleの準備
StackSet用のIAM Roleを、モニタリングアカウントとソースアカウントとの両方に作成します。
モニタリングアカウント
StackSetには、service-managed
とself-managed
という二つの実行方法があります。
前者のservice-managed
はOrganizationのCloudFormation委任アカウントで使用するものです、
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stacksets-orgs-delegated-admin.html
今回は、委任アカウントではないであろうモニタリングアカウントでStackSetを実行したいので、後者のself-managed
タイプを使用します。
self-managed
の場合、Stackとリソースの作成を実際に行うexecution role
と、execution role
へAssumeRoleする権限を持つadmin role
の二つのIAM Roleが必要です。
CloudFormationで作成する場合はこちら
AWSTemplateFormatVersion: "2010-09-09"
Description: IAM roles for CloudWatch cross-account observability
Resources:
AdminRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Principal:
Service: "cloudformation.amazonaws.com"
Action: "sts:AssumeRole"
Policies:
- PolicyName: AssumeRole
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Action:
- "sts:AssumeRole"
Resource: "*"
SinkStackSetExecutionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Principal:
AWS:
- !GetAtt AdminRole.Arn
Action:
- "sts:AssumeRole"
Policies:
- PolicyName: policies
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Resource: !GetAtt AdminRole.Arn
Action:
- iam:PassRole
- Effect: Allow
Resource: "*"
Action:
- oam:CreateSink
- oam:DeleteSink
- oam:GetSink
- oam:GetSinkPolicy
- oam:PutSinkPolicy
- cloudformation:GetTemplateSummary
- cloudformation:DescribeStackSet
- cloudformation:DescribeStacks
- cloudformation:DescribeStackSetOperation
- cloudformation:DeleteStackSet
- cloudformation:DeleteStack
- cloudformation:CreateStackSet
- cloudformation:CreateStack
- cloudformation:UpdateStackSet
- cloudformation:UpdateStack
- cloudformation:CreateStackInstances
- cloudformation:DeleteStackInstances
- cloudformation:UpdateStackInstances
- cloudformation:DescribeStackInstance
admin role
前述の通り、execution role
へAssumeRoleするだけのIAM Roleです。
今回はResource: "*"
としていて、AssumeRole先を制限していません。
trust policy
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "cloudformation.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
permission policy
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"sts:AssumeRole"
],
"Resource": "*",
"Effect": "Allow"
}
]
}
execution role
admin role
からAssumeRoleされる側その一です。
trust policy
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111111111111:role/IAMRolesForCrossAccountObservability-AdminRole"
},
"Action": "sts:AssumeRole"
}
]
}
ポリシーでは、主に三つの権限を付与しています。
- iam:PassRole
ややこしいのですが、StackSetで作成したStackの中から、さらにStackSetを作成します。
そのため、二つ目のStackSetを実行する際に、admin role
をPassRoleする権限が必要となります。 - oam
モニタリングアカウント側でcross-account observabilityの設定をする権限です。 - CloudFormation
StackとStackSetを管理する権限を付与しています。
permission policy
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"iam:PassRole"
],
"Resource": "arn:aws:iam::111111111111:role/IAMRolesForCrossAccountObservability-AdminRole",
"Effect": "Allow"
},
{
"Action": [
"oam:CreateSink",
"oam:DeleteSink",
"oam:GetSink",
"oam:GetSinkPolicy",
"oam:PutSinkPolicy",
"cloudformation:GetTemplateSummary",
"cloudformation:DescribeStackSet",
"cloudformation:DescribeStacks",
"cloudformation:DescribeStackSetOperation",
"cloudformation:DeleteStackSet",
"cloudformation:DeleteStack",
"cloudformation:CreateStackSet",
"cloudformation:CreateStack",
"cloudformation:UpdateStackSet",
"cloudformation:UpdateStack",
"cloudformation:CreateStackInstances",
"cloudformation:DeleteStackInstances",
"cloudformation:UpdateStackInstances",
"cloudformation:DescribeStackInstance"
],
"Resource": "*",
"Effect": "Allow"
}
]
}
ソースアカウント
モニタリングアカウントのStackSetが使用するIAM Role(execution role
)を用意します。
ソースアカウントが複数ある場合は、IAM Role名を共通にしておく必要がありますので、ご注意ください。
CloudFormationで作成する場合はこちら
AWSTemplateFormatVersion: 2010-09-09
Description: IAM Role for CloudWatch cross-account observability
Parameters:
MonitoringAccountId:
Type: String
MaxLength: "12"
MinLength: "12"
ExecutionRoleName:
Type: String
Default: CloudWatchCrossAccountObservabilityExecutionRole
Resources:
ExecutionRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Ref ExecutionRoleName
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
AWS:
- !Ref MonitoringAccountId
Action:
- sts:AssumeRole
Policies:
- PolicyName: CloudWatchCrossAccountObservability
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- oam:CreateLink
- oam:UpdateLink
- oam:DeleteLink
- oam:GetLink
- oam:TagResource
Resource: arn:*:oam:*:*:link/*
- Effect: Allow
Action:
- oam:CreateLink
- oam:UpdateLink
Resource: arn:*:oam:*:*:sink/*
Condition:
StringEquals:
aws:ResourceAccount: !Ref MonitoringAccountId
- Effect: Allow
Action:
- oam:ListLinks
- cloudwatch:Link
- cloudformation:DescribeStacks
- cloudformation:DeleteStack
- cloudformation:CreateStack
- cloudformation:UpdateStack
Resource: "*"
trust policyでは、モニタリングアカウントのadmin role
を許可します。
admin role
の名前が決まっている場合は、arn:aws:iam::111111111111:root
のところにRole arnを入れることで、アクセス制限を強められます。
trust policy
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111111111111:root"
},
"Action": "sts:AssumeRole"
}
]
}
ソースアカウント側で必要な権限は主に二つです。
- oam
ソースアカウント側でcross-account observabilityの設定をする権限です。 - cloudformation
モニタリングアカウント側のStackSetからの設定をもとに、ソースアカウント側にStackを作成する権限です。
permission policy
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"oam:CreateLink",
"oam:UpdateLink",
"oam:DeleteLink",
"oam:GetLink",
"oam:TagResource"
],
"Resource": "arn:*:oam:*:*:link/*",
"Effect": "Allow"
},
{
"Condition": {
"StringEquals": {
"aws:ResourceAccount": "111111111111"
}
},
"Action": [
"oam:CreateLink",
"oam:UpdateLink"
],
"Resource": "arn:*:oam:*:*:sink/*",
"Effect": "Allow"
},
{
"Action": [
"oam:ListLinks",
"cloudwatch:Link",
"cloudformation:DescribeStacks",
"cloudformation:DeleteStack",
"cloudformation:CreateStack",
"cloudformation:UpdateStack"
],
"Resource": "*",
"Effect": "Allow"
}
]
}
2. StackSet作成
まずはCloudFormationテンプレートを紹介します。
AWSTemplateFormatVersion: "2010-09-09"
Description: Cross-Account Observability
Parameters:
SinkName:
Type: String
Default: Sink
SourceAccountIds:
Type: List<String>
StackSetName:
Type: String
Default: CloudWatchCrossAccountObservability
AdministrationRoleARN:
Type: String
ExecutionRoleName:
Type: String
Default: CloudWatchCrossAccountObservabilityExecutionRole
Resources:
Sink:
Type: AWS::Oam::Sink
Properties:
Name: !Ref SinkName
Policy:
Statement:
- Effect: Allow
Action:
- oam:CreateLink
- oam:UpdateLink
Resource: "*"
Principal:
AWS: !Ref SourceAccountIds
Condition:
ForAllValues:StringEquals:
oam:ResourceTypes: AWS::CloudWatch::Metric
SourceAccount:
Type: AWS::CloudFormation::StackSet
Properties:
PermissionModel: SELF_MANAGED
StackSetName: !Ref StackSetName
AdministrationRoleARN: !Ref AdministrationRoleARN
ExecutionRoleName: !Ref ExecutionRoleName
TemplateBody: |
AWSTemplateFormatVersion: 2010-09-09
Parameters:
DestinationAccountId:
Type: String
SinkArn:
Type: String
Conditions:
SkipMonitoringAccount: !Not
- !Equals
- !Ref AWS::AccountId
- !Ref DestinationAccountId
Resources:
Link:
Type: AWS::Oam::Link
Condition: SkipMonitoringAccount
Properties:
LabelTemplate: "$AccountName"
ResourceTypes:
- "AWS::CloudWatch::Metric"
SinkIdentifier: !Ref SinkArn
Parameters:
- ParameterKey: DestinationAccountId
ParameterValue: !Ref AWS::AccountId
- ParameterKey: SinkArn
ParameterValue: !GetAtt Sink.Arn
StackInstancesGroup:
- DeploymentTargets:
Accounts: !Ref SourceAccountIds
Regions:
- !Ref AWS::Region
Parameters
必須
-
SourceAccountIds
ソースアカウントのアカウントIDを、カンマ区切りで羅列してください。 -
AdministrationRoleARN
手順1でモニタリングアカウント側に作成したadmin role
のarnを入力してください。 -
ExecutionRoleName
手順1でソースアカウント側に作成したIAM Roleの名前を指定します。
Roleの名前を統一しておく必要があったのは、ここでRole名を一つしか指定できないためです。
任意
-
SinkName
cross-account observabilityの設定名です。
Sink
は各リージョンにひとつずつしか作れないため、名前はなんでも構いません。 -
StackSetName
各リージョンに作成されるStackSetの名前です。
他にStackSetを作成済みの場合、重複しないように変更することが可能です。
構成
直接作成するリソースは二つです。
AWS::Oam::Sink
cross-account observabilityで、モニタリングアカウント側に必要なリソースです。
今回は、メトリクスのみ共有する設定になっています。
AWS::CloudFormation::StackSet
各リージョンにStackを作成したあと、それぞれのリージョンで再びStackSetを作成します。
StackSetを使うことで、別アカウントの同一リージョンに、AWS::Oam::Link
をデプロイします。
AWS::Oam::Link
ソースアカウント側のcross-account observabilityの設定用リソースです。
モニタリングアカウント側で作成したAWS::Oam::Sink
のarnが必要なため、StackSetのパラメータ経由で指定しています。
補足
メトリクス以外を集約したい場合
この記事のCloudFormationテンプレートでは、CloudWatchのうちメトリクスのみ集約されます。
ログなども集約したい場合、手順2 StackSet作成の二箇所に、必要なリソースタイプを追加します。
cross-account observabilityで指定できるリソースタイプの一覧はこちらです。
AWS::Logs::LogGroup
AWS::CloudWatch::Metric
AWS::XRay::Trace
AWS::ApplicationInsights::Application
AWS::InternetMonitor::Monitor
リソースタイプを指定しているのは、モニタリングアカウントとソースアカウントでそれぞれ一箇所ずつです。
-
AWS::Oam::Sink
モニタリングアカウント側に作成されるリソースです。
Sinkにはポリシーを設定していますので、必要なものを追加します。
Condition:
ForAllValues:StringEquals:
oam:ResourceTypes:
- AWS::Logs::LogGroup
- AWS::CloudWatch::Metric
- AWS::XRay::Trace
- AWS::ApplicationInsights::Application
- AWS::InternetMonitor::Monitor
-
AWS::Oam::Link
ソースアカウント側です。
ResrouceTypes
のところに追加します。
ResourceTypes:
- AWS::Logs::LogGroup
- AWS::CloudWatch::Metric
- AWS::XRay::Trace
- AWS::ApplicationInsights::Application
- AWS::InternetMonitor::Monitor
Organization内で展開する場合
ソースアカウントを指定する際、この記事のテンプレートではアカウントIDを全て列挙する必要があります。
しかしStackSetを使用しているため、Organization全体や、Organization内のou(Organizational Unit)単位でのcross-account observabilityの設定も当然可能です。
その場合の修正箇所は、手順2 StackSet作成のテンプレートに定義されているAWS::CloudFormation::StackSet
リソースのパラメータであるStackInstancesGroup
です。
StackInstancesGroup:
- DeploymentTargets:
Accounts: !Ref SourceAccountIds
Regions:
- !Ref AWS::Region
DeploymentTargets
のところで、Accounts
の代わりにOrganizationalUnitIds
を使用して、対象のouを指定します。
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloudformation-stackset-deploymenttargets.html
oamとは
何度かoamという単語が出てきましたが、これはCloudWatch Observability Access Manager
のことのようです。
https://docs.aws.amazon.com/OAM/latest/APIReference/Welcome.html
終わりに
複数リージョンでのcross-account observabilityの設定を楽にするためのCloudFormationテンプレートを紹介しました。