GuardDutyのFindingsをS3にエクスポートしてAthenaでテーブル化するときにトラブった話

## 記事概要
GuardDutyからS3にエクスポートした検知結果をGlue/Athena/QuickSightで分析しようとした。



## 遭遇したエラー

Glueのクローラを作成して実行したところ、下記のようなエラーが発生。

>[e102dd64-92e3-47f5-bd18-8e61c1236d7c] ERROR : Error Access Denied (Service: Amazon S3; Status Code: 403; Error Code: AccessDenied; Request ID: 9B26CDF2818CD5E0; S3 Extended Request ID: ydaNgMzEk+bSreDMVS6TCT/+dA0bHK6KBKnZwQbNa2J1hW4EN5uMoybHTq9ISd+kxDV1Vz0AzNg=) retrieving file at s3://test-chida/AWSLogs/200356542217/GuardDuty/ap-northeast-1/2020/02/25/ccd7c013-77e8-3bf2-b212-4e1e6671c308.jsonl.gz. Tables created did not infer schemas from this file.


## 原因調査

stackoverflowで同じような事象を発見。


- [amazon s3 - AWS Glue Access denied for crawler with administrator policy attached - Stack Overflow](https://stackoverflow.com/questions/51899441/aws-glue-access-denied-for-crawler-with-administrator-policy-attached)


疑わしいのは

- KMS
- S3へのアクセス権限

HTTPの403エラーは`Forbiddenエラー`と言ってアクセス権限関連のエラーなので、確かに怪しい。S3へのアクセス権限は問題なさそうなので**KMSが原因の可能性が高い。**

そういえばGuardDutyのエクスポート設定時にKMSのキーを指定したような気が…

確認してみるとGuardDutyの検知結果は、**指定したKMSキーで暗号化されてS3に出力される**ようだ。


KMSで暗号化されたデータをGlueのクローラでテーブル化する方法を考えればいい。

## 対処方法

調べてみると下記の記事に遭遇。

[amazon web services - Can you ingest an encrypted S3 Object (Text file) using AWS Glue? - Stack Overflow](https://stackoverflow.com/questions/55912339/can-you-ingest-an-encrypted-s3-object-text-file-using-aws-glue)


どうやら

- S3の暗号化が「SSE-KMS[^sse-kms]」の場合はGlueのIAMロールにKMS権限を与えればOK
- S3の暗号化が「CSE-KMS[^cse-kms]」の場合は無理

[^sse-kms]:  **S**erver-**S**ide-**E**ncryption KMS
[^cse-kms]:  **C**lient-**S**ide-**E**ncryption KMS

SSE-KMSの場合はGlueのIAMロールに下記のポリシーを与えればいいらしい。

```json
{
    "Version": "2012-10-17",
    "Statement": {
        "Effect": "Allow",
        "Action": [
            "kms:Decrypt"
        ],
        "Resource": [
            "arn:aws:kms:<Your Region>:<Your Account Number>:key/<Your Key ID>"
        ]
    }
}
```

結果、Glueのクローラはうまく動いた！
が！


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/166931/59bb2726-9801-f404-44c4-5826fe89c514.png)

結局ダメ。Athenaでテーブル確認できず…

[AWS Developer Forums: Metadata Error in Athena on table from ...](https://forums.aws.amazon.com/thread.jspa?messageID=878948)

GlueとAthenaの連携がうまくとれていないのか？Glue何もわからん。


### 暗号化されたデータをAthenaでテーブル化する

そもそもGuardDutyの検知結果がもっとシンプルだったらAthenaで直接テーブル作成ができたのだ。※複雑だったのでGlueで前処理しようとした。

もう強引にAthenaで直接`CREATE`文を実行することにした。

[JSONSerDe によるマッピングを使って、入れ子の JSON から Amazon Athena のテーブルを作成する | Amazon Web Services ブログ](https://aws.amazon.com/jp/blogs/news/create-tables-in-amazon-athena-from-nested-json-and-mappings-using-jsonserde/)

```sql
CREATE EXTERNAL TABLE guradduty_findnings (
        schemaVersion STRING,
        accountId STRING,
        region STRING,
        partition STRING,
        id STRING,
        arn STRING,
        type STRING,
        resource STRUCT < 
            resourceType: STRING,
            accessKeyDetails: STRUCT < 
                accessKeyId: STRING,
                principalId: STRING,
                userType: STRING,
                userName: STRING 
            > 
        >,
        service STRUCT < 
            serviceName: STRING,
            detectorId: STRING,
            action: STRUCT < 
                actionType: STRING,
                awsApiCallAction: STRUCT < 
                    api: STRING,
                    serviceName: STRING,
                    callerType: STRING,
                      remoteIpDetails: STRUCT < 
                        ipAddressV4: STRING,
                        organization: STRUCT < 
                            asn: STRING,
                            asnOrg: STRING,
                            isp: STRING,
                            org: STRING 
                        >,
                        country: STRUCT < 
                            countryName: STRING 
                        >,
                        city: STRUCT < 
                            cityName: STRING 
                        >,
                        geoLocation: STRUCT < 
                            lat: FLOAT,
                            lon: FLOAT 
                        > 
                    >,
                    affectedResources: STRING 
                > 
            >,
            resourceRole: STRING,
            additionalInfo: STRUCT < 
                recentApiCalls: array < 
                    STRUCT < 
                        api: STRING,
                        count: INT 
                    > 
                > 
            >,
            evidence: STRING,
            eventFirstSeen: STRING,
            eventLastSeen: STRING,
            archived: BOOLEAN,
            count: INT
        >,
        severity INT,
        createdAt STRING,
        updatedAt STRING,
        title STRING,
        description STRING 
) 
ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
LOCATION 's3://[bucket-name]/AWSLogs/200356542217/GuardDuty/'
```

今回はなぜか必要なかったが、AthenaならCSE-KMSの場合でもクエリ実行が可能らしい。
[発表: Amazon Athena が暗号化されたデータのクエリのサポートを追加 | Amazon Web Services ブログ](https://aws.amazon.com/jp/blogs/news/launch-amazon-athena-adds-support-for-querying-encrypted-data/)



## 補足ポイント

### GuardDutyのS3エクスポート機能
GuardDutyの検知結果（Findings）の保持期間は90日間[^ninty]なので、過去の検知結果はいつの間にか消えてしまう。

とはいえ、「３ヶ月前に怪しい行動してるヤツがいなかったか？」とか「前にもポートスキャン受けてたんだけど…いつだっけ」みたいな過去の検知結果を確認したいケースもあるはずだ。

GuardDutyでは結果を保存するための機能としてS3エクスポート機能がある。CloudWatch Logsへのエクスポートもあるが、結局永久的に保存されるわけではない。

[^ninty]: [Amazon GuardDuty のクォータ - Amazon GuardDuty](https://docs.aws.amazon.com/ja_jp/guardduty/latest/ug/guardduty_limits.html)

### S3暗号化

S3暗号化には5パターンある

暗号方式|説明
---|---
SSE-S3|サーバーサイド暗号化（AWS提供のS3鍵を利用）
SSE-KMS|サーバーサイド暗号化（KMS鍵を利用）
SSE-C|サーバーサイド暗号化（利用者が用意した鍵を利用）
CSE-KMS|クライアントサイド暗号化（KMS鍵を利用）
CSE-C|クライアントサイド暗号化（利用者が用意した鍵を利用）

サーバーサイド暗号化よりもクライアントサイド暗号化の方がセキュリティ面では強力だが、今回のようにトラブルが発生しやすい。

重要でないデータはSSE-S3で十分だと思われる。




## 参考

[unclear instructions · Issue #2 · aws-samples/aws-glue-samples](https://github.com/aws-samples/aws-glue-samples/issues/2)

[AWS Glue の「ERROR:Internal Service Exception」を解決する](https://aws.amazon.com/jp/premiumsupport/knowledge-center/glue-crawler-internal-service-exception/)

[S3の暗号化についてまとめてみた(2018年6月版) - 本日も乙](https://blog.jicoman.info/2018/06/s3-encryption/#%E3%83%87%E3%83%95%E3%82%A9%E3%83%AB%E3%83%88%E6%9A%97%E5%8F%B7%E5%8C%96%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8BAthena%E3%81%AE%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB%E5%AE%9A%E7%BE%A9%E3%81%AB%E3%82%88%E3%82%8B%E6%B3%A8%E6%84%8F%E7%82%B9)

[How to visualize Amazon GuardDuty findings: serverless edition | AWS Security Blog](https://aws.amazon.com/jp/blogs/security/how-to-visualize-amazon-guardduty-findings-serverless-edition/)