廃止予定のS3署名バージョン2API利用をCloudWatchEventで検出してみた

はじめに

AWSチームのすずきです。

Amazon S3 、APIリクエストの認証時に利用される署名バージョン2の廃止が予定されています。

Amazon S3 における AWS 署名バージョン 2 の廃止

Amazon S3 における署名バージョン 2 は廃止され、署名バージョン 2 の最終サポートは 2019 年 6 月 24 日に終了します。2019 年 6 月 24 日以降、Amazon S3 は署名バージョン 4 を使用して署名された API リクエストのみを受けつけます。

【超重要】対応しないと使えなくなるかも?!今、全S3ユーザがチェックすべき署名バージョン2の廃止について

今回、S3の署名バージョン2廃止により影響を受けるシステムの有無を確認するため、S3のオブジェクト操作ログをCloudTrailで記録し、 署名バージョン2に該当するS3の操作ログが存在した場合 CloudWatchEvent で検出し、Amazon SNS に通知する機会がありましたので、紹介させて頂きます。

CloudWatch Logs Insights を利用した集計、可視化については、以下の記事をご覧ください。

署名バージョン2のS3 APIログをCloudWatchInsightで集計してみた

概要図

参考

チュートリアル: CloudWatch イベント を使用して Amazon S3 オブジェクトレベル操作のログを記録する

設定

CloudTrail

  • 新規CloudTrail証跡を作成、S3のデータイベント(オブジェクトログ)専用に設定しました。

データイベント

  • ログ調査を対象とするS3バケットをデータイベントとして登録します。
  • CloudTrailのログ出力先となるS3バケットをデータイベントとして登録する場合、ログのループを避けるため「/AWSLogs/」を含まないプレフィックスを指定してください。

ストレージの場所

  • CloudTrail 証跡ログ出力先となるS3バケットを新規に作成しました。
  • 別AWSアカウントのS3バケットをCloudTrailのログ出力先として利用する事も可能です。

複数のアカウントから CloudTrail ログファイルを受け取る

  • 別アカウントのS3バケットを利用する事で、データイベント設定で指定できる「アカウントのすべての S3 バケットの選択」、ログがループする事なく利用可能になります。

CloudWatch Event

  • カスタムイベントパターンを反映したルールを作成しました。
  • イベントパターンに一致したS3 APIのログを、ターゲットとして指定したSNSトピックに通知する設定としました。

イベントパターン

{
  "detail-type": [
    "AWS API Call via CloudTrail"
  ],
  "detail": {
    "eventSource": [
      "s3.amazonaws.com"
    ],
    "additionalEventData": {
      "SignatureVersion": [
        "SigV2"
      ]
    }
  }
}

SNS

  • 通知が大量に発生する可能性があったため、メッセージはSQSに転送する設定としました。

SQS

  • SQSに到着したメッセージ数、またはメトリック「NumberOfMessagesSent」を監視する事で、署名バージョン2 を用いた S3 API利用が存在する事を確認可能です。

動作確認

OS

  • S3 APIを署名バージョン2(SigV2)で実行するAmazonLinux (2016.09)を用意しました。
$  cat /etc/system-release
Amazon Linux AMI release 2016.09

CLI

  • AmazonLinux(2016.09)バンドルのAWSCLIを利用しました。
$ aws --version
aws-cli/1.11.29 Python/2.7.12 Linux/4.4.35-33.55.amzn1.x86_64 botocore/1.4.86

S3操作

  • S3 APIのログ設定を有効化したS3バケットに書き込み操作(PutObject)を実施しました。
$ aws s3 cp test s3://<オブジェクトログ設定済みS3バケット>/dummy-0000/

CloudTrailログ確認

  • CloudTrailでログ出力先としたS3の「/AWSLog/」配下にJSON形式のログが出力されました。
{
    "Records": [
        {
            "eventVersion": "1.05",
            "userIdentity": {
                "type": "AssumedRole",
                "principalId": "00000000000000000000:i-000000000000000",
                "arn": "arn:aws:sts::00000000000:assumed-role/ec2-user/i-000000000000000",
                "accountId": "00000000000",
                "accessKeyId": "00000000000000000000",
                "sessionContext": {
                    "sessionIssuer": {
                        "type": "Role",
                        "principalId": "00000000000000000000",
                        "arn": "arn:aws:iam::00000000000:role/ec2-user",
                        "accountId": "00000000000",
                        "userName": "ec2-user"
                    },
                    "attributes": {
                        "creationDate": "2019-03-03T00:00:00Z",
                        "mfaAuthenticated": "false"
                    }
                }
            },
            "eventTime": "2019-03-03T00:00:00Z",
            "eventSource": "s3.amazonaws.com",
            "eventName": "PutObject",
            "awsRegion": "ap-northeast-1",
            "sourceIPAddress": "00.00.00.00",
            "userAgent": "[aws-cli/1.11.29 Python/2.7.12 Linux/4.4.35-33.55.amzn1.x86_64 botocore/1.4.86]",
            "requestParameters": {
                "bucketName": "test-0000-0000",
                "Host": "test-0000-0000.s3.amazonaws.com",
                "key": "dummy-0000/test"
            },
            "responseElements": null,
            "additionalEventData": {
                "SignatureVersion": "SigV2",
                "CipherSuite": "ECDHE-RSA-AES128-GCM-SHA256",
                "bytesTransferredIn": 0,
                "AuthenticationMethod": "AuthHeader",
                "x-amz-id-2": "00000000000",
                "bytesTransferredOut": 0
            },
            "requestID": "00000000000",
            "eventID": "0000-0000-0000-0000-0000",
            "readOnly": false,
            "resources": [
                {
                    "type": "AWS::S3::Object",
                    "ARN": "arn:aws:s3:::test-0000-123/dummy-0000/test"
                },
                {
                    "accountId": "00000000000",
                    "type": "AWS::S3::Bucket",
                    "ARN": "arn:aws:s3:::test-0000-0000"
                }
            ],
            "eventType": "AwsApiCall",
            "recipientAccountId": "00000000000"
        }
    ]
}

SQS

  • 署名バージョン2(SigV2)を利用したS3 APIの実行ログ、SQSのメッセージとして記録されている事を確認できました。

まとめ

S3 APIを署名バージョン 2で利用するシステムは、2019年6月24日までに 署名バージョン 4を使用するSDK、CLIへのアップグレードが必要となります。

署名バージョン2(SigV2)の利用が確認された場合、「userIdentity」「sourceIPAddress」「requestParameters」から実行環境を特定した上で、 下記公式ドキュメントなどを参考に適切な対応をご検討ください。

署名バージョン 2 から署名バージョン 4 への移行

CloudTrail証跡 をイベントソースとするCloudWatch Event、 CloudTrail のイベント課金のみで利用できます。 単純なログ抽出であれば、Amazon Athena、CloudWatchLogs、Lambdaなどを用いた実装よりも低コストで利用できますのでご活用下さい。

注意

S3オブジェクトログの取得により、CloudTrailのイベント課金(100,000 件のイベントあたり 0.1$)と、S3のログ保存コストが発生します。 S3の利用が多いシステムでは、定期的にCloudTrailのログ出力先としたS3バケットのメトリックス情報や、請求速報より発生するコストを確認してご利用ください。

また、S3のV2署名利用の確認のためにS3オブジェクトログを有効化した場合、確認が完了したS3バケットは対象から外す事をおすすめします。

  • S3 管理画面 (メトリックス)

CloudFormation

  • 今回紹介した、CloudTrail、S3、CloudWatch Event、Amazon SNS、SQSを再現するテンプレートです。

  • CloudFormationスタック作成後、CloudTrailの証跡設定でデータイベントとして調査対象とするS3バケットを指定してご利用ください。

  • 複数リージョンのS3バケットをログ対象とする場合、CloudTrailの証跡設定で「証跡情報を全てのリージョンに適用」を「はい」と設定してください。

  • CloudFormationスタックを削除する事で、CloudTrail、CloudWatch、SNS、SQSは撤去されます。CloudTrailログ出力先のS3バケットのみ手動で削除してください。

テンプレート