

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.

# Configuración de medición por hora con AWS Marketplace Metering Service
<a name="container-metering-registerusage"></a>

**nota**  
 Para las implementaciones de EKS, el software debe usar los [roles de IAM para las cuentas de servicio (IRSA)](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html) a fin de firmar la llamada a la API para la operación de la API de [https://docs.aws.amazon.com/marketplace/latest/APIReference/API_marketplace-metering_RegisterUsage.html](https://docs.aws.amazon.com/marketplace/latest/APIReference/API_marketplace-metering_RegisterUsage.html). No se admite el uso de [EKS Pod Identity](https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html), el rol de nodo ni las claves de acceso a largo plazo.  
En el caso de las implementaciones de ECS, el software debe utilizar el rol de [IAM de tareas de Amazon ECS](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html) a fin de firmar la llamada a la API para la operación de la API de [https://docs.aws.amazon.com/marketplace/latest/APIReference/API_marketplace-metering_RegisterUsage.html](https://docs.aws.amazon.com/marketplace/latest/APIReference/API_marketplace-metering_RegisterUsage.html). No se admite el uso del rol de nodo ni de claves de acceso a largo plazo.

Si el producto de contenedor utiliza precios de tareas o por pod por hora en lugar de dimensiones de precios medidos personalizadas, no es necesario definir dimensiones de medición personalizadas. Puede utilizar AWS Marketplace Metering Service para la medición por hora con productos de contenedores en AWS Marketplace. En las siguientes secciones, se muestra cómo configurar la medición por hora con AWS Marketplace Metering Service.

La operación de API `RegisterUsage` mide el uso del software por tarea de Amazon Elastic Container Service (Amazon ECS) o por pod de Amazon Elastic Kubernetes Service (Amazon EKS), por hora, con el uso prorrateado al segundo. En el caso de las tareas o los pods que tienen una vida útil muy corta, se aplica un uso mínimo de un minuto. La medición continua para el uso del software es gestionada automáticamente por el AWS Marketplace Metering Control Plane. No es necesario que su software realice ninguna acción específica de medición, excepto llamar una vez a `RegisterUsage` para medir el uso del software para comenzar.

Se debe llamar a `RegisterUsage` inmediatamente al momento de lanzar un contenedor. Si no registra el contenedor en las primeras 6 horas desde su lanzamiento, el servicio de medición de AWS Marketplace no ofrece ninguna garantía de medición respecto a los meses anteriores. Sin embargo, la medición continuará durante el mes en curso hasta que finalice el contenedor.

Siguen AWS Marketplace Metering Control Plane facturando a los clientes por la ejecución de las tareas de Amazon ECS y los pods de Amazon EKS, independientemente del estado de la suscripción del cliente. Esto elimina la necesidad de que el software realice comprobaciones de derechos tras el lanzamiento inicial correcto de la tarea o el pod. 

Para obtener más información sobre la integración de la AWS Marketplace Metering Service API con productos de contenedores con precios por hora, consulte el laboratorio sobre cómo [integrar la medición por hora](https://catalog.workshops.aws/mpseller/en-US/container/integrate-hourly) del *taller para AWS Marketplace vendedores*. 

**Topics**
+ [Requisitos previos de medición por hora](#hourly-metering-prereqs)
+ [Prueba de la integración para `RegisterUsage`](#testing-integration-for-registerusage)
+ [Control de errores para `RegisterUsage`](#hourly-metering-entitlement-error-handling)
+ [Integración de su producto de contenedor con el servicio de medición de AWS Marketplace mediante AWS SDK para Java](java-integration-example-registerusage.md)

## Requisitos previos de medición por hora
<a name="hourly-metering-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 AWS Identity and Access Management (IAM) para la tarea o el pod que ejecuta la aplicación con los permisos de IAM necesarios para realizar la llamada. `RegisterUsage` La política administrada de `AWSMarketplaceMeteringRegisterUsage` tiene estos permisos. Para obtener más información sobre la política, consulte la Referencia [ AWSMarketplaceMeteringFullAccess](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AWSMarketplaceMeteringFullAccess.html)de *políticas AWS gestionadas*.

1. (Opcional) Si desea ver el registro, le recomendamos que habilite el AWS CloudTrail registro en la definición de la tarea o el módulo.

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

## Prueba de la integración para `RegisterUsage`
<a name="testing-integration-for-registerusage"></a>

Usa la operación de la `RegisterUsage` API para probar la integración antes de enviar la imagen AWS Marketplace para su publicación.

Llame `RegisterUsage` desde la imagen del contenedor ejecutando su producto en Amazon ECS o Amazon EKS. Usa la AWS cuenta en la que estás publicando el producto AWS Marketplace. Su integración de medición debe configurarlo de forma dinámica Región de AWS, en lugar de codificarlo de forma rígida. Sin embargo, al realizar las pruebas, lance al menos una tarea de Amazon ECS o un pod de Amazon EKS que contenga su contenedor de pago en la región del Este de EE. UU. (Virginia del Norte). De este modo, el equipo de AWS Marketplace operaciones puede verificar su trabajo con los registros de esa región.

**nota**  
Si el producto es compatible con Amazon ECS y con Amazon EKS, bastará con que realice el lanzamiento solo en Amazon EKS para que podamos validar la integración.

No puede probar totalmente la integración hasta que el producto se publique con todos los metadatos y la información de precios correspondiente. Si se solicita, el equipo de operaciones del AWS Marketplace catálogo puede verificar la recepción de sus registros de medición.

## Control de errores para `RegisterUsage`
<a name="hourly-metering-entitlement-error-handling"></a>

Si la imagen del contenedor se integra con el contenedor AWS Marketplace Metering Service y recibe una excepción que no sea `ThrottlingException` al arrancar el contenedor, debe cerrar el contenedor para evitar su uso no autorizado.

Las excepciones distintas de `ThrottlingException` se lanzan solo en la llamada inicial a la operación de API `RegisterUsage`. Las llamadas posteriores desde la misma tarea de Amazon ECS o pod de Amazon EKS no iniciarán la excepción `CustomerNotSubscribedException`, ni siquiera aunque el cliente cancele la suscripción mientras la tarea se está ejecutando. A estos clientes se les sigue cobrando la ejecución de los contenedores después de darse de baja y se realiza un seguimiento de su uso.

En la siguiente tabla se describen los errores que la operación de API `RegisterUsage` podrían lanzar. Cada lenguaje de programación del AWS SDK tiene un conjunto de pautas de gestión de errores que puedes consultar para obtener información adicional. 


|  **Error**  |  **Descripción**  | 
| --- | --- | 
|  InternalServiceErrorException  |  RegisterUsage no está disponible.  | 
|  CustomerNotEntitledException  |  El cliente no tiene una suscripción válida para el producto.  | 
|  InvalidProductCodeException  |  El valor de ProductCode que se pasa como parte de la solicitud no existe.  | 
|  InvalidPublicKeyException  |  El valor de PublicKeyVersion que se pasa como parte de la solicitud no existe.  | 
|  PlatformNotSupportedException  |  AWS Marketplace no admite la medición del uso de la plataforma subyacente. Solo se admiten Amazon ECS y AWS Fargate Amazon EKS.  | 
|  ThrottlingException  |  Las llamadas a RegisterUsage están restringidas.  | 
|  InvalidRegionException  |  RegisterUsagedebe llamarse de la misma manera en Región de AWS que se lanzó la tarea de Amazon ECS o el pod de Amazon EKS. Esto impide que un contenedor elija una región (por ejemplo, withRegion(“us-east-1”)) al llamar a RegisterUsage.  | 

# Integración de su producto de contenedor con el servicio de medición de AWS Marketplace mediante AWS SDK para Java
<a name="java-integration-example-registerusage"></a>

Puede utilizarla AWS SDK para Java para integrarse con el servicio de medición de AWS Marketplace. La medición continua del uso del software la gestiona automáticamente el. AWS Marketplace Metering Control Plane No es necesario que su software realice ninguna acción específica de medición, excepto llamar una vez a `RegisterUsage` para medir el uso del software para comenzar. En este tema se proporciona un ejemplo de implementación AWS SDK para Java que se utiliza para integrarse con la acción del [Servicio de AWS Marketplace`RegisterUsage` Medición](https://docs.aws.amazon.com/marketplacemetering/latest/APIReference/Welcome.html). 

Se debe llamar a `RegisterUsage` inmediatamente al momento de lanzar un contenedor. Si no registra el contenedor en las primeras 6 horas desde su lanzamiento, el servicio de medición de AWS Marketplace no ofrece ninguna garantía de medición respecto a los meses anteriores. Sin embargo, la medición continuará durante el mes en curso hasta que finalice el contenedor.

Para obtener el código fuente completo, consulte [RegisterUsage Ejemplo de Java](#registerusage-java-example). Muchos de estos pasos se aplican independientemente del idioma del AWS SDK. 



**Pasos de ejemplo para la integración del servicio de medición de AWS Marketplace**

1. Inicie sesión en el [AWS Marketplace Management Portal](https://aws.amazon.com/marketplace/management/tour).

1. En **Assets (Recursos)**, elija **Containers (Contenedores)** para comenzar a crear un nuevo producto de contenedor. Cuando se crea un producto, se genera un código para que dicho producto pueda integrarse con la imagen del contenedor. Para obtener más información sobre el establecimiento de permisos de IAM, consulte [AWS Marketplace permisos de API de medición y asignación de derechos](iam-user-policy-for-aws-marketplace-actions.md).

1.  Descargue el [AWS Java SDK](https://aws.amazon.com/sdk-for-java/) público. 
**importante**  
 Para llamar a la medición APIs desde Amazon EKS, debe [usar un AWS SDK compatible y ejecutarlo en un](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts-minimum-sdk.html) clúster de Amazon EKS que ejecute Kubernetes 1.13 o una versión posterior. 

1.  (Opcional) Si se está integrando con la `RegisterUsage` acción y desea realizar una verificación de firma digital, debe configurar la biblioteca de verificación de [BouncyCastle](https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on)firmas en la ruta de clases de la aplicación.

   Si desea utilizar JSON Web Token (JWT), también debe incluir en la classpath de su aplicación las bibliotecas [JWT Java](https://jwt.io/). El uso de JWT proporciona un enfoque más sencillo para la verificación de firmas, pero no es obligatorio y, en su lugar, puede usarlo de forma independiente. BouncyCastle Tanto si utilizas JWT como si BouncyCastle necesitas usar un sistema de compilación como Maven para incluir las dependencias transitivas de JWT en la ruta de clases de BouncyCastle tu aplicación.

   ```
   // Required for signature verification using code sample
   <dependency>
       <groupId>org.bouncycastle</groupId>
       <artifactId>bcpkix-jdk15on</artifactId>
       <version>1.60</version>
   </dependency>
   
   // This one is only required for JWT
   <dependency>
       <groupId>com.nimbusds</groupId>
       <artifactId>nimbus-jose-jwt</artifactId>
       <version>6.0</version>
   </dependency>
   ```

1.  Llame a `RegisterUsage` desde cada imagen de contenedor de pago en su oferta de producto. `ProductCode` y `PublicKeyVersion` son parámetros obligatorios y el resto de las entradas son opcionales. A continuación, se muestra un ejemplo de carga para `RegisterUsage`. 

   ```
   {
       "ProductCode" : "string", // (required)
       "PublicKeyVersion": 1,    // (required)
       "Nonce": "string",        // (optional) to scope down the registration
                                 //            to a specific running software
                                 //            instance and guard against
                                 //            replay attacks
   }
   ```
**nota**  
Es posible que se detecten problemas transitorios al conectarse al Servicio de medición de AWS Marketplace. AWS Marketplace recomienda encarecidamente implementar los reintentos durante un máximo de 30 minutos, con una reducción exponencial, para evitar interrupciones de corta duración o problemas de red.

1.  `RegisterUsage` genera un firma digital RSA-PSS con SHA-256 que puede utilizar para verificar la autenticidad de la solicitud. La firma incluye los siguientes campos: `ProductCode`, `PublicKeyVersion` y `Nonce`. Para verificar la firma digital, debe conservar estos campos de la solicitud. El siguiente código es una respuesta de ejemplo a una llamada a `RegisterUsage`. 

   ```
   {
   "Signature": "<<JWT Token>>"
   }
   
   // Where the JWT Token is composed of 3 dot-separated, 
   // base-64 URL Encoded sections.
   // e.g. eyJhbGcVCJ9.eyJzdWIMzkwMjJ9.rrO9Qw0SXRWTe
   
   // Section 1: Header/Algorithm
   {
   "alg": "PS256",
   "typ": "JWT"
   }
   
   // Section 2: Payload
   {
   "ProductCode" : "string",
   "PublicKeyVersion": 1,
   "Nonce": "string",
   "iat": date // JWT issued at claim 
   }
   
   // Section 3: RSA-PSS SHA256 signature
   "rrO9Q4FEi3gweH3X4lrt2okf5zwIatUUwERlw016wTy_21Nv8S..."
   ```

1. Vuelva a crear una nueva versión de la imagen de contenedor que incluya la llamada a `RegisterUsage`, etiquete el contenedor y envíelo a cualquier registro de Docker que sea compatible con Amazon ECS o Amazon EKS, como Amazon ECR o Amazon ECR Public. Si utiliza Amazon ECR, asegúrese de que la cuenta que va a lanzar la tarea de Amazon ECS o el pod de Amazon EKS tiene permisos en el repositorio de Amazon ECR. De lo contrario, el lanzamiento devuelve un error.

1.  Cree un rol de [IAM](https://aws.amazon.com/iam/) que conceda permiso al contenedor para llamar a `RegisterUsage`, tal y como se define en el siguiente código. Debe proporcionar este rol de IAM en el parámetro [Rol de tarea](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html#task_role_arn) de la definición de la tarea de Amazon ECS o del pod de Amazon ECS.

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

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Action": [
                   "aws-marketplace:RegisterUsage"
                   ],
                   "Effect": "Allow",
                   "Resource": "*"
           }
       ]
   }
   ```

------

1. Cree una definición de tarea de Amazon ECS o de pod de Amazon EKS que haga referencia al contenedor que se ha integrado AWS Marketplace y haga referencia a la función de IAM que creó en el paso 7. Debe habilitar el AWS CloudTrail registro en la definición de la tarea si quiere ver el registro. 

1. Cree un clúster de Amazon ECS o Amazon EKS para ejecutar la tarea o el pod. Para obtener más información acerca de cómo crear un clúster de Amazon ECS, consulte [Creación de un clúster](https://docs.aws.amazon.com/AmazonECS/latest/userguide/create_cluster.html) en la *Guía para desarrolladores de Amazon Elastic Container Service*. Para obtener más información acerca de la creación de un clúster de Amazon EKS (con Kubernetes versión 1.1.3.x o posterior), consulte [Creación de un clúster de Amazon EKS](https://docs.aws.amazon.com/eks/latest/userguide/create_cluster.html).

1. Configure el clúster de Amazon ECS o Amazon EKS y lance la definición de tareas de Amazon ECS o el pod de Amazon EKS que creó, en el us-east-1 Región de AWS. Es solo durante este proceso de prueba, antes de que el producto esté en funcionamiento, cuando debe utilizar esta región.

1. Cuando obtenga una respuesta válida de `RegisterUsage`, podrá comenzar a crear su producto de contenedor. Si tiene alguna pregunta, póngase en contacto con el equipo de [Operaciones de vendedores de AWS Marketplace](https://aws.amazon.com/marketplace/management/contact-us/). 

## RegisterUsage Ejemplo de Java
<a name="registerusage-java-example"></a>

En el siguiente ejemplo, se utiliza el servicio AWS SDK para Java and AWS Marketplace Metering para llamar a la `RegisterUsage` operación. La verificación de la firma es opcional, pero si desea realizarla, debe incluir las bibliotecas de verificación de firmas digitales necesarias. Este ejemplo solo tiene fines ilustrativos. 

```
import com.amazonaws.auth.PEM;
import com.amazonaws.services.marketplacemetering.AWSMarketplaceMetering;
import com.amazonaws.services.marketplacemetering.AWSMarketplaceMeteringClientBuilder;
import com.amazonaws.services.marketplacemetering.model.RegisterUsageRequest;
import com.amazonaws.services.marketplacemetering.model.RegisterUsageResult;
import com.amazonaws.util.json.Jackson;
import com.fasterxml.jackson.databind.JsonNode;
import com.nimbusds.jose.JWSObject;
import com.nimbusds.jose.JWSVerifier;
import com.nimbusds.jose.crypto.RSASSAVerifier;
import java.io.ByteArrayInputStream;
import java.nio.charset.StandardCharsets;
import java.security.PublicKey;
import java.security.Security;
import java.security.Signature;
import java.security.interfaces.RSAPublicKey;
import java.util.Base64;
import java.util.Optional;
import java.util.UUID;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

/**
 * Class for making calls out to &MKT; Metering Service.
 */
class RegisterUsage {

    private static final String PRODUCT_CODE = ".......";

    private final AWSMarketplaceMetering registerUsageClient;
    private final SignatureVerifier signatureVerifier;
    private final int publicKeyVersion;

    public RegisterUsage(final SignatureVerifier signatureVerifier) {
        this.signatureVerifier = signatureVerifier;
        this.publicKeyVersion = PublicKeyProvider.PUBLIC_KEY_VERSION;
        this.registerUsageClient = AWSMarketplaceMeteringClientBuilder.standard().build();
    }

    /**
     * Shows how to call RegisterUsage client and verify digital signature.
     */
    public void callRegisterUsage() {
        RegisterUsageRequest request = new RegisterUsageRequest()
                .withProductCode(PRODUCT_CODE)
                .withPublicKeyVersion(publicKeyVersion)
                .withNonce(UUID.randomUUID().toString());

        // Execute call to RegisterUsage (only need to call once at container startup)
        RegisterUsageResult result = this.registerUsageClient.registerUsage(request);

        // Verify Digital Signature w/o JWT
        boolean isSignatureValid = this.signatureVerifier.verify(request, result);
        if (!isSignatureValid) {
            throw new RuntimeException("Revoke entitlement, digital signature invalid.");
        }
    }
}

/**
 * Signature verification class with both a JWT-library based verification
 * and a non-library based implementation.
 */
class SignatureVerifier {
    private static BouncyCastleProvider BC = new BouncyCastleProvider();

    private static final String SIGNATURE_ALGORITHM = "SHA256withRSA/PSS";

    private final PublicKey publicKey;

    public SignatureVerifier(PublicKeyProvider publicKeyProvider) {
        this.publicKey = publicKeyProvider.getPublicKey().orElse(null);
        Security.addProvider(BC);
    }

    /**
     * Example signature verification using the NimbusJOSEJWT library to verify the JWT Token.
     *
     * @param request RegisterUsage Request.
     * @param result  RegisterUsage Result.
     * @return true if the token matches.
     */
    public boolean verifyUsingNimbusJOSEJWT(final RegisterUsageRequest request, final RegisterUsageResult result) {
        if (!getPublicKey().isPresent()) {
            return false;
        }

        try {
            JWSVerifier verifier = new RSASSAVerifier((RSAPublicKey) getPublicKey().get());
            JWSObject jwsObject = JWSObject.parse(result.getSignature());
            return jwsObject.verify(verifier) && validatePayload(jwsObject.getPayload().toString(), request, result);
        } catch (Exception e) {
            // log error
            return false;
        }
    }

    /**
     * Example signature verification without any JWT library support.
     *
     * @param request RegisterUsage Request.
     * @param result  RegisterUsage Result.
     * @return true if the token matches.
     */
    public boolean verify(final RegisterUsageRequest request, final RegisterUsageResult result) {
        if (!getPublicKey().isPresent()) {
            return false;
        }
        try {
            String[] jwtParts = result.getSignature().split("\\.");
            String header = jwtParts[0];
            String payload = jwtParts[1];
            String payloadSignature = jwtParts[2];

            Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM, BC);
            signature.initVerify(getPublicKey().get());
            signature.update(String.format("%s.%s", header, payload).getBytes(StandardCharsets.UTF_8));
            boolean verified = signature.verify(Base64.getUrlDecoder()
                    .decode(payloadSignature.getBytes(StandardCharsets.UTF_8)));

            String decodedPayload = new String(Base64.getUrlDecoder().decode(payload));
            return verified && validatePayload(decodedPayload, request, result);
        } catch (Exception e) {
            // log error
            return false;
        }
    }

    /**
     * Validate each value in the returned payload matches values originally
     * supplied in the request to RegisterUsage. TimeToLiveInMillis and
     * PublicKeyExpirationTimestamp will have the values in the payload compared
     * to values in the signature
     */
    private boolean validatePayload(final String payload, final RegisterUsageRequest request,
                                    final RegisterUsageResult result) {
        try {
            JsonNode payloadJson = Jackson.getObjectMapper().readTree(payload);
            boolean matches = payloadJson.get("productCode")
                    .asText()
                    .equals(request.getProductCode());
            matches = matches && payloadJson.get("nonce")
                    .asText()
                    .equals(request.getNonce());
            return matches = matches && payloadJson.get("publicKeyVersion")
                    .asText()
                    .equals(String.valueOf(request.getPublicKeyVersion()));

        } catch (Exception ex) {
            // log error
            return false;
        }
    }

    private Optional<PublicKey> getPublicKey() {
        return Optional.ofNullable(this.publicKey);
    }
}

/**
 * Public key provider taking advantage of the &AWS; PEM Utility.
 */
class PublicKeyProvider {
    // Replace with your public key. Ensure there are new-lines ("\n") in the
    // string after "-----BEGIN PUBLIC KEY-----\n" and before "\n-----END PUBLIC KEY-----".
    private static final String PUBLIC_KEY =
            "-----BEGIN PUBLIC KEY-----\n"
                    + "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDdlatRjRjogo3WojgGHFHYLugd\n"
                    + "UWAY9iR3fy4arWNA1KoS8kVw33cJibXr8bvwUAUparCwlvdbH6dvEOfou0/gCFQs\n"
                    + "HUfQrSDv+MuSUMAe8jzKE4qW+jK+xQU9a03GUnKHkkle+Q0pX/g6jXZ7r1/xAK5D\n"
                    + "o2kQ+X5xK9cipRgEKwIDAQAB\n"
                    + "-----END PUBLIC KEY-----";

    public static final int PUBLIC_KEY_VERSION = 1;

    public Optional<PublicKey> getPublicKey() {
        try {
            return Optional.of(PEM.readPublicKey(new ByteArrayInputStream(
                    PUBLIC_KEY.getBytes(StandardCharsets.UTF_8))));
        } catch (Exception e) {
            // log error
            return Optional.empty();
        }
    }
}
```