Integrando um produto AWS Marketplace for Containers Anywhere com o License Manager - AWS Marketplace

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

Integrando um produto AWS Marketplace for Containers Anywhere com o License Manager

Siga estas instruções para fazer a integração AWS License Manager com um produto AWS Marketplace for Containers EKS Anywhere para Amazon ECS Anywhere, Amazon AnywhereEC2, Amazon ou infraestrutura local.

Para obter informações gerais sobre a integração do License Manager com AWS Marketplace, incluindo os modelos de licença disponíveis, consulteContrate preços para produtos de contêiner com AWS License Manager. Para obter mais informações sobre o AWS License Manager, consulte o Guia do usuário do AWS License Manager e a Referência de comandos do AWS License Manager.

Integrando um produto AWS Marketplace for Containers Anywhere com o License Manager

Use as instruções a seguir para integrar seu produto AWS Marketplace for Containers Anywhere com AWS License Manager o.

Para integrar seu produto AWS Marketplace for Containers Anywhere com o License Manager
  1. Abra um navegador da web e faça login no Portal de gerenciamento do AWS Marketplace.

  2. Crie um ID para seu produto de contêiner realizando as etapas a seguir. Você usará esse ID na imagem do contêiner para verificações de licença em uma etapa posterior.

    1. Na barra de menus, expanda Assets (Ativos) e selecione Container (Contêiner).

    2. Insira um nome voltado ao cliente para o produto e selecione Criar. Você pode alterar esse nome depois.

    3. Anote o ID do produto. Você o usará ao criar ou atualizar os detalhes de preços do produto.

      dica

      Se você perder o ID do produto, poderá encontrá-lo Portal de gerenciamento do AWS Marketplace escolhendo Contêiner no menu Ativos. A página Contêineres mostra uma lista de seus produtos com os produtos associadosIDs.

  3. Baixe o público mais recente AWS SDK e instale-o em seu aplicativo de contêiner. Você pode encontrar instruções de instalação de sua preferência AWS SDK em Tools to Build on AWS.

    nota

    Para chamar as API operações do License Manager do Amazon EKS Anywhere ou de um cluster Kubernetes que não seja fornecido pela AWS, você deve usar um compatível. AWS SDK Para ver uma lista dos compatíveis AWS SDKs, consulte Usando um compatível AWS SDK.

  4. Crie um AWS License Manager cliente com um provedor de credenciais personalizado para que ele possa fornecer credenciais para o aplicativo de contêiner implantado no local e no AWS local. Para obter o código-fonte completo de um provedor de credenciais personalizado, LicenseCredentialProvider, consulte as seções a seguir:

    LicenseCredentialsProviderestende a cadeia AWS SDK de provedores de credenciais padrão para uso local adicionando. LicenseManagerTokenCredentialsProvider Isso fornece credenciais usando tokens de identidade OIDC emitidos pelo License Manager em ambientes locais. Você deve incluir o código-fonte do LicenseCredentialsProvider no caminho de classe do seu aplicativo.

    nota

    Estender o DefaultCredentialsProvider permite que o mesmo aplicativo de contêiner obtenha credenciais ao ser executado em AWS e quando executado em um ambiente local. Se o aplicativo de contêiner já usa uma cadeia de provedores de credenciais personalizada em vez do padrão, ele também pode ser estendido adicionando LicenseManagerTokenCredentialsProvider à cadeia personalizada.

    O trecho de código a seguir é um exemplo de criação de um AWS License Manager cliente usando Java.

    LicenseManagerClientBuilder clientBuilder = LicenseManagerClient.builder().credentialsProvider(LicenseCredentialsProvider.create());
  5. Chame a CheckoutLicense API operação usando o aws license-manager checkout-license comando de cada imagem de contêiner pago em sua oferta de produto. Isso verifica se o comprador tem o direito de usar uma licença para o aplicativo. Se o comprador tiver direito ao aplicativo, CheckoutLicense obterá êxito e devolverá os direitos solicitados e os valores. Se o comprador não tiver direito ao aplicativo, CheckoutLicense lançará uma exceção.

    Os seguintes parâmetros são necessários ao chamar a CheckoutLicense API operação:

    • CheckoutType: os valores válidos são PROVISIONAL ou PERPETUAL:

      • Use PERPETUAL quando a quantidade de direitos retirados será esgotada do conjunto.

        Exemplo: o comprador tem o direito de processar 500 GB de dados. À medida que continua processando os dados, a quantidade é retirada e esgotada do conjunto de 500 GB.

      • Use PROVISIONAL para direitos de licença flutuante, em que os direitos são retirados do conjunto e devolvidos após o uso.

        Exemplo: o usuário tem direito a 500 usuários simultâneos no aplicativo. Conforme os usuários fazem login ou se desconectam, eles são retirados ou retornados ao conjunto de 500 usuários. Para saber mais sobre direitos de licença flutuante, consulte Direitos de licença flutuante no License Manager.

    • ClientToken: um identificador exclusivo e que diferencia maiúsculas e minúsculas. Recomendamos usar um aleatório UUID para cada solicitação exclusiva.

    • Entitlements: uma lista de direitos a serem verificados.

      • Para direitos de recursos, forneça as propriedades Name e Unit assim.

        { "Name": "<Entitlement_Name>", "Unit": "None" }
      • Para direitos contados, forneça as propriedades Name, Unit e Count assim.

        { "Name": "<Entitlement_Name>", "Unit": "<Entitlement_Unit>", "Value": <Desired_Count> }
    • KeyFingerprint: a impressão digital de chave para licenças emitidas pelo AWS Marketplace é aws:294406891311:AWS/Marketplace:issuer-fingerprint. O uso dessa impressão digital de chave garante que a licença seja emitida por AWS Marketplace e não por uma entidade não confiável.

    • ProductSKU— O ID do produto gerado Portal de gerenciamento do AWS Marketplace nas etapas anteriores.

    O trecho a seguir é um exemplo de uma chamada usando a CheckoutLicense API operação usando o. 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"
    nota

    Para verificar as licenças, os aplicativos de contêiner exigem acesso de saída à rede para usar o License Manager. Os aplicativos implantados on-premises podem ter acesso de saída lento ou não confiável à rede. Esses aplicativos devem incluir novas tentativas adequadas ao chamar o License Manager. Para obter mais informações, consulte Práticas recomendadas para integração com o License Manager para implantações on-premises.

  6. Ligue para a CheckoutLicense API operação regularmente para identificar quaisquer alterações nas licenças dos clientes devido a renovações, upgrades ou cancelamentos feitos em. AWS Marketplace A cadência depende do aplicativo. Recomendamos verificar as licenças uma vez por dia para receber as alterações automaticamente sem a intervenção do comprador.

    Um aplicativo implantado on-premises pode ter acesso não confiável à rede de saída para verificar as licenças em um ritmo regular. Nesses casos, o aplicativo deve usar licenças em cache para obter resiliência suficiente. Para obter mais informações, consulte Práticas recomendadas para integração com o License Manager para implantações on-premises.

  7. Depois de integrar a chamada CheckoutLicense ao seu aplicativo de contêiner, crie uma nova versão da imagem de contêiner do Docker com as alterações.

  8. Atualize o gráfico Helm do seu aplicativo para aceitar um segredo do Kubernetes como entrada opcional que contém a configuração para acessar licenças usando o License Manager. APIs O segredo de configuração conterá um token de identidade emitido pelo License Manager e uma AWS Identity and Access Management função que será usada pelo provedor de credenciais personalizado descrito anteriormente para obter AWS credenciais para chamar o License Manager APIs quando o aplicativo de contêiner for implantado localmente. Além disso, adicione a Região da AWS como uma entrada com um valor padrão deus-east-1.

    Os compradores que implantam o aplicativo de contêiner localmente podem criar o segredo do Kubernetes por meio da experiência do AWS Marketplace comprador em produtos de contêiner. Forneça o nome do segredo do Kubernetes como entrada para o comando helm install. O segredo da configuração tem o seguinte formato:

    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. Atualize o modelo de implantação do aplicativo no gráfico do Helm para imagens de contêiner integradas AWS License Manager para incluir o seguinte:

    • Conta de serviço para pod — A conta de serviço é necessária para implantações do Helm na Amazon. EKS Ele é usado para obter permissões para chamar as API operações do License Manager configurando IAM funções para a conta de serviço na imagem do contêiner. Para obter mais informações sobre IAM funções para contas de serviço, consulte IAMfunções para contas de serviço.

    • Acesso à licença para implantações locais — O segredo da configuração da licença é necessário para fornecer credenciais e permissões apropriadas para chamar as API operações do License Manager para implantações do Helm em ambientes locais. Os compradores gerarão e fornecerão o segredo da licença à Helm a partir da experiência do AWS Marketplace comprador.

    O snippet de código a seguir é um exemplo de especificação de implantação com a conta de serviço, a configuração da licença e o segredo de extração da imagem.

    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 }}
    nota

    O segredo da configuração da licença é opcional. Os compradores usam o valor somente para implantações on-premises. Para AWS implantações, a especificação de implantação deve incluir uma conta de serviço para as imagens integradas do License Manager.

  10. Teste a integração do License Manager localmente e na Amazon EKS executando as etapas nas seguintes seções:

    1. Teste da integração do License Manager localmente

    2. Testando a integração do License Manager na Amazon EKS

  11. Depois de verificar com êxito a integração do License Manager no local AWS e no local, você pode criar sua lista de produtos de contêiner seguindo as etapas emCriar um produto de contêiner.

Teste da integração do License Manager localmente

Você pode usar o minikube ou qualquer outra configuração para testar a integração do License Manager em qualquer cluster Kubernetes localmente. Certifique-se de que o cluster Kubernetes tenha acesso de saída à Internet para chamar as operações do License Manager. API

Para testar uma integração do License Manager localmente
  1. Crie uma licença de teste em uma conta de vendedor de teste com os direitos desejados. Para configurar uma licença de teste, consulte CreateLicensena AWS License Manager APIReferência. Ou use o script a seguir para criar uma licença de teste e, em seguida, criar uma concessão de licença para uma conta de comprador de teste para consumir a licença. O script a seguir usa as credenciais da conta de vendedor de teste.

    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. Crie um segredo do Kubernetes com o token de licença e a IAM função usando o formato secreto definido anteriormente. Use a CreateToken API operação License Manager para gerar um token de licença. Em seguida, use a IAM CreateRole API operação para criar uma IAM função com permissões e uma política de confiança. Veja o exemplo no script seguinte. O script a seguir usa as credenciais da conta de comprador de teste.

    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. Configure qualquer cluster Kubernetes hospedado fora. AWS Use-o para testar se os aplicativos AWS License Manager API de contêiner podem se conectar a outros ambientes AWS e se o provedor de credenciais personalizadas está bem integrado ao aplicativo.

  4. Implante o token de licença e a IAM função gerados anteriormente no cluster local do Kubernetes.

    kubectl create secret generic "awsmp-license-access-config" \ --from-literal=license_token=${TOKEN} \ --from-literal=iam_role=${ROLE_ARN}
  5. Implante seu aplicativo por meio do Helm com o nome secreto como entrada e verifique se o aplicativo pode chamar as API operações do License Manager para realizar verificações de direitos. Para alterações nas especificações do Helm e da implantação, consulte a Etapa 9 em Integrando um produto AWS Marketplace for Containers Anywhere com o License Manager.

Testando a integração do License Manager na Amazon EKS

Você também pode testar a integração do License Manager na AmazonEKS. Teste para garantir que o aplicativo possa chamar as API operações do License Manager sem o segredo da configuração da licença. Certifique-se também de que a conta de serviço possa ser usada para configurar IAM funções para contas de serviço (IRSA) e fornecer credenciais relevantes para o aplicativo.

Para testar a integração do License Manager na Amazon EKS
  1. Crie uma licença de teste em uma conta de vendedor de teste com os direitos desejados. Consulte a CreateLicense APIreferência para configurar sua licença de teste ou use o script a seguir para criar uma e criar uma concessão de licença para uma conta de comprador de teste para consumir a licença. O script a seguir usa as credenciais da conta de vendedor de teste.

    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. Crie um EKS cluster de teste da Amazon com as configurações desejadas ou execute os seguintes comandos para usar uma configuração padrão.

    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. Crie uma conta de serviço para um cluster existente e associe-a a uma IAM função. O comando a seguir cria uma IAM função com AWSLicenseManagerConsumptionPolicy o. Em seguida, o comando o anexa à conta de test_sa serviço do EKS cluster da Amazon em que as imagens integradas do License Manager devem ser implantadas. Como resultado, a conta de serviço pode obter as credenciais apropriadas para chamar as API operações do License Manager.

    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. Implante o aplicativo por meio do Helm na conta de serviço em que a IAM função está associada ao comando anterior. Verifique se o aplicativo pode chamar as API operações do License Manager para realizar verificações de direitos.

Direitos de licença flutuante no License Manager

Com licenças flutuantes, à medida que os usuários acessam o aplicativo, uma licença é retirada do conjunto de licenças disponíveis. À medida que os usuários se desconectam, as licenças são adicionadas novamente ao conjunto de licenças disponíveis.

Para licenças flutuantes, o aplicativo usa a CheckoutLicense API operação para verificar os direitos do pool de direitos quando o recurso está sendo usado. A resposta da CheckoutLicense API operação inclui um token de consumo de licença, que é um identificador exclusivo para o checkout. O token de consumo de licença pode realizar ações adicionais nos direitos que são retirados, como devolvê-los ao conjunto de licenças ou estender a finalização da compra.

Quando o recurso não está mais em uso, o aplicativo usa a CheckInLicense API operação para verificar o direito de volta ao pool.

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

Se a devolução de uma licença ao conjunto falhar, por exemplo, se o aplicativo falhar durante a operação, o direito será devolvido ao conjunto automaticamente após 60 minutos. Por esse motivo, se o recurso estiver em uso por mais de 60 minutos, é uma prática recomendada manter o direito retirado do conjunto. Para fazer isso, use a ExtendLicenseConsumption API operação enquanto o recurso estiver sendo usado.

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

Práticas recomendadas para integração com o License Manager para implantações on-premises

Implantações de aplicativos de contêiner em um ambiente on-premises podem encontrar acesso não confiável à rede de saída. Use as práticas recomendadas a seguir para aumentar a resiliência e evitar a interrupção do serviço para os compradores devido a possíveis problemas causados pela baixa conectividade com a Internet:

  • Nova tentativa adequada — Problemas transitórios de rede podem impedir que seu aplicativo se conecte a. AWS License Manager Implemente novas tentativas por até 30 minutos, com recuo exponencial. Isso pode ajudar a evitar interrupções de curto prazo ou problemas de rede.

  • Evitar limites rígidos: os aplicativos implantados em clusters conectados podem verificar regularmente as licenças para identificar quaisquer alterações devido a atualizações ou renovações. Com o acesso externo não confiável, o aplicativo pode não conseguir identificar essas alterações. Sempre que possível, o aplicativo deve evitar a interrupção do serviço aos compradores devido à incapacidade de verificar as licenças por meio do License Manager. Os aplicativos podem recorrer a uma experiência de teste gratuito ou de código aberto quando a licença expirar e não podem verificar se a licença é válida.

  • Notificar os clientes: ao usar uma licença em cache, quaisquer alterações na licença (incluindo renovações ou upgrades) não são refletidas automaticamente na workload em execução. Notifique os clientes (que eles devem permitir o acesso externo ao aplicativo novamente temporariamente para que o aplicativo possa atualizar a licença em cache). Por exemplo, notifique os clientes por meio do próprio aplicativo ou da documentação. Da mesma forma, ao recorrer a um conjunto inferior de funcionalidades, notifique os clientes que os direitos estão esgotados ou que a licença expirou. Em seguida, eles podem optar por atualizar ou renovar.

LicenseManagerCredentialsProvider: implementação de Java

LicenseCredentialsProviderestende a cadeia AWS SDK de provedores de credenciais padrão para uso local adicionando. 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

LicenseManagerTokenCredentialsProviderfornece credenciais usando tokens de identidade OIDC emitidos pelo License Manager em ambientes locais. Você deve incluir o código-fonte do LicenseCredentialsProvider no caminho de classe do seu aplicativo.

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: implementação do Golang

LicenseCredentialsProvider

LicenseCredentialsProviderestende a cadeia AWS SDK de provedores de credenciais padrão para uso local adicionando. 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

LicenseManagerTokenCredentialsProviderfornece credenciais usando tokens de identidade OIDC emitidos pelo License Manager em ambientes locais. Você deve incluir o código-fonte do LicenseCredentialsProvider no caminho de classe do seu aplicativo.

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 } }