

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

# Configuration du comptage horaire avec AWS Marketplace Metering Service
<a name="container-metering-registerusage"></a>

**Note**  
 Pour les déploiements Amazon EKS, votre logiciel doit utiliser les [rôles IAM pour les comptes de service (IRSA)](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html) afin de signer l'appel d'API pour l'[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)opération d'API. Avec [EKS Pod Identity](https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html), le rôle de nœud ou les clés d'accès à long terme ne sont pas pris en charge.  
Pour les déploiements Amazon ECS, votre logiciel doit utiliser le rôle [IAM de la tâche Amazon ECS](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html) pour signer l'appel d'API pour l'opération d'[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)API. L'utilisation du rôle de nœud ou de clés d'accès à long terme n'est pas prise en charge.

Si votre produit en conteneur utilise une tarification par heure, par tâche ou par dosette au lieu de mesures personnalisées, vous n'avez pas besoin de définir des dimensions de mesure personnalisées. Vous pouvez utiliser AWS Marketplace Metering Service pour le comptage horaire des produits en conteneur. AWS Marketplace Les sections suivantes expliquent comment configurer le comptage horaire avec AWS Marketplace Metering Service.

Le fonctionnement de l'`RegisterUsage`API mesure l'utilisation du logiciel par tâche Amazon Elastic Container Service (Amazon ECS) ou par pod Amazon Elastic Kubernetes Service (Amazon EKS), par heure, l'utilisation étant calculée au prorata de la seconde. Un minimum d'une minute d'utilisation s'applique aux tâches de courte durée. La mesure continue pour l'utilisation du logiciel est automatiquement gérée par le AWS Marketplace Metering Control Plane. Votre logiciel n'est pas obligé d'effectuer des actions spécifiques de mesure, sauf d'en appeler `RegisterUsage` une seule fois pour que le mesurage de l'utilisation du logiciel commence.

`RegisterUsage`doit être appelé immédiatement au moment du lancement d'un conteneur. Si vous n'enregistrez pas le conteneur dans les 6 premières heures suivant son lancement, AWS Marketplace Metering Service ne fournit aucune garantie de comptage pour les mois précédents. Cependant, le comptage se poursuivra pour le mois en cours jusqu'à la fin du conteneur.

Les clients AWS Marketplace Metering Control Plane continuent d'être facturés pour l'exécution de tâches Amazon ECS et de pods Amazon EKS, quel que soit l'état de leur abonnement. Votre logiciel n'a donc plus besoin de vérifier les droits après le lancement initial réussi de la tâche ou du module. 

Pour plus d'informations sur l'intégration de AWS Marketplace Metering Service l'API aux produits en conteneur avec une tarification horaire, consultez le laboratoire d'[intégration au comptage horaire](https://catalog.workshops.aws/mpseller/en-US/container/integrate-hourly) de l'*atelier destiné aux AWS Marketplace vendeurs*. 

**Topics**
+ [Prérequis pour la mesure horaire](#hourly-metering-prereqs)
+ [Tester l'intégration pour `RegisterUsage`](#testing-integration-for-registerusage)
+ [Gestion des erreurs pour `RegisterUsage`](#hourly-metering-entitlement-error-handling)
+ [Intégrer votre produit conteneur au service de mesure AWS Marketplace à l'aide du AWS SDK pour Java](java-integration-example-registerusage.md)

## Prérequis pour la mesure horaire
<a name="hourly-metering-prereqs"></a>

Avant de publier le produit, vous devez effectuer les opérations suivantes :

1. Créez un nouveau produit conteneur dans Portail de gestion AWS Marketplace le et notez son code produit.

   Pour de plus amples informations, veuillez consulter [Vue d'ensemble : Création d'un produit en conteneur](container-product-getting-started.md#create-container-product).

1. Utilisez un rôle Gestion des identités et des accès AWS (IAM) pour la tâche ou le module exécutant votre application avec les autorisations IAM nécessaires pour appeler. `RegisterUsage` La politique gérée par IAM `AWSMarketplaceMeteringRegisterUsage` dispose de ces autorisations. Pour plus d'informations sur la politique, consultez [ AWSMarketplaceMeteringFullAccess](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AWSMarketplaceMeteringFullAccess.html)la *référence des stratégies AWS gérées*.

1. (Facultatif) Si vous souhaitez voir la journalisation, nous vous recommandons d'activer la AWS CloudTrail journalisation dans la définition de la tâche ou du module.

1. Effectuez un appel test à l'opération d'`RegisterUsage`API avec un enregistrement de toutes les dimensions de tarification que vous définissez.

## Tester l'intégration pour `RegisterUsage`
<a name="testing-integration-for-registerusage"></a>

Utilisez l'opération `RegisterUsage` API pour tester votre intégration avant de soumettre votre image à des AWS Marketplace fins de publication.

Appelez `RegisterUsage` depuis l'image du conteneur en exécutant votre produit sur Amazon ECS ou Amazon EKS. Utilisez le AWS compte que vous utilisez pour mettre le produit en vente AWS Marketplace. Votre intégration de mesure doit définir le de manière dynamique Région AWS, plutôt que de le coder en dur. Toutefois, lors du test, lancez au moins une tâche Amazon ECS ou un pod Amazon EKS contenant votre conteneur payant dans la région USA Est (Virginie du Nord). Ce faisant, l'équipe AWS Marketplace des opérations peut vérifier votre travail à l'aide des journaux de cette région.

**Note**  
Si votre produit prend en charge à la fois Amazon ECS et Amazon EKS, il vous suffit de le lancer dans Amazon EKS pour que nous puissions valider votre intégration.

Vous ne pouvez pas tester totalement l'intégration tant que votre produit n’a pas été publié avec toutes les métadonnées requises et les informations de tarification. Sur demande, l'équipe chargée des opérations du AWS Marketplace catalogue peut vérifier la réception de vos relevés de mesure.

## Gestion des erreurs pour `RegisterUsage`
<a name="hourly-metering-entitlement-error-handling"></a>

Si l'image de votre conteneur s'intègre à AWS Marketplace Metering Service et reçoit une exception autre qu'`ThrottlingException`au démarrage du conteneur, vous devez mettre fin au conteneur pour empêcher toute utilisation non autorisée.

Les exceptions autres que ne `ThrottlingException` sont émises que lors de l'appel initial à l'opération `RegisterUsage` d'API. Les appels suivants provenant de la même tâche Amazon ECS ou du même pod Amazon EKS ne sont pas lancés, `CustomerNotSubscribedException` même si le client se désabonne alors que la tâche ou le module est toujours en cours d'exécution. Ces clients sont toujours facturés pour la gestion des conteneurs après leur désinscription, et leur utilisation est suivie.

Le tableau suivant décrit les erreurs que l'opération `RegisterUsage` d'API peut générer. Chaque langage de programmation du AWS SDK possède un ensemble de directives de gestion des erreurs auxquelles vous pouvez vous référer pour plus d'informations. 


|  **Error (Erreur)**  |  **Description**  | 
| --- | --- | 
|  InternalServiceErrorException  |  RegisterUsage n'est pas disponible.  | 
|  CustomerNotEntitledException  |  Le client ne dispose pas d'un abonnement valable pour le produit.  | 
|  InvalidProductCodeException  |  La valeur ProductCode transmise dans le cadre de la requête n'existe pas.  | 
|  InvalidPublicKeyException  |  La valeur PublicKeyVersion transmise dans le cadre de la requête n'existe pas.  | 
|  PlatformNotSupportedException  |  AWS Marketplace ne prend pas en charge la mesure de l'utilisation à partir de la plateforme sous-jacente. Seuls Amazon ECS, Amazon EKS et Amazon AWS Fargate sont pris en charge.  | 
|  ThrottlingException  |  Les appels vers RegisterUsage sont limités.  | 
|  InvalidRegionException  |  RegisterUsagedoit être appelée de la même manière Région AWS que la tâche Amazon ECS ou le pod Amazon EKS a été lancé. Cela empêche un conteneur de choisir une région (par exemple, withRegion(“us-east-1”)) lorsqu’il appelle RegisterUsage.  | 

# Intégrer votre produit conteneur au service de mesure AWS Marketplace à l'aide du AWS SDK pour Java
<a name="java-integration-example-registerusage"></a>

Vous pouvez utiliser le AWS SDK pour Java pour intégrer le service de mesure AWS Marketplace. La mesure continue pour l'utilisation du logiciel est automatiquement gérée par le AWS Marketplace Metering Control Plane. Votre logiciel n'est pas obligé d'effectuer des actions spécifiques de mesure, sauf d'en appeler `RegisterUsage` une seule fois pour que le mesurage de l'utilisation du logiciel commence. Cette rubrique fournit un exemple d'implémentation utilisant le AWS SDK pour Java pour intégrer l'`RegisterUsage`action [AWS Marketplace du service](https://docs.aws.amazon.com/marketplacemetering/latest/APIReference/Welcome.html) de mesure. 

`RegisterUsage`doit être appelé immédiatement au moment du lancement d'un conteneur. Si vous n'enregistrez pas le conteneur dans les 6 premières heures suivant son lancement, AWS Marketplace Metering Service ne fournit aucune garantie de comptage pour les mois précédents. Cependant, le comptage se poursuivra pour le mois en cours jusqu'à la fin du conteneur.

Pour la source complète, consultez [RegisterUsage Exemple Java](#registerusage-java-example). La plupart de ces étapes s'appliquent quelle que soit la langue du AWS SDK. 



**Exemples d'étapes pour l'intégration du service de mesure AWS Marketplace**

1. Connectez-vous au [Portail de gestion AWS Marketplace](https://aws.amazon.com/marketplace/management/tour).

1. À partir de **Assets (Ressources)**, choisissez **Containers (Conteneurs)** pour commencer à créer un produit de conteneur. La création du produit génère le code produit pour l'intégration du produit à votre image de conteneur. Pour plus d'informations sur la définition des autorisations IAM, consultez[AWS Marketplace autorisations de l'API de mesure et d'autorisation](iam-user-policy-for-aws-marketplace-actions.md).

1.  Téléchargez le kit [Java SDK AWS](https://aws.amazon.com/sdk-for-java/) public. 
**Important**  
 Pour appeler le compteur APIs depuis Amazon EKS, vous devez [utiliser un AWS SDK compatible et l'exécuter sur un](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts-minimum-sdk.html) cluster Amazon EKS exécutant Kubernetes 1.13 ou version ultérieure. 

1.  (Facultatif) Si vous intégrez l'`RegisterUsage`action et que vous souhaitez effectuer une vérification de signature numérique, vous devez configurer la bibliothèque de vérification de [BouncyCastle](https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on)signature dans le chemin de classe de votre application.

   Si vous souhaitez utiliser JSON Web Token (JWT), vous devez également inclure des bibliothèques [JWT Java](https://jwt.io/) dans votre chemin de classe d'applications. L'utilisation de JWT fournit une approche plus simple de la vérification des signatures, mais elle n'est pas obligatoire, et vous pouvez utiliser le mode autonome BouncyCastle à la place. Que vous utilisiez JWT ou BouncyCastle que vous deviez utiliser un système de compilation tel que Maven pour inclure les dépendances transitives de BouncyCastle ou JWT dans le chemin de classe de votre application.

   ```
   // 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.  Appelez `RegisterUsage` à partir de chaque image de conteneur payante dans votre offre de produit. `ProductCode` et `PublicKeyVersion` sont des paramètres obligatoires et toutes les autres entrées sont facultatives. Voici un exemple de charge utile pour `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
   }
   ```
**Note**  
Il est possible que des problèmes transitoires se produisent lors de la connexion au service de mesure AWS Marketplace. AWS Marketplace recommande vivement d'implémenter des tentatives d'une durée maximale de 30 minutes, avec des interruptions exponentielles, afin d'éviter les pannes de courte durée ou les problèmes de réseau.

1.  `RegisterUsage` génère une signature numérique RSA-PSS à l'aide de SHA-256 que vous pouvez utiliser pour vérifier l'authenticité de la requête. La signature inclut les champs suivants : `ProductCode`, `PublicKeyVersion`, et `Nonce`. Pour vérifier la signature numérique, vous devez conserver ces champs à partir de la requête. Le code suivant est un exemple de réponse à un appel `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. Reconstruisez une nouvelle version de l'image de votre conteneur qui inclut l'`RegisterUsage`appel, balisez le conteneur et envoyez-la vers n'importe quel registre de conteneurs compatible avec Amazon ECS ou Amazon EKS, tel qu'Amazon ECR ou Amazon ECR Public. Si vous utilisez Amazon ECR, assurez-vous que le compte qui lance la tâche Amazon ECS ou le pod Amazon EKS dispose d'autorisations sur le référentiel Amazon ECR. Dans le cas contraire, le lancement échoue.

1.  Créez un rôle [IAM](https://aws.amazon.com/iam/) qui accorde l'autorisation à votre conteneur d'appeler `RegisterUsage`, tel que défini dans le code suivant. Vous devez fournir ce rôle IAM dans le paramètre [Task Role](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html#task_role_arn) de la tâche Amazon ECS ou de la définition du pod Amazon EKS.

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

****  

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

------

1. Créez une tâche Amazon ECS ou une définition de module Amazon EKS qui fait référence au conteneur intégré AWS Marketplace et au rôle IAM que vous avez créé à l'étape 7. Vous devez activer la AWS CloudTrail journalisation dans la définition de tâche si vous souhaitez voir la journalisation. 

1. Créez un cluster Amazon ECS ou Amazon EKS pour exécuter votre tâche ou votre pod. Pour plus d'informations sur la création d'un cluster Amazon ECS, consultez la section [Création d'un cluster](https://docs.aws.amazon.com/AmazonECS/latest/userguide/create_cluster.html) dans le manuel *Amazon Elastic Container Service Developer Guide*. Pour plus d'informations sur la création d'un cluster Amazon EKS (à l'aide de Kubernetes version 1.1.3.x ou ultérieure), consultez Création [d'un](https://docs.aws.amazon.com/eks/latest/userguide/create_cluster.html) cluster Amazon EKS.

1. Configurez le cluster Amazon ECS ou Amazon EKS et lancez la définition de tâche Amazon ECS ou le pod Amazon EKS que vous avez créé, dans le us-east-1 Région AWS. Ce n'est que pendant ce processus de test, avant que le produit ne soit mis en service, que vous devez utiliser cette région.

1. Lorsque vous recevez une réponse valide de `RegisterUsage`, vous pouvez commencer à créer votre produit de conteneur. Pour toute question, contactez l’équipe responsable des [opérations vendeur AWS Marketplace](https://aws.amazon.com/marketplace/management/contact-us/). 

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

L'exemple suivant utilise le service de AWS Marketplace mesure AWS SDK pour Java et pour appeler l'`RegisterUsage`opération. La vérification de la signature est facultative, mais si vous souhaitez l'effectuer, vous devez inclure les bibliothèques de vérification de signatures numériques nécessaires. Cet exemple est donné uniquement à titre d'illustration. 

```
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();
        }
    }
}
```