Skip to content
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

chore(Java): New KeyStore KMS Configuration Examples #1034

Draft
wants to merge 12 commits into
base: main
Choose a base branch
from
Draft
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
16 changes: 0 additions & 16 deletions DynamoDbEncryption/runtimes/net/DynamoDbEncryption.sln

This file was deleted.

3 changes: 1 addition & 2 deletions Examples/runtimes/java/DynamoDbEncryption/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,9 @@ Overview:
├── src
│ ├── main/java/software/amazon/cryptography/examples: Examples source
│ │ ├── BasicPutGetExample: Example using AWS DB ESDK to Put and Get an encrypted item from DynamoDB
│ │ ├── CreateKeyStoreTableExample: Example creating a Keystore DynamoDB table for use with a hierarchical keyring
│ │ ├── CreateKeyStoreKeyExample: Example creating a branch key in a Keystore DynamoDB table
│ │ ├── clientsupplier: Examples using a custom KMS ClientSupplier
│ │ ├── enhanced: Examples using the DynamoDbEnhancedClient
│ │ ├── hierarchy: Examples using the Hierarchy Keyring and Key Store to reduce calls to KMS
│ │ ├── itemencryptor: Examples using the DynamoDbItemEncryptor
│ │ ├── keyring: Examples creating and using different keyrings
│ │ └── searchableencryption: Examples demonstrating searchable encryption configuration and usage
Expand Down
10 changes: 9 additions & 1 deletion Examples/runtimes/java/DynamoDbEncryption/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,17 @@ dependencies {
implementation("software.amazon.awssdk:dynamodb-enhanced")
implementation("software.amazon.awssdk:kms")
implementation("software.amazon.awssdk:sts")

implementation("software.amazon.awssdk:apache-client:2.19.0")
implementation("org.bouncycastle:bcprov-jdk18on:1.72")

// https://mvnrepository.com/artifact/org.projectlombok/lombok
implementation("org.projectlombok:lombok:1.18.30")
annotationProcessor("org.projectlombok:lombok:1.18.30")
// https://mvnrepository.com/artifact/com.google.code.findbugs/jsr305
implementation("com.google.code.findbugs:jsr305:3.0.2")
// https://mvnrepository.com/artifact/org.apache.commons/commons-lang3
implementation("org.apache.commons:commons-lang3:3.14.0")

// https://mvnrepository.com/artifact/org.testng/testng
testImplementation("org.testng:testng:7.5")
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package software.amazon.cryptography.examples;

import javax.annotation.Nonnull;
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
import software.amazon.awssdk.http.SdkHttpClient;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.sts.StsClient;
import software.amazon.awssdk.services.sts.auth.StsAssumeRoleCredentialsProvider;
import software.amazon.awssdk.services.sts.model.AssumeRoleRequest;

public class CredentialUtils {

public static StsAssumeRoleCredentialsProvider credsForRole(
@Nonnull String roleArn,
@Nonnull String roleSessionName,
@Nonnull Region region,
@Nonnull SdkHttpClient httpClient,
@Nonnull AwsCredentialsProvider creds
) {
StsAssumeRoleCredentialsProvider provider = StsAssumeRoleCredentialsProvider
.builder()
.stsClient(
StsClient
.builder()
.httpClient(httpClient)
.region(region)
.credentialsProvider(creds)
.build()
)
.refreshRequest(
AssumeRoleRequest
.builder()
.roleArn(roleArn)
.roleSessionName(roleSessionName)
.durationSeconds(900) // 15 minutes by 60 seconds
.build()
)
.build();
// Force credential resolution.
// If the host does not have permission to use these credentials,
// we want to fail early.
// This may not be appropriate in a production environment,
// as it is "greedy initialization".
provider.resolveCredentials();
return provider;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package software.amazon.cryptography.examples;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.apache.commons.lang3.StringUtils;

public class EnvUtils {

@Nonnull
public static String envOrDefault(
@Nonnull String key,
@Nonnull String _default
) {
@Nullable
String maybe = System.getenv(key);
if (StringUtils.isEmpty(maybe)) {
return _default;
}
return maybe;
}

@Nonnull
public static String envOrFail(@Nonnull String key) {
@Nullable
String maybe = System.getenv(key);
if (StringUtils.isEmpty(maybe)) {
throw new RuntimeException(String.format("Env had no key: %s", key));
}
return maybe;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package software.amazon.cryptography.examples.hierarchy.controlPlane;

import java.time.Duration;
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
import software.amazon.awssdk.http.SdkHttpClient;
import software.amazon.awssdk.http.apache.ApacheHttpClient;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.cryptography.keystore.KeyStore;
import software.amazon.cryptography.keystore.model.CreateKeyInput;

/*
The Hierarchical Keyring Example and Searchable Encryption Examples
rely on the existence of a DDB-backed key store with pre-existing
branch key material or beacon key material.

See the "Create KeyStore Table Example" for how to first set up
the DDB Table that will back this KeyStore.

This example demonstrates configuring a KeyStore and then
using a helper method to create a branch key and beacon key
that share the same Id, then return that Id.
We will always create a new beacon key alongside a new branch key,
even if you are not using searchable encryption.

This key creation should occur within your control plane.
*/
@SuppressWarnings("UnnecessaryLocalVariable")
public class CreateBranchKeyExample {

public static String KeyStoreCreateKey(
String keyStoreTableName,
String logicalKeyStoreName,
String kmsKeyArn,
DynamoDbClient keystoreAdminDDBClient,
SdkHttpClient kmsHTTPClient,
AwsCredentialsProvider kmsCredentials
) {
final StrictKeyStoreFactory factory = new StrictKeyStoreFactory(
kmsHTTPClient,
keystoreAdminDDBClient,
keyStoreTableName,
logicalKeyStoreName
);
// 1. Configure your KeyStore resource.
// See StrictKeyStoreFactory.
// Only Strict KeyStores can Create or Version Branch Keys
final KeyStore keystore = factory.getKeyStore(kmsKeyArn, kmsCredentials);

// 2. Create a new branch key and beacon key in our KeyStore.
// Both the branch key and the beacon key will share an Id.
// This creation is eventually consistent.
// This MUST be done before data can be encrypted or decrypted with this Branch Key.
// Ideally, for the Multi-Tenant use case,
// Branch Key Creation is executed when a tenant
// onboards to the service or application.
final String branchKeyId = keystore
.CreateKey(CreateKeyInput.builder().build())
.branchKeyIdentifier();

return branchKeyId;
}

public static void main(final String[] args) {
if (args.length <= 1) {
throw new IllegalArgumentException(
"To run this example, include the keyStoreTableName, logicalKeyStoreName, and kmsKeyArn in args"
);
}
final String keyStoreTableName = args[0];
final String logicalKeyStoreName = args[1];
final String kmsKeyArn = args[2];
// It is more efficient to re-use these than create unique ones for DDB & KMS.
final AwsCredentialsProvider defaultCreds =
DefaultCredentialsProvider.create();
final SdkHttpClient httpClient = ApacheHttpClient
.builder()
.connectionTimeToLive(Duration.ofSeconds(5))
.build();
final DynamoDbClient keystoreAdminDDBClient = DynamoDbClient
.builder()
.httpClient(httpClient)
.credentialsProvider(defaultCreds)
.build();
KeyStoreCreateKey(
keyStoreTableName,
logicalKeyStoreName,
kmsKeyArn,
keystoreAdminDDBClient,
httpClient,
defaultCreds
);
}
}
Loading
Loading