src/main/java/com/amazonaws/encryptionsdk/kms/AwsKmsMrkAwareMasterKeyProvider.java [392:547]:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      throw new AwsCryptoException(
          "Can't use non-ARN key identifiers or aliases when " + "no default region is set");
    }
    /* Precondition (untested): Discovery filter is only valid in discovery mode. */
    if (!isDiscovery && discoveryFilter != null) {
      throw new IllegalArgumentException(
          "Strict mode cannot be configured with a " + "discovery filter.");
    }
    /* Precondition (untested): Discovery mode can not have any keys to filter. */
    if (isDiscovery && !keyIds.isEmpty()) {
      throw new IllegalArgumentException("Discovery mode can not be configured with keys.");
    }
    // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.6
    // # If an AWS SDK Default Region can not be
    // # obtained initialization MUST fail.
    if (isDiscovery && discoveryMrkRegion == null) {
      throw new IllegalArgumentException("Discovery MRK region can not be null.");
    }

    this.regionalClientSupplier_ = supplier;
    this.defaultRegion_ = defaultRegion;
    this.keyIds_ = Collections.unmodifiableList(new ArrayList<>(keyIds));

    this.isDiscovery_ = isDiscovery;
    this.discoveryFilter_ = discoveryFilter;
    this.discoveryMrkRegion_ = discoveryMrkRegion;
    this.grantTokens_ = grantTokens;
  }

  // = compliance/framework/aws-kms/aws-kms-mrk-are-unique.txt#2.5
  // # The caller MUST provide:
  /** Refactored into a pure function to facilitate testing and correctness. */
  static void assertMrksAreUnique(List<String> keyIdentifiers) {

    List<String> duplicateMultiRegionKeyIdentifiers =
        keyIdentifiers.stream()
            /* Collect a map of resource to identifier.
             * This lets me group duplicates by "resource".
             * This is because the identifier can be either an ARN or a raw identifier.
             * By having the both the key id and the identifier I can ensure the uniqueness of
             * the key id and the error message to the caller can contain both identifiers
             * to facilitate debugging.
             */
            .collect(
                Collectors.groupingBy(
                    AwsKmsMrkAwareMasterKeyProvider::getResourceForResourceTypeKey))
            .entrySet()
            .stream()
            // = compliance/framework/aws-kms/aws-kms-mrk-are-unique.txt#2.5
            // # If there are zero duplicate resource ids between the multi-region
            // # keys, this function MUST exit successfully
            .filter(maybeDuplicate -> maybeDuplicate.getValue().size() > 1)
            // = compliance/framework/aws-kms/aws-kms-mrk-are-unique.txt#2.5
            // # If the list does not contain any multi-Region keys (aws-kms-key-
            // # arn.md#identifying-an-aws-kms-multi-region-key) this function MUST
            // # exit successfully.
            //
            .filter(maybeMrk -> isMRK(maybeMrk.getKey()))
            /* Flatten the duplicate identifiers into a single list. */
            .flatMap(mrkEntry -> mrkEntry.getValue().stream())
            .collect(Collectors.toList());

    // = compliance/framework/aws-kms/aws-kms-mrk-are-unique.txt#2.5
    // # If any duplicate multi-region resource ids exist, this function MUST
    // # yield an error that includes all identifiers with duplicate resource
    // # ids not only the first duplicate found.
    if (duplicateMultiRegionKeyIdentifiers.size() > 1) {
      throw new IllegalArgumentException(
          "Duplicate multi-region keys are not allowed:\n"
              + String.join(", ", duplicateMultiRegionKeyIdentifiers));
    }
  }

  /**
   * Helper method for
   *
   * @see AwsKmsMrkAwareMasterKeyProvider#assertMrksAreUnique(List)
   *     <p>Refoactored into a pure function to simplify testing and ensure correctness.
   */
  static String getResourceForResourceTypeKey(String identifier) {
    final AwsKmsCmkArnInfo info = parseInfoFromKeyArn(identifier);
    if (info == null) return identifier;

    if (!info.getResourceType().equals("key")) {
      return identifier;
    }

    return info.getResource();
  }

  /** Returns "aws-kms" */
  @Override
  public String getDefaultProviderId() {
    return PROVIDER_NAME;
  }

  // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.7
  // # The input MUST be the same as the Master Key Provider Get Master Key
  // # (../master-key-provider-interface.md#get-master-key) interface.
  /**
   * Added flexibility in matching multi-Region keys from different regions.
   *
   * @see KmsMasterKey#getMasterKey(String, String)
   */
  @Override
  public AwsKmsMrkAwareMasterKey getMasterKey(final String providerId, final String requestedKeyArn)
      throws UnsupportedProviderException, NoSuchMasterKeyException {
    // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.7
    // # The function MUST only provide master keys if the input provider id
    // # equals "aws-kms".
    if (!canProvide(providerId)) {
      throw new UnsupportedProviderException();
    }

    /* There SHOULD only be one match.
     * An unambiguous multi-region key for the family
     * of related multi-region keys is required.
     * See `assertMrksAreUnique`.
     * However, in the case of single region keys or aliases,
     * duplicates _are_ possible.
     */
    Optional<String> matchedArn =
        keyIds_.stream().filter(t -> awsKmsArnMatchForDecrypt(t, requestedKeyArn)).findFirst();
    // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.7
    // # In strict mode, the requested AWS KMS key ARN MUST
    // # match a member of the configured key ids by using AWS KMS MRK Match
    // # for Decrypt (aws-kms-mrk-match-for-decrypt.md#implementation)
    // # otherwise this function MUST error.
    if (!isDiscovery_ && !matchedArn.isPresent()) {
      throw new NoSuchMasterKeyException("Key must be in supplied list of keyIds.");
    }

    final AwsKmsCmkArnInfo requestedKeyArnInfo = parseInfoFromKeyArn(requestedKeyArn);
    // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.7
    // # In discovery mode, the requested
    // # AWS KMS key identifier MUST be a well formed AWS KMS ARN.
    if (isDiscovery_ && requestedKeyArnInfo == null) {
      throw new NoSuchMasterKeyException(
          "Cannot use AWS KMS identifiers " + "when in discovery mode.");
    }
    // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.7
    // # In
    // # discovery mode if a discovery filter is configured the requested AWS
    // # KMS key ARN's "partition" MUST match the discovery filter's
    // # "partition" and the AWS KMS key ARN's "account" MUST exist in the
    // # discovery filter's account id set.
    if (isDiscovery_
        && discoveryFilter_ != null
        && !discoveryFilter_.allowsPartitionAndAccount(
            requestedKeyArnInfo.getPartition(), requestedKeyArnInfo.getAccountId())) {
      throw new NoSuchMasterKeyException(
          "Cannot use key in partition "
              + requestedKeyArnInfo.getPartition()
              + " with account id "
              + requestedKeyArnInfo.getAccountId()
              + " with configured discovery filter.");
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



src/main/java/com/amazonaws/encryptionsdk/kmssdkv2/AwsKmsMrkAwareMasterKeyProvider.java [335:527]:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      throw new AwsCryptoException(
          "Can't use non-ARN key identifiers or aliases when " + "no default region is set");
    }
    /* Precondition: Discovery filter is only valid in discovery mode. */
    if (!isDiscovery && discoveryFilter != null) {
      throw new IllegalArgumentException(
          "Strict mode cannot be configured with a " + "discovery filter.");
    }
    /* Precondition: Discovery mode can not have any keys to filter. */
    if (isDiscovery && !keyIds.isEmpty()) {
      throw new IllegalArgumentException("Discovery mode can not be configured with keys.");
    }
    // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.6
    // # If an AWS SDK Default Region can not be
    // # obtained initialization MUST fail.
    if (isDiscovery && discoveryMrkRegion == null) {
      throw new IllegalArgumentException("Discovery MRK region can not be null.");
    }

    this.regionalClientSupplier_ = supplier;
    this.defaultRegion_ = defaultRegion;
    this.keyIds_ = Collections.unmodifiableList(new ArrayList<>(keyIds));

    this.isDiscovery_ = isDiscovery;
    this.discoveryFilter_ = discoveryFilter;
    this.discoveryMrkRegion_ = discoveryMrkRegion;
    this.grantTokens_ = grantTokens;
  }

  // = compliance/framework/aws-kms/aws-kms-mrk-are-unique.txt#2.5
  // # The caller MUST provide:
  /** Refactored into a pure function to facilitate testing and correctness. */
  static void assertMrksAreUnique(List<String> keyIdentifiers) {

    List<String> duplicateMultiRegionKeyIdentifiers =
        keyIdentifiers.stream()
            /* Collect a map of resource to identifier.
             * This lets me group duplicates by "resource".
             * This is because the identifier can be either an ARN or a raw identifier.
             * By having the both the key id and the identifier I can ensure the uniqueness of
             * the key id and the error message to the caller can contain both identifiers
             * to facilitate debugging.
             */
            .collect(
                Collectors.groupingBy(
                    AwsKmsMrkAwareMasterKeyProvider::getResourceForResourceTypeKey))
            .entrySet()
            .stream()
            // = compliance/framework/aws-kms/aws-kms-mrk-are-unique.txt#2.5
            // # If there are zero duplicate resource ids between the multi-region
            // # keys, this function MUST exit successfully
            .filter(maybeDuplicate -> maybeDuplicate.getValue().size() > 1)
            // = compliance/framework/aws-kms/aws-kms-mrk-are-unique.txt#2.5
            // # If the list does not contain any multi-Region keys (aws-kms-key-
            // # arn.md#identifying-an-aws-kms-multi-region-key) this function MUST
            // # exit successfully.
            //
            /* Postcondition: Filter out duplicate resources that are not multi-region keys.
             * I expect only have duplicates of specific multi-region keys.
             * In JSON something like
             * {
             *      "mrk-edb7fe6942894d32ac46dbb1c922d574" : [
             *          "arn:aws:kms:us-west-2:111122223333:key/mrk-edb7fe6942894d32ac46dbb1c922d574",
             *          "arn:aws:kms:us-east-2:111122223333:key/mrk-edb7fe6942894d32ac46dbb1c922d574"
             *      ]
             *  }
             */
            .filter(maybeMrk -> isMRK(maybeMrk.getKey()))
            /* Flatten the duplicate identifiers into a single list. */
            .flatMap(mrkEntry -> mrkEntry.getValue().stream())
            .collect(Collectors.toList());

    // = compliance/framework/aws-kms/aws-kms-mrk-are-unique.txt#2.5
    // # If any duplicate multi-region resource ids exist, this function MUST
    // # yield an error that includes all identifiers with duplicate resource
    // # ids not only the first duplicate found.
    if (duplicateMultiRegionKeyIdentifiers.size() > 1) {
      throw new IllegalArgumentException(
          "Duplicate multi-region keys are not allowed:\n"
              + String.join(", ", duplicateMultiRegionKeyIdentifiers));
    }
  }

  /**
   * Helper method for
   *
   * @see AwsKmsMrkAwareMasterKeyProvider#assertMrksAreUnique(List)
   *     <p>Refoactored into a pure function to simplify testing and ensure correctness.
   */
  static String getResourceForResourceTypeKey(String identifier) {
    final AwsKmsCmkArnInfo info = parseInfoFromKeyArn(identifier);
    /* Check for early return (Postcondition): Non-ARNs may be raw resources.
     * Raw aliases ('alias/my-key')
     * or key ids ('mrk-edb7fe6942894d32ac46dbb1c922d574').
     */
    if (info == null) return identifier;

    /* Check for early return (Postcondition): Return the identifier for non-key resource types.
     * I only care about duplicate multi-region *keys*.
     * Any other resource type
     * should get filtered out.
     * I return the entire identifier
     * on the off chance that
     * a customer has created
     * an alias with a name `mrk-*`.
     * This way such an alias
     * can never accidentally
     * collided with an existing multi-region key
     * or a duplicate alias.
     */
    if (!info.getResourceType().equals("key")) {
      return identifier;
    }

    /* Postcondition: Return the key id.
     * This will be used
     * to find different regional replicas of
     * the same multi-region key
     * because the key id for replicas is always the same.
     */
    return info.getResource();
  }

  /** Returns "aws-kms" */
  @Override
  public String getDefaultProviderId() {
    return PROVIDER_NAME;
  }

  // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.7
  // # The input MUST be the same as the Master Key Provider Get Master Key
  // # (../master-key-provider-interface.md#get-master-key) interface.
  /**
   * Added flexibility in matching multi-Region keys from different regions.
   *
   * @see KmsMasterKey#getMasterKey(String, String)
   */
  @Override
  public AwsKmsMrkAwareMasterKey getMasterKey(final String providerId, final String requestedKeyArn)
      throws UnsupportedProviderException, NoSuchMasterKeyException {
    // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.7
    // # The function MUST only provide master keys if the input provider id
    // # equals "aws-kms".
    if (!canProvide(providerId)) {
      throw new UnsupportedProviderException();
    }

    /* There SHOULD only be one match.
     * An unambiguous multi-region key for the family
     * of related multi-region keys is required.
     * See `assertMrksAreUnique`.
     * However, in the case of single region keys or aliases,
     * duplicates _are_ possible.
     */
    Optional<String> matchedArn =
        keyIds_.stream().filter(t -> awsKmsArnMatchForDecrypt(t, requestedKeyArn)).findFirst();
    // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.7
    // # In strict mode, the requested AWS KMS key ARN MUST
    // # match a member of the configured key ids by using AWS KMS MRK Match
    // # for Decrypt (aws-kms-mrk-match-for-decrypt.md#implementation)
    // # otherwise this function MUST error.
    if (!isDiscovery_ && !matchedArn.isPresent()) {
      throw new NoSuchMasterKeyException("Key must be in supplied list of keyIds.");
    }

    final AwsKmsCmkArnInfo requestedKeyArnInfo = parseInfoFromKeyArn(requestedKeyArn);
    // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.7
    // # In discovery mode, the requested
    // # AWS KMS key identifier MUST be a well formed AWS KMS ARN.
    /* Precondition: Discovery mode requires requestedKeyArn be an ARN.
     * This function is called on the encrypt path.
     * It _may_ be the case that a raw key id, for example, was configured.
     */
    if (isDiscovery_ && requestedKeyArnInfo == null) {
      throw new NoSuchMasterKeyException(
          "Cannot use AWS KMS identifiers " + "when in discovery mode.");
    }
    // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.7
    // # In
    // # discovery mode if a discovery filter is configured the requested AWS
    // # KMS key ARN's "partition" MUST match the discovery filter's
    // # "partition" and the AWS KMS key ARN's "account" MUST exist in the
    // # discovery filter's account id set.
    if (isDiscovery_
        && discoveryFilter_ != null
        && !discoveryFilter_.allowsPartitionAndAccount(
            requestedKeyArnInfo.getPartition(), requestedKeyArnInfo.getAccountId())) {
      throw new NoSuchMasterKeyException(
          "Cannot use key in partition "
              + requestedKeyArnInfo.getPartition()
              + " with account id "
              + requestedKeyArnInfo.getAccountId()
              + " with configured discovery filter.");
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



