

Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.

# Contrata los precios de los productos en contenedores con AWS License Manager
<a name="container-license-manager-integration"></a>

En el caso de los productos basados en contenedores con precios por contrato, puede utilizarlos AWS License Manager para asociar licencias a su producto. AWS License Manager es una herramienta de administración de licencias que permite a su aplicación realizar un seguimiento y actualizar las licencias (también conocidas como derechos) que haya adquirido un cliente. En esta sección se proporciona información sobre cómo integrar su producto con. AWS License Manager Una vez completada la integración, puede publicar su listado de productos en AWS Marketplace.

Si va a integrar License Manager con un AWS Marketplace producto de Containers Anywhere para Amazon EKS Anywhere, Amazon ECS Anywhere, Amazon Elastic Compute Cloud (Amazon EC2) o una infraestructura local, siga las instrucciones que se indican en. [Integración de una versión AWS Marketplace para Containers Anywhere con License Manager](container-anywhere-license-manager-integration.md)

Para obtener más información al respecto AWS License Manager, consulte la [Guía del AWS License Manager usuario](https://docs.aws.amazon.com/license-manager/latest/userguide/license-manager.html) y la [AWS License Manager](https://docs.aws.amazon.com/cli/latest/reference/license-manager/index.html)sección de la Referencia de *AWS CLI comandos*.

Para obtener más información sobre la integración AWS License Manager con productos de contenedores con precios contractuales, consulta el laboratorio de [integración con pagos anticipados](https://catalog.workshops.aws/mpseller/en-US/container/integrate-contract) del *taller para AWS Marketplace vendedores*.

**Topics**
+ [Precios contractuales para productos de contenedores](#container-contracts)
+ [Modelos de licencia](#container-LM-license-models)
+ [AWS License Manager requisitos previos de integración](#container-LM-prereqs)
+ [Integración de un producto de contenedor en License Manager](#container-integrate-with-LM)
+ [Operaciones de API del License Manager](#container-LM-API-calls)
+ [Renovaciones y actualizaciones de licencias](#container-LM-lic-renew-upgrade)
+ [Integración de una versión AWS Marketplace para Containers Anywhere con License Manager](container-anywhere-license-manager-integration.md)

## Precios contractuales para productos de contenedores
<a name="container-contracts"></a>

En el caso de los productos basados en contenedores con precios contractuales, AWS Marketplace facture a sus clientes por adelantado o según el calendario de pagos que usted defina, en función del contrato entre usted y su cliente. Desde ese momento, tienen derecho a utilizar esos recursos. 

Para fijar sus precios, elija una o más duraciones de contrato que ofrezca a los clientes. Puede introducir precios diferentes para cada duración de contrato. Sus opciones son duraciones de 1 mes, 12 meses, 24 meses y 36 meses. En el caso de las ofertas privadas, puede especificar una duración personalizada en meses (hasta 60 meses). 

Elija la categoría que mejor describa los precios de su producto. Los clientes pueden ver la categoría de precios en el sitio web. AWS Marketplace Puede elegir entre **ancho de banda** (GB/s, MB/s), **datos** (GB, MB, TB), **hosts**, **solicitudes**, **niveles** o **usuarios**. Si ninguna de las categorías predefinidas se ajusta a sus necesidades, puede elegir la categoría más genérica **unidades** . 

La oferta permite agregar hasta 24 dimensiones.


**Ejemplo: aplicación de almacenamiento de datos**  

|   | Precio de 1 mes | Precio de 12 meses  | Precio de 24 meses  | Precio de 36 meses  | 
| --- | --- | --- | --- | --- | 
|  Datos no cifrados (GB)  |  1,50 USD/GB  |  16,00 USD/GB  |  30,00 USD/GB  |  60,00 USD/GB  | 
|  Datos cifrados (GB)  |  1,55 USD/GB  |  16,60 USD/GB  |  31,20 USD/GB  |  61,20 USD/GB  | 


**Ejemplo: Producto de monitorización de registros**  

|   | Precio de 1 mes | Precio de 12 meses  | Precio de 24 meses | Precio de 36 meses | 
| --- | --- | --- | --- | --- | 
|  Básico (10 hosts supervisados, 5 contenedores supervisados)  |  100 USD  |  1.000 \$1  | 2.000 \$1  | 4.000 \$1 | 
|  Estándar (20 hosts supervisados, 10 contenedores supervisados)  |  \$1200  |  2.000 \$1  | 4.000 \$1  | 8000\$1 | 
|  Profesional (40 hosts supervisados, 20 contenedores supervisados)  |  400 \$1  |  4.000 \$1  | 8000 DÓLARES  | 16.000 DÓLARES | 
|  Hosts adicionales supervisados por hora  | 10 DÓLARES  | 100 USD  |  \$1200 | 400 \$1 | 
|  Contenedores adicionales supervisados por hora  | 10\$1  | 100 USD  |  \$1200 | 400 \$1 | 

**nota**  
Los precios pueden ser para las siguientes duraciones: 1 mes, 12 meses, 24 meses o 36 meses. Puedes optar por ofrecer una o varias de estas opciones para el producto. Las duraciones deben ser las mismas en cada dimensión.   

**Example**  
Por ejemplo, en el caso de que tengas `AdminUsers` dimensiones `ReadOnlyUsers` y dimensiones, si ofreces un precio anual ReadOnlyUsers`AdminUsers`, también debes ofrecer un precio anual.


### Renovaciones automáticas
<a name="ami-contracts-automatic-renewals"></a>

 Cuando los clientes compren tu producto AWS Marketplace mediante contratos de contenedores, pueden aceptar renovar automáticamente las condiciones del contrato. Los clientes siguen pagando los derechos cada mes o durante 1, 2 o 3 años. 

Los clientes pueden cambiar su configuración de renovación en cualquier momento. Para obtener más información, consulte [Modificación de un contrato existente](https://docs.aws.amazon.com/marketplace/latest/buyerguide/buyer-container-contracts.html#modify-existing-contract) en la *Guía del comprador de AWS Marketplace *.

## Modelos de licencia
<a name="container-LM-license-models"></a>

AWS Marketplace la integración AWS License Manager admite dos modelos de licencia:
+ [Modelo de licencia configurable](#container-LM-config-lic-model)
+ [Modelo de licencia por niveles](#container-LM-tiered-lic-model)

### Modelo de licencia configurable
<a name="container-LM-config-lic-model"></a>

El modelo de licencia configurable (también conocido como modelo de licencia cuantificable) da derecho al comprador a una cantidad específica de recursos una vez que haya adquirido una licencia. 

Establezca una dimensión de precios y un precio por unidad. A continuación, el comprador puede elegir la cantidad de recursos que quiere comprar.

**Example de dimensión del precio y del precio por unidad**  
Puede establecer una dimensión de precios (como la copia de seguridad de datos) y un precio por unidad (por ejemplo, 30 USD por unidad).  
El comprador puede elegir entre comprar 5, 10 o 20 unidades.   
Su producto rastrea y mide el uso para medir la cantidad de recursos consumidos.

Con el modelo de configuración, los derechos se cuentan de una de estas dos maneras:
+ [Licencias reducidas](#container-floating-lic)
+ [Licencias flotantes](#container-floating-lic) 

#### Licencia reducidas
<a name="container-drawndown-lic"></a>

 La licencia se extrae del conjunto de licencias permitidas en el momento de su uso. Ese derecho se retira de forma permanente y no se puede devolver al conjunto de licencias.

**Example de procesamiento una cantidad limitada de datos**  
Un usuario tiene derecho a procesar 500 GB de datos. A medida que se siguen procesando los datos, la cantidad se extrae del conjunto de 500 GB hasta que se consuman todas las licencias de 500 GB.

En el caso de las licencias reducibles, puede utilizar la operación de API `CheckoutLicense` para comprobar las unidades de licencia (derechos) que se consumen. 

**Example de respaldo en Amazon S3 durante un número de unidades/año**  
Tiene un producto de almacenamiento que permite realizar copias de seguridad en Amazon Simple Storage Service de hasta 1024 unidades de datos durante un año. Puede lanzar su aplicación mediante varias instancias de Amazon EC2. Su aplicación tiene un mecanismo para rastrear y agregar datos. El software ejecuta la operación de API `CheckoutLicense` con el identificador del producto en cada copia de seguridad o a intervalos fijos para actualizar las cantidades consumidas.   
En este ejemplo, el software llama a la operación de API `CheckoutLicense` para comprobar 10 unidades de datos. Cuando la capacidad total alcanza el límite de copias de seguridad que el cliente ha adquirido, se produce un error en la llamada a la API.

**Solicitud**

```
linux-machine ~]$ aws license-manager checkout-license\
--product-sku "2205b290-19e6-4c76-9eea-377d6bf7la47" \
--checkout-type "PERPETUAL" \
--key-fingerprint "aws:294406891311:AWS/Marketplace:issuer-fingerprint" \
--entitlements "Name=DataConsumption, Value=l0, Unit=Count" \
--client-token "AKIAIOSFODNN7EXAMPLE"
```

**Respuesta**

```
{"CheckoutType": "PERPETUAL",
"EntitlementsAllowed": [{
"Name": "IntermediateTier",
"Units": "None"
}],
"Expiration": "2021-04-22Tl9:02:36",
"IssuedAt": "2021-04-22Tl8:02:36",
"LicenseArn": "arn:aws:license-manager::294406891311:license:l-16bf01b...",
"LicenseConsumptionToken": "AKIAIOSFODNN7EXAMPLE"
}
```

#### Licencias flotantes
<a name="container-floating-lic"></a>

 La licencia se devuelve al conjunto de la cantidad permitida de licencias después de su uso.

En el caso de las licencias flotantes, la aplicación retira los derechos del conjunto de derechos mediante la operación de API `CheckoutLicense` cuando se utiliza el recurso. La respuesta de la operación de API `CheckoutLicense` incluye un token de consumo de licencias, que es un identificador único para el proceso de compra. El token de consumo de la licencia se puede utilizar para realizar acciones adicionales con respecto a los derechos retirados, como reintegrarlos en la licencia o prolongar el proceso de retirada.

Para reintegrar los derechos en el conjunto, use la operación de API `CheckInLicense` cuando el recurso ya no esté en uso.

```
aws license-manager check-in-license --license-consumption-token "f1603b3c1f574b7284db84..."
```

Si no se registra el derecho (en caso de que la aplicación se bloquee), el derecho se reintegra automáticamente en el conjunto después de 60 minutos. Si el recurso se usa durante más de 60 minutos, se recomienda mantener el derecho excluido del conjunto mediante la operación de API `ExtendLicenseConsumption` mientras se utilice el recurso.

```
aws license-manager extend-license-consumption --license-consumption-token "f1603b3c1f574b7284..."
```

**Example de número de usuarios a partir de un límite superior fijo**  
Un usuario tiene derecho a 500 usuarios simultáneos en la aplicación. A medida que los usuarios inician y cierran sesión, los usuarios se retiran y devuelven al grupo de 500 usuarios. Sin embargo, la aplicación no puede retirar más de 500 usuarios del grupo porque el límite máximo fijado es 500 usuarios simultáneos.

En el caso de derechos variables, puede utilizar la operación de API `CheckInLicense` para devolver las unidades de licencia al conjunto de derechos. 

**Example de número de usuarios simultáneos durante un año**  
El precio de su producto se basa en la cantidad de usuarios simultáneos. El cliente adquiere una licencia para 10 usuarios durante un año. El cliente lanza el software proporcionando permisos (de IAM) de AWS Identity and Access Management . Cuando un usuario inicia sesión, la aplicación llama a la operación de API `CheckoutLicense` para reducir la cantidad en 1. Cuando el usuario cierra sesión, la aplicación devuelve la licencia al conjunto mediante una llamada a la operación de API `CheckInLicense`. Si no llama a `CheckInLicense`, la unidad de licencia se registrará automáticamente después de 1 hora.

**nota**  
En la siguiente solicitud, `key-fingerprint` no es un valor de marcador de posición, sino de valor real de la huella digital con la que se publicarán todas las licencias.

**Solicitud**

```
aws license-manager checkout-license\
--product-sku "2205b290-19e6-4c76-9eea-377d6bf7la47" \
--checkout-type "PROVISIONAL" \
--key-fingerprint "aws:294406891311:AWS/Marketplace:issuer-fingerprint" \
--entitlements "Name=ReadOnlyUSers, Value=l0, Unit=Count" \
--client-token "AKIAIOSFODNN7EXAMPLE"
```

**Respuesta**

```
{
  "CheckoutType": "PROVISIONAL",
  "EntitlementsAllowed": [
    {
      "Name": "ReadOnlyUsers", 
      "Count": 10,
      "Units": "Count",
      "Value": "Enabled"
    }
},
  "Expiration": "2021-04-22Tl9:02: 36",
  "IssuedAt": "2021-04-22Tl8:02:36",
  "LicenseArn": "arn:aws:license-manager::294406891311:license:l-16bf01b...",
  "LicenseConsumptionToken": "AKIAIOSFODNN7EXAMPLE"
}
```

### Modelo de licencia por niveles
<a name="container-LM-tiered-lic-model"></a>

El modelo de licencia por niveles da derecho al comprador a un nivel o nivel específico de características de la aplicación una vez que el comprador haya adquirido una licencia. 

Puede crear niveles para su producto, como Básico, Intermedio y Premium. A continuación, el comprador selecciona uno de los niveles predefinidos.

La aplicación no necesita rastrear ni medir el uso de la aplicación.

Con el modelo de licencia por niveles, los derechos no se cuentan, sino que representan un nivel de servicio adquirido por el cliente. 

Si desea ofrecer funciones agrupadas, es preferible utilizar niveles. 

**Example de los niveles Básico, Intermedio y Premium**  
Un cliente puede firmar un contrato para uno de los tres niveles posibles del software: Básico, Intermedio o Premium. Cada uno de estos niveles tiene sus propios precios. El software puede identificar el nivel al que se ha registrado el cliente invocando la operación de API `CheckoutLicense` y especificando todos los niveles posibles en la solicitud.   
La respuesta a la solicitud contiene el derecho correspondiente al nivel que el cliente ha adquirido. En función de esta información, el software puede proporcionar la experiencia de cliente adecuada.

#### Solicitud
<a name="container-LM-tiered-request"></a>

```
linux-machine  ~]$ aws  license-manager   checkout-license\
--product-sku  "2205b290-19e6-4c76-9eea-377d6bf7la47"  \
--checkout-type  "PROVISIONAL"  \
--key-fingerprint  "aws:294406891311:AWS/Marketplace:issuer-fingerprint" \
--entitlements  "Name=BasicTier,  Unit=None"   "Name=IntermediateTier,  Unit=None"	\ "Name=PremiumTier, Unit=None"
```

#### Respuesta
<a name="container-LM-tiered-response"></a>

```
{
  "CheckoutType": "PROVISIONAL",
  "EntitlementsAllowed": [
    {
      "Name": "IntermediateTier", 
      "Units": "None"
    }
},
  "Expiration": "2021-04-22Tl9:02:36",
  "IssuedAt": "2021-04-22Tl8:02:36",
  "LicenseArn": "arn:aws:license-manager::294406891311:license:l-16bf01b...",
  "LicenseConsumptionToken": "AKIAIOSFODNN7EXAMPLE"
}
```

## AWS License Manager requisitos previos de integración
<a name="container-LM-prereqs"></a>

Antes de publicar el producto, debe hacer lo siguiente:

1. Cree un nuevo producto contenedor en el AWS Marketplace Management Portal y anote su código de producto.

   Para obtener más información, consulte [Descripción general: creación de un producto de contenedor](container-product-getting-started.md#create-container-product).

1. Utilice un rol de IAM para la tarea o pod que ejecuta la aplicación con los permisos de IAM necesarios para llamar a las operaciones de API `CheckoutLicense`, `ExtendLicenseConsumption` y `CheckInLicense`.

   Los permisos de IAM necesarios se detallan en la siguiente política de IAM.

------
#### [ JSON ]

****  

   ```
   {
      "Version":"2012-10-17",		 	 	 
      "Statement":[
         {
            "Sid":"VisualEditorO",
            "Effect":"Allow",
            "Action":[
               "license-manager:CheckoutLicense",
               "license-manager:GetLicense",
               "license-manager:CheckInLicense",
               "license-manager:ExtendLicenseConsumption",
               "license-manager:ListReceivedLicenses"
            ],
            "Resource":"*"
         }
      ]
   }
   ```

------

1. Realice una llamada de prueba a la operación de API `RegisterUsage` con un registro para todas las dimensiones de precios que defina.

## Integración de un producto de contenedor en License Manager
<a name="container-integrate-with-LM"></a>

**Para integrar su producto basado en contenedores en License Manager**

1. Configure los permisos de IAM para llamar a License Manager. Para obtener más información, consulte [AWS License Manager requisitos previos de integración](#container-LM-prereqs).

1. Descarga el AWS SDK.
**nota**  
No configure AWS las credenciales en su software. AWS las credenciales del comprador se obtienen automáticamente en tiempo de ejecución cuando el contenedor se ejecuta en una instancia de Amazon EC2, una tarea de Amazon ECS o un pod de Amazon EKS.

1. Agregue comprobaciones de licencia a su producto.

   Su producto puede ejecutar la operación de API `CheckoutLicense` en cualquier lugar donde deba realizarse la verificación de la licencia. Para comprobar la licencia, el producto debe saber:

   1. El emisor de confianza de la licencia (AWS Marketplace).

   1. El SKU (ID del producto) del producto de la aplicación

   1. El derecho a comprobar la existencia de esta solicitud

   Las llamadas a la API varían según el tipo de licencias de precios que configure.

1. Publica tu listado de productos en. AWS Marketplace

## Operaciones de API del License Manager
<a name="container-LM-API-calls"></a>

Para administrar las licencias almacenadas en la cuenta de License Manager del cliente, el software puede utilizar las siguientes operaciones de API:
+ `GetLicense`: una API que el software puede consultar. Recupera el estado de una licencia comprada (es decir, vencida o que vence pronto) y envía una notificación de estado al cliente.
+ `CheckoutLicense`: descubre las licencias que el usuario ha adquirido. También puede utilizar la operación de API `CheckoutLicense` para actualizar la cantidad de licencias cuando el usuario haya consumido cierta cantidad de licencias. Con `CheckoutLicense`, puede seguir comprobando las cantidades de licencias que utiliza el cliente. Cuando el cliente agota todas las licencias, esta llamada devuelve un error. Para obtener información sobre la cadencia de ejecución sugerida para ejecutar `CheckoutLicense`, consulte [Renovaciones y actualizaciones de licencias](#container-LM-lic-renew-upgrade).
+ `ExtendLicenseConsumption`: en el caso de dimensiones flotantes, cuando el software retire una licencia, la licencia volverá al conjunto automáticamente transcurridos 60 minutos. Si desea prolongar el tiempo que la licencia permanece retirada, utilice la operación de API `ExtendLicenseConsumption` para ampliarla otros 60 minutos.
+ `CheckInLicense`: en el caso de dimensiones flotantes, cuando desee devolver la licencia al conjunto de derechos, utilice la operación de API `CheckInLicense`.
+ API de `ListReceivedLicenses`: muestra las licencias adquiridas por el comprador.

## Renovaciones y actualizaciones de licencias
<a name="container-LM-lic-renew-upgrade"></a>

Los clientes pueden renovar o actualizar sus licencias en el AWS Marketplace Management Portal. Tras realizar una compra adicional, AWS Marketplace genera una nueva versión de la licencia que refleja los nuevos derechos. El software lee los nuevos derechos mediante las mismas operaciones de API. No tiene que hacer nada diferente en términos de integración de License Manager para administrar las renovaciones y actualizaciones.

Debido a las renovaciones, actualizaciones, vencimientos, etc. de licencias, le recomendamos que su producto ejecute la operación de API `CheckoutLicense` con regularidad mientras esté en uso. Si utiliza la operación de API `CheckoutLicense` de forma regular, el producto puede detectar cambios en los derechos, como las actualizaciones o el vencimiento.

Te recomendamos que realices la llamada a la API `CheckoutLicense` cada 15 minutos. 

# Integración de una versión AWS Marketplace para Containers Anywhere con License Manager
<a name="container-anywhere-license-manager-integration"></a>

Como AWS Marketplace vendedor, puede realizar la integración AWS License Manager con un AWS Marketplace producto de Containers Anywhere para Amazon EKS Anywhere, Amazon ECS Anywhere, Amazon EC2 o una infraestructura local. Las siguientes secciones proporcionan instrucciones para esta integración.

Para obtener información general sobre la integración de License Manager con AWS Marketplace, incluidos los modelos de licencia disponibles, consulte[Contrata los precios de los productos en contenedores con AWS License Manager](container-license-manager-integration.md). Para obtener más información sobre AWS License Manager, consulte la [Guía del usuario de AWS License Manager](https://docs.aws.amazon.com/license-manager/latest/userguide/license-manager.html) y la sección [AWS License Manager](https://docs.aws.amazon.com/cli/latest/reference/license-manager/index.html) de la *Referencia de comandos de la AWS CLI *.

**Topics**
+ [Integración de un producto AWS Marketplace de for Containers Anywhere con License Manager](#containers-anywhere-integrate-with-LM)
+ [Prueba de la integración de License Manager localmente](#container-testing-LM-integration-locally)
+ [Prueba de la integración de License Manager en Amazon EKS](#container-testing-LM-integration-EKS)
+ [Derechos de licencias flotantes con License Manager](#container-LM-floating-license)
+ [Prácticas recomendadas para la integración en License Manager para implementaciones en las instalaciones](#container-LM-best-practices-on-prem)
+ [`LicenseManagerCredentialsProvider`: implementación de Java](#container-license-manager-cred-provider-java)
+ [`LicenseManagerCredentialsProvider`: implementación de `Golang`](#container-license-manager-cred-provider-golang)

## Integración de un producto AWS Marketplace de for Containers Anywhere con License Manager
<a name="containers-anywhere-integrate-with-LM"></a>

Siga las siguientes instrucciones para integrar su AWS Marketplace producto de Containers Anywhere con AWS License Manager.

**Para integrar su AWS Marketplace producto de Containers Anywhere con License Manager**

1. Abra un navegador web e inicie sesión en [AWS Marketplace Management Portal](https://aws.amazon.com/marketplace/management/).

1. Cree un ID de producto para su producto de contenedor realizando los siguientes pasos. Utilizará este ID en su imagen del contenedor para comprobar las licencias en un paso posterior.

   1. En la barra de menús, expanda **Recursos** y elija **Contenedor**.

   1. Introduzca un nombre orientado al cliente para su producto y elija **Crear**. Puede cambiar este nombre posteriormente.

   1. Anote el **ID del proyecto**. Lo usará al crear o actualizar los detalles de precios del producto.
**sugerencia**  
Si pierde el identificador de su producto, puede encontrarlo AWS Marketplace Management Portal seleccionando **Container** en el menú **Activos**. La página **Contenedores** muestra una lista de tus productos con el producto asociado IDs.

1. Descarga el último AWS SDK público y, a continuación, instálalo en tu aplicación contenedora. Encontrará las instrucciones de instalación del AWS SDK que prefiera en [Tools to Build on AWS](https://aws.amazon.com/tools/).
**nota**  
Para llamar a las operaciones de la API de License Manager desde Amazon EKS Anywhere o desde un clúster de Kubernetes no proporcionado por AWS, debe usar un SDK compatible. AWS Para ver una lista de los compatibles AWS SDKs, consulte [Uso de un SDK](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts-minimum-sdk.html) compatible. AWS 

1. Cree un AWS License Manager cliente con un proveedor de credenciales personalizado para que pueda proporcionar credenciales a la aplicación contenedora implementada tanto en las instalaciones AWS como en las instalaciones. Para ver el código fuente completo de un proveedor de credenciales personalizado, `LicenseCredentialProvider`, consulte las siguientes secciones:
   + [`LicenseManagerCredentialsProvider`: implementación de Java](#container-license-manager-cred-provider-java)
   + [`LicenseManagerCredentialsProvider`: implementación de `Golang`](#container-license-manager-cred-provider-golang)

    `LicenseCredentialsProvider`amplía la cadena de proveedores de credenciales predeterminada del AWS SDK para su uso local mediante la adición de. `LicenseManagerTokenCredentialsProvider` Esta acción proporciona credenciales mediante el uso de tokens de identidad emitidos por el OIDC de License Manager en entornos locales. Debe incluir el código fuente para `LicenseCredentialsProvider` en la ruta de clases de su aplicación.
**nota**  
Ampliar el `DefaultCredentialsProvider` permite que la misma aplicación contenedora obtenga credenciales cuando se ejecuta en un entorno local AWS y cuando se ejecuta en él. Si la aplicación de contenedor ya usa una cadena de proveedores de credenciales personalizada en lugar de la predeterminada, también se puede ampliar agregando `LicenseManagerTokenCredentialsProvider` a la cadena personalizada.

   El siguiente fragmento de código es un ejemplo de cómo crear un AWS License Manager cliente con Java.

   ```
   LicenseManagerClientBuilder clientBuilder = LicenseManagerClient.builder().credentialsProvider(LicenseCredentialsProvider.create());
   ```

1. Llame a la operación de API `CheckoutLicense` mediante el comando `aws license-manager checkout-license` de cada imagen de contenedor de pago de su oferta de productos. Esto comprueba que el comprador tiene derecho a utilizar una licencia para su aplicación. Si el comprador tiene derecho a la solicitud, `CheckoutLicense` acepta y devuelve los derechos solicitados y sus valores. Si el comprador no tiene derecho a la solicitud, `CheckoutLicense` arroja una excepción.

   Se requieren los siguientes parámetros para llamar a la operación de API `CheckoutLicense`:
   + `CheckoutType`: los valores válidos son `PROVISIONAL` o `PERPETUAL`:
     + Use `PERPETUAL` cuando se agote la cantidad de derechos retirados del conjunto.

       Ejemplo: el comprador tiene derecho a procesar 500 GB de datos. A medida que continúa procesando los datos, la cantidad se descuenta y se agota del conjunto de 500 GB.
     + Utilice `PROVISIONAL` para derechos de licencia flotantes, en los que los derechos se retiran del conjunto y se devuelven después de su uso.

       Ejemplo: el usuario tiene derecho a 500 usuarios simultáneos en la aplicación. A medida que los usuarios inician o cierran sesión, los usuarios son descontados o devueltos al grupo de 500 usuarios. Para obtener más información sobre los derechos de licencia flotantes, consulte [Derechos de licencias flotantes con License Manager](#container-LM-floating-license).
   + `ClientToken`: un identificador único que distingue entre mayúsculas y minúsculas. Recomendamos usar un UUID aleatorio para cada solicitud única.
   + `Entitlements`: una lista de derechos para retirar.
     + En el caso de derechos de características, proporcione las propiedades `Name` y `Unit` como se indica a continuación.

       ```
       {
         "Name": "<Entitlement_Name>",
         "Unit": "None"
       }
       ```
     + Para los derechos contados, proporcione las propiedades `Name`, `Unit` y `Count` de la siguiente manera.

       ```
       {
         "Name": "<Entitlement_Name>",
         "Unit": "<Entitlement_Unit>",
         "Value": <Desired_Count>
       }
       ```
   + `KeyFingerprint`: la huella digital clave de las licencias emitidas por AWS Marketplace es `aws:294406891311:AWS/Marketplace:issuer-fingerprint`. El uso de esta huella digital clave garantiza que la licencia sea emitida por una entidad poco fiable AWS Marketplace y no por ella.
   + `ProductSKU`— El identificador del producto generado AWS Marketplace Management Portal en los pasos anteriores.

   El siguiente fragmento es un ejemplo de una llamada que utiliza la operación de API `CheckoutLicense` mediante la 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 comprobar las licencias, las aplicaciones de contenedor requieren acceso a la red saliente para poder utilizar License Manager. Es posible que las aplicaciones implementadas en las instalaciones experimenten un acceso lento o poco fiable a la red saliente. Estas aplicaciones deben incluir los reintentos adecuados al llamar a License Manager. Para obtener más información, consulte [Prácticas recomendadas para la integración en License Manager para implementaciones en las instalaciones](#container-LM-best-practices-on-prem).

1. Llame a la operación de API `CheckoutLicense` con regularidad para identificar cualquier cambio en las licencias de los clientes debido a renovaciones, actualizaciones o cancelaciones realizadas en AWS Marketplace. La cadencia depende de la aplicación. Recomendamos comprobar las licencias una vez al día para detectar los cambios automáticamente sin la intervención del comprador.

   Es posible que una aplicación implementada en las instalaciones tenga un acceso a la red saliente poco fiable para comprobar las licencias con regularidad. En esos casos, la aplicación debe utilizar licencias almacenadas en caché para garantizar una resiliencia suficiente. Para obtener más información, consulte [Prácticas recomendadas para la integración en License Manager para implementaciones en las instalaciones](#container-LM-best-practices-on-prem).

1. Tras integrar la llamada a `CheckoutLicense` en la aplicación de contenedor, cree una nueva versión de la imagen del contenedor de Docker con los cambios.

1. Actualice el diagrama de Helm de su aplicación para aceptar un secreto de Kubernetes como entrada opcional que contenga la configuración para acceder a las licencias mediante License Manager. APIs El secreto de configuración contendrá un token de identidad emitido por License Manager y un AWS Identity and Access Management rol que utilizará el proveedor de credenciales personalizadas descrito anteriormente para obtener AWS credenciales para llamar a License Manager APIs cuando la aplicación contenedora se despliegue localmente. Además, agregue la Región de AWS como entrada con un valor predeterminado de `us-east-1`.

   Los compradores que desplieguen la aplicación contenedora de forma local pueden crear el secreto de Kubernetes a través de la AWS Marketplace experiencia de compra de productos en contenedores. Proporcione el nombre del secreto de Kubernetes como entrada al comando `helm install`. El secreto de configuración se configura en el siguiente 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
   ```

1. Actualice la plantilla de despliegue de la aplicación en el diagrama de Helm para las imágenes de contenedores integradas con ellas para incluir AWS License Manager lo siguiente:
   + Cuenta de servicio para el pod: la cuenta de servicio es necesaria para las implementaciones de Helm en Amazon EKS. Se utiliza a fin de obtener permisos para llamar a las operaciones de la API de License Manager mediante la configuración de roles de IAM para la cuenta de servicio en la imagen del contenedor. Para obtener más información acerca de los roles de IAM para cuentas de servicio, consulte [Roles de IAM para cuentas de servicio](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html).
   + Acceso con licencia para implementaciones locales: el secreto de configuración de la licencia es necesario para proporcionar las credenciales y los permisos adecuados para llamar a las operaciones de API de License Manager para las implementaciones de Helm en entornos locales. Los compradores generarán y proporcionarán el secreto de licencia a Helm a partir de su experiencia de AWS Marketplace compra.

   El siguiente fragmento de código es un ejemplo de especificación de implementación con el secreto de la cuenta de servicio, la configuración de la licencia y la imagen extraída.

   ```
   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**  
El secreto de configuración de la licencia es opcional. Los compradores solo utilizan el valor para las implementaciones locales. Para AWS las implementaciones, la especificación de implementación debe incluir una cuenta de servicio para las imágenes integradas de License Manager.

1. Pruebe la integración de License Manager de forma local y en Amazon EKS siguiendo los pasos de las siguientes secciones:

   1. [Prueba de la integración de License Manager localmente](#container-testing-LM-integration-locally)

   1. [Prueba de la integración de License Manager en Amazon EKS](#container-testing-LM-integration-EKS)

1. Tras comprobar correctamente la integración de License Manager tanto en AWS las instalaciones como en las instalaciones, puede crear su listado de productos de contenedores siguiendo los pasos que se indican en[Descripción general: creación de un producto de contenedor](container-product-getting-started.md#create-container-product).

## Prueba de la integración de License Manager localmente
<a name="container-testing-LM-integration-locally"></a>

Puede usar minikube o cualquier otra configuración para probar la integración de License Manager en clústeres de Kubernetes de forma local. Asegúrese de que el clúster de Kubernetes tenga acceso saliente a Internet para llamar a las operaciones de API de License Manager.

**Para probar una integración de License Manager localmente**

1. Cree una licencia de prueba en una cuenta de vendedor de prueba con los derechos que desee. Para configurar una licencia de prueba, consulte la *referencia [CreateLicense](https://docs.aws.amazon.com/license-manager/latest/APIReference/API_CreateLicense.html)de la AWS License Manager API*. O bien, utilice el siguiente script para crear una licencia de prueba y, a continuación, cree una concesión de licencia a una cuenta de comprador de prueba para consumir la licencia. El siguiente script usa las credenciales de la cuenta de vendedor de prueba.

   ```
   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"
   ```

1. Cree un secreto de Kubernetes con el token de licencia y el rol de IAM utilizando el formato secreto definido anteriormente. Utilice la operación de API `CreateToken` de License Manager para generar un token de licencia. A continuación, utilice la operación de API `CreateRole` de IAM para crear un rol de IAM con permisos y una política de confianza. Vea un ejemplo en el siguiente script. El siguiente script utiliza las credenciales de la cuenta de comprador de prueba.

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

1. Configura cualquier clúster de Kubernetes alojado en un entorno externo. AWSÚselo para comprobar que las aplicaciones contenedoras pueden conectarse a la AWS License Manager API desde entornos distintos AWS y que el proveedor de credenciales personalizadas está bien integrado en la aplicación.

1. Implemente el token de licencia y el rol de IAM generados anteriormente en el clúster local de Kubernetes.

   ```
   kubectl create secret generic "awsmp-license-access-config" \
   --from-literal=license_token=${TOKEN} \
   --from-literal=iam_role=${ROLE_ARN}
   ```

1. Implemente su aplicación a través de Helm con el nombre del secreto como entrada y compruebe que la aplicación puede llamar a las operaciones de API de License Manager para realizar comprobaciones de derechos. Para ver los cambios en Helm y en las especificaciones de implementación, consulte el paso 9 de [Integración de un producto AWS Marketplace de for Containers Anywhere con License Manager](#containers-anywhere-integrate-with-LM).

## Prueba de la integración de License Manager en Amazon EKS
<a name="container-testing-LM-integration-EKS"></a>

También puede probar la integración de License Manager en Amazon EKS. Compruebe que la aplicación puede llamar a las operaciones de API de License Manager sin el secreto de configuración de la licencia. Asegúrese también de que la cuenta de servicio se pueda utilizar para configurar los roles de IAM para las cuentas de servicio (IRSA) y proporcionar las credenciales pertinentes a la aplicación.

**Para probar la integración de License Manager en Amazon EKS**

1. Cree una licencia de prueba en una cuenta de vendedor de prueba con los derechos que desee. Consulte la [referencia de la CreateLicense API](https://docs.aws.amazon.com/license-manager/latest/APIReference/API_CreateLicense.html) para configurar su licencia de prueba o utilice el siguiente script para crear una y crear una concesión de licencia a una cuenta de comprador de prueba para consumir la licencia. El siguiente script usa las credenciales de la cuenta de vendedor de prueba.

   ```
   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"
   ```

1. Cree un clúster de Amazon EKS de prueba con las configuraciones deseadas o ejecute los siguientes comandos para usar una configuración predeterminada.

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

1. Cree una cuenta de servicio para un clúster existente y asócielo a rol de IAM. Ejecute el siguiente comando para crear el rol de IAM con `AWSLicenseManagerConsumptionPolicy`. A continuación, el comando lo adjunta a la cuenta de servicio de `test_sa` del clúster de Amazon EKS donde se deben implementar las imágenes integradas de License Manager. Como resultado, la cuenta de servicio puede obtener las credenciales adecuadas para llamar a las operaciones de la API de 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
   ```

1. Implemente la aplicación mediante Helm en la cuenta de servicio a la que está asociada el rol de IAM desde el comando anterior. Compruebe que la aplicación pueda llamar a las operaciones de la API de License Manager para realizar comprobaciones de derechos.

## Derechos de licencias flotantes con License Manager
<a name="container-LM-floating-license"></a>

En el caso de las licencias flotantes, a medida que los usuarios inician sesión en la aplicación, se extrae una licencia del conjunto de licencias disponibles. A medida que los usuarios cierran sesión, las licencias se vuelven a agregar al conjunto de licencias disponibles.

En el caso de las licencias flotantes, la aplicación utiliza la operación de API `CheckoutLicense` para retirar los derechos del conjunto de derechos cuando se utiliza el recurso. La respuesta de la operación de API `CheckoutLicense` incluye un token de consumo de licencias, que es un identificador único para el proceso de compra. El token de consumo de licencias puede realizar acciones adicionales en los derechos que se retiran, como reintegrarlos al conjunto de licencias o prolongar el proceso de retirada.

Cuando el recurso deja de estar en uso, la aplicación utiliza la operación de API `CheckInLicense` para reintegrar los derechos en el conjunto.

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

Si se produce un error al reintegrar una licencia en el conjunto, por ejemplo, si la aplicación se bloquea durante la operación, el derecho se reintegra automáticamente en el conjunto transcurridos 60 minutos. Por este motivo, si el recurso se utiliza durante más de 60 minutos, se recomienda mantener el derecho retirado del conjunto. Para ello, utilice la operación de API `ExtendLicenseConsumption` siempre que se utilice el recurso.

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

## Prácticas recomendadas para la integración en License Manager para implementaciones en las instalaciones
<a name="container-LM-best-practices-on-prem"></a>

Las implementaciones de aplicaciones de contenedores en un entorno local pueden dar lugar a un acceso a la red saliente poco fiable. Utilice las siguientes prácticas recomendadas para aumentar la resiliencia y evitar que los compradores interrumpan el servicio debido a posibles problemas causados por una mala conectividad a Internet:
+ **Reintento adecuado**: los problemas transitorios de red pueden impedir que la aplicación se conecte a ella. AWS License Manager Implemente reintentos para hasta 30 minutos, con una reducción exponencial. Esta opción puede ayudar a evitar interrupciones a corto plazo o problemas de red.
+ **Evite límites estrictos**: las aplicaciones implementadas en clústeres conectados pueden comprobar periódicamente las licencias para identificar cualquier cambio debido a actualizaciones o renovaciones. Con un acceso saliente poco fiable, es posible que la aplicación no pueda identificar esos cambios. Siempre que sea posible, la aplicación debe evitar la interrupción del servicio a los compradores debido a la imposibilidad de comprobar las licencias a través de License Manager. Las aplicaciones pueden volver a una versión de prueba gratuita o de código abierto cuando la licencia vence y no pueden comprobar si una licencia es válida.
+ **Notifique a los clientes**: cuando se utiliza una licencia en caché, los cambios en la licencia (incluidas las renovaciones o las actualizaciones) no se reflejan automáticamente en la carga de trabajo en curso. Notifique a sus clientes (que deben volver a permitir el acceso saliente a la aplicación de forma temporal) para que la aplicación pueda actualizar su licencia en caché. Por ejemplo, notifique a los clientes a través de la propia aplicación o a través de su documentación. Del mismo modo, cuando recurra a un conjunto más reducido de funcionalidades, notifique a los clientes que sus derechos están agotados o que la licencia ha caducado. Luego, pueden elegir entre actualizar o renovar.

## `LicenseManagerCredentialsProvider`: implementación de Java
<a name="container-license-manager-cred-provider-java"></a>

`LicenseCredentialsProvider`amplía la cadena de proveedores de credenciales predeterminada del AWS SDK para su uso local mediante la adición de. `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` proporciona credenciales mediante el uso de tokens de identidad emitidos por el OIDC de License Manager en entornos en las instalaciones. Debe incluir el código fuente para `LicenseCredentialsProvider` en la ruta de clases de su aplicación.

```
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`: implementación de `Golang`
<a name="container-license-manager-cred-provider-golang"></a>

**`LicenseCredentialsProvider`**

`LicenseCredentialsProvider`amplía la cadena de proveedores de credenciales predeterminada del AWS SDK para su uso local mediante la adición de. `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` proporciona credenciales mediante el uso de tokens de identidad emitidos por el OIDC de License Manager en entornos en las instalaciones. Debe incluir el código fuente para `LicenseCredentialsProvider` en la ruta de clases de su aplicación.

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