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


はじめに

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

Athenaの構築が終わって、QueryEditorでSQLが発行できるようになった状態からスタートです。
クライアントとして Redshiftの接続クライアントツールの比較でも紹介したDBeaverを使ってJDBC接続します。

まずはググってみると、こういうのがヒットします。
Athenaを守り、Athenaで攻める P17~22
ロールを使ってアクセスすればよい!と分かったところで、作業を進めます。

接続設定

IAMの設定

まずはAWS側で設定を行います。
以下のような関連性になります。

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

ポリシーの作成

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

{
    "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できる権限だけです。

{
    "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制限を行います。

{
  "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 に接続する

ドライバ設定

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

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

このjarファイルは、上記の 一時的認証情報を使用して~ のページにある
カスタム認証情報プロバイダの .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
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のシークレットキー

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