OpenSearchのIAM認証によるcurlリクエストの注意点
目次
はじめに
クラウドインテグレーション部の渡邊です。
今回はAmazon OpenSearch Service (以降、OpenSearchと呼ぶ)の認証について説明します。
OpenSearchの接続時の認証はSAML、Cognito、IAM、Basicなどがありますが、今回はIAM認証を中心に取り上げます。
IAM認証で接続する際に、実行環境がEC2とECSで異なる点があるため、そちらについて触れます。
本記事の事前作業でロールマッピングを行って、その情報に基づいて制御します。
ロールマッピングについて補足
Elasticsearchディストリビューションである、Open Distroには独自の権限管理モデルがあります。
そのモデルには、ロールというOpenSearchへの権限をまとめた単位があります。
そのロールとAWSのIAMロールを結びつけることを、ロールマッピングといいます。
こちらを利用することで、IAMロールに基づいて、OpenSearchへの細かい権限制御を行うことができます。
よって、今回IAMロールで細かい権限制御を行うために、このロールマッピングというものを行う必要があります。
環境情報
- OpenSearch 2.7
- Amazon Linux 2023
- AWS Fargate プラットフォームバージョン 1.4.0
- php:8.1.9-fpm-bullseye
- jq-1.6
- curl 8.2.1 (ECS)
- curl 8.0.1 (EC2)
※curl
コマンドで--aws-sigv4
フラグを使えるようにするために、7.75以上のバージョンが必要です。
事前準備
-
ECS
- ロールマッピング用のECSのタスクロール(IAMロール)を用意
- 公式ドキュメントを参考にECS Execができる環境を用意
- 本筋ではないため設定の詳細は割愛しますが、動作環境を確認するためにAmazon ECS Exec Checkerが有用
-
EC2
- ロールマッピング用のEC2インスタンスのIAMロールを用意
-
OpenSearch
- きめ細かなアクセスコントロールを有効にしたOpenSearchを作成
- ドメインアクセスポリシーの設定はきめ細かなアクセスコントロールのみを使用
- ドメインアクセスポリシーの設定はきめ細かなアクセスコントロールのみを使用
- きめ細かなアクセスコントロールを有効にしたOpenSearchを作成
-
- OpenSearchでロールマッピング設定
- この時点ではIAMにより認証できないので、パスワード認証でロールマッピングを行います。
- 以下にロールマッピングのコマンドを示します。
- OpenSearchでロールマッピング設定
※事前に以下の環境変数を設定してください。
USERNAME=<マスターユーザ名> PASSWORD=<マスターユーザパスワード> ENDPOINT=<opensearchエンドポイント> EC2_ROLE=<ec2にアタッチしたiamロールarn>
ECS_TASK_ROLE=<ECSにアタッチしたタスクロールARN>
ロールall_access
と、EC2のIAMロールおよびECSのタスクロールをロールマッピングします。all_access
は、OpenSearchのクラスターに対するフルアクセス権限のあるロールです。
※補足 all_access
というロールがフルアクセス権限に対応するロールと説明しましたが、マスターユーザと同等の権限を得るためには不十分です。
マスターユーザと同等の権限を得るためには、ロールsecurity_manager
とall_access
を別途アタッチする必要があります。
以下のリクエスト例では、all_access
のみ権限を持つユーザによってリクエストした場合、ロールマッピング情報の取得に失敗しております。
$ curl -XGET -u "<all_access権限を持つユーザ>:<all_access権限を持つユーザのパスワード>" -H "Content-Type: application/json" "https://${ENDPOINT}:443/_plugins/_security/api/rolesmapping/all_access?pretty" { "status" : "FORBIDDEN", "message" : "No permission to access REST API: User <新規作成ユーザ名> with Security roles [all_access] does not have any role privileged for admin access. No ssl info found in request." }
マスターユーザ名もロールマッピングのフィールドusers
に含めることに注意して、以下のようにロールマッピングしてください。
$ curl -XPUT -u "${USERNAME}:${PASSWORD}" -H "Content-Type: application/json" "https://${ENDPOINT}:443/_plugins/_security/api/rolesmapping/all_access" -d "{\"backend_roles\" : [ \"${EC2_ROLE}\" , \"${ECS_TASK_ROLE}\"],\"users\" : [ \"${USERNAME}\"]}" {"status":"OK","message":"'all_access' updated."}
ロールマッピングの情報を確認します。
$ curl -XGET -u "${USERNAME}:${PASSWORD}" -H "Content-Type: application/json" "https://${ENDPOINT}:443/_plugins/_security/api/rolesmapping/all_access?pretty" { "all_access" : { "hosts" : [ ], "users" : [ "<マスターユーザ名>" ], "reserved" : false, "hidden" : false, "backend_roles" : [ "<ec2にアタッチしたiamロールarn>", "<ecsにアタッチしたタスクロールarn>" ], "and_backend_roles" : [ ] } }
backend_roles
の値としてIAMロールのARN、users
の値としてマスターユーザ名が含まれているため、想定通りです。
パターン1:EC2の場合
後にIAM認証情報を利用したリクエストを実施するために、環境変数を設定します。
TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"` ROLE_NAME=`curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/meta-data/iam/security-credentials/` CRED=`curl -s -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/iam/security-credentials/${ROLE_NAME}/` AWS_ACCESS_KEY_ID=`echo $CRED | jq -r ".AccessKeyId"` AWS_SECRET_ACCESS_KEY=`echo $CRED | jq -r ".SecretAccessKey"` AWS_SESSION_TOKEN=`echo $CRED | jq -r ".Token"` REGION="ap-northeast-1" SERVICE="es"
動作確認するために、インデックスの一覧を取得します。
こちらのリクエストでは、パスワードではなく取得したIAMロールの認証情報を利用しています。
$ curl -k -XGET "https://${ENDPOINT}:443/_cat/indices" -H "X-Amz-Security-Token: ${AWS_SESSION_TOKEN}" --aws-sigv4 "aws:amz:${REGION}:${SERVICE}" --user "${AWS_ACCESS_KEY_ID}:${AWS_SECRET_ACCESS_KEY}" green open .opensearch-observability 4BaVs933R-iUPlDojYx5SQ 1 0 0 0 208b 208b green open .kibana_1 IaEGo5pvSp-m5efRTLR-EA 1 0 0 0 208b 208b green open .opendistro_security N9V2uNSXRNGVI-doFhkqag 1 0 10 3 74.7kb 74.7kb
インデックスの一覧が取得できていますね。
パターン2:ECS(Fargate)の場合
コンテナに直接入ってコマンドを実行するために、ECS Execを使っています。
以下コマンドでコンテナにログインします。
$ aws ecs execute-command --region ap-northeast-1 --cluster <クラスター名> --task <タスクID> --container <コンテナ名> --command "/bin/bash" --interactive
以下の環境変数を設定します。
Fargate環境の場合、メタデータの取得するパスやアドレスがEC2とは異なるため、注意する必要があります。
CRED=`curl 169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI` AWS_ACCESS_KEY_ID=`echo $CRED | jq -r ".AccessKeyId"` AWS_SECRET_ACCESS_KEY=`echo $CRED | jq -r ".SecretAccessKey"` AWS_SESSION_TOKEN=`echo $CRED | jq -r ".Token"` REGION="ap-northeast-1" SERVICE="es"
EC2で実施した場合と同様に、動作確認をします。
$ curl -k -XGET "https://${ENDPOINT}:443/_cat/indices" -H "X-Amz-Security-Token: ${AWS_SESSION_TOKEN}" --aws-sigv4 "aws:amz:${REGION}:${SERVICE}" --user "${AWS_ACCESS_KEY_ID}:${AWS_SECRET_ACCESS_KEY}" green open .opensearch-observability 4BaVs933R-iUPlDojYx5SQ 1 0 0 0 208b 208b green open .kibana_1 IaEGo5pvSp-m5efRTLR-EA 1 0 0 0 208b 208b green open .opendistro_security N9V2uNSXRNGVI-doFhkqag 1 0 10 3 74.7kb 74.7kb
EC2のときと同じ結果でした!
まとめ
- IAM認証を行うためには、ロールマッピングする必要がある。
- ロールマッピングは、Open DistroのロールとAWSのIAMロールを結びつけること。
- リクエスト実施時の注意点
- メタデータの取得するパスやアドレスが、EC2とは異なる。
curl
コマンドで--aws-sigv4
フラグを使えるようにするため、7.75以上のバージョンが必要
【参考】
curlの–aws-sigv4を使って、IAMロールでアクセス制限したOpenSearch(旧: ElasticSearch)にリクエストする
アジアクエスト株式会社では一緒に働いていただける方を募集しています。
興味のある方は以下のURLを御覧ください。