クラウドインテグレーション部の渡邊です。
今回はAmazon OpenSearch Service (以降、OpenSearchと呼ぶ)の認証について説明します。
OpenSearchの接続時の認証はSAML、Cognito、IAM、Basicなどがありますが、今回はIAM認証を中心に取り上げます。
IAM認証で接続する際に、実行環境がEC2とECSで異なる点があるため、そちらについて触れます。
本記事の事前作業でロールマッピングを行って、その情報に基づいて制御します。
Elasticsearchディストリビューションである、Open Distroには独自の権限管理モデルがあります。
そのモデルには、ロールというOpenSearchへの権限をまとめた単位があります。
そのロールとAWSのIAMロールを結びつけることを、ロールマッピングといいます。
こちらを利用することで、IAMロールに基づいて、OpenSearchへの細かい権限制御を行うことができます。
よって、今回IAMロールで細かい権限制御を行うために、このロールマッピングというものを行う必要があります。
curl
コマンドで--aws-sigv4
フラグを使えるようにするために、7.75以上のバージョンが必要です。ECS
EC2
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
の値としてマスターユーザ名が含まれているため、想定通りです。
後に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
インデックスの一覧が取得できていますね。
コンテナに直接入ってコマンドを実行するために、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のときと同じ結果でした!
curl
コマンドで--aws-sigv4
フラグを使えるようにするため、7.75以上のバージョンが必要【参考】
curlの–aws-sigv4を使って、IAMロールでアクセス制限したOpenSearch(旧: ElasticSearch)にリクエストする