Integración de su producto de contenedor con el servicio de medición AWS Marketplace mediante el AWS SDK for Java - AWS Marketplace

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.

Integración de su producto de contenedor con el servicio de medición AWS Marketplace mediante el AWS SDK for Java

Puede usarlo AWS SDK for Java para integrarse con el servicio de medición de AWS Marketplace. La medición continua para el uso del software es gestionada automáticamente por el AWS Marketplace Metering Control Plane. No es necesario que el software realice ninguna acción específica de medición, excepto llamar RegisterUsage una vez para comenzar a medir el uso del software. En este tema se proporciona un ejemplo de implementación que utiliza la AWS SDK for Java para integrarse con la acción del servicio de AWS Marketplace medición. RegisterUsage

Se debe llamar a RegisterUsage inmediatamente al momento de lanzar un contenedor. Si no registras el contenedor en las primeras 6 horas del lanzamiento del contenedor, AWS Marketplace Metering Service no ofrece ninguna garantía de medición para 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. Muchos de estos pasos se aplican independientemente del AWS SDK idioma.

Ejemplos de pasos para la integración AWS del servicio de medición de Marketplace
  1. Inicie sesión en el AWS Marketplace Management Portal.

  2. 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 información sobre cómo configurar IAM los permisos, consulteAWS Marketplace permisos de API de medición y asignación de derechos.

  3. Descargue la versión pública de AWSJava SDK.

    importante

    Para llamar a la medición APIs desde AmazonEKS, debes usar un clúster de Amazon compatible AWS SDK y ejecutarlo en un EKS clúster de Amazon que ejecute Kubernetes 1.13 o una versión posterior.

  4. (Opcional) Si te estás integrando con la RegisterUsage acción y quieres realizar una verificación de firma digital, debes configurar la biblioteca de verificación de BouncyCastlefirmas en la ruta de clases de tu aplicación.

    Si quieres usar JSON Web Token (JWT), también debes incluir las bibliotecas JWTJava en la ruta de clases de tu aplicación. Su uso JWT proporciona un enfoque más sencillo para la verificación de firmas, pero no es obligatorio y, en su lugar, se puede utilizar de forma independiente BouncyCastle . Ya sea que utilices JWT o BouncyCastle necesites usar un sistema de compilación como Maven para incluir las dependencias transitivas de BouncyCastle o JWT en la ruta de clases de 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>
  5. 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 AWS Marketplace Metering Service. 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.

  6. RegisterUsagegenera una RSA firma PSS digital con el código SHA -256 que se puede utilizar para comprobar 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..."
  7. Reconstruye una nueva versión de la imagen de tu contenedor que incluya la RegisterUsage llamada, etiqueta el contenedor y envíala a cualquier registro de contenedores que sea compatible con Amazon ECS o AmazonEKS, como Amazon ECR o Amazon ECR Public. Si utilizas AmazonECR, asegúrate de que la cuenta que lanza la ECS tarea de Amazon o el EKS pod de Amazon tenga permisos en el ECR repositorio de Amazon. De lo contrario, el lanzamiento devuelve un error.

  8. Crea un IAMrol que conceda permiso para que tu contenedor llameRegisterUsage, tal y como se define en el siguiente código. Debes proporcionar esta IAM función en el parámetro Función de tarea de la definición de la ECS tarea de Amazon o del EKS pod de Amazon.

    { "Version": "2012-10-17", "Statement": [ { "Action": [ "aws-marketplace:RegisterUsage" ], "Effect": "Allow", "Resource": "*" } ] }
  9. Crea una definición de ECS tarea o EKS pod de Amazon que haga referencia al contenedor que se ha integrado AWS Marketplace y haga referencia al IAM rol que creaste en el paso 7. Deberías habilitar el AWS CloudTrail registro en la definición de la tarea si quieres ver el registro.

  10. Crea un Amazon ECS o un EKS clúster de Amazon para ejecutar tu tarea o pod. Para obtener más información sobre la creación de un ECS clúster de Amazon, consulte Creación de un clúster en la Guía para desarrolladores de Amazon Elastic Container Service. Para obtener más información sobre la creación de un EKS clúster de Amazon (con la versión 1.1.3.x o posterior de Kubernetes), consulte Creación de un clúster de Amazon. EKS

  11. Configura Amazon ECS o el EKS clúster de Amazon y lanza la definición de ECS tareas de Amazon o el EKS pod de Amazon que has creado, 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.

  12. 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.

RegisterUsage Ejemplo de Java

En el siguiente ejemplo, se utiliza el servicio AWS SDK for 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 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(); } } }