AWS Marketplace for Containers Anywhere と License Manager の統合 - AWS Marketplace

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

AWS Marketplace for Containers Anywhere と License Manager の統合

AWS Marketplace 販売者は、Amazon Anywhere、Amazon Anywhere、Amazon EKS 、EC2またはオンプレミスインフラストラクチャ用の for AWS Marketplace Containers ECS Anywhere 製品 AWS License Manager と統合できます。以下のセクションでは、この統合の手順について説明します。

使用可能なライセンスモデルを含む AWS Marketplace、 と License Manager の統合に関する一般的な情報については、「」を参照してくださいを使用したコンテナ製品の契約料金 AWS License Manager。 AWS License Managerの詳細については、「AWS License Manager ユーザーガイド」および「AWS CLI コマンドリファレンス」の「AWS License Manager セクション」を参照してください。

AWS Marketplace for Containers Anywhere 製品を License Manager と統合する

for AWS Marketplace Containers Anywhere 製品を と統合するには、以下の手順に従います AWS License Manager。

AWS Marketplace for Containers Anywhere 製品を License Manager と統合するには
  1. ウェブブラウザを開き、AWS Marketplace 管理ポータル にサインインします。

  2. 以下のステップを実行して、コンテナ製品の製品 ID を作成します。この ID をコンテナイメージで使用して、後のステップでライセンスチェックを行います。

    1. メニューバーから [Assets (アセット)] を展開し、[コンテナ] を選択します。

    2. 商品に購入者向けの名前を入力し、[作成] を選択します。この名前は後で変更できます。

    3. [プロジェクト ID] を書き留めます。製品料金の詳細を作成または更新するときに使用します。

      ヒント

      製品 ID を紛失した場合は、アセットメニューからコンテナ AWS Marketplace 管理ポータル を選択すると、 で確認できます。Containers ページには、関連する製品 を含む製品のリストが表示されますIDs。

  3. 最新のパブリック AWS SDKをダウンロードし、コンテナアプリケーションにインストールします。希望 AWS SDKのインストール手順については、 で構築するツールAWSを参照してください。

    注記

    Amazon EKS Anywhere または によって提供されていない Kubernetes クラスターから License Manager APIオペレーションを呼び出すには AWS、サポートされている を使用する必要があります AWS SDK。サポートされている のリストを表示するには AWS SDKs、「サポートされている の使用 AWS SDK」を参照してください。

  4. カスタム認証情報プロバイダーを使用して AWS License Manager クライアントを作成し、デプロイされたコンテナアプリケーション AWS とオンプレミスに認証情報を提供できるようにします。カスタム認証情報プロバイダー (LicenseCredentialProvider) の完全なソースコードについては、以下のセクションを参照してください。

    LicenseCredentialsProvider は、 を追加することで、 AWS SDKのデフォルトの認証情報プロバイダーチェーンをオンプレミス用に拡張しますLicenseManagerTokenCredentialsProvider。これにより、オンプレミス環境で License Manager がOIDC発行した ID トークンを使用して認証情報が提供されます。LicenseCredentialsProvider のソースコードをアプリケーションのクラスパスに含める必要があります。

    注記

    を拡張DefaultCredentialsProviderすると、オンプレミス環境で を実行するとき AWS と を実行するときに、同じコンテナアプリケーションが認証情報を取得できます。コンテナアプリケーションが既にデフォルトではなくカスタム認証情報プロバイダーチェーンを使用している場合は、LicenseManagerTokenCredentialsProvider をカスタムチェーンに追加して拡張することもできます。

    次のコードスニペットは、Java を使用して AWS License Manager クライアントを作成する例です。

    LicenseManagerClientBuilder clientBuilder = LicenseManagerClient.builder().credentialsProvider(LicenseCredentialsProvider.create());
  5. 製品オファリングの各有料コンテナイメージの aws license-manager checkout-license コマンドを使用して、 CheckoutLicenseAPIオペレーションを呼び出します。これにより、購入者がアプリケーションのライセンスを使用する使用権限があるかどうかが確認されます。購入者にアプリケーションに対する使用権限がある場合は、CheckoutLicense は、申請を承諾し、リクエストされた使用権限とその値を返します。購入者にアプリケーションに対する使用権限がない場合は、CheckoutLicense は、例外をスローします。

    CheckoutLicense API オペレーションを呼び出すときは、次のパラメータが必要です。

    • CheckoutType - 有効な値は PROVISIONAL または PERPETUAL です。

      • チェックアウトされた使用権限の数がプールからなくなる場合に、PERPETUAL を使用します。

        例: 購入者には 500 GB のデータを処理する権限があります。データの処理を続けると、500 GB のプールからその量が引き出され、使い果たされます。

      • 使用権がプールからチェックアウトされ、使用後に返却されるフローティングライセンス使用権に PROVISIONAL を使用します。

        例: ユーザーには、アプリケーション内で同時に 500 人のユーザーを使用する権利があります。ユーザーがログインまたはログアウトすると、そのユーザーは引き出されるか、500 人のユーザープールに戻ります。フローティングライセンス使用権限の詳細については、「License Manager を使用したフローティングライセンス使用権限」を参照してください。

    • ClientToken - 大文字と小文字が区別される一意の識別子。一意のリクエストUUIDごとにランダムを使用することをお勧めします。

    • Entitlements - チェックアウトする使用権限のリスト。

      • 機能の使用権限の場合は、Name プロパティと Unit プロパティを次のように指定します。

        { "Name": "<Entitlement_Name>", "Unit": "None" }
      • カウント対象使用権限については、以下のように、Name プロパティ、Unit プロパティ、および Count プロパティを指定します。

        { "Name": "<Entitlement_Name>", "Unit": "<Entitlement_Unit>", "Value": <Desired_Count> }
    • KeyFingerprint - AWS Marketplace が発行するライセンスのキーフィンガープリントは aws:294406891311:AWS/Marketplace:issuer-fingerprint です。このキーフィンガープリントを使用すると、ライセンスは信頼できないエンティティによって発行 AWS Marketplace されるのではなく、 によって発行されます。

    • ProductSKU – 前のステップ AWS Marketplace 管理ポータル で で生成された製品 ID。

    次のスニペットは、 を使用する CheckoutLicenseAPIオペレーションを使用した呼び出しの例です AWS CLI。

    aws license-manager checkout-license \ --product-sku "2205b290-19e6-4c76-9eea-377d6bf71a47" \ --checkout-type "PROVISIONAL" \ --client-token "79464194dca9429698cc774587a603a1" \ --entitlements "Name=AWS::Marketplace::Usage/Drawdown/DataConsumption, Value=10, Unit=Gigabytes" \ --key-fingerprint "aws:294406891311:AWS/Marketplace:issuer-fingerprint"
    注記

    ライセンスを確認するには、コンテナアプリケーションが License Manager を使用するためのアウトバウンドネットワークアクセスが必要です。オンプレミスでデプロイされたアプリケーションでは、アウトバウンドネットワークアクセスの信頼性が低くなったり、速度が低下する可能性があります。これらのアプリケーションでは、License Manager を呼び出す際に適切に再試行する必要があります。詳細については、「オンプレミスデプロイでの License Manager との統合に関するベストプラクティス」を参照してください。

  6. で行われた更新、アップグレード、またはキャンセルによるお客様のライセンスの変更を特定するために、定期的に CheckoutLicenseAPIオペレーションを呼び出します AWS Marketplace。ケイデンスはアプリケーションによって異なります。購入者の介入なしに変更が自動的に反映されるように、1 日 1 回ライセンスを確認することをお勧めします。

    オンプレミスにデプロイされたアプリケーションでは、定期的にライセンスをチェックするためのアウトバウンドネットワークアクセスが信頼できない場合があります。このような場合、アプリケーションは十分な耐障害性を保つためにキャッシュされたライセンスを使用する必要があります。詳細については、「オンプレミスデプロイでの License Manager との統合に関するベストプラクティス」を参照してください。

  7. CheckoutLicense 呼び出しをコンテナアプリケーションと統合したら、変更を加えた新しいバージョンの Docker コンテナイメージを構築します。

  8. License Manager を使用してライセンスにアクセスする設定を含むオプションの入力として Kubernetes シークレットを受け入れるように、アプリケーションの Helm チャートを更新しますAPIs。設定シークレットには、License Manager によって発行された ID トークンと、コンテナアプリケーションがオンプレミスにデプロイされたAPIsときに License Manager を呼び出すための AWS 認証情報を取得するために、前述のカスタム認証情報プロバイダーによって使用される AWS Identity and Access Management ロールが含まれます。また、デフォルト値 us-east-1 を使用して AWS リージョン を入力として追加します。

    コンテナアプリケーションをオンプレミスにデプロイする購入者は、コンテナ製品の AWS Marketplace 購入者エクスペリエンスを通じて Kubernetes シークレットを作成できます。Kubernetes シークレット名を helm install コマンドへの入力として指定します。設定シークレットは次の形式で構成されます。

    apiVersion: v1 kind: Secret metadata: name: aws-marketplace-license-config type: Opaque stringData: license_token: <token_value> // License Manager issued JWT token iam_role: <role_arn> // AWS Identity and Access Management role to assume with license token
  9. と統合されたコンテナイメージの Helm チャートのアプリケーションデプロイテンプレートを更新 AWS License Manager して、以下を含めます。

    • ポッドのサービスアカウント – Amazon での Helm デプロイにはサービスアカウントが必要ですEKS。コンテナイメージでサービスアカウントのIAMロールを設定することで、License Manager APIオペレーションを呼び出すアクセス許可を取得するために使用されます。サービスアカウントのIAMロールの詳細については、IAM「サービスアカウントのロール」を参照してください。

    • オンプレミスデプロイのライセンスアクセス – オンプレミス環境での Helm デプロイの License Manager APIオペレーションを呼び出すための認証情報と適切なアクセス許可を提供するために、ライセンス設定シークレットが必要です。購入者は、 AWS Marketplace 購入者エクスペリエンスからライセンスシークレットを生成して Helm に提供します。

    以下のコードスニペットは、サービスアカウント、ライセンス設定、イメージプルシークレットを含むデプロイ仕様のサンプルです。

    apiVersion: apps/v1 kind: Deployment metadata: name: example-app spec: replicas: 1 selector: matchLabels: app: example-app template: metadata: labels: app: example-app spec: // Service account for pod serviceAccountName: {{ .Values.serviceAccountName }} containers: - name: example-app image: example-app ports: - containerPort: 8001 // Add the following conditional attributes {{ - if .Values.awsmp.licenseConfigSecretName }} //Mount the license volume to the container image volumeMounts: - name: awsmp-product-license mountPath: "/var/run/secrets/product-license" //Add following environment variable to container for credential provider env: - name: AWS_WEB_IDENTITY_REFRESH_TOKEN_FILE value: "/var/run/secrets/product-license/license_token" - name: AWS_ROLE_ARN valueFrom: secretKeyRef: name: {{ .Values.aws.licenseConfigSecretName }} key: iam_role //Mount the license secret as a volume to the pod volumes: - name: awsmp-product-license secret: secretName: {{ .Values.aws.licenseConfigSecretName }} optional: true {{ - end }}
    注記

    ライセンス設定シークレットはオプションです。購入者はこの値をオンプレミスデプロイにのみ使用します。 AWS デプロイの場合、デプロイ仕様には License Manager 統合イメージのサービスアカウントを含める必要があります。

  10. 以下のセクションの手順EKSを実行して、License Manager の統合をローカルおよび Amazon でテストします。

    1. License Manager 統合のローカルテスト

    2. Amazon での License Manager 統合のテスト EKS

  11. License Manager の統合をオンプレミス AWS とオンプレミスの両方で正常に検証したら、「」の手順に従ってコンテナ製品リストを作成できます概要: コンテナ製品を作成する

License Manager 統合のローカルテスト

minikube やその他のセットアップを使用して、ローカルで任意の Kubernetes クラスターで License Manager の統合をテストできます。Kubernetes クラスターに、License Manager APIオペレーションを呼び出すアウトバウンドインターネットアクセスがあることを確認します。

License Manager 統合をローカルでテストするには
  1. テスト用販売者アカウントで、希望する使用権限を持つテストライセンスを作成します。テストライセンスを設定するには、 リファレンスCreateLicenseの「」を参照してください。 AWS License Manager API または、次のスクリプトを使用してテストライセンスを作成し、テスト購入者アカウントにライセンスを付与してライセンスを使用します。次のスクリプトでは、テスト用販売者アカウントの認証情報を使用しています。

    read -p 'AWS Account for test buyer: ' TEST_BUYER_ACCOUNT_ID read -p 'License entitlements: ' ENTITLEMENTS # TEST_SELLER_ACCOUNT_ID="109876543210" # ENTITLEMENTS="{\"Name\": \"ByData\",\"MaxCount\": 1000,\"Overage\":true,\"Unit\": \"Gigabits\",\"AllowCheckIn\": true}" # Create License NOW=$(date +"%Y-%m-%dT00:00:00+00:00") PRODUCT_NAME="My awesome product" PRODUCT_SKU="c97b7825-44c4-4f42-b025-12baa4c171e0" LICENSE_BENEFICIARY=" arn:aws:iam::$TEST_BUYER_ACCOUNT_ID:root " LICENSE_ISSUER_NAME="test-seller" LICENSE_NAME="test-seller-license" CLIENT_TOKEN="b3920968-a94f-4547-af07-3dd232319367" CONSUMPTION_TTL=180 CONSUMPTION_RENEW_TYPE="None" HOME_REGION="us-east-1" LICENSE_ARN=$(aws license-manager create-license --license-name "$LICENSE_NAME" --product-name "$PRODUCT_NAME" --product-sku "$PRODUCT_SKU" --issuer Name="$LICENSE_ISSUER_NAME" --home-region "$HOME_REGION" --validity Begin="$NOW" --entitlements "$ENTITLEMENTS" --beneficiary "$LICENSE_BENEFICIARY" --consumption-configuration RenewType="$CONSUMPTION_RENEW_TYPE",ProvisionalConfiguration={MaxTimeToLiveInMinutes=$CONSUMPTION_TTL} --client-token "$CLIENT_TOKEN" | jq -r ".LicenseArn" ) echo "License arn: $LICENSE_ARN" # Create Grant GRANT_TOKEN="e9a14140-4fca-4219-8230-57511a6ea6" GRANT_NAME="test-grant" GRANT_ARN=$(aws license-manager create-grant --grant-name "$GRANT_NAME" --license-arn "$LICENSE_ARN" --principals "$LICENSE_BENEFICIARY" --home-region "$HOME_REGION" --client-token "$GRANT_TOKEN" --allowed-operations "CheckoutLicense" "CheckInLicense" "ExtendConsumptionLicense" "CreateToken" | jq -r ".GrantArn") echo "Grant arn: $GRANT_ARN"
  2. 前に定義したシークレット形式を使用して、ライセンストークンとIAMロールを使用して Kubernetes シークレットを作成します。License Manager CreateTokenAPIオペレーションを使用して、ライセンストークンを生成します。次に、 IAMCreateRoleAPIオペレーションを使用して、アクセス許可と信頼ポリシーを持つIAMロールを作成します。このスクリプトの例を参照してください。次のスクリプトでは、テスト用購入者アカウントの認証情報を使用しています。

    read -p 'AWS Account for test license: ' TEST_ACCOUNT_ID read -p 'License Arn' LICENSE_ARN # Create IAM Role ROLE_NAME="AWSLicenseManagerConsumptionTestRole" ROLE_DESCRIPTION="Role to test AWS License Manager integration on-prem" ROLE_POLICY_ARN="arn:aws:iam::aws:policy/service-role/AWSLicenseManagerConsumptionPolicy" ROLE_TRUST_POLICY="{\"Version\": \"2012-10-17\",\"Statement\": [{ \"Effect\":\"Allow\", \"Principal\": { \"Federated\": \"openid-license-manager.amazonaws.com\" }, \"Action\": \"sts:AssumeRoleWithWebIdentity\",\"Condition\": { \"ForAnyValue:StringLike\": { \"openid-license-manager.amazonaws.com:amr\": \"aws:license-manager:token-issuer-account-id:${TEST_ACCOUNT_ID}\" }}}]}" ROLE_SESSION_DURATION=3600 ROLE_ARN=$(aws iam create-role --role-name "$ROLE_NAME" --description "$ROLE_DESCRIPTION" --assume-role-policy-document "$ROLE_TRUST_POLICY" --max-session-duration $ROLE_SESSION_DURATION | jq ".Role" | jq -r ".Arn") aws iam attach-role-policy --role-name "$ROLE_NAME" --policy-arn "$ROLE_POLICY_ARN" echo "Role arn: $ROLE_ARN" # Create Token CLIENT_TOKEN="b3920968-a94f-4547-af07-3dd232319367" TOKEN=$(aws license-manager create-token --license-arn $LICENSE_ARN --role-arns $ROLE_ARN --client-token $CLIENT_TOKEN | jq '.Token') echo "License access token: $TOKEN"c
  3. の外部でホストされている Kubernetes クラスターを設定します AWS。これを使用して、コンテナアプリケーションが 以外の環境から に接続 AWS License Manager APIできること、 AWS およびカスタム認証情報プロバイダーがアプリケーションに適切に統合されていることをテストします。

  4. 以前に生成されたライセンストークンとIAMロールをローカル Kubernetes クラスターにデプロイします。

    kubectl create secret generic "awsmp-license-access-config" \ --from-literal=license_token=${TOKEN} \ --from-literal=iam_role=${ROLE_ARN}
  5. シークレット名を入力として Helm 経由でアプリケーションをデプロイし、アプリケーションが License Manager APIオペレーションを呼び出してエンタイトルメントチェックを実行できることを確認します。Helm とデプロイ仕様の変更については、AWS Marketplace for Containers Anywhere 製品を License Manager と統合する の「ステップ 9」を参照してください。

Amazon での License Manager 統合のテスト EKS

Amazon で License Manager の統合をテストすることもできますEKS。アプリケーションがライセンス設定シークレットなしで License Manager APIオペレーションを呼び出せることをテストします。また、サービスアカウントを使用して、サービスアカウントのIAMロール (IRSA) を設定し、アプリケーションに関連する認証情報を提供できることを確認してください。

Amazon で License Manager 統合をテストするには EKS
  1. テスト用販売者アカウントで、希望する使用権限を持つテストライセンスを作成します。CreateLicense API リファレンスを参照してテストライセンスをセットアップするか、次のスクリプトを使用してテストライセンスを作成し、テスト購入者アカウントにライセンス許可を作成してライセンスを消費します。次のスクリプトでは、テスト用販売者アカウントの認証情報を使用しています。

    read -p 'AWS Account for test buyer: ' TEST_BUYER_ACCOUNT_ID read -p 'License entitlements: ' ENTITLEMENTS # TEST_SELLER_ACCOUNT_ID="109876543210" # ENTITLEMENTS="{\"Name\": \"ByData\",\"MaxCount\": 1000,\"Overage\": true,\"Unit\": \"Gigabits\",\"AllowCheckIn\": true}" # Create License NOW=$(date +"%Y-%m-%dT00:00:00+00:00") PRODUCT_NAME="My awesome product" PRODUCT_SKU="c97b7825-44c4-4f42-b025-12baa4c171e0" LICENSE_BENEFICIARY=" arn:aws:iam::$TEST_BUYER_ACCOUNT_ID:root " LICENSE_ISSUER_NAME="test-seller" LICENSE_NAME="test-seller-license" CLIENT_TOKEN="b3920968-a94f-4547-af07-3dd232319367" CONSUMPTION_TTL=180 CONSUMPTION_RENEW_TYPE="None" HOME_REGION="us-east-1" LICENSE_ARN=$(aws license-manager create-license --license-name "$LICENSE_NAME" --product-name "$PRODUCT_NAME" --product-sku "$PRODUCT_SKU" --issuer Name="$LICENSE_ISSUER_NAME" --home-region "$HOME_REGION" --validity Begin="$NOW" --entitlements "$ENTITLEMENTS" --beneficiary "$LICENSE_BENEFICIARY" --consumption-configuration RenewType="$CONSUMPTION_RENEW_TYPE",ProvisionalConfiguration={MaxTimeToLiveInMinutes=$CONSUMPTION_TTL} --client-token "$CLIENT_TOKEN" | jq -r ".LicenseArn" ) echo "License arn: $LICENSE_ARN" # Create Grant GRANT_TOKEN="e9a14140-4fca-4219-8230-57511a6ea6" GRANT_NAME="test-grant" GRANT_ARN=$(aws license-manager create-grant --grant-name "$GRANT_NAME" --license-arn "$LICENSE_ARN" --principals "$LICENSE_BENEFICIARY" --home-region "$HOME_REGION" --client-token "$GRANT_TOKEN" --allowed-operations "CheckoutLicense" "CheckInLicense" "ExtendConsumptionLicense" "CreateToken" | jq -r ".GrantArn") echo "Grant arn: $GRANT_ARN"
  2. 目的の設定のテスト Amazon EKSクラスターを作成するか、以下のコマンドを実行してデフォルト設定を使用します。

    aws ec2 create-key-pair --region us-west-2 --key-name eks-key-pair
    eksctl create cluster \ --name awsmp-eks-test-example \ --region us-west-2 \ --with-oidc \ --ssh-access \ --ssh-public-key eks-key-pair
  3. 既存のクラスターのサービスアカウントを作成し、IAMロールに関連付けます。次のコマンドは、 でIAMロールを作成しますAWSLicenseManagerConsumptionPolicy。次に、 コマンドは License Manager 統合イメージをデプロイする Amazon EKSクラスターtest_saのサービスアカウントにアタッチします。その結果、サービスアカウントは License Manager APIオペレーションを呼び出すための適切な認証情報を取得できます。

    eksctl create iamserviceaccount \ --name test_sa \ --namespace test_namespace \ --cluster awsmp-eks-test-example \ --attach-policy-arn "arn:aws:iam::aws:policy/service-role/AWSLicenseManagerConsumptionPolicy" \ --approve \ --override-existing-serviceaccounts
  4. IAM ロールが前のコマンドから関連付けられているサービスアカウントに Helm 経由でアプリケーションをデプロイします。アプリケーションが License Manager APIオペレーションを呼び出してエンタイトルメントチェックを実行できることを確認します。

License Manager を使用したフローティングライセンス使用権限

フローティングライセンスでは、ユーザーがアプリケーションにログインすると、使用可能なライセンスのプールからライセンスが引き出されます。ユーザーがログアウトすると、ライセンスは使用可能なライセンスのプールに再び追加されます。

フローティングライセンスの場合、アプリケーションは CheckoutLicenseAPIオペレーションを使用して、リソースが使用されているときにエンタイトルメントプールからエンタイトルメントをチェックアウトします。CheckoutLicense API オペレーションのレスポンスには、チェックアウトの一意の識別子であるライセンス消費トークンが含まれます。ライセンス消費トークンは、チェックアウトした使用権限をライセンスプールに戻したり、チェックアウトを延長したりするなど、追加のアクションを実行できます。

リソースが使用されなくなった場合、アプリケーションは CheckInLicenseAPIオペレーションを使用して、権限をプールに戻します。

aws license-manager check-in-license \ --license-consumption-token "f1603b3c1f574b7284db84a9e771ee12"

オペレーション中にアプリケーションがクラッシュした場合など、ライセンスをプールにチェックインし直せなかった場合、60 分後に使用権限が自動的にプールにチェックインされます。このため、リソースが 60 分以上使用されている場合は、使用権限をプールからチェックアウトしたままにしておくことがベストプラクティスです。これを行うには、リソースが使用されている限り、 ExtendLicenseConsumptionAPIオペレーションを使用します。

aws license-manager extend-license-consumption \ --license-consumption-token "f1603b3c1f574b7284db84a9e771ee12"

オンプレミスデプロイでの License Manager との統合に関するベストプラクティス

オンプレミス環境にコンテナアプリケーションをデプロイすると、信頼性の低いアウトバウンドネットワークアクセスが発生する可能性があります。以下のベストプラクティスを活用して回復性を高め、インターネット接続の不備による潜在的な問題による購入者のサービスの中断を回避してください。

  • 適切な再試行 — 一時的なネットワークの問題により、アプリケーションが に接続できなくなる可能性があります AWS License Manager。最大で 30 分間の再試行をし、指数関数的にバックオフを行います。これにより、短期的な停止やネットワークの問題を回避できます。

  • ハードリミットの回避 - 接続されたクラスターにデプロイされたアプリケーションは、定期的にライセンスをチェックして、アップグレードや更新による変更を特定できます。アウトバウンドアクセスの信頼性が低いと、アプリケーションはそれらの変更を識別できない可能性があります。可能な限り、アプリケーションは、License Manager を通じてライセンスを確認できないことによる購入者へのサービスの中断を避ける必要があります。ライセンスの有効期限が切れてライセンスが有効かどうかを確認できなくなると、アプリケーションは無料試用エクスペリエンスまたはオープンソースエクスペリエンスに頼ることができます。

  • 顧客への通知 - キャッシュ型ライセンスを使用する場合、ライセンスへの変更 (更新やアップグレードを含む) は、実行中のワークロードに自動的に反映されません。アプリケーションがキャッシュされたライセンスを更新できるように、アプリケーションへのアウトバウンドアクセスを一時的に再度許可する必要があることを顧客に通知します。例えば、アプリケーション自体またはドキュメントを通じて顧客に通知します。同様に、下位の機能に頼る場合は、その使用権限がなくなったか、ライセンスの有効期限が切れていることを顧客に通知します。その後、顧客はアップグレードまたは更新のどちらかを選択できます。

LicenseManagerCredentialsProvider - Java 実装

LicenseCredentialsProvider は、 を追加することで、 AWS SDKのデフォルトの認証情報プロバイダーチェーンをオンプレミス用に拡張しますLicenseManagerTokenCredentialsProvider

LicenseCredentialsProvider

package com.amazon.awsmp.license; import software.amazon.awssdk.auth.credentials.AwsCredentials; import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; import software.amazon.awssdk.auth.credentials.AwsCredentialsProviderChain; import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider; import software.amazon.awssdk.auth.credentials.internal.LazyAwsCredentialsProvider; import software.amazon.awssdk.utils.SdkAutoCloseable; public class LicenseCredentialsProvider implements AwsCredentialsProvider, SdkAutoCloseable { private static final LicenseCredentialsProvider CREDENTIALS_PROVIDER = new LicenseCredentialsProvider(); private final LazyAwsCredentialsProvider providerChain; private LicenseCredentialsProvider() { this.providerChain = createChain(); } public static LicenseCredentialsProvider create() { return CREDENTIALS_PROVIDER; } @Override public AwsCredentials resolveCredentials() { return this.providerChain.resolveCredentials(); } @Override public void close() { this.providerChain.close(); } private LazyAwsCredentialsProvider createChain() { return LazyAwsCredentialsProvider.create(() -> { AwsCredentialsProvider[] credentialsProviders = new AwsCredentialsProvider[]{ DefaultCredentialsProvider.create(), LicenseManagerTokenCredentialsProvider.create()}; return AwsCredentialsProviderChain.builder().reuseLastProviderEnabled(true) .credentialsProviders(credentialsProviders).build(); }); } }

LicenseManagerTokenCredentialsProvider

LicenseManagerTokenCredentialsProvider は、オンプレミス環境で License Manager がOIDC発行した ID トークンを使用して認証情報を提供します。LicenseCredentialsProvider のソースコードをアプリケーションのクラスパスに含める必要があります。

package com.amazon.awsmp.license; import software.amazon.awssdk.auth.credentials.AnonymousCredentialsProvider; import software.amazon.awssdk.auth.credentials.AwsCredentials; import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; import software.amazon.awssdk.core.SdkSystemSetting; import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; import software.amazon.awssdk.core.retry.RetryPolicyContext; import software.amazon.awssdk.core.retry.conditions.OrRetryCondition; import software.amazon.awssdk.core.retry.conditions.RetryCondition; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.regions.providers.DefaultAwsRegionProviderChain; import software.amazon.awssdk.services.licensemanager.LicenseManagerClient; import software.amazon.awssdk.services.licensemanager.model.GetAccessTokenRequest; import software.amazon.awssdk.services.licensemanager.model.GetAccessTokenResponse; import software.amazon.awssdk.services.sts.StsClient; import software.amazon.awssdk.services.sts.auth.StsAssumeRoleWithWebIdentityCredentialsProvider; import software.amazon.awssdk.services.sts.model.AssumeRoleWithWebIdentityRequest; import software.amazon.awssdk.services.sts.model.IdpCommunicationErrorException; import software.amazon.awssdk.utils.IoUtils; import software.amazon.awssdk.utils.SdkAutoCloseable; import software.amazon.awssdk.utils.StringUtils; import software.amazon.awssdk.utils.SystemSetting; import java.io.IOException; import java.io.InputStream; import java.io.UncheckedIOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.time.Duration; import java.util.function.Supplier; public class LicenseManagerTokenCredentialsProvider implements AwsCredentialsProvider, SdkAutoCloseable { private final StsAssumeRoleWithWebIdentityCredentialsProvider credentialsProvider; private final RuntimeException loadException; private Path licenseAccessTokenFile; private String roleArn; private String roleSessionName; private StsClient stsClient; private LicenseManagerClient lmClient; public static LicenseManagerTokenCredentialsProvider create() { return new Builder().build(); } @Override public AwsCredentials resolveCredentials() { if (this.loadException != null) { throw this.loadException; } return this.credentialsProvider.resolveCredentials(); } @Override public void close() { IoUtils.closeQuietly(this.credentialsProvider, null); IoUtils.closeQuietly(this.stsClient, null); IoUtils.closeIfCloseable(this.lmClient, null); } private LicenseManagerTokenCredentialsProvider(Builder builder) { StsAssumeRoleWithWebIdentityCredentialsProvider credentialsProvider = null; RuntimeException loadException = null; try { this.licenseAccessTokenFile = Paths.get(StringUtils.trim(LicenseSystemSetting.AWS_WEB_IDENTITY_REFRESH_TOKEN_FILE.getStringValueOrThrow())); this.roleArn = SdkSystemSetting.AWS_ROLE_ARN.getStringValueOrThrow(); this.roleSessionName = SdkSystemSetting.AWS_ROLE_SESSION_NAME.getStringValue().orElse("aws-sdk-java-" + System.currentTimeMillis()); this.stsClient = builder.stsClient != null ? builder.stsClient : StsClientFactory.create(); this.lmClient = builder.lmClient != null ? builder.lmClient : LicenseManagerClientFactory.create(); AssumeRoleWithWebIdentityRequest request = AssumeRoleWithWebIdentityRequest.builder() .roleArn(this.roleArn).roleSessionName(this.roleSessionName).build(); Supplier<AssumeRoleWithWebIdentityRequest> supplier = new AssumeRoleRequestSupplier(request, this.licenseAccessTokenFile, this.lmClient); credentialsProvider = StsAssumeRoleWithWebIdentityCredentialsProvider.builder() .stsClient(this.stsClient).refreshRequest(supplier).build(); } catch (RuntimeException ex) { loadException = ex; } this.credentialsProvider = credentialsProvider; this.loadException = loadException; } public static final class Builder { private Path licenseAccessTokenFile; private String roleArn; private String roleSessionName; private StsClient stsClient; private LicenseManagerClient lmClient; public LicenseManagerTokenCredentialsProvider build() { return new LicenseManagerTokenCredentialsProvider(this); } public LicenseManagerTokenCredentialsProvider.Builder licenseAccessTokenFile(Path licenseAccessTokenFile) { this.licenseAccessTokenFile = licenseAccessTokenFile; return this; } public LicenseManagerTokenCredentialsProvider.Builder roleArn(String roleArn) { this.roleArn = roleArn; return this; } public LicenseManagerTokenCredentialsProvider.Builder roleSessionName(String roleSessionName) { this.roleSessionName = roleSessionName; return this; } public LicenseManagerTokenCredentialsProvider.Builder stsClient(StsClient stsClient) { this.stsClient = stsClient; return this; } public LicenseManagerTokenCredentialsProvider.Builder lmClient(LicenseManagerClient lmClient) { this.lmClient = lmClient; return this; } } private static final class AssumeRoleRequestSupplier implements Supplier { private final LicenseManagerClient lmClient; private final AssumeRoleWithWebIdentityRequest request; private final Path webIdentityRefreshTokenFile; AssumeRoleRequestSupplier(final AssumeRoleWithWebIdentityRequest request, final Path webIdentityRefreshTokenFile, final LicenseManagerClient lmClient) { this.lmClient = lmClient; this.request = request; this.webIdentityRefreshTokenFile = webIdentityRefreshTokenFile; } public AssumeRoleWithWebIdentityRequest get() { return this.request.toBuilder() .webIdentityToken(getIdentityToken()) .build(); } private String getIdentityToken() { return refreshIdToken(readRefreshToken(this.webIdentityRefreshTokenFile)); } private String readRefreshToken(Path file) { try (InputStream webIdentityRefreshTokenStream = Files.newInputStream(file)) { return IoUtils.toUtf8String(webIdentityRefreshTokenStream); } catch (IOException e) { throw new UncheckedIOException(e); } } private String refreshIdToken(String licenseRefreshToken) { final GetAccessTokenRequest request = GetAccessTokenRequest.builder() .token(licenseRefreshToken) .build(); GetAccessTokenResponse response = this.lmClient.getAccessToken(request); return response.accessToken(); } } private static final class LicenseManagerClientFactory { private static final Duration DEFAULT_API_TIMEOUT = Duration.ofSeconds(30); private static final Duration DEFAULT_API_ATTEMPT_TIMEOUT = Duration.ofSeconds(10); public static LicenseManagerClient create() { return getLicenseManagerClient(); } private static LicenseManagerClient getLicenseManagerClient() { ClientOverrideConfiguration configuration = ClientOverrideConfiguration.builder() .apiCallTimeout(DEFAULT_API_TIMEOUT) .apiCallAttemptTimeout(DEFAULT_API_ATTEMPT_TIMEOUT) .build(); LicenseManagerClient client = LicenseManagerClient.builder() .region(configureLicenseManagerRegion()) .credentialsProvider(AnonymousCredentialsProvider.create()) .overrideConfiguration(configuration).build(); return client; } private static Region configureLicenseManagerRegion() { Region defaultRegion = Region.US_EAST_1; Region region; try { region = (new DefaultAwsRegionProviderChain()).getRegion(); } catch (RuntimeException ex) { region = defaultRegion; } return region; } } private static final class StsClientFactory { private static final Duration DEFAULT_API_TIMEOUT = Duration.ofSeconds(30); private static final Duration DEFAULT_API_ATTEMPT_TIMEOUT = Duration.ofSeconds(10); public static StsClient create() { return getStsClient(); } private static StsClient getStsClient() { OrRetryCondition retryCondition = OrRetryCondition.create(new StsRetryCondition(), RetryCondition.defaultRetryCondition()); ClientOverrideConfiguration configuration = ClientOverrideConfiguration.builder() .apiCallTimeout(DEFAULT_API_TIMEOUT) .apiCallAttemptTimeout(DEFAULT_API_ATTEMPT_TIMEOUT) .retryPolicy(r -> r.retryCondition(retryCondition)) .build(); return StsClient.builder() .region(configureStsRegion()) .credentialsProvider(AnonymousCredentialsProvider.create()) .overrideConfiguration(configuration).build(); } private static Region configureStsRegion() { Region defaultRegion = Region.US_EAST_1; Region stsRegion; try { stsRegion = (new DefaultAwsRegionProviderChain()).getRegion(); } catch (RuntimeException ex) { stsRegion = defaultRegion; } return stsRegion; } private static final class StsRetryCondition implements RetryCondition { public boolean shouldRetry(RetryPolicyContext context) { return context.exception() instanceof IdpCommunicationErrorException; } } } private enum LicenseSystemSetting implements SystemSetting { AWS_WEB_IDENTITY_REFRESH_TOKEN_FILE("aws.webIdentityRefreshTokenFile"); private String systemProperty; private String defaultValue = null; LicenseSystemSetting(String systemProperty) { this.systemProperty = systemProperty; } @Override public String property() { return this.systemProperty; } @Override public String environmentVariable() { return this.name(); } @Override public String defaultValue() { return this.defaultValue; } } }

LicenseManagerCredentialsProvider - Golang 実装

LicenseCredentialsProvider

LicenseCredentialsProvider は、 を追加することで、 AWS SDKのデフォルトの認証情報プロバイダーチェーンをオンプレミス用に拡張しますLicenseManagerTokenCredentialsProvider

package lib import ( "context" "fmt" "sync" "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/config" ) // LicenseCredentialsProvider is the custom credential provider that can retrieve valid temporary aws credentials type LicenseCredentialsProvider struct { fallBackProvider aws.CredentialsProvider mux sync.RWMutex licenseCredentials aws.Credentials err error } // NewLicenseCredentialsProvider method will create a LicenseCredentialProvider Object which contains valid temporary aws credentials func NewLicenseCredentialsProvider() (*LicenseCredentialsProvider, error) { licenseCredentialProvider := &LicenseCredentialsProvider{} fallBackProvider, err := createCredentialProvider() if err != nil { return licenseCredentialProvider, fmt.Errorf("failed to create LicenseCredentialsProvider, %w", err) } licenseCredentialProvider.fallBackProvider = fallBackProvider return licenseCredentialProvider, nil } // Retrieve method will retrieve temporary aws credentials from the credential provider func (l *LicenseCredentialsProvider) Retrieve(ctx context.Context) (aws.Credentials, error) { l.mux.RLock() defer l.mux.RUnlock() l.licenseCredentials, l.err = l.fallBackProvider.Retrieve(ctx) return l.licenseCredentials, l.err } func createCredentialProvider() (aws.CredentialsProvider, error) { // LoadDefaultConfig will examine all "default" credential providers ctx := context.TODO() cfg, err := config.LoadDefaultConfig(ctx) if err != nil { return nil, fmt.Errorf("failed to create FallBackProvider, %w", err) } var useFallbackProvider bool if cfg.Credentials != nil { if _, err := cfg.Credentials.Retrieve(ctx); err != nil { // If the "default" credentials provider cannot retrieve credentials, enable fallback to customCredentialsProvider. useFallbackProvider = true } } else { useFallbackProvider = true } if useFallbackProvider { customProvider, err := newLicenseManagerTokenCredentialsProvider() if err != nil { return cfg.Credentials, fmt.Errorf("failed to create fallBackProvider, %w", err) } // wrap up customProvider with CredentialsCache to enable caching cfg.Credentials = aws.NewCredentialsCache(customProvider) } return cfg.Credentials, nil }

LicenseManagerTokenCredentialsProvider

LicenseManagerTokenCredentialsProvider は、オンプレミス環境で License Manager がOIDC発行した ID トークンを使用して認証情報を提供します。LicenseCredentialsProvider のソースコードをアプリケーションのクラスパスに含める必要があります。

package lib import ( "context" "fmt" "io/ioutil" "os" "sync" "time" "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/service/sts" ) const awsRefreshTokenFilePathEnvVar = "AWS_LICENSE_ACCESS_FILE" // licenseManagerTokenCredentialsProvider defines and contains StsAssumeRoleWithWebIdentityProvider type licenseManagerTokenCredentialsProvider struct { stsCredentialProvider *stsAssumeRoleWithWebIdentityProvider mux sync.RWMutex licenseCredentials aws.Credentials err error } // Retrieve method will retrieve credentials from credential provider. // Make this method public to make this provider satisfies CredentialProvider interface func (a *licenseManagerTokenCredentialsProvider) Retrieve(ctx context.Context) (aws.Credentials, error) { a.mux.RLock() defer a.mux.RUnlock() a.licenseCredentials, a.err = a.stsCredentialProvider.Retrieve(ctx) return a.licenseCredentials, a.err } // newLicenseManagerTokenCredentialsProvider will create and return a LicenseManagerTokenCredentialsProvider Object which wraps up stsAssumeRoleWithWebIdentityProvider func newLicenseManagerTokenCredentialsProvider() (*licenseManagerTokenCredentialsProvider, error) { // 1. Retrieve variables From yaml environment envConfig, err := config.NewEnvConfig() if err != nil { return &licenseManagerTokenCredentialsProvider{}, fmt.Errorf("failed to create LicenseManagerTokenCredentialsProvider, %w", err) } roleArn := envConfig.RoleARN var roleSessionName string if envConfig.RoleSessionName == "" { roleSessionName = fmt.Sprintf("aws-sdk-go-v2-%v", time.Now().UnixNano()) } else { roleSessionName = envConfig.RoleSessionName } tokenFilePath := os.Getenv(awsRefreshTokenFilePathEnvVar) b, err := ioutil.ReadFile(tokenFilePath) if err != nil { return &licenseManagerTokenCredentialsProvider{}, fmt.Errorf("failed to create LicenseManagerTokenCredentialsProvider, %w", err) } refreshToken := aws.String(string(b)) // 2. Create stsClient cfg, err := config.LoadDefaultConfig(context.TODO()) if err != nil { return &licenseManagerTokenCredentialsProvider{}, fmt.Errorf("failed to create LicenseManagerTokenCredentialsProvider, %w", err) } stsClient := sts.NewFromConfig(cfg, func(o *sts.Options) { o.Region = configureStsClientRegion(cfg.Region) o.Credentials = aws.AnonymousCredentials{} }) // 3. Configure StsAssumeRoleWithWebIdentityProvider stsCredentialProvider := newStsAssumeRoleWithWebIdentityProvider(stsClient, roleArn, roleSessionName, refreshToken) // 4. Build and return return &licenseManagerTokenCredentialsProvider{ stsCredentialProvider: stsCredentialProvider, }, nil } func configureStsClientRegion(configRegion string) string { defaultRegion := "us-east-1" if configRegion == "" { return defaultRegion } else { return configRegion } }