nogamincho technical memo

Mainly AWS and Java

CloudWatch LogsのVPCエンドポイントポリシーを試してみた

はじめに

CloudWatch Logs, CloudWatch EventsのVPCエンドポイントにおいて、VPCエンドポイントポリシーが記述できるようになっていました。

どのような挙動になるか、実際に動作を検証してみました。

VPCエンドポイントおよびVPCエンドポイントポリシーの説明も記載しているので、不必要であれば読み飛ばしてください。)

VPCエンドポイントとは

VPC内からAWSリソースへのアクセス(APIリクエスト)を送信する際にインターネット経由ではなくAWS内のNWをプライベート通信できるようにするためのエンドポイントです。

通常、プライベートサブネットのEC2インスタンスAPIリクエストを送信する際にはNAT Gateway(またはNATインスタンス)が必要です。

しかし、VPCエンドポイントを利用すればAWS内のNWのみ通信できるようになる(=インターネットに出る必要がない)ため、経路の担保および通信量の削減が見込まれます。

VPCエンドポイントポリシーとは

簡単に言えば、VPCエンドポイントに記載できるIAMポリシーのようなものです。 VPCエンドポイントを通過するAWSへのリクエストはそのポリシーの制約を受けます。

(IAMポリシーで許可していても、VPCエンドポイントポリシー許可していなければリクエストは拒否される)

VPCエンドポイントにはGateway型、Interface型の2種類が存在しますが、VPCエンドポイントポリシーを記述できるのはGateway型を採用しているS3とDynamoDBのVPCエンドポイントのみでした。

今回の対応により、CloudWatch LogsおよびCloudWatch EventsのVPCエンドポイントがInteface型のVPCエンドポイントとしては初めてVPCエンドポイントポリシーが記述できるようになりました。

VPCエンドポイントポリシーのユースケース

VPCエンドポイントを利用することで何が嬉しいのでしょうか?

一番は、他アカウントのリソースへのアクセスを制限できることだと私は認識しています。

S3を例に挙げます。

VPCエンドポイントを利用しているもののポリシーで制限を設けていない場合、他アカウントのアクセスキーを利用することで、EC2から他アカウントのS3バケットへデータを持ち出すことができます。

EC2上に機密情報等が保管されている場合、以下のようなケースでデータの漏洩が起こりえます。

  • システムの運用担当が悪意を持って操作する
  • EC2に対してOSコマンドインジェクションが行われる
  • EC2がマルウェアに感染する

f:id:nogamincho:20190216170254p:plain
VPCエンドポイントポリシーのユースケース

そのため、私がVPCエンドポイントポリシーを利用する場合、それらのリスクへの対応として、自アカウントのリソースのみに制限を行うようにしています。 (S3バケットの追加頻度が極めて低いからできることかもしれませんが…)

実際にやってみた

事前準備

  1. com.amazonaws.ap-northeast-1.logsVPCエンドポイントを作成する。 f:id:nogamincho:20190216170730p:plain com.amazonaws.ap-northeast-1.logsとcom.amazonaws.ap-northeast-1.eventsを選んだ場合のみ、最下部にポリシーを記述できるようになります。
  2. ポリシーを記述する。 ポリシーは以下のように、log-group-allowedというロググループへのみリクエストを許可しています。 f:id:nogamincho:20190216162340p:plain
  3. VPCエンドポイントを作成したサブネットにEC2を作成します。(EC2用のIAMロールにはCloudWatchLogsFullAccessのポリシーを付与する)
  4. ロググループとログストリームを作成する。
$ aws logs create-log-group --log-group-name logs-test-allowed
$ aws logs create-log-stream --log-group-name logs-test-allowed --log-stream-name logs-stream
$ aws logs create-log-group --log-group-name logs-test-denied
$ aws logs create-log-stream --log-group-name logs-test-denied --log-stream-name logs-stream

動作検証

作成したEC2にログインしてCLIでリクエストを送ることで動作を確認します。

VPCエンドポイント経由でのリクエストの確認

digコマンドで、logs.ap-northeast-1.amazonaws.comへのリクエストがVPCエンドポイントを向いていることを確認します。

プライベートIPが返ってきているため、VPCエンドポイント経由でリクエストが送られていることを確認できました。

[ec2-user@ip-172-31-29-146 ~]$ dig logs.ap-northeast-1.amazonaws.com

; <<>> DiG 9.9.4-RedHat-9.9.4-61.amzn2.1.1 <<>> logs.ap-northeast-1.amazonaws.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 30198
;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;logs.ap-northeast-1.amazonaws.com. IN  A

;; ANSWER SECTION:
logs.ap-northeast-1.amazonaws.com. 60 IN A  172.31.10.218
logs.ap-northeast-1.amazonaws.com. 60 IN A  172.31.20.109
logs.ap-northeast-1.amazonaws.com. 60 IN A  172.31.44.227

;; Query time: 2 msec
;; SERVER: 172.31.0.2#53(172.31.0.2)
;; WHEN: 土  2月 16 05:50:36 UTC 2019
;; MSG SIZE  rcvd: 110

ポリシーの動作の確認

先程作成したlogs-test-allowed, logs-test-deniedのロググループへテストデータを送信します。

logs-test-allowedのロググループへのput-log-eventsは成功しました。

[ec2-user@ip-172-31-29-146 ~]$ aws logs put-log-events --log-group-name logs-test-allowed --log-stream-name log-stream --log-events timestamp=1550295898001,message=ExampleEvent1 timestamp=1550295898002,message=ExampleEvent2
{
    "nextSequenceToken": "49592304407703484745949521076996311451170380XXXXXXXXXXXX"
}

logs-test-deniedのロググループへのput-log-eventsは失敗しました。

[ec2-user@ip-172-31-29-146 ~]$ aws logs put-log-events --log-group-name logs-test-denied --log-stream-name log-stream --log-events timestamp=1550295898001,message=ExampleEvent1 timestamp=1550295898002,message=ExampleEvent2

An error occurred (AccessDeniedException) when calling the PutLogEvents operation: User: arn:aws:sts::XXXXXXXXXXXX:assumed-role/ec2-logs-fullaccess-role/i-XXXXXXXXXXXX is not authorized to perform: logs:PutLogEvents on resource: arn:aws:logs:ap-northeast-1:XXXXXXXXXXXX:log-group:logs-test-denied:log-stream:log-stream

これらにより、CloudWatch LogsのVPCエンドポイントにおいて、VPCエンドポイントポリシーが適用されていることを確認できました。

最後に

  • VPCエンドポイントポリシーはVPCからのリソースアクセスを制限する上で重要な機能であり、多量のデータを転送することができるCloudWatch Logsで対応されたことで、データの漏洩リスクを低減させられます。
  • 他のInterface型エンドポイントでも同様の対応がされると、よりセキュアなVPC環境が構築できるので更なる展開を期待します。

AWS API呼び出しのCloudTrailでのデバッグ方法

はじめに

CloudTrailはAWS APIの呼び出しを記録するサービスです。

基本的には監視や監査目的で利用されるものですが、API呼び出しのログですので、リクエストの内容や、一部のケースではレスポンスも確認できます。

WorkSpacesの設定を変更する際にCloudTrailのログが有用だったため、その際のデバッグ方法を記載します。

どんなログが取れるのか?

ログのレコードの定義は以下のようになります。 厳密には、IAMによるAPI呼び出しだけではなく、「コンソールのサインイン」「AWSサービス よるAPI呼び出し」もログに記録されます。

CloudTrailレコードの内容

S3に出力される場合、以下のようなRecordsフィールドに配列形式で保存されます。

{
  "Records" : [
    {
      "eventVersion" : "1.02",
      "userIdentity" :
      {
        "type" : "IAMUser",
        "principalId" : "user_id",
        "arn" : "user_arn",
        "accountId" : "account_id",
        "accessKeyId" : "access_key_id",
        "userName" : "username"
      },
      "eventTime" : "event_time",
      "eventSource" : "workspaces.amazonaws.com",
      "eventName" : "DescribeWorkspaces",
      "awsRegion" : "region",
      "sourceIPAddress" : "IP_address",
      "userAgent" : "user_agent",
      "requestParameters" :
      {
        "requestContext" :
        {
          "awsAccountId" : "account_id"
        }
      },
      "responseElements" :
      {
        "workspaces" : [
          {
            "bundleId" : "bundle_id",
            "userName" : "workspace_user_name",
            "ipAddress" : ";ip_address",
            "directoryId" : ";directory_id",
            "state" : "state",
            "workspaceId" : "workspace_id",
            "subnetId" : "subnet_id"
          }
        ]
      },
      "requestID" : "request_id",
      "eventID" : "event_id",
      "eventType" : "AwsApiCall",
      "recipientAccountId" : "account_id"
    }
  ]
}

どうやって見るのか?

CloudTrailはS3へのファイル出力およびCloudWatch Logsへの出力に対応しています。直近90日のログであれば、以下のようにマネジメントコンソールから参照することも可能です。 CloudTrail

どんなことがわかるのか?

新規にWorkSpaceを作成した場合、バンドルサイズを上げる(≒インスタンスタイプを上げる)には、6時間待つ必要があります。(後から知った)

実際にその操作を行ったところ、AWSマネジメントコンソールからではERRORとのみ表示され、なぜその操作が失敗したのかわかりません。

CLIでWorkSpacesの状態を確認しましたが同様にわかりませんでした。

なので、その操作のCloudTrailのログを確認してみました。

{
    "eventVersion": "1.05",
    "userIdentity": {
        "type": "IAMUser",
        "principalId": "AIDAXXXXXXXXXXXXXXX",
        "arn": "arn:aws:iam::XXXXXXXXXXXX:user/nogamincho",
        "accountId": "XXXXXXXXXXXX",
        "accessKeyId": "ASIAXXXXXXXXXXXX",
        "userName": "nogamincho",
        "sessionContext": {
            "attributes": {
                "mfaAuthenticated": "true",
                "creationDate": "2018-12-26T07:53:21Z"
            }
        },
        "invokedBy": "signin.amazonaws.com"
    },
    "eventTime": "2018-12-26T10:57:49Z",
    "eventSource": "workspaces.amazonaws.com",
    "eventName": "ModifyWorkspaceProperties",
    "awsRegion": "ap-northeast-1",
    "sourceIPAddress": "XXXXXXXXXXXX",
    "userAgent": "signin.amazonaws.com",
    "errorCode": "InvalidResourceStateException",
    "errorMessage": "Action not supported.  Property update not allowed within 21,600 seconds of creation.",
    "requestParameters": {
        "workspaceProperties": {
            "computeTypeName": "VALUE"
        },
        "workspaceId": "ws-XXXXXXXXXXXX",
        "requestContext": {
            "awsAccountId": "XXXXXXXXXXXX"
        }
    },
    "responseElements": null,
    "requestID": "XXXXXXXXXXXX",
    "eventID": "XXXXXXXXXXXX",
    "eventType": "AwsApiCall",
    "recipientAccountId": "XXXXXXXXXXXX"
}

成功した場合には存在しない、errorCode, errorMessageのフィールドが存在します。 こちらにはご丁寧なエラーメッセージが表示されており、6時間待てとのことでした。

"errorCode": "InvalidResourceStateException",
"errorMessage": "Action not supported.  Property update not allowed within 21,600 seconds of creation.",

その他、権限周りのデバッグでも利用していますが、それはまた別途書きます。

まとめ

  • CloudTrailログは監視・監査目的だけではなく、APIの呼び出し結果も確認できる。