Skip to content

AWS SDK v2 support #516

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 22 commits into from
Mar 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 15 additions & 13 deletions pom.xml
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -38,29 +38,31 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties> </properties>


<dependencyManagement>
<dependencies>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>bom</artifactId>
<version>2.17.136</version>
<optional>true</optional>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

<dependencies> <dependencies>
<!-- Support AWS SDK v1 -->
<dependency> <dependency>
<groupId>com.amazonaws</groupId> <groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk</artifactId> <artifactId>aws-java-sdk</artifactId>
<version>1.12.131</version> <version>1.12.146</version>
<optional>true</optional>
</dependency>

<!-- Support AWS SDK v2 -->
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>bom</artifactId>
<version>2.17.110</version>
<optional>true</optional> <optional>true</optional>
<type>pom</type>
<scope>import</scope>
</dependency> </dependency>


<dependency> <dependency>
<groupId>software.amazon.awssdk</groupId> <groupId>software.amazon.awssdk</groupId>
<artifactId>kms</artifactId> <artifactId>kms</artifactId>
<version>2.17.109</version> <version>2.17.136</version>
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>


Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -24,13 +24,29 @@ public class VersionInfo {
* Loads the version of the library * Loads the version of the library
*/ */
public static String loadUserAgent() { public static String loadUserAgent() {
return USER_AGENT_PREFIX + versionNumber();
}

/**
* This returns the API name compatible with the AWS SDK v2
*
* @return the name of the library with a tag indicating intended for AWS SDK v2
*/
public static String apiName() {
return USER_AGENT_PREFIX.substring(0, USER_AGENT_PREFIX.length() - 1);
}

/*
* String representation of the library version e.g. 2.3.3
*/
public static String versionNumber() {
try { try {
final Properties properties = new Properties(); final Properties properties = new Properties();
final ClassLoader loader = VersionInfo.class.getClassLoader(); final ClassLoader loader = VersionInfo.class.getClassLoader();
properties.load(loader.getResourceAsStream("project.properties")); properties.load(loader.getResourceAsStream("project.properties"));
return USER_AGENT_PREFIX + properties.getProperty("version"); return properties.getProperty("version");
} catch (final IOException ex) { } catch (final IOException ex) {
return USER_AGENT_PREFIX + UNKNOWN_VERSION; return UNKNOWN_VERSION;
} }
} }
} }
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ private AwsKmsMrkAwareMasterKey(
"AwsKmsMrkAwareMasterKey must be configured with an AWS KMS client."); "AwsKmsMrkAwareMasterKey must be configured with an AWS KMS client.");
} }


/* Precondition: A provider is required. */
if (provider == null) { if (provider == null) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"AwsKmsMrkAwareMasterKey must be configured with a source provider."); "AwsKmsMrkAwareMasterKey must be configured with a source provider.");
Expand Down Expand Up @@ -177,7 +176,6 @@ public DataKey<AwsKmsMrkAwareMasterKey> generateDataKey(
// # The response's "KeyId" // # The response's "KeyId"
// # MUST be valid. // # MUST be valid.
final String gdkResultKeyId = gdkResult.getKeyId(); final String gdkResultKeyId = gdkResult.getKeyId();
/* Exceptional Postcondition: Must have an AWS KMS ARN from AWS KMS generateDataKey. */
if (parseInfoFromKeyArn(gdkResultKeyId) == null) { if (parseInfoFromKeyArn(gdkResultKeyId) == null) {
throw new IllegalStateException("Received an empty or invalid keyId from KMS"); throw new IllegalStateException("Received an empty or invalid keyId from KMS");
} }
Expand Down Expand Up @@ -212,7 +210,6 @@ public DataKey<AwsKmsMrkAwareMasterKey> encryptDataKey(
final Map<String, String> encryptionContext, final Map<String, String> encryptionContext,
final DataKey<?> dataKey) { final DataKey<?> dataKey) {
final SecretKey key = dataKey.getKey(); final SecretKey key = dataKey.getKey();
/* Precondition: The key format MUST be RAW. */
if (!key.getFormat().equals("RAW")) { if (!key.getFormat().equals("RAW")) {
throw new IllegalArgumentException("Only RAW encoded keys are supported"); throw new IllegalArgumentException("Only RAW encoded keys are supported");
} }
Expand All @@ -237,7 +234,6 @@ public DataKey<AwsKmsMrkAwareMasterKey> encryptDataKey(
final String encryptResultKeyId = encryptResult.getKeyId(); final String encryptResultKeyId = encryptResult.getKeyId();
// = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.11 // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.11
// # The AWS KMS Encrypt response MUST contain a valid "KeyId". // # The AWS KMS Encrypt response MUST contain a valid "KeyId".
/* Postcondition: Must have an AWS KMS ARN from AWS KMS encrypt. */
if (parseInfoFromKeyArn(encryptResultKeyId) == null) { if (parseInfoFromKeyArn(encryptResultKeyId) == null) {
throw new IllegalStateException("Received an empty or invalid keyId from KMS"); throw new IllegalStateException("Received an empty or invalid keyId from KMS");
} }
Expand Down Expand Up @@ -326,7 +322,6 @@ public DataKey<AwsKmsMrkAwareMasterKey> decryptDataKey(
// = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.9 // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.9
// # The output MUST be the same as the Master Key Decrypt Data Key // # The output MUST be the same as the Master Key Decrypt Data Key
// # (../master-key-interface.md#decrypt-data-key) interface. // # (../master-key-interface.md#decrypt-data-key) interface.
/* Exceptional Postcondition: Master key was unable to decrypt. */
.orElseThrow(() -> buildCannotDecryptDksException(exceptions)); .orElseThrow(() -> buildCannotDecryptDksException(exceptions));
} }


Expand Down Expand Up @@ -358,7 +353,6 @@ static DataKey<AwsKmsMrkAwareMasterKey> decryptSingleEncryptedDataKey(
.withKeyId(awsKmsIdentifier))); .withKeyId(awsKmsIdentifier)));


final String decryptResultKeyId = decryptResult.getKeyId(); final String decryptResultKeyId = decryptResult.getKeyId();
/* Exceptional Postcondition: Must have a CMK ARN from AWS KMS to match. */
if (decryptResultKeyId == null) { if (decryptResultKeyId == null) {
throw new IllegalStateException("Received an empty keyId from KMS"); throw new IllegalStateException("Received an empty keyId from KMS");
} }
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -284,7 +284,6 @@ static KmsMasterKeyProvider.RegionalClientSupplier clientFactory(
: AWSKMSClientBuilder.standard(); : AWSKMSClientBuilder.standard();


return region -> { return region -> {
/* Check for early return (Postcondition): If a client already exists, use that. */
if (clientCache.containsKey(region)) { if (clientCache.containsKey(region)) {
return clientCache.get(region); return clientCache.get(region);
} }
Expand Down Expand Up @@ -381,10 +380,6 @@ private AwsKmsMrkAwareMasterKeyProvider(
// # kms-mrk-are-unique.md#Implementation) and the function MUST return // # kms-mrk-are-unique.md#Implementation) and the function MUST return
// # success. // # success.
assertMrksAreUnique(keyIds); assertMrksAreUnique(keyIds);
/* Precondition: A region is required to contact AWS KMS.
* This is an edge case because the default region will be the same as the SDK default,
* but it is still possible.
*/
if (!isDiscovery if (!isDiscovery
&& defaultRegion == null && defaultRegion == null
&& keyIds.stream() && keyIds.stream()
Expand Down Expand Up @@ -447,16 +442,6 @@ static void assertMrksAreUnique(List<String> keyIdentifiers) {
// # arn.md#identifying-an-aws-kms-multi-region-key) this function MUST // # arn.md#identifying-an-aws-kms-multi-region-key) this function MUST
// # exit successfully. // # 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())) .filter(maybeMrk -> isMRK(maybeMrk.getKey()))
/* Flatten the duplicate identifiers into a single list. */ /* Flatten the duplicate identifiers into a single list. */
.flatMap(mrkEntry -> mrkEntry.getValue().stream()) .flatMap(mrkEntry -> mrkEntry.getValue().stream())
Expand All @@ -481,35 +466,12 @@ static void assertMrksAreUnique(List<String> keyIdentifiers) {
*/ */
static String getResourceForResourceTypeKey(String identifier) { static String getResourceForResourceTypeKey(String identifier) {
final AwsKmsCmkArnInfo info = parseInfoFromKeyArn(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; 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")) { if (!info.getResourceType().equals("key")) {
return identifier; 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(); return info.getResource();
} }


Expand Down Expand Up @@ -559,10 +521,6 @@ public AwsKmsMrkAwareMasterKey getMasterKey(final String providerId, final Strin
// = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.7 // = compliance/framework/aws-kms/aws-kms-mrk-aware-master-key-provider.txt#2.7
// # In discovery mode, the requested // # In discovery mode, the requested
// # AWS KMS key identifier MUST be a well formed AWS KMS ARN. // # 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) { if (isDiscovery_ && requestedKeyArnInfo == null) {
throw new NoSuchMasterKeyException( throw new NoSuchMasterKeyException(
"Cannot use AWS KMS identifiers " + "when in discovery mode."); "Cannot use AWS KMS identifiers " + "when in discovery mode.");
Expand Down
Loading