OpenSearchのIAM認証によるcurlリクエストの注意点

    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を作成
          • ドメインアクセスポリシーの設定はきめ細かなアクセスコントロールのみを使用 
            2023-09-05-17-21-11
        • OpenSearchでロールマッピング設定
          • この時点ではIAMにより認証できないので、パスワード認証でロールマッピングを行います。
          • 以下にロールマッピングのコマンドを示します。

      ※事前に以下の環境変数を設定してください。

      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_managerall_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 7.75.0 IS SMALLER

      Amazon ES の権限モデル

      追加のマスターユーザー

      Open Distro Documentation

      Security

      curlの–aws-sigv4を使って、IAMロールでアクセス制限したOpenSearch(旧: ElasticSearch)にリクエストする

      Users and roles

      ECS Fargate で 169.254.169.254 が含まれるエラーが発生するときの対処法

      きめ細かなアクセスコントロール