

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# を使用してコンテナ製品を AWS Marketplace Metering Service と統合する AWS SDK for Java
<a name="java-integration-example-registerusage"></a>

を使用して AWS SDK for Java 、AWS Marketplace Metering Service と統合できます。ソフトウェア使用のための継続的な計測は、 によって自動的に処理されます AWS Marketplace Metering Control Plane。ソフトウェアでは、開始に使用するソフトウェアの計測のために `RegisterUsage` を 1 回呼び出すこと以外に、計測に固有のアクションを実行する必要はありません。このトピックでは、 を使用して [AWS Marketplace Metering Service](https://docs.aws.amazon.com/marketplacemetering/latest/APIReference/Welcome.html) の `RegisterUsage`アクションと統合 AWS SDK for Java する実装例を示します。

`RegisterUsage` はコンテナを起動したらすぐに呼び出す必要があります。コンテナの起動から最初の 6 時間以内にコンテナを登録しない場合、AWS Marketplace Metering Service は前月分の計測保証を提供しません。ただし、計測は当月以降、コンテナが終了するまで継続されます。

完全なソースコードについては、「[RegisterUsage Java の例](#registerusage-java-example)」を参照してください。これらのステップの多くは、 AWS SDK 言語に関係なく適用されます。



**AWS Marketplace Metering Service 統合の手順の例**

1. [AWS Marketplace 管理ポータル](https://aws.amazon.com/marketplace/management/tour) にサインインします。

1. [**Assets (アセット)**] から [**コンテナ**] を選択して、新しいコンテナ製品の作成を開始します。製品を作成すると、製品とコンテナイメージを統合するための製品コードが生成されます。IAM アクセス許可の設定については、「[AWS Marketplace 計測と使用権限 API アクセス許可](iam-user-policy-for-aws-marketplace-actions.md)」を参照してください。

1.  公開 [AWS Java SDK](https://aws.amazon.com/sdk-for-java/) をダウンロードします。
**重要**  
 Amazon EKS から計測 APIs を呼び出すには、[サポートされている AWS SDK を使用し](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts-minimum-sdk.html)、Kubernetes 1.13 以降を実行している Amazon EKS クラスターで を実行する必要があります。

1.  (オプション) `RegisterUsage` アクションを統合し、デジタル署名検証を実行する場合は、アプリケーションのクラスパスで [BouncyCastle](https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on) 署名検証ライブラリを設定する必要があります。

   JSON ウェブトークン (JWT) を使用する場合は、アプリケーションのクラスパスに [JWT Java](https://jwt.io/) ライブラリも含める必要があります。JWT を使用することで署名検証により簡単にアプローチできますが、必須ではありません。代わりにスタンドアロン BouncyCastle を使用できます。JWT を使用するか BouncyCastle を使用するかにかかわらず、アプリケーションのクラスパスに BouncyCastle または JWT の推移従属性を含めるには、Maven などのビルドシステムを使用する必要があります。

   ```
   // 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.  製品提供の各有料コンテナイメージから `RegisterUsage` を呼び出します。`ProductCode` と `PublicKeyVersion` は必須パラメータとなり、その他の入力はすべてオプションです。`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
   }
   ```
**注記**  
AWS Marketplace 計測サービスへの接続に一時的な問題が発生する可能性があります。 AWS Marketplace では、短期的な停止やネットワークの問題を避けるため、指数関数的なバックオフを含めて最大 30 分間の再試行を実施することを強くお勧めします。

1.  `RegisterUsage` は、リクエストの信頼性の検証に使用できる SHA-256 を使用して、RSA-PSS デジタル署名を生成します。署名には、`ProductCode`、`PublicKeyVersion`、`Nonce` のフィールドが含まれています。デジタル署名を検証するには、リクエストからこれらのフィールドを保持する必要があります。次のコードは、`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. `RegisterUsage` 呼び出しを含むコンテナイメージを再構築し、コンテナにタグ付けして、Amazon ECR または Amazon ECR Public など、Amazon ECS または Amazon EKS と互換性がある任意のコンテナレジストリにプッシュします。Amazon ECR を使用している場合は、Amazon ECS タスクまたは Amazon EKS ポッドを起動するアカウントに、Amazon ECR リポジトリへのアクセス許可があることを確認します。そうしないと、起動は失敗します。

1.  次のコードで定義されているように、コンテナが `RegisterUsage` を呼び出すアクセス許可を付与する [IAM](https://aws.amazon.com/iam/) ロールを作成します。Amazon ECS タスクまたは Amazon EKS ポッド定義の[タスクロール](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html#task_role_arn)パラメータでこの IAM ロールを指定する必要があります。

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

****  

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

------

1. と統合されたコンテナを参照 AWS Marketplace し、ステップ 7 で作成した IAM ロールを参照する Amazon ECS タスクまたは Amazon EKS ポッド定義を作成します。 AWS CloudTrail ログ記録を表示するには、タスク定義でログ記録を有効にする必要があります。

1. Amazon ECS または Amazon EKS クラスターを作成して、タスクまたはポッドを実行します。Amazon ECS クラスターの作成の詳細については、「*Amazon Elastic Container Service デベロッパーガイド*」の「[クラスターの作成](https://docs.aws.amazon.com/AmazonECS/latest/userguide/create_cluster.html)」を参照してください。Amazon EKS クラスターの作成 (Kubernetes バージョン 1.1.3.x 以降を使用) の詳細については、「[Amazon EKS クラスターの作成](https://docs.aws.amazon.com/eks/latest/userguide/create_cluster.html)」を参照してください。

1. Amazon ECS または Amazon EKS クラスターを設定し、us-east-1 で作成した Amazon ECS タスク定義または Amazon EKS ポッドを起動します AWS リージョン。製品が本番稼働になる前のこのテストプロセス中にのみ、このリージョンを使用する必要があります。

1. `RegisterUsage` から有効なレスポンスを取得すると、コンテナ製品の作成を開始することができます。ご質問がある場合は、[AWS Marketplace Seller Operations](https://aws.amazon.com/marketplace/management/contact-us/) チームまでお問い合わせください。

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

次の例では、 AWS SDK for Java および AWS Marketplace Metering Service を使用して `RegisterUsage`オペレーションを呼び出します。署名の検証はオプションですが、署名の検証を実行する場合は、必要なデジタル署名検証ライブラリを含める必要があります。この例は、例示のみを目的としています。

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