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 が含まれるエラーが発生するときの対処法

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

    アジアクエスト株式会社では一緒に働いていただける方を募集しています。
    興味のある方は以下のURLを御覧ください。