Integrando seu produto de contêiner com o AWS Marketplace Metering Service usando o AWS SDK for Java - AWS Marketplace

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

Integrando seu produto de contêiner com o AWS Marketplace Metering Service usando o AWS SDK for Java

Você pode usar o AWS SDK for Java para se integrar ao AWS Marketplace Metering Service. A medição contínua para uso do software é feita automaticamente pelo AWS Marketplace Metering Control Plane. Seu software não precisa realizar nenhuma ação específica de medição, exceto chamar RegisterUsage uma vez para que a medição do uso do software comece. Este tópico fornece um exemplo de implementação usando o AWS SDK for Java para integrar com a RegisterUsage ação do AWS Marketplace Metering Service.

RegisterUsage deve ser chamado imediatamente no momento de execução de um contêiner. Se você não registrar o contêiner nas primeiras 6 horas após o lançamento do contêiner, o AWS Marketplace Metering Service não fornecerá nenhuma garantia de medição dos meses anteriores. No entanto, a medição continuará durante o mês atual até que o contêiner termine.

Para obter o código-fonte completo, consulte RegisterUsage Exemplo de Java. Muitas dessas etapas se aplicam independentemente do AWS SDK idioma.

Exemplos de etapas para a integração AWS do Marketplace Metering Service
  1. Faça login no Portal de gerenciamento do AWS Marketplace.

  2. Em Assets (Ativos), selecione Containers (Contêineres) para começar a criar um produto de contêiner. A criação do produto gera o código para a integração do produto com a imagem de contêiner. Para obter informações sobre como definir IAM permissões, consulteAWS Marketplace permissões da API de medição e titulação.

  3. Baixe o AWSJava públicoSDK.

    Importante

    Para chamar a medição APIs da AmazonEKS, você deve usar um cluster compatível AWS SDK e executá-lo em um EKS cluster da Amazon executando o Kubernetes 1.13 ou posterior.

  4. (Opcional) Se você estiver se integrando à RegisterUsage ação e quiser realizar a verificação de assinatura digital, precisará configurar a biblioteca de verificação de BouncyCastleassinatura no caminho de classe do seu aplicativo.

    Se quiser usar o JSON Web Token (JWT), você também deve incluir bibliotecas JWTJava no classpath do seu aplicativo. JWTO uso fornece uma abordagem mais simples para a verificação de assinatura, mas não é obrigatório. Em vez disso, você pode usar o modo autônomo. BouncyCastle Se você usa JWT ou BouncyCastle, você precisa usar um sistema de compilação como o Maven para incluir dependências transitivas de BouncyCastle ou JWT no classpath do seu aplicativo.

    // 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>
  5. Chame RegisterUsage de cada imagem de contêiner paga na oferta do produto. ProductCode e PublicKeyVersion são parâmetros obrigatórios, e todas as outras entradas são opcionais. Esta é uma carga útil de exemplo 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

    É possível ver problemas transitórios na conexão com o AWS Marketplace Metering Service. AWS Marketplace recomenda fortemente a implementação de novas tentativas por até 30 minutos, com recuo exponencial, para evitar interrupções de curto prazo ou problemas de rede.

  6. RegisterUsagegera uma assinatura PSS digital RSA - usando SHA -256 que você pode usar para verificar a autenticidade da solicitação. A assinatura inclui os seguintes campos: ProductCode, PublicKeyVersion e Nonce. Para verificar a assinatura digital, você deve manter esses campos da solicitação. Este código é uma resposta de exemplo para uma chamada 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..."
  7. Reconstrua uma nova versão da imagem do contêiner que inclua a RegisterUsage chamada, marque o contêiner e envie-o para qualquer registro de contêiner compatível com a Amazon ECS ou a AmazonEKS, como Amazon ECR ou Amazon ECR Public. Se você estiver usando a AmazonECR, certifique-se de que a conta que está iniciando a ECS tarefa da Amazon ou o EKS pod da Amazon tenha permissões no ECR repositório da Amazon. Caso contrário, ocorrerá uma falha na inicialização.

  8. Crie uma IAMfunção que conceda permissão para que seu contêiner chameRegisterUsage, conforme definido no código a seguir. Você deve fornecer essa IAM função no parâmetro Task Role da definição de ECS tarefa da Amazon ou EKS pod da Amazon.

    { "Version": "2012-10-17", "Statement": [ { "Action": [ "aws-marketplace:RegisterUsage" ], "Effect": "Allow", "Resource": "*" } ] }
  9. Crie uma ECS tarefa da Amazon ou uma definição de EKS pod da Amazon que faça referência ao contêiner que se integrou AWS Marketplace e faça referência à IAM função que você criou na etapa 7. Você deve habilitar o AWS CloudTrail registro na definição da tarefa se quiser ver o registro.

  10. Crie um EKS cluster Amazon ECS ou Amazon para executar sua tarefa ou pod. Para obter mais informações sobre a criação de um ECS cluster da Amazon, consulte Como criar um cluster no Guia do desenvolvedor do Amazon Elastic Container Service. Para obter mais informações sobre a criação de um EKS cluster da Amazon (usando o Kubernetes versão 1.1.3.x ou posterior), consulte Criação de um cluster da Amazon. EKS

  11. Configure o EKS cluster da Amazon ECS ou da Amazon e inicie a definição de ECS tarefa da Amazon ou o EKS pod da Amazon que você criou, no us-east-1 Região da AWS. É somente durante este processo de teste, antes de o produto estar ativo, que você precisa usar essa região.

  12. Você pode começar a criar seu produto de contêiner assim que obtiver uma resposta válida de RegisterUsage. Se tiver dúvidas, entre em contato com a equipe de Operações do vendedor do AWS Marketplace.

RegisterUsage Exemplo de Java

O exemplo a seguir usa o AWS SDK for Java e AWS Marketplace Metering Service para chamar a RegisterUsage operação. A verificação de assinatura é opcional, mas se quiser executar a verificação de assinatura, você deverá incluir as bibliotecas de verificação de assinatura digital obrigatórias. Esse exemplo é apenas para fins de ilustração.

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