|
| 1 | +package software.amazon.cryptography.examples.hierarchy.controlPlane; |
| 2 | + |
| 3 | +import java.time.Duration; |
| 4 | + |
| 5 | +import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; |
| 6 | +import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider; |
| 7 | +import software.amazon.awssdk.http.SdkHttpClient; |
| 8 | +import software.amazon.awssdk.http.apache.ApacheHttpClient; |
| 9 | +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; |
| 10 | +import software.amazon.cryptography.keystore.KeyStore; |
| 11 | +import software.amazon.cryptography.keystore.model.CreateKeyInput; |
| 12 | + |
| 13 | +/* |
| 14 | + The Hierarchical Keyring Example and Searchable Encryption Examples |
| 15 | + rely on the existence of a DDB-backed key store with pre-existing |
| 16 | + branch key material or beacon key material. |
| 17 | +
|
| 18 | + See the "Create KeyStore Table Example" for how to first set up |
| 19 | + the DDB Table that will back this KeyStore. |
| 20 | +
|
| 21 | + This example demonstrates configuring a KeyStore and then |
| 22 | + using a helper method to create a branch key and beacon key |
| 23 | + that share the same Id, then return that Id. |
| 24 | + We will always create a new beacon key alongside a new branch key, |
| 25 | + even if you are not using searchable encryption. |
| 26 | +
|
| 27 | + This key creation should occur within your control plane. |
| 28 | + */ |
| 29 | +@SuppressWarnings("UnnecessaryLocalVariable") |
| 30 | +public class CreateBranchKeyExample { |
| 31 | + public static String KeyStoreCreateKey( |
| 32 | + String keyStoreTableName, |
| 33 | + String logicalKeyStoreName, |
| 34 | + String kmsKeyArn, |
| 35 | + DynamoDbClient keystoreAdminDDBClient, |
| 36 | + SdkHttpClient kmsHTTPClient, |
| 37 | + AwsCredentialsProvider kmsCredentials |
| 38 | + ) { |
| 39 | + final StrictKeyStoreFactory factory = new StrictKeyStoreFactory( |
| 40 | + kmsHTTPClient, |
| 41 | + keystoreAdminDDBClient, |
| 42 | + keyStoreTableName, |
| 43 | + logicalKeyStoreName); |
| 44 | + // 1. Configure your KeyStore resource. |
| 45 | + // See StrictKeyStoreFactory. |
| 46 | + // Only Strict KeyStores can Create or Version Branch Keys |
| 47 | + final KeyStore keystore = factory.getKeyStore(kmsKeyArn, kmsCredentials); |
| 48 | + |
| 49 | + // 2. Create a new branch key and beacon key in our KeyStore. |
| 50 | + // Both the branch key and the beacon key will share an Id. |
| 51 | + // This creation is eventually consistent. |
| 52 | + // This MUST be done before data can be encrypted or decrypted with this Branch Key. |
| 53 | + // Ideally, for the Multi-Tenant use case, |
| 54 | + // Branch Key Creation is executed when a tenant |
| 55 | + // onboards to the service or application. |
| 56 | + final String branchKeyId = keystore.CreateKey(CreateKeyInput.builder().build()).branchKeyIdentifier(); |
| 57 | + |
| 58 | + return branchKeyId; |
| 59 | + } |
| 60 | + |
| 61 | + public static void main(final String[] args) { |
| 62 | + if (args.length <= 1) { |
| 63 | + throw new IllegalArgumentException("To run this example, include the keyStoreTableName, logicalKeyStoreName, and kmsKeyArn in args"); |
| 64 | + } |
| 65 | + final String keyStoreTableName = args[0]; |
| 66 | + final String logicalKeyStoreName = args[1]; |
| 67 | + final String kmsKeyArn = args[2]; |
| 68 | + // It is more efficient to re-use these than create unique ones for DDB & KMS. |
| 69 | + final AwsCredentialsProvider defaultCreds = DefaultCredentialsProvider.create(); |
| 70 | + final SdkHttpClient httpClient = ApacheHttpClient.builder() |
| 71 | + .connectionTimeToLive(Duration.ofSeconds(5)).build(); |
| 72 | + final DynamoDbClient keystoreAdminDDBClient = DynamoDbClient.builder() |
| 73 | + .httpClient(httpClient) |
| 74 | + .credentialsProvider(defaultCreds) |
| 75 | + .build(); |
| 76 | + KeyStoreCreateKey(keyStoreTableName, logicalKeyStoreName, kmsKeyArn, keystoreAdminDDBClient, httpClient, defaultCreds); |
| 77 | + } |
| 78 | +} |
0 commit comments