MackerelのAWSインテグレーションで必要なRoleをCloudFormation一撃で作ってみる(外部ID, SES, StepFunctions対応)

AWS事業本部 梶原@福岡オフィスです。以前

https://dev.classmethod.jp/cloud/mackerel-aws-role-cloudformation/

Mackerelで自分が監視したいサービスのReadOnly権限を選んで作成できるCloudFormationテンプレートを作りました!!! そう、後から別のサービスの監視追加をしたい時は、テンプレートの更新をしてパラメータを変更すればいいだけです。(すばら

と言ってたら、

「外部IDの更新ができないよ。」

という声をきいて、更新しようと調べていたら、いつの間にか、SESとStepFunctionsがAWS Integrationに追加されていたので勢いあまって追加更新しました。

https://mackerel.io/ja/blog/archive/2019/05/29

割り当てるロールの権限などはMackerelの公式ドキュメントに沿っています。 https://mackerel.io/ja/docs/entry/integrations/aws

ということで、さくさく行きます。

※API Gatewayのリソースは東京リージョン(ap-northeast-1::/*)としてますので、他のリージョンの場合は適時変更ください

MackerelのAWSインテグレーションの作成

1. AWSコンソールにログイン

https://ap-northeast-1.console.aws.amazon.com/console/home?region=ap-northeast-1#

2. このボタンをポチっとする。

3. Mackerel のAWS Integrationの作成のページから外部IDを取得して設定する(New!)

https://mackerel.io/my?tab=awsIntegration

CloudFormationのパラメータのExternalIdに入力する

4. CloudFormationのパラメータで監視が必要なサービスを選択(true)にする。

パラメータのデフォルト設定ではEC2, RDS, Redshift, CloudFront, Lambdaを有効にしています ので、監視したいサービスをtrueまたは、監視しない(権限を渡したくない)場合はfalseに変更してください

※全部選んで(10くらい)、エラーが発生した場合は、ポリシーの上限緩和を実施しているかご確認ください。また、必要に応じて上限緩和をおこなってください。

5. CloudFormationの実行をします。

□AWS CloudFormation によって IAM リソースがカスタム名で作成される場合があることを承認します。
のチェックをいれてください

6. OutputにMackerel用のRoleのArnがでてくる

メモります。

7. MackerelのAWSインテグレーションの作成画面にもどってOutputのRoleのArnを設定します。

ここで作成 -> https://mackerel.io/my?tab=awsIntegration

上でコピーしたARNを入れます。

リージョンを選択します。有効な場合はロールArnの横に☑がつくので確認してください。

8. 監視する

で、後は、Mackerelで、いい感じに監視しちゃってください!(今年2度目)

監視方法はdevelopre.IOのMackerel特集などをご参考に
https://dev.classmethod.jp/?s=mackerel

まとめ

割り当てるロールの権限などはMackerelの公式ドキュメントに沿っています。 https://mackerel.io/ja/docs/entry/integrations/aws

Mackerelは更新が速いので、ほんとこれ・・・ CloudFormationのスタックのアップデートでできるようにしといてよかった。 外部IDの更新により、セキュリティは向上していますので、これからも積極的に対応していきたいです。

自分でRoleつくるって、ちょっとハードル高いと思ってるので、少し低くできたらなら幸いです。 Cloudfromtaionのパラメータでの条件設定、Role作成の分岐などもご参考になれば。

テンプレートはこちら

AWSTemplateFormatVersion: "2010-09-09"
Description: "IAM Assume Role for Mackerel"
Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Label:
          default: "External ID"
        Parameters:
          - ExternalId
      - Label:
          default: "Compute"
        Parameters:
          - AmazonEC2ReadOnlyAccess
          - ECSReadOnlyAccess
          - AWSLambdaReadOnlyAccess
      - Label:
          default: "Storage"
        Parameters:
          - AmazonS3ReadOnlyAccess
      - Label:
          default: "Database"
        Parameters:
          - AmazonRDSReadOnlyAccess
          - AmazonDynamoDBReadOnlyAccess
          - AmazonElastiCacheReadOnlyAccess
          - AmazonRedshiftReadOnlyAccess
      - Label:
          default: "Networking & Content Delivery"
        Parameters:
          - CloudFrontReadOnlyAccess
          - APIGatewayReadOnlyAccess
      - Label:
          default: "Analytics"
        Parameters:
          - AmazonKinesisReadOnlyAccess
          - AmazonESReadOnlyAccess
      - Label:
          default: "Application Integration"
        Parameters:
          - AWSStepFunctionsReadOnlyAccess
          - AmazonSQSReadOnlyAccess
      - Label:
          default: "Customer Engagement"
        Parameters:
          - AmazonSESReadOnlyAccess
      - Label:
          default: "Management & Governance"
        Parameters:
          - CloudWatchReadOnlyAccess
    ParameterLabels:
      ExternalId:
        default: "Mackerel AWS Integration External Id"
      AmazonEC2ReadOnlyAccess:
        default: "EC2, ELB (CLB), ALB, NLB"
      ECSReadOnlyAccess:
        default: "ECS"
      AWSLambdaReadOnlyAccess:
        default: "Lambda"
      AmazonS3ReadOnlyAccess:
        default: "S3"
      AmazonRDSReadOnlyAccess:
        default: "RDS"
      AmazonDynamoDBReadOnlyAccess:
        default: "DynamoDB"
      AmazonElastiCacheReadOnlyAccess:
        default: "ElastiCache"
      AmazonRedshiftReadOnlyAccess:
        default: "Redshift"
      CloudFrontReadOnlyAccess:
        default: "CloudFront"
      APIGatewayReadOnlyAccess:
        default: "API Gateway"
      AmazonKinesisReadOnlyAccess:
        default: "Kinesis"
      AmazonESReadOnlyAccess:
        default: "ES"
      AmazonSQSReadOnlyAccess:
        default: "SQS"
      AmazonSESReadOnlyAccess:
        default: "SES"
      AWSStepFunctionsReadOnlyAccess:
        default: "Step Functions"
      CloudWatchReadOnlyAccess:
        default: "CloudWatch"
Parameters:
  ExternalId:
    Description: Please update External ID (https://mackerel.io/my?tab=awsIntegration)
    Default: Mackerel-AWS-Integration
    Type: String
  AmazonEC2ReadOnlyAccess:
    Description: Monitoring EC2
    Type: String
    Default: yes
    AllowedValues: [yes, no]
  AmazonRDSReadOnlyAccess:
    Description: Monitoring RDS
    Type: String
    Default: yes
    AllowedValues: [yes, no]
  AmazonElastiCacheReadOnlyAccess:
    Description: Monitoring ElastiCache
    Type: String
    Default: yes
    AllowedValues: [yes, no]
  AmazonRedshiftReadOnlyAccess:
    Description: Monitoring Redshift
    Type: String
    Default: no
    AllowedValues: [yes, no]
  AWSLambdaReadOnlyAccess:
    Description: Monitoring AWS Lambda
    Type: String
    Default: no
    AllowedValues: [yes, no]
  AmazonSQSReadOnlyAccess:
    Description: Monitoring SQS
    Type: String
    Default: no
    AllowedValues: [yes, no]
  AmazonDynamoDBReadOnlyAccess:
    Description: Monitoring DynamoDB
    Type: String
    Default: no
    AllowedValues: [yes, no]
  CloudFrontReadOnlyAccess:
    Description: Monitoring CloudFront
    Type: String
    Default: no
    AllowedValues: [yes, no]
  APIGatewayReadOnlyAccess:
    Description: Monitoring API Gateway (apigateway:GET, apigateway:OPTIONS)
    Type: String
    Default: no
    AllowedValues: [yes, no]
  AmazonKinesisReadOnlyAccess:
    Description: Monitoring Kinesis
    Type: String
    Default: no
    AllowedValues: [yes, no]
  AmazonS3ReadOnlyAccess:
    Description: Monitoring S3
    Type: String
    Default: no
    AllowedValues: [yes, no]
  AmazonESReadOnlyAccess:
    Description: Monitoring ES
    Type: String
    Default: no
    AllowedValues: [yes, no]
  ECSReadOnlyAccess:
    Description: Monitoring ECS (ecs:Describe*, ecs:List*)
    Type: String
    Default: no
    AllowedValues: [yes, no]
  AmazonSESReadOnlyAccess:
    Description: Monitoring SES (ses:Describe*)
    Type: String
    Default: no
    AllowedValues: [yes, no]
  AWSStepFunctionsReadOnlyAccess:
    Description: Monitoring Step Functions
    Type: String
    Default: no
    AllowedValues: [yes, no]
  CloudWatchReadOnlyAccess:
    Description: Monitoring CloudWatch (if CloudFront only, API Gateway only, Kinesis only, S3 only, ES only, ECS only, SES only, Step Functions only)
    Type: String
    Default: no
    AllowedValues: [yes, no]
Conditions:
  AmazonEC2ReadOnlyAccess: !Equals [ !Ref AmazonEC2ReadOnlyAccess, yes ]
  AmazonRDSReadOnlyAccess: !Equals [ !Ref AmazonRDSReadOnlyAccess, yes ]
  AmazonElastiCacheReadOnlyAccess: !Equals [ !Ref AmazonElastiCacheReadOnlyAccess, yes ]
  AmazonRedshiftReadOnlyAccess: !Equals [ !Ref AmazonRedshiftReadOnlyAccess, yes ]
  AWSLambdaReadOnlyAccess: !Equals [ !Ref AWSLambdaReadOnlyAccess, yes ]
  AmazonSQSReadOnlyAccess: !Equals [ !Ref AmazonSQSReadOnlyAccess, yes ]
  AmazonDynamoDBReadOnlyAccess: !Equals [ !Ref AmazonDynamoDBReadOnlyAccess, yes ]
  CloudFrontReadOnlyAccess: !Equals [ !Ref CloudFrontReadOnlyAccess, yes ]
  APIGatewayReadOnlyAccess: !Equals [ !Ref APIGatewayReadOnlyAccess, yes ]
  AmazonKinesisReadOnlyAccess: !Equals [ !Ref AmazonKinesisReadOnlyAccess, yes ]
  AmazonS3ReadOnlyAccess: !Equals [ !Ref AmazonS3ReadOnlyAccess, yes ]
  AmazonESReadOnlyAccess: !Equals [ !Ref AmazonESReadOnlyAccess, yes ]
  ECSReadOnlyAccess: !Equals [ !Ref ECSReadOnlyAccess, yes ]
  AmazonSESReadOnlyAccess: !Equals [ !Ref AmazonSESReadOnlyAccess, yes ]
  AWSStepFunctionsReadOnlyAccess: !Equals [ !Ref AWSStepFunctionsReadOnlyAccess, yes ]
  CloudWatchReadOnlyAccess: !Equals [ !Ref CloudWatchReadOnlyAccess, yes ]
Resources:
  MackerelAWSIntegrationRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: "MackerelAWSIntegrationRole"
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
        - Action: "sts:AssumeRole"
          Effect: "Allow"
          Principal:
              AWS: "arn:aws:iam::217452466226:root"
          Condition:
            StringEquals:
              sts:ExternalId: !Ref ExternalId
      ManagedPolicyArns:
        - !If [AmazonEC2ReadOnlyAccess, "arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess", !Ref "AWS::NoValue"]
        - !If [AmazonRDSReadOnlyAccess, "arn:aws:iam::aws:policy/AmazonRDSReadOnlyAccess", !Ref "AWS::NoValue"]
        - !If [AmazonElastiCacheReadOnlyAccess, "arn:aws:iam::aws:policy/AmazonElastiCacheReadOnlyAccess", !Ref "AWS::NoValue"]
        - !If [AmazonRedshiftReadOnlyAccess, "arn:aws:iam::aws:policy/AmazonRedshiftReadOnlyAccess", !Ref "AWS::NoValue"]
        - !If [AWSLambdaReadOnlyAccess, "arn:aws:iam::aws:policy/AWSLambdaReadOnlyAccess", !Ref "AWS::NoValue"]
        - !If [AmazonSQSReadOnlyAccess, "arn:aws:iam::aws:policy/AmazonSQSReadOnlyAccess", !Ref "AWS::NoValue"]
        - !If [AmazonDynamoDBReadOnlyAccess, "arn:aws:iam::aws:policy/AmazonDynamoDBReadOnlyAccess", !Ref "AWS::NoValue"]
        - !If [CloudFrontReadOnlyAccess, "arn:aws:iam::aws:policy/CloudFrontReadOnlyAccess", !Ref "AWS::NoValue"]
        - !If [AmazonKinesisReadOnlyAccess, "arn:aws:iam::aws:policy/AmazonKinesisReadOnlyAccess", !Ref "AWS::NoValue"]
        - !If [AmazonS3ReadOnlyAccess, "arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess", !Ref "AWS::NoValue"]
        - !If [AmazonESReadOnlyAccess, "arn:aws:iam::aws:policy/AmazonESReadOnlyAccess", !Ref "AWS::NoValue"]
        - !If [AWSStepFunctionsReadOnlyAccess, "arn:aws:iam::aws:policy/AWSStepFunctionsReadOnlyAccess", !Ref "AWS::NoValue"]
        - !If [CloudWatchReadOnlyAccess, "arn:aws:iam::aws:policy/CloudWatchReadOnlyAccess", !Ref "AWS::NoValue"]
  APIGatewayGetPolicy:
    Condition: APIGatewayReadOnlyAccess
    Type: AWS::IAM::Policy
    Properties:
      PolicyName: "APIGatewayGetPolicy"
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Action:
              - apigateway:GET
              - apigateway:OPTIONS
            Resource: arn:aws:apigateway:ap-northeast-1::/*
      Roles:
        - !Ref MackerelAWSIntegrationRole
  ECSDescribePolicy:
    Condition: ECSReadOnlyAccess
    Type: AWS::IAM::Policy
    Properties:
      PolicyName: "ECSDescribePolicy"
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Action:
              - ecs:Describe*
              - ecs:List*
            Resource: "*"
      Roles:
        - !Ref MackerelAWSIntegrationRole
  SESDescribePolicy:
    Condition: AmazonSESReadOnlyAccess
    Type: AWS::IAM::Policy
    Properties:
      PolicyName: "SESDescribePolicy"
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Action:
              - ses:Describe*
            Resource: "*"
      Roles:
        - !Ref MackerelAWSIntegrationRole
Outputs:
  MackerelAWSIntegrationRoleArn:
    Value: !GetAtt MackerelAWSIntegrationRole.Arn

参考URL