0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

CloudWatch cross-account observabilityを、CloudFormation StackSetsで複数リージョンに展開する

Last updated at Posted at 2024-10-02

はじめに

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-managedself-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が必要です。
スクリーンショット 2024-09-05 9.36.22.png

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テンプレートを紹介しました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?