8
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

「セキュアで堅牢なAWSアカウント」を実現する CloudFormationテンプレート - ④アクセスキーのローテーションと削除

Last updated at Posted at 2020-02-05

はじめに

AWSにはアカウントやリソースへの脅威検知に対応した、AWS IAM Access Analyzer, AWS Security Hub, Amazon Detective, Amazon Inspector, Amazon GuardDuty, AWS CloudTrail, AWS Config などのサービスが用意されています。

また、AWS Security Hub では、CIS AWS Foundations Standard , Payment Card Industry Data Security Standard , AWS Foundational Security Best Practices Standard などのセキュリティ標準が公開されており、このガイドラインは、AWSアカウントをセキュアに保つために必要なAWSのセキュリティ設定を集めたベストプラクティス集として活用できます。

本記事では、アカウントやリソースへの脅威検知が可能なAWSサービスを有効化するとともに、上記のセキュリティ標準に限りなく準拠することで、セキュアで堅牢なAWSアカウントを実現します。また、これらをお手軽に実現できるCloudFormationテンプレートを公開しています。

このCloudFormationテンプレートの実行はこちらから。

cloudformation-launch-stack

アクセスキーのローテーション

アクセスキー とは、IAM ユーザーまたは ルートユーザー の 長期的な認証情報を指し、AWS SDK や AWS API を実行する際にこのアクセスキーを指定することで、このアクセスキーに許可された権限を実行することができます。したがって、このアクセスキーが外部に流出した場合には、 第三者がアカウントへの永続的アクセスを取得する可能性 があります。そこで、CIS AWS Foundations Benchmark および AWS Foundational Security Best Practices Standard では、

セキュリティ標準 No. 内容
CIS AWS Foundations Standard 1.3 90 日間以上使用されていない認証情報は無効にします
CIS AWS Foundations Standard 1.4 アクセスキーは 90 日ごとに更新します
AWS Foundational Security Best Practices Standard IAM.3 IAM ユーザーのアクセスキーは 90 日ごとに更新する必要があります。

というガイドラインを規定しており、アクセスキーの定期的なローテーションによって、意図せぬアクセスのリスクを低減するように求めています。

上記ガイドラインに準拠するためには、AWS Config を用いて、定期的に現在の状態の確認 を行う必要があります。また、上記基準を満たしていないことが判明した場合は、当該のアクセスキーを無効化、もしくは削除 する必要があります。

1. AWS Configの有効化

AWS Config を設定して、上記ガイドラインに準拠しているかどうかを定期的に確認します。「セキュアで堅牢なAWSアカウント」を実現する CloudFormationテンプレート - ①サービスの有効化も合わせてご覧ください。

サービスにリンクされたロールの作成

AWS Config で使用する Service-Linked Role を作成します。この Service-Linked Role は、 AWSリソースへの読み込み権限S3への書き込み権限Config に、また、IAMとSystemManagerへの書き込み権限Config Remediation にそれぞれ付与します。

Resources:
  ServiceLinkedRoleForConfig:
    Type: AWS::IAM::ServiceLinkedRole
    UpdateReplacePolicy: Retain
    DeletionPolicy: Retain
    Properties: 
      AWSServiceName: config.amazonaws.com
      Description: A service-linked role required for AWS Config to access your resources.
  ServiceLinkedRoleForConfigRemediation:
    Type: AWS::IAM::ServiceLinkedRole
    UpdateReplacePolicy: Retain
    DeletionPolicy: Retain
    Properties: 
      AWSServiceName: remediation.config.amazonaws.com 
      Description: A service-linked role required for AWS Config Remediation to access your resources.

AWS Configの有効化

AWS ConfigDeliveryChannelConfigurationRecorder を作成します。

Resources:
  ConfigDeliveryChannel:
    Type: AWS::Config::DeliveryChannel
    Properties:
      Name: default
      S3BucketName: !Ref S3ForConfig
  ConfigConfigurationRecorder:
    Type: AWS::Config::ConfigurationRecorder
    Properties:
      Name: default
      RecordingGroup:
        AllSupported: true
        IncludeGlobalResourceTypes: true
      RoleARN: !Sub arn:aws:iam::DefaultSecuritySettings:role/aws-service-role/config.amazonaws.com/AWSServiceRoleForConfig

Amazon S3 バケットを作成

設定情報 (履歴ファイルやスナップショット) を保存するために使用する、Amazon S3 バケットと、それに紐づくバケットポリシーを作成します。

Resources:
  S3ForConfig:
    Type: 'AWS::S3::Bucket'
    UpdateReplacePolicy: Retain
    DeletionPolicy: Retain
    Properties:
      BucketEncryption:
        ServerSideEncryptionConfiguration: 
          - ServerSideEncryptionByDefault: 
              SSEAlgorithm: AES256
      BucketName: !Sub defaultsecuritysettings-config-${AWS::Region}-${AWS::AccountId}
      LifecycleConfiguration:
        Rules:
          - Id: ExpirationInDays
            ExpirationInDays: 60
            Status: Enabled
      PublicAccessBlockConfiguration: 
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true
  S3BucketPolicyForConfig:
    Type: AWS::S3::BucketPolicy
    Properties: 
      Bucket: !Ref S3ForConfig
      PolicyDocument:
        Version: 2012-10-17
        Id: !Ref S3ForConfig
        Statement:
          - Effect: Allow
            Principal:
              Service: config.amazonaws.com
            Action:
              - 's3:GetBucketAcl'
              - 's3:ListBucket'
            Resource:
              - !GetAtt S3ForConfig.Arn
          - Effect: Allow
            Principal:
              Service: config.amazonaws.com
            Action:
              - 's3:PutObject'
            Resource:
              - !Join
                - ''
                - - !GetAtt S3ForConfig.Arn
                  - /AWSLogs/
                  - !Sub ${AWS::AccountId}
                  - /Config/*
            Condition:
              StringEquals:
                s3:x-amz-acl: bucket-owner-full-control
          - Effect: Deny
            Principal: '*'
            Action: 's3:*'
            Resource: 
              - !GetAtt S3ForConfig.Arn
              - !Join
                - ''
                - - !GetAtt S3ForConfig.Arn
                  - /*
            Condition:
              Bool: 
                aws:SecureTransport: false

2. AWS Configを用いた定期チェック

AWSによって管理されている AWS Config マネージドルール の中に、 ACCESS_KEYS_ROTATED という名称で、アクティブなアクセスキーが指定された日数内にローテーションされるかどうかを確認できるルール が用意されているので、これを追加します。

Resources:
  ConfigIamAccessKeysRotated:
    DependsOn:
      - ConfigConfigurationRecorder
    Type: 'AWS::Config::ConfigRule'
    Properties:
      ConfigRuleName: access-keys-rotated
      Description: アクティブなアクセスキーが、maxAccessKeyAge で指定された日数内にローテーションされるかどうかを確認します。
      InputParameters:
        maxAccessKeyAge: 90
      Source:
        Owner: AWS
        SourceIdentifier: ACCESS_KEYS_ROTATED

上記で設定した AWS Config ルールは定期的に実行され、アカウントがこのルールに準拠しているかどうかの判定が行われます。しかし、これらの設定は、ルールに準拠しているかどうかを判定するだけであるため、もしルールに非準拠であることが判明した場合には、該当するアクセスキーを手動で削除する必要があります

3. Lambdaを用いたアクセスキーの強制削除

そこで、以下の内容も設定に加えることで、ガイドラインの基準に違反するアクセスキーを強制的に削除 することができます。ただし下記の設定は、ユーザに確認を求めることなく問答無用にアクセスキーを削除してしまう ため、下記設定を加えるかどうかについては 慎重な検討が必要 です。またもしこの設定を適用する場合でも、ご自身のアカウントの運用ポリシーに合った内容に処理を書き換えることをオススメします

Amazon EventBridgeの追加

AWS Config が発行する Amazon EventBridgeのうち、AWS Configに非準拠のルールが検知された場合のみを抽出して、後述の アクセスキーを強制削除するLambdaの実行トリガ にします。

  CloudWatchEventsForConfigIamAccessKeysRotated:
    Type: 'AWS::Events::Rule'
    Properties: 
      Description: EventBridge about Config when IAM Access Keys are rotated.
      EventPattern:
        source:
          - aws.config
        detail-type: 
          - Config Rules Compliance Change
        detail:
          configRuleName:
            - !Ref ConfigIamAccessKeysRotated
          messageType:
            - ComplianceChangeNotification
          newEvaluationResult:
            complianceType:
              - NON_COMPLIANT
      Name: Config
      State: ENABLED
      Targets:
        - Arn: !GetAtt LambdaDeleteExpiredAccessKeys.Arn
          Id: lambda

Lambda 関数の追加

アクセスキーを強制削除するLambdaを作成します。このLambdaは、AWS Configから通知された内容が、 アクティブなアクセスキーが指定された日数(=90日)内にローテーションされるかどうかを確認できる、access-keys-rotated に関連するものであることを確認した上で、作成から90日が経過したアクセスキーのみを削除 します。

  LambdaDeleteExpiredAccessKeys:
    Type: 'AWS::Lambda::Function'
    Properties:
      Code:
        ZipFile: |
          import boto3
          import datetime
          import time
          import logging
          logger = logging.getLogger()
          logger.setLevel(logging.INFO)
          def lambda_handler(event, context):
              logger.info(str(event))
            
              if 'detail' in event:
                  detail = event['detail']
                  if 'configRuleName' in detail:
                      # access-keys-rotated
                      if detail['configRuleName'] == 'access-keys-rotated':
                          iam = boto3.client('iam')
                          users = iam.list_users()
                          for user in users['Users']:
                              if detail['resourceId'] == user['UserId']:
                                  access_keys = iam.list_access_keys(
                                      UserName=user['UserName']
                                      )
                                  for access_key in access_keys['AccessKeyMetadata']:
                                      create_date = access_key['CreateDate'].timestamp()
                                      now = time.time()
                                      if now - create_date > 60*60*24*90:
                                          response = iam.delete_access_key(
                                              UserName=user['UserName'],
                                              AccessKeyId=access_key['AccessKeyId']
                                          )
      Description: 有効期限が過ぎたアクセスキーを削除します
      FunctionName: deleteExpiredAccessKeys
      Handler: index.lambda_handler
      MemorySize: 128
      Role: !GetAtt IAMRoleForLambda.Arn
      Runtime: python3.7
      Tags:
        - Key: !Ref TagKey
          Value: !Ref TagValue
      Timeout: 3
      TracingConfig:
        Mode: Active
  LambdaDeleteExpiredAccessKeysPermission:
    Type: 'AWS::Lambda::Permission'
    Properties:
      Action: lambda:InvokeFunction
      FunctionName: !Ref LambdaDeleteExpiredAccessKeys
      Principal: events.amazonaws.com
      SourceArn: !GetAtt CloudWatchEventsForConfigIamAccessKeysRotated.Arn
  LambdaDeleteExpiredAccessKeysLogGroup:
    Type: AWS::Logs::LogGroup
    Properties: 
      LogGroupName: !Sub /aws/lambda/${LambdaDeleteExpiredAccessKeys}
      RetentionInDays: 60

下記のCloudFormationテンプレートを実行することで、上記設定を含む、 AWS IAM Access Analyzer, AWS Security Hub, Amazon Detective, Amazon Inspector, Amazon GuardDuty, AWS CloudTrail, AWS Config などのサービス全てを有効化することも、今回の設定を含むAWS Configのみを有効化することも可能です。

作成されるAWSサービス CloudFormationテンプレート
全てのセキュリティサービス cloudformation-launch-stack
AWS Configのみ cloudformation-launch-stack

関連リンク

  1. サービスの有効化 - 「セキュアで堅牢なAWSアカウント」を実現する CloudFormationテンプレート
  2. パスワードポリシーの自動修復 - 「セキュアで堅牢なAWSアカウント」を実現する CloudFormationテンプレート
  3. モニタリングと通知の設定 - 「セキュアで堅牢なAWSアカウント」を実現する CloudFormationテンプレート
  4. アクセスキーのローテーションと削除 - 「セキュアで堅牢なAWSアカウント」を実現する CloudFormationテンプレート
  5. 全てのVPCでフローログを有効化する - 「セキュアで堅牢なAWSアカウント」を実現する CloudFormationテンプレート
  6. SSHとRDPのアクセスを制限する - 「セキュアで堅牢なAWSアカウント」を実現する CloudFormationテンプレート
  7. デフォルトセキュリティグループを無効化する - 「セキュアで堅牢なAWSアカウント」を実現する CloudFormationテンプレート
  8. S3バケットのサーバサイド暗号化 - セキュアで堅牢なAWSアカウント」を実現する CloudFormationテンプレート
8
5
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
8
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?