AthenaにIP制限で接続する方法

# はじめに
Athenaに接続するときにアクセスキーを使ってつなぐわけですが、
接続元のIPアドレスによる制限もかけておきたい。という時の方法です。

Athenaの構築が終わって、QueryEditorでSQLが発行できるようになった状態からスタートです。
クライアントとして [Redshiftの接続クライアントツールの比較](https://qiita.com/_konishi_/items/47732f0dc5c33b751d98)でも紹介したDBeaverを使ってJDBC接続します。

まずはググってみると、こういうのがヒットします。
[Athenaを守り、Athenaで攻める](https://www.slideshare.net/NavitimeJapan/athenaathena) P17～22
ロールを使ってアクセスすればよい！と分かったところで、作業を進めます。
 
# 接続設定
## IAMの設定
まずはAWS側で設定を行います。
以下のような関連性になります。

```
IAMユーザ：MyAthenaUser
　↓
AssumeRole
　↓
ロール：MyAthenaRole@MyAthenaUser　←割り当て← ポリシー：MyAthenaPolicy
```

### ポリシーの作成
ロールに割り当てるポリシー __MyAthenaPolicy__ を作ります。
Athenaへの実質的な権限管理をするのがこれになります。
AWSによる管理のポリシーにAmazonAthenaFullAccessというのがあるので、それを書き換えて使います。

```JavaScript
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "athena:*"
            ],
            "Resource": [
                "*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "glue:CreateDatabase",
                "glue:DeleteDatabase",
                "glue:GetDatabase",
                "glue:GetDatabases",
                "glue:UpdateDatabase",
                "glue:CreateTable",
                "glue:DeleteTable",
                "glue:BatchDeleteTable",
                "glue:UpdateTable",
                "glue:GetTable",
                "glue:GetTables",
                "glue:BatchCreatePartition",
                "glue:CreatePartition",
                "glue:DeletePartition",
                "glue:BatchDeletePartition",
                "glue:UpdatePartition",
                "glue:GetPartition",
                "glue:GetPartitions",
                "glue:BatchGetPartition"
            ],
            "Resource": [
                "*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetBucketLocation",
                "s3:GetObject",
                "s3:ListBucket",
                "s3:ListBucketMultipartUploads",
                "s3:ListMultipartUploadParts",
                "s3:AbortMultipartUpload",
                "s3:CreateBucket",
                "s3:PutObject"
            ],
            "Resource": [
                "arn:aws:s3:::aws-athena-query-results-*"  // (1)
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::athena-examples*"  // (2)
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket",
                "s3:GetBucketLocation",
                "s3:ListAllMyBuckets"
            ],
            "Resource": [
                "*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "sns:ListTopics",
                "sns:GetTopicAttributes"
            ],
            "Resource": [
                "*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "cloudwatch:PutMetricAlarm",
                "cloudwatch:DescribeAlarms",
                "cloudwatch:DeleteAlarms"
            ],
            "Resource": [
                "*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "lakeformation:GetDataAccess"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}
```
上記の(1)(2)の箇所は書き換えます。

- (1):Athenaのクエリ結果を保存するS3の場所になります。  
Athena > Settings のQuery result locationの値です。
- (2):Athenaの参照先のS3バケットのパスになります。  
Glueで設定した各テーブルの参照先のものです。

作成したポリシーを __MyAthenaPolicy__ という名前で保存します。

### ユーザの作成
ここでは __MyAthenaUser__ というユーザを作ります。
権限は __MyAthenaRole@MyAthenaUser__ （後で作成）にAssumeRoleできる権限だけです。

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "sts:AssumeRole",
            "Resource": "arn:aws:iam::[アカウントID]:role/MyAthenaRole@MyAthenaUser"
        }
    ]
}
```

ユーザの追加で __プログラムによるアクセス__ にだけチェックを入れ、ユーザを作成します。
作成時に表示された アクセスキーID、シークレットキーはメモしておきます。

### ロールの設定
ロール __MyAthenaRole@MyAthenaUser__ を作成します。
IAM > ロール > ロールの作成

信頼されたエンティティの種類 で __別のAWSアカウント__ を選び、
自分自身のアカウントIDを入力します。
（後で変更します）

アタッチするポリシーとして、先ほど作成したポリシー __MyAthenaPolicy__ を指定して作成します。
このロールは __MyAthenaRole@MyAthenaUser__ という名前にします。

作成したら、信頼されたエンティティを変更します。
ロール __MyAthenaRole@MyAthenaUser__ を開き、信頼関係の編集でJsonを変更します。
ここでIP制限を行います。

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::[アカウントID]:user/MyAthenaUser"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "IpAddress": {
          "aws:SourceIp": "xxx.xxx.xxx.xxx/32"
        }
      }
    }
  ]
}
```
特定IPのMyAthenaUserからのAssumeRoleを許可する。という設定です。

これでIAMの設定は終了です。

## DBeaverの設定
接続クライアントであるDBeaverからJDBCで接続する設定をします。
DBeaverはインストール済みだとします。
使用したバージョンは6.1.4です。

以下のページを参考に作業します。
[一時的認証情報を使用してフェデレーティッドアイデンティティで、Amazon Athena に接続する](https://aws.amazon.com/jp/blogs/news/connect-to-amazon-athena-with-federated-identities-using-temporary-credentials/)

### ドライバ設定
すでにAthenaドライバの設定があるのですが、
IP制限を使った接続には使えないので新たにドライバを作ります。
ここは将来のバージョンによって、改善されるかもしれません。（願望）

既存のAthenaドライバはAthenaJDBC42_2.0.7.jarを使うのですが、
AssumeRoleするには __athena-jdbc-custom-credentials-provider-0.0.1-SNAPSHOT.jar__ も必要になります。

このjarファイルは、上記の 一時的認証情報を使用して～ のページにある 
[カスタム認証情報プロバイダの .jar ファイル](https://s3.amazonaws.com/athena-blog-jdbc-custom-credentials-provider/athena-jdbc-custom-credentials-provider-0.0.1-SNAPSHOT.jar)
からダウンロードします。

AthenaJDBC42_2.0.7.jarは以下からダウンロードします。
https://s3.amazonaws.com/athena-downloads/drivers/JDBC/SimbaAthenaJDBC_2.0.7/AthenaJDBC42_2.0.7.jar

メニューの __データベース > ドライバーマネージャー__ を開きます。

| 項目 | 値 |
|----|---|
| ドライバ名 | 適当に決めます。ここではAthenaIAMとします |
| クラス名 | com.simba.athena.jdbc.Driver |
| カテゴリー | AWS |
| ライブラリ | AthenaJDBC42_2.0.7.jar <br> athena-jdbc-custom-credentials-provider-0.0.1-SNAPSHOT.jar |

ライブラリはそれぞれのjarを保存した場所を指定します。

### 接続設定

作成したAthenaIAMドライバーを使っての接続設定をします。
普通のAthenaドライバーと同じ設定です。

| 項目 | 値 |
|----|---|
| Region |Athenaのリージョン。東京ならap-northeast-1|
|S3 location |Athenaのクエリ結果を保存するS3の場所|
|AWS Access Key |MyAthenaUserのアクセスキー|
|AWS Secret Key |MyAthenaUserのシークレットキー|

設定が終わったらつないでみましょう！