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?

AWS ConfigをCloudFormationで有効化する際のハマりポイント2選

0
Posted at

AWS ConfigをCloudFormationで有効化する際のハマりポイント2選

AWS ConfigをCloudFormationで構築する際に躓いたポイントをまとめます。
同じエラーで困っている方の参考になれば幸いです。

環境

  • AWS CloudFormation
  • AWS Config(初回有効化)

ハマりポイント① サービスリンクロールが自動作成されない

発生したエラー

Resource handler returned message: "Service role name AWSServiceRoleForConfig 
has been taken in this account, please try a different suffix."

または、ConfigurationRecorderが30分以上 CREATE_IN_PROGRESS のまま止まる。

原因

AWS ConfigはIAMサービスリンクロール(AWSServiceRoleForConfig)を使用しますが、
AWSのサービスを初めて使うアカウントではこのロールが存在しない場合があります。

存在しない状態でConfigurationRecorderを作成しようとすると処理が止まります。

解決策

CloudFormationテンプレートに AWS::IAM::ServiceLinkedRole を追加してロールを明示的に作成します。

ConfigServiceLinkedRole:
  Type: AWS::IAM::ServiceLinkedRole
  Properties:
    AWSServiceName: config.amazonaws.com
    Description: "Service-linked role for AWS Config"

注意点

一度スタックが作成に成功すると AWSServiceRoleForConfig がアカウントに残ります。
その状態で再度スタックを作成しようとすると「すでに存在する」エラーが発生します。

対処法: 2回目以降のスタック作成時は AWS::IAM::ServiceLinkedRole のリソース定義をテンプレートから削除してください。

ハマりポイント② ConfigurationRecorder と DeliveryChannel の循環依存

発生したエラー(パターンA)

DeliveryChannel → ConfigurationRecorder の順で作成しようとした場合:

Configuration recorder is not available to put delivery channel.
(NoAvailableConfigurationRecorderException)

発生したエラー(パターンB)

ConfigurationRecorder → DeliveryChannel の順で作成しようとした場合:

Delivery channel is not available to start configuration recorder.
(NoAvailableDeliveryChannelException)

原因

AWS::Config::ConfigurationRecorderAWS::Config::DeliveryChannel
お互いに循環依存の関係にあります。

AWSのドキュメントには「ConfigurationRecorderを先に作成せよ」と記載がありますが、
実際には DependsOn で順番を制御するとどちらの順番でもエラーになります。

参考:aws/aws-cdk Issue #3577

解決策

ConfigurationRecorderDeliveryChannel はお互いに DependsOn してはいけません。
両リソースともS3バケットポリシーにのみ依存させ、CloudFormationに並列で作成させます。

# ✅ 正しい依存関係
ConfigurationRecorder:
  Type: AWS::Config::ConfigurationRecorder
  DependsOn:
    - ConfigBucketPolicy  # S3のみに依存
  Properties:
    ...

DeliveryChannel:
  Type: AWS::Config::DeliveryChannel
  DependsOn:
    - ConfigBucketPolicy  # S3のみに依存(ConfigurationRecorderへの依存はNG)
  Properties:
    ...
# ❌ NG例その1:DeliveryChannel が ConfigurationRecorder に依存
DeliveryChannel:
  DependsOn:
    - ConfigurationRecorder  # → NoAvailableConfigurationRecorderException

# ❌ NG例その2:ConfigurationRecorder が DeliveryChannel に依存
ConfigurationRecorder:
  DependsOn:
    - DeliveryChannel  # → NoAvailableDeliveryChannelException

最終的に動作したテンプレート全文

※SecurityHubCSPM検証用です。

AWSTemplateFormatVersion: "2010-09-09"
Description: >
  AWS Config baseline. Creates DeliveryChannel/Recorder,
  uses existing AWSServiceRoleForConfig (does NOT create ServiceLinkedRole).

Parameters:
  ConfigBucketName:
    Type: String
    Description: "Globally unique S3 bucket name for AWS Config delivery (3-63 chars, lowercase letters, numbers, hyphens, dots)."
    MinLength: 3
    MaxLength: 63
    AllowedPattern: "^[a-z0-9][a-z0-9.-]*[a-z0-9]$"
    ConstraintDescription: "3〜63文字。小文字英数字・ハイフン・ドットのみ使用可。先頭・末尾は英数字。"

  ConfigBucketPrefix:
    Type: String
    Default: aws-config
    Description: "Prefix for AWS Config objects in the bucket. Do NOT include leading/trailing '/'."
    AllowedPattern: "^[A-Za-z0-9][A-Za-z0-9._-]*$"
    ConstraintDescription: "Use only letters/numbers/._- and do not start with '/'. Do not include '/'."

Resources:
  ConfigBucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Ref ConfigBucketName
      BucketEncryption:
        ServerSideEncryptionConfiguration:
          - ServerSideEncryptionByDefault:
              SSEAlgorithm: AES256
      VersioningConfiguration:
        Status: Enabled
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true

  ConfigBucketPolicy:
    Type: AWS::S3::BucketPolicy
    DependsOn: ConfigBucket
    Properties:
      Bucket: !Ref ConfigBucket
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Sid: AWSConfigBucketPermissionsCheck
            Effect: Allow
            Principal:
              Service: config.amazonaws.com
            Action: s3:GetBucketAcl
            Resource: !GetAtt ConfigBucket.Arn

          - Sid: AWSConfigBucketDelivery
            Effect: Allow
            Principal:
              Service: config.amazonaws.com
            Action: s3:PutObject
            Resource: !Sub "${ConfigBucket.Arn}/${ConfigBucketPrefix}/AWSLogs/${AWS::AccountId}/Config/*"
            Condition:
              StringEquals:
                s3:x-amz-acl: bucket-owner-full-control

  # ConfigurationRecorder と DeliveryChannel は循環依存のため
  # お互いに DependsOn してはいけない。両方ともS3にのみ依存させる。
  ConfigurationRecorder:
    Type: AWS::Config::ConfigurationRecorder
    DependsOn:
      - ConfigBucketPolicy
    Properties:
      Name: default
      RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/config.amazonaws.com/AWSServiceRoleForConfig
      RecordingGroup:
        AllSupported: false
        IncludeGlobalResourceTypes: false
        ResourceTypes:
          - AWS::CloudFront::Distribution
          - AWS::ElasticLoadBalancingV2::LoadBalancer
          - AWS::ElasticLoadBalancingV2::Listener
          - AWS::ElasticLoadBalancingV2::TargetGroup
          - AWS::EC2::Instance
          - AWS::EC2::SecurityGroup
          - AWS::EC2::NetworkInterface
          - AWS::EC2::VPC
          - AWS::EC2::Subnet
          - AWS::EC2::RouteTable
          - AWS::EC2::NetworkAcl
          - AWS::EC2::InternetGateway
          - AWS::EC2::NatGateway
          - AWS::EC2::EIP
          - AWS::EC2::Volume
          - AWS::EC2::FlowLog
          - AWS::S3::Bucket
          - AWS::RDS::DBInstance
          - AWS::RDS::DBSubnetGroup

  DeliveryChannel:
    Type: AWS::Config::DeliveryChannel
    DependsOn:
      - ConfigBucketPolicy
    Properties:
      Name: default
      S3BucketName: !Ref ConfigBucket
      S3KeyPrefix: !Ref ConfigBucketPrefix

Outputs:
  ConfigBucketOut:
    Value: !Ref ConfigBucket
  DeliveryChannelOut:
    Value: default
  RecorderOut:
    Value: default
  RoleArnUsed:
    Value: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/config.amazonaws.com/AWSServiceRoleForConfig

まとめ

ハマりポイント 原因 解決策
ConfigurationRecorderが止まる AWSServiceRoleForConfigが存在しない AWS::IAM::ServiceLinkedRole をテンプレートに追加
どちらの順番でもエラーになる ConfigurationRecorderとDeliveryChannelの循環依存 お互いに DependsOn せず、両方をS3にのみ依存させる

CloudFormationに慣れていると DependsOn で順番制御しようとしてしまいがちですが、
AWS Config特有の仕様として覚えておくと良さそうです。

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?