From 0c96697dcea708f0864d0214afcc2dc6ad1a671c Mon Sep 17 00:00:00 2001 From: Bradley Hess Date: Wed, 14 Nov 2018 09:44:27 -0500 Subject: [PATCH 01/15] Ensure that all snippets return a representation of their results --- kms/src/main/java/com/example/Snippets.java | 33 +++++++++++++++------ 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/kms/src/main/java/com/example/Snippets.java b/kms/src/main/java/com/example/Snippets.java index 2ad7268d7b4..600db69910e 100644 --- a/kms/src/main/java/com/example/Snippets.java +++ b/kms/src/main/java/com/example/Snippets.java @@ -36,6 +36,7 @@ import com.google.api.services.cloudkms.v1.model.SetIamPolicyRequest; import com.google.api.services.cloudkms.v1.model.UpdateCryptoKeyPrimaryVersionRequest; import java.io.IOException; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.kohsuke.args4j.CmdLineException; @@ -128,7 +129,7 @@ public static CryptoKey createCryptoKey(String projectId, String locationId, Str /** * Creates a new crypto key version for the given id. */ - public static void createCryptoKeyVersion( + public static CryptoKeyVersion createCryptoKeyVersion( String projectId, String locationId, String keyRingId, String cryptoKeyId) throws IOException { // Create the Cloud KMS client. @@ -147,6 +148,7 @@ public static void createCryptoKeyVersion( .execute(); System.out.println(newVersion); + return newVersion; } // [END kms_create_cryptokey_version] @@ -511,9 +513,9 @@ public static Policy removeMemberFromKeyRingPolicy( // [END kms_remove_member_from_keyring_policy] /** - * Prints all the key rings in the given project. + * Lists all the key rings in the given project. */ - public static void listKeyRings(String projectId, String locationId) throws IOException { + public static List listKeyRings(String projectId, String locationId) throws IOException { // Create the Cloud KMS client. CloudKMS kms = createAuthorizedClient(); @@ -530,19 +532,24 @@ public static void listKeyRings(String projectId, String locationId) throws IOEx // Print the returned key rings if (null != response.getKeyRings()) { + ArrayList result = new ArrayList<>(); System.out.println("Key Rings: "); for (KeyRing keyRing : response.getKeyRings()) { + result.add(keyRing); System.out.println(keyRing.getName()); } + return result; } else { System.out.println("No keyrings defined."); + return Collections.emptyList(); } } /** - * Prints all crypto keys in the given key ring. + * Lists all crypto keys in the given key ring. */ - public static void listCryptoKeys(String projectId, String locationId, String keyRingId) + public static List listCryptoKeys( + String projectId, String locationId, String keyRingId) throws IOException { // Create the Cloud KMS client. CloudKMS kms = createAuthorizedClient(); @@ -552,6 +559,7 @@ public static void listCryptoKeys(String projectId, String locationId, String ke "projects/%s/locations/%s/keyRings/%s", projectId, locationId, keyRingId); + ArrayList results = new ArrayList<>(); ListCryptoKeysResponse cryptoKeys = null; do { // Print every page of keys cryptoKeys = kms.projects().locations().keyRings() @@ -561,15 +569,18 @@ public static void listCryptoKeys(String projectId, String locationId, String ke .execute(); for (CryptoKey key : cryptoKeys.getCryptoKeys()) { + results.add(key); System.out.println(key); } } while (cryptoKeys.getNextPageToken() != null); + + return results; } /** - * Prints all the versions for the given crypto key. + * Lists all the versions for the given crypto key. */ - public static void listCryptoKeyVersions( + public static List listCryptoKeyVersions( String projectId, String locationId, String keyRingId, String cryptoKeyId) throws IOException { // Create the Cloud KMS client. @@ -586,15 +597,19 @@ public static void listCryptoKeyVersions( .list(cryptoKeys) .execute(); + ArrayList results = new ArrayList<>(); for (CryptoKeyVersion version : versions.getCryptoKeyVersions()) { System.out.println(version); + results.add(version); } + + return results; } /** * Sets a version as the primary version for a crypto key. */ - public static void setPrimaryVersion(String projectId, String locationId, String keyRingId, + public static CryptoKey setPrimaryVersion(String projectId, String locationId, String keyRingId, String cryptoKeyId, String versionId) throws IOException { // Create the Cloud KMS client. CloudKMS kms = createAuthorizedClient(); @@ -609,7 +624,7 @@ public static void setPrimaryVersion(String projectId, String locationId, String new UpdateCryptoKeyPrimaryVersionRequest().setCryptoKeyVersionId(versionId)).execute(); System.out.println(key); - + return key; } From 85328cef84653c20aef03bddbaf957e2f0a3e1de Mon Sep 17 00:00:00 2001 From: Bradley Hess Date: Wed, 14 Nov 2018 07:32:11 -0500 Subject: [PATCH 02/15] Convert Quickstart --- kms/pom.xml | 5 ++ kms/src/main/java/com/example/Quickstart.java | 74 ++++++------------- 2 files changed, 26 insertions(+), 53 deletions(-) diff --git a/kms/pom.xml b/kms/pom.xml index e9e34c762a7..0d567e75594 100644 --- a/kms/pom.xml +++ b/kms/pom.xml @@ -22,6 +22,11 @@ + + com.google.cloud + google-cloud-kms + 0.70.0-beta + com.google.apis google-api-services-cloudkms diff --git a/kms/src/main/java/com/example/Quickstart.java b/kms/src/main/java/com/example/Quickstart.java index eda21547ce7..95d28408488 100644 --- a/kms/src/main/java/com/example/Quickstart.java +++ b/kms/src/main/java/com/example/Quickstart.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 Google Inc. + * Copyright 2018 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,71 +19,39 @@ // [START kms_quickstart] // Imports the Google Cloud client library -import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; -import com.google.api.client.http.HttpTransport; -import com.google.api.client.http.javanet.NetHttpTransport; -import com.google.api.client.json.JsonFactory; -import com.google.api.client.json.jackson2.JacksonFactory; -import com.google.api.services.cloudkms.v1.CloudKMS; -import com.google.api.services.cloudkms.v1.CloudKMSScopes; -import com.google.api.services.cloudkms.v1.model.KeyRing; -import com.google.api.services.cloudkms.v1.model.ListKeyRingsResponse; +import com.google.api.gax.core.CredentialsProvider; +import com.google.api.gax.core.GoogleCredentialsProvider; +import com.google.auth.Credentials; +import com.google.cloud.kms.v1.KeyManagementServiceClient; +import com.google.cloud.kms.v1.KeyManagementServiceClient.ListKeyRingsPagedResponse; +import com.google.cloud.kms.v1.KeyManagementServiceSettings; +import com.google.cloud.kms.v1.KeyRing; +import com.google.cloud.kms.v1.LocationName; + import java.io.IOException; public class Quickstart { - /** - * Creates an authorized CloudKMS client service using Application Default Credentials. - * - * @return an authorized CloudKMS client - * @throws IOException if there's an error getting the default credentials. - */ - public static CloudKMS createAuthorizedClient() throws IOException { - // Create the credential - HttpTransport transport = new NetHttpTransport(); - JsonFactory jsonFactory = new JacksonFactory(); - // Authorize the client using Application Default Credentials - // @see https://g.co/dv/identity/protocols/application-default-credentials - GoogleCredential credential = GoogleCredential.getApplicationDefault(transport, jsonFactory); - - // Depending on the environment that provides the default credentials (e.g. Compute Engine, App - // Engine), the credentials may require us to specify the scopes we need explicitly. - // Check for this case, and inject the scope if required. - if (credential.createScopedRequired()) { - credential = credential.createScoped(CloudKMSScopes.all()); - } - - return new CloudKMS.Builder(transport, jsonFactory, credential) - .setApplicationName("CloudKMS snippets") - .build(); - } public static void main(String... args) throws Exception { String projectId = args[0]; // The location of the Key Rings String location = args[1]; - // Create the Cloud KMS client. - CloudKMS kms = createAuthorizedClient(); + // Create the KeyManagementServiceClient using try-with-resources to manage client cleanup. + // GAP: missing ability to set application name + // see https://github.com/googleapis/gax-java/issues/614 + try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) { - // The resource name of the cryptoKey - String keyRingPath = String.format( - "projects/%s/locations/%s", - projectId, location); + // The resource name of the location to search + String locationPath = LocationName.format(projectId, location); - // Make the RPC call - ListKeyRingsResponse response = kms.projects().locations() - .keyRings() - .list(keyRingPath) - .execute(); + // Make the RPC call + ListKeyRingsPagedResponse response = client.listKeyRings(locationPath); - // Print the returned key rings - if (null != response.getKeyRings()) { - System.out.println("Key Rings: "); - for (KeyRing keyRing : response.getKeyRings()) { - System.out.println(keyRing.getName()); + // Iterate over all KeyRings (which may cause more result pages to be loaded automatically) + for (KeyRing keyRing : response.iterateAll()) { + System.out.println("Found KeyRing: " + keyRing.getName()); } - } else { - System.out.println("No key rings defined."); } } } From f942cb85af415cbe52bdab5ad1685327603cf304 Mon Sep 17 00:00:00 2001 From: Bradley Hess Date: Wed, 14 Nov 2018 08:03:08 -0500 Subject: [PATCH 03/15] Move CryptFile test into CryptFileIT --- .../test/java/com/example/CryptFileIT.java | 70 +++++++++++++++++++ kms/src/test/java/com/example/SnippetsIT.java | 14 ---- 2 files changed, 70 insertions(+), 14 deletions(-) create mode 100644 kms/src/test/java/com/example/CryptFileIT.java diff --git a/kms/src/test/java/com/example/CryptFileIT.java b/kms/src/test/java/com/example/CryptFileIT.java new file mode 100644 index 00000000000..bee9e35d7dc --- /dev/null +++ b/kms/src/test/java/com/example/CryptFileIT.java @@ -0,0 +1,70 @@ +/* + * Copyright 2018 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example; + +import static com.google.common.truth.Truth.assertThat; + +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * Integration (system) tests for {@link Quickstart}. + */ +@RunWith(JUnit4.class) +@SuppressWarnings("checkstyle:abbreviationaswordinname") +public class CryptFileIT { + + @BeforeClass + public static void setUpClass() throws Exception { + SnippetsIT.setUpClass(); + } + + /** + * Destroys all the keys created during this test run. + */ + @AfterClass + public static void tearDownClass() throws Exception { + SnippetsIT.tearDownClass(); + } + + @Before + public void setUp() throws Exception { + Snippets.createCryptoKeyVersion( + SnippetsIT.PROJECT_ID, SnippetsIT.LOCATION_ID, SnippetsIT.KEY_RING_ID, + SnippetsIT.CRYPTO_KEY_ID); + } + + @Test + public void encryptDecrypt_encryptsAndDecrypts() throws Exception { + // Encrypt ENCRYPT_STRING with the current primary version. + byte[] ciphertext = CryptFile.encrypt( + SnippetsIT.PROJECT_ID, SnippetsIT.LOCATION_ID, SnippetsIT.KEY_RING_ID, + SnippetsIT.CRYPTO_KEY_ID, SnippetsIT.ENCRYPT_STRING.getBytes()); + + assertThat(new String(ciphertext)).isNotEqualTo(SnippetsIT.ENCRYPT_STRING); + + byte[] plaintext = CryptFile.decrypt( + SnippetsIT.PROJECT_ID, SnippetsIT.LOCATION_ID, SnippetsIT.KEY_RING_ID, + SnippetsIT.CRYPTO_KEY_ID, ciphertext); + + assertThat(new String(plaintext)).isEqualTo(SnippetsIT.ENCRYPT_STRING); + } +} diff --git a/kms/src/test/java/com/example/SnippetsIT.java b/kms/src/test/java/com/example/SnippetsIT.java index 5b280518409..11e3f6c1952 100644 --- a/kms/src/test/java/com/example/SnippetsIT.java +++ b/kms/src/test/java/com/example/SnippetsIT.java @@ -335,18 +335,4 @@ public void addAndRemoveMemberToKeyRingPolicy_addsDisplaysAndRemoves() throws Ex assertThat(bout.toString()).doesNotContainMatch(TEST_USER); } - - @Test - public void encryptDecrypt_encryptsAndDecrypts() throws Exception { - // Encrypt ENCRYPT_STRING with the current primary version. - byte[] ciphertext = CryptFile.encrypt( - PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID, ENCRYPT_STRING.getBytes()); - - assertThat(new String(ciphertext)).isNotEqualTo(ENCRYPT_STRING); - - byte[] plaintext = CryptFile.decrypt( - PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID, ciphertext); - - assertThat(new String(plaintext)).isEqualTo(ENCRYPT_STRING); - } } From 874d5e47d23bbf20465325b6a8e15ca6bbe9e75a Mon Sep 17 00:00:00 2001 From: Bradley Hess Date: Wed, 14 Nov 2018 07:52:35 -0500 Subject: [PATCH 04/15] Convert CryptFile --- kms/src/main/java/com/example/CryptFile.java | 91 ++++++++------------ 1 file changed, 35 insertions(+), 56 deletions(-) diff --git a/kms/src/main/java/com/example/CryptFile.java b/kms/src/main/java/com/example/CryptFile.java index 205c6356335..dfd615e1437 100644 --- a/kms/src/main/java/com/example/CryptFile.java +++ b/kms/src/main/java/com/example/CryptFile.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 Google Inc. + * Copyright 2018 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,17 +16,12 @@ package com.example; -import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; -import com.google.api.client.http.HttpTransport; -import com.google.api.client.http.javanet.NetHttpTransport; -import com.google.api.client.json.JsonFactory; -import com.google.api.client.json.jackson2.JacksonFactory; -import com.google.api.services.cloudkms.v1.CloudKMS; -import com.google.api.services.cloudkms.v1.CloudKMSScopes; -import com.google.api.services.cloudkms.v1.model.DecryptRequest; -import com.google.api.services.cloudkms.v1.model.DecryptResponse; -import com.google.api.services.cloudkms.v1.model.EncryptRequest; -import com.google.api.services.cloudkms.v1.model.EncryptResponse; +import com.google.cloud.kms.v1.CryptoKeyName; +import com.google.cloud.kms.v1.DecryptResponse; +import com.google.cloud.kms.v1.EncryptResponse; +import com.google.cloud.kms.v1.KeyManagementServiceClient; +import com.google.protobuf.ByteString; + import java.io.IOException; import org.kohsuke.args4j.CmdLineException; import org.kohsuke.args4j.CmdLineParser; @@ -34,29 +29,15 @@ public class CryptFile { /** - * Creates an authorized CloudKMS client service using Application Default Credentials. + * Creates a KeyManagementServiceClient using Application Default Credentials. * - * @return an authorized CloudKMS client + * @return an authorized KeyManagementServiceClient. * @throws IOException if there's an error getting the default credentials. */ - public static CloudKMS createAuthorizedClient() throws IOException { - // Create the credential - HttpTransport transport = new NetHttpTransport(); - JsonFactory jsonFactory = new JacksonFactory(); - // Authorize the client using Application Default Credentials - // @see https://g.co/dv/identity/protocols/application-default-credentials - GoogleCredential credential = GoogleCredential.getApplicationDefault(transport, jsonFactory); - - // Depending on the environment that provides the default credentials (e.g. Compute Engine, App - // Engine), the credentials may require us to specify the scopes we need explicitly. - // Check for this case, and inject the scope if required. - if (credential.createScopedRequired()) { - credential = credential.createScoped(CloudKMSScopes.all()); - } - - return new CloudKMS.Builder(transport, jsonFactory, credential) - .setApplicationName("CloudKMS CryptFile") - .build(); + public static KeyManagementServiceClient createClient() throws IOException { + // GAP: missing ability to set application name + // see https://github.com/googleapis/gax-java/issues/614 + return KeyManagementServiceClient.create(); } // [START kms_encrypt] @@ -67,20 +48,19 @@ public static CloudKMS createAuthorizedClient() throws IOException { public static byte[] encrypt( String projectId, String locationId, String keyRingId, String cryptoKeyId, byte[] plaintext) throws IOException { - // The resource name of the cryptoKey - String resourceName = String.format( - "projects/%s/locations/%s/keyRings/%s/cryptoKeys/%s", - projectId, locationId, keyRingId, cryptoKeyId); - // Create the Cloud KMS client. - CloudKMS kms = createAuthorizedClient(); + // Create the KeyManagementServiceClient using try-with-resources to manage client cleanup. + try (KeyManagementServiceClient client = createClient()) { + + // The resource name of the cryptoKey + String resourceName = CryptoKeyName.format(projectId, locationId, keyRingId, cryptoKeyId); - EncryptRequest request = new EncryptRequest().encodePlaintext(plaintext); - EncryptResponse response = kms.projects().locations().keyRings().cryptoKeys() - .encrypt(resourceName, request) - .execute(); + // Encrypt the plaintext with Cloud KMS. + EncryptResponse response = client.encrypt(resourceName, ByteString.copyFrom(plaintext)); - return response.decodeCiphertext(); + // Extract the ciphertext from the response. + return response.getCiphertext().toByteArray(); + } } // [END kms_encrypt] @@ -89,23 +69,22 @@ public static byte[] encrypt( /** * Decrypts the provided ciphertext with the specified crypto key. */ - public static byte[] decrypt(String projectId, String locationId, String keyRingId, - String cryptoKeyId, byte[] ciphertext) + public static byte[] decrypt( + String projectId, String locationId, String keyRingId, String cryptoKeyId, byte[] ciphertext) throws IOException { - // Create the Cloud KMS client. - CloudKMS kms = createAuthorizedClient(); - // The resource name of the cryptoKey - String cryptoKeyName = String.format( - "projects/%s/locations/%s/keyRings/%s/cryptoKeys/%s", - projectId, locationId, keyRingId, cryptoKeyId); + // Create the KeyManagementServiceClient using try-with-resources to manage client cleanup. + try (KeyManagementServiceClient client = createClient()) { + + // The resource name of the cryptoKey + String resourceName = CryptoKeyName.format(projectId, locationId, keyRingId, cryptoKeyId); - DecryptRequest request = new DecryptRequest().encodeCiphertext(ciphertext); - DecryptResponse response = kms.projects().locations().keyRings().cryptoKeys() - .decrypt(cryptoKeyName, request) - .execute(); + // Decrypt the ciphertext with Cloud KMS. + DecryptResponse response = client.decrypt(resourceName, ByteString.copyFrom(ciphertext)); - return response.decodePlaintext(); + // Extract the plaintext from the response. + return response.getPlaintext().toByteArray(); + } } // [END kms_decrypt] From becda1f8aeb7e05981ca13cb0ed3e79b3da39443 Mon Sep 17 00:00:00 2001 From: Bradley Hess Date: Wed, 14 Nov 2018 11:37:21 -0500 Subject: [PATCH 05/15] Rewrite ITs to rely on structured output --- kms/src/main/java/com/example/Snippets.java | 14 +- .../test/java/com/example/AsymmetricIT.java | 13 +- .../test/java/com/example/CryptFileIT.java | 54 ++- .../test/java/com/example/QuickstartIT.java | 62 +-- kms/src/test/java/com/example/SnippetsIT.java | 369 ++++++++---------- 5 files changed, 249 insertions(+), 263 deletions(-) diff --git a/kms/src/main/java/com/example/Snippets.java b/kms/src/main/java/com/example/Snippets.java index 600db69910e..4fd0d3b245d 100644 --- a/kms/src/main/java/com/example/Snippets.java +++ b/kms/src/main/java/com/example/Snippets.java @@ -219,19 +219,27 @@ public static CryptoKeyVersion enableCryptoKeyVersion( public static CryptoKeyVersion destroyCryptoKeyVersion( String projectId, String locationId, String keyRingId, String cryptoKeyId, String version) throws IOException { - // Create the Cloud KMS client. - CloudKMS kms = createAuthorizedClient(); // The resource name of the cryptoKey version String cryptoKeyVersion = String.format( "projects/%s/locations/%s/keyRings/%s/cryptoKeys/%s/cryptoKeyVersions/%s", projectId, locationId, keyRingId, cryptoKeyId, version); + return destroyCryptoKeyVersion(cryptoKeyVersion); + } + + /** + * Marks the given version of a crypto key to be destroyed at a scheduled future point. + */ + public static CryptoKeyVersion destroyCryptoKeyVersion(String resourceName) throws IOException { + // Create the Cloud KMS client. + CloudKMS kms = createAuthorizedClient(); + DestroyCryptoKeyVersionRequest destroyRequest = new DestroyCryptoKeyVersionRequest(); CryptoKeyVersion destroyed = kms.projects().locations().keyRings().cryptoKeys() .cryptoKeyVersions() - .destroy(cryptoKeyVersion, destroyRequest) + .destroy(resourceName, destroyRequest) .execute(); System.out.println(destroyed); diff --git a/kms/src/test/java/com/example/AsymmetricIT.java b/kms/src/test/java/com/example/AsymmetricIT.java index 635a36ac4cc..e367d1c1966 100644 --- a/kms/src/test/java/com/example/AsymmetricIT.java +++ b/kms/src/test/java/com/example/AsymmetricIT.java @@ -16,34 +16,25 @@ package com.example; -import static com.google.common.truth.Truth.assertThat; import static junit.framework.Assert.fail; import static junit.framework.TestCase.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -import com.google.api.client.googleapis.json.GoogleJsonError; import com.google.api.client.googleapis.json.GoogleJsonResponseException; import com.google.api.services.cloudkms.v1.CloudKMS; import com.google.api.services.cloudkms.v1.model.CryptoKey; import com.google.api.services.cloudkms.v1.model.CryptoKeyVersionTemplate; import com.google.api.services.cloudkms.v1.model.KeyRing; -import java.io.ByteArrayOutputStream; + import java.io.IOException; -import java.io.PrintStream; import java.nio.charset.StandardCharsets; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.PublicKey; import java.security.spec.InvalidKeySpecException; import java.util.Arrays; -import java.util.Base64; -import java.util.UUID; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Before; + import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/kms/src/test/java/com/example/CryptFileIT.java b/kms/src/test/java/com/example/CryptFileIT.java index bee9e35d7dc..4a09f6a792d 100644 --- a/kms/src/test/java/com/example/CryptFileIT.java +++ b/kms/src/test/java/com/example/CryptFileIT.java @@ -18,8 +18,14 @@ import static com.google.common.truth.Truth.assertThat; +import com.google.api.services.cloudkms.v1.model.CryptoKey; +import com.google.api.services.cloudkms.v1.model.CryptoKeyVersion; +import com.google.api.services.cloudkms.v1.model.KeyRing; + +import java.util.List; +import java.util.UUID; + import org.junit.AfterClass; -import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; @@ -32,39 +38,53 @@ @SuppressWarnings("checkstyle:abbreviationaswordinname") public class CryptFileIT { + private static final String PROJECT_ID = System.getenv("GOOGLE_CLOUD_PROJECT"); + private static final String LOCATION_ID = "global"; + private static final String KEY_RING_ID = "test-key-ring-" + UUID.randomUUID().toString(); + private static final String CRYPTO_KEY_ID = UUID.randomUUID().toString(); + private static final String ENCRYPT_STRING = + "Everyone shall sit under their own vine and fig tree"; + + /** + * Creates a CryptoKey for use during this test run. + */ @BeforeClass public static void setUpClass() throws Exception { - SnippetsIT.setUpClass(); + KeyRing keyRing = Snippets.createKeyRing(PROJECT_ID, LOCATION_ID, KEY_RING_ID); + assertThat(keyRing.getName()).contains("keyRings/" + KEY_RING_ID); + + CryptoKey cryptoKey = + Snippets.createCryptoKey(PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID); + assertThat(cryptoKey.getName()).contains(String.format( + "keyRings/%s/cryptoKeys/%s", KEY_RING_ID, CRYPTO_KEY_ID)); } /** - * Destroys all the keys created during this test run. + * Destroys all the key versions created during this test run. */ @AfterClass public static void tearDownClass() throws Exception { - SnippetsIT.tearDownClass(); - } - - @Before - public void setUp() throws Exception { - Snippets.createCryptoKeyVersion( - SnippetsIT.PROJECT_ID, SnippetsIT.LOCATION_ID, SnippetsIT.KEY_RING_ID, - SnippetsIT.CRYPTO_KEY_ID); + List versions = + Snippets.listCryptoKeyVersions(PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID); + + for (CryptoKeyVersion v : versions) { + if (!v.getState().equals("DESTROY_SCHEDULED")) { + Snippets.destroyCryptoKeyVersion(v.getName()); + } + } } @Test public void encryptDecrypt_encryptsAndDecrypts() throws Exception { // Encrypt ENCRYPT_STRING with the current primary version. byte[] ciphertext = CryptFile.encrypt( - SnippetsIT.PROJECT_ID, SnippetsIT.LOCATION_ID, SnippetsIT.KEY_RING_ID, - SnippetsIT.CRYPTO_KEY_ID, SnippetsIT.ENCRYPT_STRING.getBytes()); + PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID, ENCRYPT_STRING.getBytes()); - assertThat(new String(ciphertext)).isNotEqualTo(SnippetsIT.ENCRYPT_STRING); + assertThat(new String(ciphertext)).isNotEqualTo(ENCRYPT_STRING); byte[] plaintext = CryptFile.decrypt( - SnippetsIT.PROJECT_ID, SnippetsIT.LOCATION_ID, SnippetsIT.KEY_RING_ID, - SnippetsIT.CRYPTO_KEY_ID, ciphertext); + PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID, ciphertext); - assertThat(new String(plaintext)).isEqualTo(SnippetsIT.ENCRYPT_STRING); + assertThat(new String(plaintext)).isEqualTo(ENCRYPT_STRING); } } diff --git a/kms/src/test/java/com/example/QuickstartIT.java b/kms/src/test/java/com/example/QuickstartIT.java index 1ca8675b64e..1cbf09fe87e 100644 --- a/kms/src/test/java/com/example/QuickstartIT.java +++ b/kms/src/test/java/com/example/QuickstartIT.java @@ -18,10 +18,16 @@ import static com.google.common.truth.Truth.assertThat; +import com.google.api.services.cloudkms.v1.model.CryptoKey; +import com.google.api.services.cloudkms.v1.model.CryptoKeyVersion; +import com.google.api.services.cloudkms.v1.model.KeyRing; + import java.io.ByteArrayOutputStream; import java.io.PrintStream; +import java.util.List; +import java.util.UUID; + import org.junit.AfterClass; -import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; @@ -34,40 +40,52 @@ @SuppressWarnings("checkstyle:abbreviationaswordinname") public class QuickstartIT { - private ByteArrayOutputStream bout; - private PrintStream out; + private static final String PROJECT_ID = System.getenv("GOOGLE_CLOUD_PROJECT"); + private static final String LOCATION_ID = "global"; + private static final String KEY_RING_ID = "test-key-ring-" + UUID.randomUUID().toString(); + private static final String CRYPTO_KEY_ID = UUID.randomUUID().toString(); + /** + * Creates a CryptoKey for use during this test run. + */ @BeforeClass public static void setUpClass() throws Exception { - SnippetsIT.setUpClass(); - ByteArrayOutputStream bout = new ByteArrayOutputStream(); - PrintStream out = new PrintStream(bout); - System.setOut(out); + KeyRing keyRing = Snippets.createKeyRing(PROJECT_ID, LOCATION_ID, KEY_RING_ID); + assertThat(keyRing.getName()).contains("keyRings/" + KEY_RING_ID); + + CryptoKey cryptoKey = + Snippets.createCryptoKey(PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID); + assertThat(cryptoKey.getName()).contains(String.format( + "keyRings/%s/cryptoKeys/%s", KEY_RING_ID, CRYPTO_KEY_ID)); } /** - * Destroys all the keys created during this test run. + * Destroys all the key versions created during this test run. */ @AfterClass public static void tearDownClass() throws Exception { - SnippetsIT.tearDownClass(); - } - - @Before - public void setUp() throws Exception { - bout = new ByteArrayOutputStream(); - out = new PrintStream(bout); - System.setOut(out); - - Snippets.createCryptoKeyVersion( - SnippetsIT.PROJECT_ID, SnippetsIT.LOCATION_ID, SnippetsIT.KEY_RING_ID, - SnippetsIT.CRYPTO_KEY_ID); + List versions = + Snippets.listCryptoKeyVersions(PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID); + + for (CryptoKeyVersion v : versions) { + if (!v.getState().equals("DESTROY_SCHEDULED")) { + Snippets.destroyCryptoKeyVersion(v.getName()); + } + } } @Test public void listKeyRings_printsKeyRing() throws Exception { - Quickstart.main(SnippetsIT.PROJECT_ID, SnippetsIT.LOCATION_ID); + PrintStream originalOut = System.out; + ByteArrayOutputStream redirected = new ByteArrayOutputStream(); + + System.setOut(new PrintStream(redirected)); - assertThat(bout.toString()).contains(String.format("keyRings/%s", SnippetsIT.KEY_RING_ID)); + try { + Quickstart.main(PROJECT_ID, LOCATION_ID); + assertThat(redirected.toString()).contains(String.format("keyRings/%s", KEY_RING_ID)); + } finally { + System.setOut(originalOut); + } } } diff --git a/kms/src/test/java/com/example/SnippetsIT.java b/kms/src/test/java/com/example/SnippetsIT.java index 11e3f6c1952..3b81adf0d25 100644 --- a/kms/src/test/java/com/example/SnippetsIT.java +++ b/kms/src/test/java/com/example/SnippetsIT.java @@ -19,16 +19,18 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertTrue; -import com.google.api.client.googleapis.json.GoogleJsonError; -import com.google.api.client.googleapis.json.GoogleJsonResponseException; -import java.io.ByteArrayOutputStream; -import java.io.PrintStream; +import com.google.api.services.cloudkms.v1.model.Binding; +import com.google.api.services.cloudkms.v1.model.CryptoKey; +import com.google.api.services.cloudkms.v1.model.CryptoKeyVersion; +import com.google.api.services.cloudkms.v1.model.KeyRing; +import com.google.api.services.cloudkms.v1.model.Policy; + +import java.util.List; import java.util.UUID; import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.junit.After; + import org.junit.AfterClass; -import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; @@ -41,298 +43,245 @@ @SuppressWarnings("checkstyle:abbreviationaswordinname") public class SnippetsIT { - static final String PROJECT_ID = System.getenv("GOOGLE_CLOUD_PROJECT"); - static final String LOCATION_ID = "global"; - static final String KEY_RING_ID = "test-snippets-key-ring"; - static final String CRYPTO_KEY_ID = UUID.randomUUID().toString(); - static final String TEST_USER = "serviceAccount:" + private static final String PROJECT_ID = System.getenv("GOOGLE_CLOUD_PROJECT"); + private static final String LOCATION_ID = "global"; + private static final String KEY_RING_ID = "test-key-ring-" + UUID.randomUUID().toString(); + private static final String CRYPTO_KEY_ID = UUID.randomUUID().toString(); + private static final String TEST_USER = "serviceAccount:" + "131304031188-compute@developer.gserviceaccount.com"; - static final String TEST_ROLE = "roles/viewer"; - static final String ENCRYPT_STRING = "Everyone shall sit under their own vine and fig tree"; - - private static PrintStream realOut; - - private ByteArrayOutputStream bout; - private PrintStream out; + private static final String TEST_ROLE = "roles/viewer"; + /** + * Creates a CryptoKey for use during this test run. + */ @BeforeClass public static void setUpClass() throws Exception { - ByteArrayOutputStream bout = new ByteArrayOutputStream(); - PrintStream out = new PrintStream(bout); - realOut = System.out; - System.setOut(out); - - // Since you can't delete keyrings & cryptokeys atm, these tests assume they already exist. - // Use the snippets functions to create them. - try { - Snippets.createKeyRing(PROJECT_ID, LOCATION_ID, KEY_RING_ID); - - // Since there's no way to delete keyrings atm, have two branches - one for the first time the - // test is run, one for after the key already exists - assertThat(bout.toString()).contains("keyRings/" + KEY_RING_ID); + KeyRing keyRing = Snippets.createKeyRing(PROJECT_ID, LOCATION_ID, KEY_RING_ID); + assertThat(keyRing.getName()).contains("keyRings/" + KEY_RING_ID); - } catch (GoogleJsonResponseException e) { - GoogleJsonError error = e.getDetails(); - assertThat(error.getCode()).isEqualTo(409); - assertThat(error.getMessage()).contains("keyRings/" + KEY_RING_ID); - } - - try { - Snippets.createCryptoKey(PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID); - - // Since there's no way to delete keyrings atm, have two branches - one for the first time the - // test is run, one for after the key already exists - assertThat(bout.toString()).contains(String.format( - "keyRings/%s/cryptoKeys/%s", KEY_RING_ID, CRYPTO_KEY_ID)); - - } catch (GoogleJsonResponseException e) { - GoogleJsonError error = e.getDetails(); - assertThat(error.getCode()).isEqualTo(409); - assertThat(error.getMessage()).contains(String.format( - "keyRings/%s/cryptoKeys/%s", KEY_RING_ID, CRYPTO_KEY_ID)); - } - - // Create a CryptoKeyVersion and set it as primary. - Snippets.createCryptoKeyVersion(PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID); - Matcher matcher = Pattern.compile( - ".*cryptoKeyVersions/(\\d+)\",.*\"state\":\"ENABLED\".*", - Pattern.DOTALL | Pattern.MULTILINE).matcher(bout.toString().trim()); - assertTrue(matcher.matches()); - - String primaryVersion = matcher.group(1); - - Snippets.setPrimaryVersion(PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID, primaryVersion); + CryptoKey cryptoKey = + Snippets.createCryptoKey(PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID); + assertThat(cryptoKey.getName()).contains(String.format( + "keyRings/%s/cryptoKeys/%s", KEY_RING_ID, CRYPTO_KEY_ID)); } /** - * Destroys all the keys created during this test run. + * Destroys all the key versions created during this test run. */ @AfterClass public static void tearDownClass() throws Exception { - ByteArrayOutputStream bout = new ByteArrayOutputStream(); - PrintStream out = new PrintStream(bout); - System.setOut(out); - - String stdout; - try { - Snippets.listCryptoKeyVersions(PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID); - stdout = bout.toString(); - } finally { - System.setOut(realOut); - } - - String[] lines = stdout.split("\n"); - Pattern keyVersion = Pattern.compile( - ".*cryptoKeyVersions/(\\d+)\",\"state\":\"(EN|DIS)ABLED\".*", - Pattern.DOTALL | Pattern.MULTILINE); - - for (String line : lines) { - Matcher matcher = keyVersion.matcher(line); - if (!matcher.matches()) { - continue; + List versions = + Snippets.listCryptoKeyVersions(PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID); + + for (CryptoKeyVersion v : versions) { + if (!v.getState().equals("DESTROY_SCHEDULED")) { + Snippets.destroyCryptoKeyVersion(v.getName()); } - - String version = matcher.group(1); - Snippets - .destroyCryptoKeyVersion(PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID, version); } } - @Before - public void setUp() throws Exception { - bout = new ByteArrayOutputStream(); - out = new PrintStream(bout); - System.setOut(out); - } - - @After - public void tearDown() { - System.setOut(realOut); - } - @Test - public void listKeyRings_printsKeyRing() throws Exception { - Snippets.listKeyRings(PROJECT_ID, LOCATION_ID); - - assertThat(bout.toString()).contains(String.format("keyRings/%s", KEY_RING_ID)); + public void listKeyRings_retrievesKeyRing() throws Exception { + List keyRings = Snippets.listKeyRings(PROJECT_ID, LOCATION_ID); + assertThat(keyRings).isNotEmpty(); + assertThat(keyRings.get(0).getName()).contains(String.format("projects/%s", PROJECT_ID)); } @Test - public void listCryptoKeys_printsCryptoKeys() throws Exception { - Snippets.listCryptoKeys(PROJECT_ID, LOCATION_ID, KEY_RING_ID); - - assertThat(bout.toString()).contains( + public void listCryptoKeys_retrievesCryptoKeys() throws Exception { + List keys = Snippets.listCryptoKeys(PROJECT_ID, LOCATION_ID, KEY_RING_ID); + assertThat(keys).isNotEmpty(); + assertThat(keys.get(0).getName()).contains( String.format("keyRings/%s/cryptoKeys/%s", KEY_RING_ID, CRYPTO_KEY_ID)); } @Test - public void listCryptoKeyVersions_printsVersions() throws Exception { - Snippets.listCryptoKeyVersions(PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID); + public void listCryptoKeyVersions_retrievesVersions() throws Exception { + List versions = + Snippets.listCryptoKeyVersions(PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID); + + for (CryptoKeyVersion v : versions) { + assertThat(v.getName()).contains(String.format( + "keyRings/%s/cryptoKeys/%s/cryptoKeyVersions/", KEY_RING_ID, CRYPTO_KEY_ID)); - assertThat(bout.toString()).containsMatch(String.format( - "keyRings/%s/cryptoKeys/%s/cryptoKeyVersions/\\d+\",.*\"state\":\"ENABLED\"", - KEY_RING_ID, CRYPTO_KEY_ID)); + if (v.getState().equals("ENABLED")) { + return; + } + } + + // at least one version should be enabled, so we should never make it here + assertTrue("no versions are enabled", false); } @Test public void disableCryptoKeyVersion_disables() throws Exception { - Snippets.createCryptoKeyVersion(PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID); - - Matcher matcher = Pattern.compile(".*cryptoKeyVersions/(\\d+)\",.*\"state\":\"ENABLED\".*", - Pattern.DOTALL | Pattern.MULTILINE).matcher(bout.toString().trim()); - assertTrue(matcher.matches()); - String version = matcher.group(1); - - Snippets.disableCryptoKeyVersion(PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID, version); - assertThat(bout.toString()).containsMatch(String.format( - "keyRings/%s/cryptoKeys/%s/cryptoKeyVersions/%s\",.*\"state\":\"DISABLED\"", - KEY_RING_ID, CRYPTO_KEY_ID, version)); + CryptoKeyVersion version = Snippets.createCryptoKeyVersion( + PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID); + + String versionId = parseVersionId(version.getName()); + + CryptoKeyVersion disabled = Snippets.disableCryptoKeyVersion( + PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID, versionId); + assertThat(disabled.getState()).isEqualTo("DISABLED"); } @Test public void enableCryptoKeyVersion_enables() throws Exception { - Snippets.createCryptoKeyVersion(PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID); - - Matcher matcher = Pattern.compile(".*cryptoKeyVersions/(\\d+)\",.*\"state\":\"ENABLED\".*", - Pattern.DOTALL | Pattern.MULTILINE).matcher(bout.toString().trim()); - assertTrue(matcher.matches()); - String version = matcher.group(1); + CryptoKeyVersion version = Snippets.createCryptoKeyVersion( + PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID); + + String versionId = parseVersionId(version.getName()); // Disable the new key version - Snippets.disableCryptoKeyVersion(PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID, version); - assertThat(bout.toString()).containsMatch(String.format( - "keyRings/%s/cryptoKeys/%s/cryptoKeyVersions/%s\",.*\"state\":\"DISABLED\"", - KEY_RING_ID, CRYPTO_KEY_ID, version)); + CryptoKeyVersion disabled = Snippets.disableCryptoKeyVersion( + PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID, versionId); + assertThat(disabled.getState()).isEqualTo("DISABLED"); // Enable the now-disabled key version - Snippets.enableCryptoKeyVersion(PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID, version); - assertThat(bout.toString()).containsMatch(String.format( - "keyRings/%s/cryptoKeys/%s/cryptoKeyVersions/%s\",.*\"state\":\"ENABLED\"", - KEY_RING_ID, CRYPTO_KEY_ID, version)); - + CryptoKeyVersion enabled = Snippets.enableCryptoKeyVersion( + PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID, versionId); + assertThat(enabled.getState()).isEqualTo("ENABLED"); } @Test public void destroyCryptoKeyVersion_destroys() throws Exception { - Snippets.createCryptoKeyVersion(PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID); - - Matcher matcher = Pattern.compile(".*cryptoKeyVersions/(\\d+)\",.*\"state\":\"ENABLED\".*", - Pattern.DOTALL | Pattern.MULTILINE).matcher(bout.toString().trim()); - assertTrue(matcher.matches()); - - String version = matcher.group(1); + CryptoKeyVersion version = Snippets.createCryptoKeyVersion( + PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID); - Snippets.destroyCryptoKeyVersion(PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID, version); + String versionId = parseVersionId(version.getName()); - assertThat(bout.toString()).containsMatch(String.format( - "keyRings/%s/cryptoKeys/%s/cryptoKeyVersions/%s\",.*\"state\":\"DESTROY_SCHEDULED\"", - KEY_RING_ID, CRYPTO_KEY_ID, version)); + // Destroy the new key version + CryptoKeyVersion destroyScheduled = Snippets.destroyCryptoKeyVersion( + PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID, versionId); + assertThat(destroyScheduled.getState()).isEqualTo("DESTROY_SCHEDULED"); } @Test public void restoreCryptoKeyVersion_restores() throws Exception { - Snippets.createCryptoKeyVersion(PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID); + CryptoKeyVersion version = Snippets.createCryptoKeyVersion( + PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID); - Matcher matcher = Pattern.compile(".*cryptoKeyVersions/(\\d+)\",.*\"state\":\"ENABLED\".*", - Pattern.DOTALL | Pattern.MULTILINE).matcher(bout.toString().trim()); - assertTrue(matcher.matches()); + String versionId = parseVersionId(version.getName()); - String version = matcher.group(1); - - // Only key versions schedule for destruction are restorable, so schedule this key + // Only key versions scheduled for destruction are restorable, so schedule this key // version for destruction. - Snippets.destroyCryptoKeyVersion(PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID, version); - - assertThat(bout.toString()).containsMatch(String.format( - "keyRings/%s/cryptoKeys/%s/cryptoKeyVersions/%s\",.*\"state\":\"DESTROY_SCHEDULED\"", - KEY_RING_ID, CRYPTO_KEY_ID, version)); + CryptoKeyVersion destroyScheduled = Snippets.destroyCryptoKeyVersion( + PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID, versionId); + assertThat(destroyScheduled.getState()).isEqualTo("DESTROY_SCHEDULED"); // Now restore the key version. - Snippets.restoreCryptoKeyVersion(PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID, version); - - assertThat(bout.toString()).containsMatch(String.format( - "keyRings/%s/cryptoKeys/%s/cryptoKeyVersions/%s\",.*\"state\":\"DISABLED\"", - KEY_RING_ID, CRYPTO_KEY_ID, version)); + CryptoKeyVersion restored = Snippets.restoreCryptoKeyVersion( + PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID, versionId); + assertThat(restored.getState()).isEqualTo("DISABLED"); } @Test public void setPrimaryVersion_createKeyAndSetPrimaryVersion() throws Exception { // We can't test that setPrimaryVersion actually took effect via a list call because of // caching. So we test that the call was successful. - Snippets.createCryptoKeyVersion(PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID); - - Matcher matcher = Pattern.compile(".*cryptoKeyVersions/(\\d+)\",.*\"state\":\"ENABLED\".*", - Pattern.DOTALL | Pattern.MULTILINE).matcher(bout.toString().trim()); - assertTrue(matcher.matches()); + CryptoKeyVersion version = Snippets.createCryptoKeyVersion( + PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID); + assertThat(version.getState()).isEqualTo("ENABLED"); - String version = matcher.group(1); + String versionId = parseVersionId(version.getName()); - Snippets.setPrimaryVersion(PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID, version); - assertThat(bout.toString()).containsMatch(String.format( - "primary.*keyRings/%s/cryptoKeys/%s/cryptoKeyVersions/%s", - KEY_RING_ID, CRYPTO_KEY_ID, version)); + CryptoKey key = Snippets.setPrimaryVersion( + PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID, versionId); + assertThat(key.getPrimary().getName()).isEqualTo(version.getName()); } @Test public void addAndRemoveMemberToCryptoKeyPolicy_addsDisplaysAndRemoves() throws Exception { - // Make sure the policy doesn't already have our test user - Snippets.getCryptoKeyPolicy(PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID); + // Retrieve the current policy + Policy policy = Snippets.getCryptoKeyPolicy( + PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID); - assertThat(bout.toString()).doesNotContainMatch(TEST_USER); + // Make sure the policy doesn't already have our test user + if (policy.getBindings() != null) { // TODO: remove when we use the GAPIC client + for (Binding binding : policy.getBindings()) { + for (String m : binding.getMembers()) { + assertThat(TEST_USER).isNotEqualTo(m); + } + } + } try { // Add the test user, and make sure the policy has it - Snippets.addMemberToCryptoKeyPolicy( + Policy added = Snippets.addMemberToCryptoKeyPolicy( PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID, TEST_USER, TEST_ROLE); - Snippets.getCryptoKeyPolicy(PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID); - - assertThat(bout.toString()).containsMatch(TEST_USER); + for (Binding binding : added.getBindings()) { + for (String m : binding.getMembers()) { + if (TEST_USER.equals(m)) { + return; + } + } + } - // Now remove the test user, and make sure the policy no longer has it - bout.reset(); + // We should've returned in the previous loop; fail if we didn't. + assertTrue("No policy binding containing TEST_USER exists", false); } finally { - Snippets.removeMemberFromCryptoKeyPolicy( + // Now remove the test user, and make sure the policy no longer has it + Policy removed = Snippets.removeMemberFromCryptoKeyPolicy( PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID, TEST_USER, TEST_ROLE); + if (policy.getBindings() != null) { // TODO: remove when we use the GAPIC client + for (Binding binding : removed.getBindings()) { + for (String m : binding.getMembers()) { + assertThat(TEST_USER).isNotEqualTo(m); + } + } + } } - - assertThat(bout.toString()).doesNotContainMatch("Response:.*" + TEST_USER); - - bout.reset(); - Snippets.getCryptoKeyPolicy(PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID); - - assertThat(bout.toString()).doesNotContainMatch(TEST_USER); } @Test public void addAndRemoveMemberToKeyRingPolicy_addsDisplaysAndRemoves() throws Exception { - // Make sure the policy doesn't already have our test user - Snippets.getKeyRingPolicy(PROJECT_ID, LOCATION_ID, KEY_RING_ID); + // Retrieve the current policy + Policy policy = Snippets.getKeyRingPolicy(PROJECT_ID, LOCATION_ID, KEY_RING_ID); - assertThat(bout.toString()).doesNotContainMatch(TEST_USER); + // Make sure the policy doesn't already have our test user + if (policy.getBindings() != null) { // TODO: remove when we use the GAPIC client + for (Binding binding : policy.getBindings()) { + for (String m : binding.getMembers()) { + assertThat(TEST_USER).isNotEqualTo(m); + } + } + } try { // Add the test user, and make sure the policy has it - Snippets.addMemberToKeyRingPolicy( + Policy added = Snippets.addMemberToKeyRingPolicy( PROJECT_ID, LOCATION_ID, KEY_RING_ID, TEST_USER, TEST_ROLE); - Snippets.getKeyRingPolicy(PROJECT_ID, LOCATION_ID, KEY_RING_ID); - - assertThat(bout.toString()).containsMatch(TEST_USER); + for (Binding binding : added.getBindings()) { + for (String m : binding.getMembers()) { + if (TEST_USER.equals(m)) { + return; + } + } + } - // Now remove the test user, and make sure the policy no longer has it - bout.reset(); + // We should've returned in the previous loop; fail if we didn't. + assertTrue("No policy binding containing TEST_USER exists", false); } finally { - Snippets.removeMemberFromKeyRingPolicy( + // Now remove the test user, and make sure the policy no longer has it + Policy removed = Snippets.removeMemberFromKeyRingPolicy( PROJECT_ID, LOCATION_ID, KEY_RING_ID, TEST_USER, TEST_ROLE); + if (policy.getBindings() != null) { // TODO: remove when we use the GAPIC client + for (Binding binding : removed.getBindings()) { + for (String m : binding.getMembers()) { + assertThat(TEST_USER).isNotEqualTo(m); + } + } + } } + } - assertThat(bout.toString()).doesNotContainMatch("Response:.*" + TEST_USER); - - bout.reset(); - Snippets.getKeyRingPolicy(PROJECT_ID, LOCATION_ID, KEY_RING_ID); - - assertThat(bout.toString()).doesNotContainMatch(TEST_USER); + public static String parseVersionId(String versionName) { + Pattern versionIdPattern = Pattern.compile(".*/cryptoKeyVersions/(\\d+)"); + Matcher matcher = versionIdPattern.matcher(versionName); + assertThat(matcher.find()).isTrue(); + return matcher.group(1); } } From c81ef3ddbf9763ab57562c59950a302d1f2c9e37 Mon Sep 17 00:00:00 2001 From: Bradley Hess Date: Wed, 14 Nov 2018 09:30:38 -0500 Subject: [PATCH 06/15] Rework snippets --- kms/src/main/java/com/example/Snippets.java | 628 ++++++++---------- .../test/java/com/example/CryptFileIT.java | 14 +- .../test/java/com/example/QuickstartIT.java | 14 +- kms/src/test/java/com/example/SnippetsIT.java | 76 +-- 4 files changed, 337 insertions(+), 395 deletions(-) diff --git a/kms/src/main/java/com/example/Snippets.java b/kms/src/main/java/com/example/Snippets.java index 4fd0d3b245d..d88ecab9094 100644 --- a/kms/src/main/java/com/example/Snippets.java +++ b/kms/src/main/java/com/example/Snippets.java @@ -16,58 +16,43 @@ package com.example; -import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; -import com.google.api.client.http.HttpTransport; -import com.google.api.client.http.javanet.NetHttpTransport; -import com.google.api.client.json.JsonFactory; -import com.google.api.client.json.jackson2.JacksonFactory; -import com.google.api.services.cloudkms.v1.CloudKMS; -import com.google.api.services.cloudkms.v1.CloudKMSScopes; -import com.google.api.services.cloudkms.v1.model.Binding; -import com.google.api.services.cloudkms.v1.model.CryptoKey; -import com.google.api.services.cloudkms.v1.model.CryptoKeyVersion; -import com.google.api.services.cloudkms.v1.model.DestroyCryptoKeyVersionRequest; -import com.google.api.services.cloudkms.v1.model.KeyRing; -import com.google.api.services.cloudkms.v1.model.ListCryptoKeyVersionsResponse; -import com.google.api.services.cloudkms.v1.model.ListCryptoKeysResponse; -import com.google.api.services.cloudkms.v1.model.ListKeyRingsResponse; -import com.google.api.services.cloudkms.v1.model.Policy; -import com.google.api.services.cloudkms.v1.model.RestoreCryptoKeyVersionRequest; -import com.google.api.services.cloudkms.v1.model.SetIamPolicyRequest; -import com.google.api.services.cloudkms.v1.model.UpdateCryptoKeyPrimaryVersionRequest; +import com.google.cloud.kms.v1.CryptoKey; +import com.google.cloud.kms.v1.CryptoKey.CryptoKeyPurpose; +import com.google.cloud.kms.v1.CryptoKeyName; +import com.google.cloud.kms.v1.CryptoKeyVersion; +import com.google.cloud.kms.v1.CryptoKeyVersion.CryptoKeyVersionState; +import com.google.cloud.kms.v1.CryptoKeyVersionName; +import com.google.cloud.kms.v1.KeyManagementServiceClient; +import com.google.cloud.kms.v1.KeyManagementServiceClient.ListCryptoKeyVersionsPagedResponse; +import com.google.cloud.kms.v1.KeyManagementServiceClient.ListCryptoKeysPagedResponse; +import com.google.cloud.kms.v1.KeyManagementServiceClient.ListKeyRingsPagedResponse; +import com.google.cloud.kms.v1.KeyRing; +import com.google.cloud.kms.v1.KeyRingName; +import com.google.cloud.kms.v1.LocationName; +import com.google.iam.v1.Binding; +import com.google.iam.v1.Policy; +import com.google.protobuf.FieldMask; +import com.google.protobuf.util.FieldMaskUtil; + import java.io.IOException; import java.util.ArrayList; -import java.util.Collections; import java.util.List; + import org.kohsuke.args4j.CmdLineException; import org.kohsuke.args4j.CmdLineParser; public class Snippets { /** - * Creates an authorized CloudKMS client service using Application Default Credentials. + * Creates a KeyManagementServiceClient using Application Default Credentials. * - * @return an authorized CloudKMS client + * @return an authorized KeyManagementServiceClient. * @throws IOException if there's an error getting the default credentials. */ - public static CloudKMS createAuthorizedClient() throws IOException { - // Create the credential - HttpTransport transport = new NetHttpTransport(); - JsonFactory jsonFactory = new JacksonFactory(); - // Authorize the client using Application Default Credentials - // @see https://g.co/dv/identity/protocols/application-default-credentials - GoogleCredential credential = GoogleCredential.getApplicationDefault(transport, jsonFactory); - - // Depending on the environment that provides the default credentials (e.g. Compute Engine, App - // Engine), the credentials may require us to specify the scopes we need explicitly. - // Check for this case, and inject the scope if required. - if (credential.createScopedRequired()) { - credential = credential.createScoped(CloudKMSScopes.all()); - } - - return new CloudKMS.Builder(transport, jsonFactory, credential) - .setApplicationName("CloudKMS snippets") - .build(); + public static KeyManagementServiceClient createClient() throws IOException { + // GAP: missing ability to set application name + // see https://github.com/googleapis/gax-java/issues/614 + return KeyManagementServiceClient.create(); } // [START kms_create_keyring] @@ -78,18 +63,16 @@ public static CloudKMS createAuthorizedClient() throws IOException { public static KeyRing createKeyRing(String projectId, String locationId, String keyRingId) throws IOException { // Create the Cloud KMS client. - CloudKMS kms = createAuthorizedClient(); - - // The resource name of the location associated with the KeyRing. - String parent = String.format("projects/%s/locations/%s", projectId, locationId); - // Create the KeyRing for your project. - KeyRing keyring = kms.projects().locations().keyRings() - .create(parent, new KeyRing()) - .setKeyRingId(keyRingId) - .execute(); - - System.out.println(keyring); - return keyring; + try (KeyManagementServiceClient client = createClient()) { + + // The resource name of the location associated with the KeyRing. + String parent = LocationName.format(projectId, locationId); + + // Create the KeyRing for your project. + KeyRing keyRing = client.createKeyRing(parent, keyRingId, KeyRing.newBuilder().build()); + + return keyRing; + } } // [END kms_create_keyring] @@ -101,26 +84,22 @@ public static KeyRing createKeyRing(String projectId, String locationId, String public static CryptoKey createCryptoKey(String projectId, String locationId, String keyRingId, String cryptoKeyId) throws IOException { - // Create the Cloud KMS client. - CloudKMS kms = createAuthorizedClient(); - // The resource name of the location associated with the KeyRing. - String parent = String.format( - "projects/%s/locations/%s/keyRings/%s", projectId, locationId, keyRingId); + // Create the Cloud KMS client. + try (KeyManagementServiceClient client = createClient()) { + // The resource name of the location associated with the KeyRing. + String parent = KeyRingName.format(projectId, locationId, keyRingId); - // This will allow the API access to the key for encryption and decryption. - String purpose = "ENCRYPT_DECRYPT"; - CryptoKey cryptoKey = new CryptoKey(); - cryptoKey.setPurpose(purpose); + // This will allow the API access to the key for encryption and decryption. + CryptoKey cryptoKey = CryptoKey.newBuilder() + .setPurpose(CryptoKeyPurpose.ENCRYPT_DECRYPT) + .build(); - // Create the CryptoKey for your project. - CryptoKey createdKey = kms.projects().locations().keyRings().cryptoKeys() - .create(parent, cryptoKey) - .setCryptoKeyId(cryptoKeyId) - .execute(); + // Create the CryptoKey for your project. + CryptoKey createdKey = client.createCryptoKey(parent, cryptoKeyId, cryptoKey); - System.out.println(createdKey); - return createdKey; + return createdKey; + } } // [END kms_create_cryptokey] @@ -133,22 +112,16 @@ public static CryptoKeyVersion createCryptoKeyVersion( String projectId, String locationId, String keyRingId, String cryptoKeyId) throws IOException { // Create the Cloud KMS client. - CloudKMS kms = createAuthorizedClient(); + try (KeyManagementServiceClient client = createClient()) { - // The resource name of the cryptoKey - String cryptoKeys = String.format( - "projects/%s/locations/%s/keyRings/%s/cryptoKeys/%s", - projectId, locationId, keyRingId, cryptoKeyId); + // The resource name of the cryptoKey + String cryptoKey = CryptoKeyName.format(projectId, locationId, keyRingId, cryptoKeyId); - CryptoKeyVersion version = new CryptoKeyVersion(); + CryptoKeyVersion version = CryptoKeyVersion.newBuilder().build(); - CryptoKeyVersion newVersion = kms.projects().locations().keyRings().cryptoKeys() - .cryptoKeyVersions() - .create(cryptoKeys, version) - .execute(); - - System.out.println(newVersion); - return newVersion; + CryptoKeyVersion newVersion = client.createCryptoKeyVersion(cryptoKey, version); + return newVersion; + } } // [END kms_create_cryptokey_version] @@ -161,24 +134,29 @@ public static CryptoKeyVersion disableCryptoKeyVersion( String projectId, String locationId, String keyRingId, String cryptoKeyId, String version) throws IOException { // Create the Cloud KMS client. - CloudKMS kms = createAuthorizedClient(); + try (KeyManagementServiceClient client = createClient()) { + + // The resource name of the cryptoKey version + String versionName = CryptoKeyVersionName.format( + projectId, locationId, keyRingId, cryptoKeyId, version); - // The resource name of the cryptoKey version - String cryptoKeyVersion = String.format( - "projects/%s/locations/%s/keyRings/%s/cryptoKeys/%s/cryptoKeyVersions/%s", - projectId, locationId, keyRingId, cryptoKeyId, version); + // Retrieve the current state + CryptoKeyVersion current = client.getCryptoKeyVersion(versionName); - CryptoKeyVersion newVersionState = new CryptoKeyVersion() - .setState("DISABLED"); + // Build a copy that updates the state to disabled + CryptoKeyVersion updated = CryptoKeyVersion.newBuilder() + .setName(current.getName()) + .setState(CryptoKeyVersionState.DISABLED) + .build(); - CryptoKeyVersion response = kms.projects().locations().keyRings().cryptoKeys() - .cryptoKeyVersions() - .patch(cryptoKeyVersion, newVersionState) - .setUpdateMask("state") - .execute(); + // Create a FieldMask that only allows 'state' to be updated + FieldMask fieldMask = FieldMaskUtil.fromString(CryptoKeyVersion.class, "state"); - System.out.println(response); - return response; + // Update the version state + CryptoKeyVersion response = client.updateCryptoKeyVersion(updated, fieldMask); + + return response; + } } // [END kms_disable_cryptokey_version] @@ -189,25 +167,31 @@ public static CryptoKeyVersion disableCryptoKeyVersion( public static CryptoKeyVersion enableCryptoKeyVersion( String projectId, String locationId, String keyRingId, String cryptoKeyId, String version) throws IOException { + // Create the Cloud KMS client. - CloudKMS kms = createAuthorizedClient(); + try (KeyManagementServiceClient client = createClient()) { + + // The resource name of the cryptoKey version + String versionName = CryptoKeyVersionName.format( + projectId, locationId, keyRingId, cryptoKeyId, version); + + // Retrieve the current state + CryptoKeyVersion current = client.getCryptoKeyVersion(versionName); - // The resource name of the cryptoKey version - String cryptoKeyVersion = String.format( - "projects/%s/locations/%s/keyRings/%s/cryptoKeys/%s/cryptoKeyVersions/%s", - projectId, locationId, keyRingId, cryptoKeyId, version); + // Build a copy that updates the state to enabled + CryptoKeyVersion updated = CryptoKeyVersion.newBuilder() + .setName(current.getName()) + .setState(CryptoKeyVersionState.ENABLED) + .build(); - CryptoKeyVersion newVersionState = new CryptoKeyVersion() - .setState("ENABLED"); + // Create a FieldMask that only allows 'state' to be updated + FieldMask fieldMask = FieldMaskUtil.fromString(CryptoKeyVersion.class, "state"); - CryptoKeyVersion response = kms.projects().locations().keyRings().cryptoKeys() - .cryptoKeyVersions() - .patch(cryptoKeyVersion, newVersionState) - .setUpdateMask("state") - .execute(); + // Update the version state + CryptoKeyVersion response = client.updateCryptoKeyVersion(updated, fieldMask); - System.out.println(response); - return response; + return response; + } } // [END kms_enable_cryptokey_version] @@ -220,30 +204,18 @@ public static CryptoKeyVersion destroyCryptoKeyVersion( String projectId, String locationId, String keyRingId, String cryptoKeyId, String version) throws IOException { - // The resource name of the cryptoKey version - String cryptoKeyVersion = String.format( - "projects/%s/locations/%s/keyRings/%s/cryptoKeys/%s/cryptoKeyVersions/%s", - projectId, locationId, keyRingId, cryptoKeyId, version); - - return destroyCryptoKeyVersion(cryptoKeyVersion); - } - - /** - * Marks the given version of a crypto key to be destroyed at a scheduled future point. - */ - public static CryptoKeyVersion destroyCryptoKeyVersion(String resourceName) throws IOException { // Create the Cloud KMS client. - CloudKMS kms = createAuthorizedClient(); + try (KeyManagementServiceClient client = createClient()) { - DestroyCryptoKeyVersionRequest destroyRequest = new DestroyCryptoKeyVersionRequest(); + // The resource name of the cryptoKey version + String versionName = CryptoKeyVersionName.format( + projectId, locationId, keyRingId, cryptoKeyId, version); - CryptoKeyVersion destroyed = kms.projects().locations().keyRings().cryptoKeys() - .cryptoKeyVersions() - .destroy(resourceName, destroyRequest) - .execute(); + // Destroy the cryptoKey version + CryptoKeyVersion destroyed = client.destroyCryptoKeyVersion(versionName); - System.out.println(destroyed); - return destroyed; + return destroyed; + } } // [END kms_destroy_cryptokey_version] @@ -255,23 +227,18 @@ public static CryptoKeyVersion destroyCryptoKeyVersion(String resourceName) thro public static CryptoKeyVersion restoreCryptoKeyVersion( String projectId, String locationId, String keyRingId, String cryptoKeyId, String version) throws IOException { - // Create the Cloud KMS client. - CloudKMS kms = createAuthorizedClient(); - // The resource name of the cryptoKey version - String cryptoKeyVersion = String.format( - "projects/%s/locations/%s/keyRings/%s/cryptoKeys/%s/cryptoKeyVersions/%s", - projectId, locationId, keyRingId, cryptoKeyId, version); + // Create the Cloud KMS client. + try (KeyManagementServiceClient client = createClient()) { - RestoreCryptoKeyVersionRequest restoreRequest = new RestoreCryptoKeyVersionRequest(); + // The resource name of the cryptoKey version + String versionName = CryptoKeyVersionName.format( + projectId, locationId, keyRingId, cryptoKeyId, version); - CryptoKeyVersion restored = kms.projects().locations().keyRings().cryptoKeys() - .cryptoKeyVersions() - .restore(cryptoKeyVersion, restoreRequest) - .execute(); + CryptoKeyVersion restored = client.restoreCryptoKeyVersion(versionName); - System.out.println(restored); - return restored; + return restored; + } } // [END kms_restore_cryptokey_version] @@ -280,24 +247,21 @@ public static CryptoKeyVersion restoreCryptoKeyVersion( /** * Retrieves the IAM policy for the given crypto key. */ - public static Policy getCryptoKeyPolicy(String projectId, String locationId, String keyRingId, - String cryptoKeyId) + public static Policy getCryptoKeyPolicy( + String projectId, String locationId, String keyRingId, String cryptoKeyId) throws IOException { + // Create the Cloud KMS client. - CloudKMS kms = createAuthorizedClient(); + try (KeyManagementServiceClient client = createClient()) { - // The resource name of the cryptoKey - String cryptoKey = String.format( - "projects/%s/locations/%s/keyRings/%s/cryptoKeys/%s", - projectId, locationId, keyRingId, cryptoKeyId); + // The resource name of the cryptoKey version + String keyName = CryptoKeyName.format(projectId, locationId, keyRingId, cryptoKeyId); - // Get the current IAM policy and add the new account to it. - Policy iamPolicy = kms.projects().locations().keyRings().cryptoKeys() - .getIamPolicy(cryptoKey) - .execute(); + // Get the current IAM policy and add the new account to it. + Policy iamPolicy = client.getIamPolicy(keyName); - System.out.println(iamPolicy.getBindings()); - return iamPolicy; + return iamPolicy; + } } // [END kms_get_cryptokey_policy] @@ -309,20 +273,16 @@ public static Policy getCryptoKeyPolicy(String projectId, String locationId, Str public static Policy getKeyRingPolicy(String projectId, String locationId, String keyRingId) throws IOException { // Create the Cloud KMS client. - CloudKMS kms = createAuthorizedClient(); + try (KeyManagementServiceClient client = createClient()) { - // The resource name of the keyring - String keyring = String.format( - "projects/%s/locations/%s/keyRings/%s", - projectId, locationId, keyRingId); + // The resource name of the cryptoKey version + String keyRingName = KeyRingName.format(projectId, locationId, keyRingId); - // Get the current IAM policy and add the new account to it. - Policy iamPolicy = kms.projects().locations().keyRings() - .getIamPolicy(keyring) - .execute(); + // Get the current IAM policy and add the new account to it. + Policy iamPolicy = client.getIamPolicy(keyRingName); - System.out.println(iamPolicy.getBindings()); - return iamPolicy; + return iamPolicy; + } } // [END kms_get_keyring_policy] @@ -349,37 +309,33 @@ public static Policy addMemberToCryptoKeyPolicy( String projectId, String locationId, String keyRingId, String cryptoKeyId, String member, String role) throws IOException { + // Create the Cloud KMS client. - CloudKMS kms = createAuthorizedClient(); - - // The resource name of the cryptoKey version - String cryptoKey = String.format( - "projects/%s/locations/%s/keyRings/%s/cryptoKeys/%s", - projectId, locationId, keyRingId, cryptoKeyId); - - // Get the current IAM policy - Policy iamPolicy = getCryptoKeyPolicy(projectId, locationId, keyRingId, cryptoKeyId); - - // Add the new account to it. - Binding newBinding = new Binding() - .setRole(role) - .setMembers(Collections.singletonList(member)); - List bindings = iamPolicy.getBindings(); - if (null == bindings) { - bindings = Collections.singletonList(newBinding); - } else { - bindings.add(newBinding); - } - iamPolicy.setBindings(bindings); + try (KeyManagementServiceClient client = createClient()) { + + // The resource name of the cryptoKey version + String keyName = CryptoKeyName.format(projectId, locationId, keyRingId, cryptoKeyId); + + // Get the current IAM policy + Policy iamPolicy = client.getIamPolicy(keyName); + + // Create a new binding with the selected role and member + Binding newBinding = Binding.newBuilder() + .setRole(role) + .addMembers(member) + .build(); + + // Create a new IAM policy containing the existing settings plus the new binding. + Policy newPolicy = Policy.newBuilder() + .mergeFrom(iamPolicy) + .addBindings(newBinding) + .build(); - // Set the new IAM Policy. - Policy newIamPolicy = kms.projects().locations().keyRings() - .cryptoKeys() - .setIamPolicy(cryptoKey, new SetIamPolicyRequest().setPolicy(iamPolicy)) - .execute(); + // Set the new IAM Policy. + Policy policyResult = client.setIamPolicy(keyName, newPolicy); - System.out.println("Response: " + newIamPolicy); - return newIamPolicy; + return policyResult; + } } // [END kms_add_member_to_cryptokey_policy] @@ -404,37 +360,33 @@ public static Policy addMemberToCryptoKeyPolicy( public static Policy addMemberToKeyRingPolicy( String projectId, String locationId, String keyRingId, String member, String role) throws IOException { + // Create the Cloud KMS client. - CloudKMS kms = createAuthorizedClient(); - - // The resource name of the keyring version - String keyring = String.format( - "projects/%s/locations/%s/keyRings/%s", - projectId, locationId, keyRingId); - - // Get the current IAM policy - Policy iamPolicy = getKeyRingPolicy(projectId, locationId, keyRingId); - - // Add the new account to it. - Binding newBinding = new Binding() - .setRole(role) - .setMembers(Collections.singletonList(member)); - List bindings = iamPolicy.getBindings(); - if (null == bindings) { - bindings = Collections.singletonList(newBinding); - } else { - bindings.add(newBinding); - } - iamPolicy.setBindings(bindings); + try (KeyManagementServiceClient client = createClient()) { + + // The resource name of the cryptoKey version + String keyRingName = KeyRingName.format(projectId, locationId, keyRingId); + + // Get the current IAM policy + Policy iamPolicy = client.getIamPolicy(keyRingName); - // Set the new IAM Policy. - Policy newIamPolicy = kms.projects().locations() - .keyRings() - .setIamPolicy(keyring, new SetIamPolicyRequest().setPolicy(iamPolicy)) - .execute(); + // Create a new binding with the selected role and member + Binding newBinding = Binding.newBuilder() + .setRole(role) + .addMembers(member) + .build(); - System.out.println("Response: " + newIamPolicy); - return newIamPolicy; + // Create a new IAM policy containing the existing settings plus the new binding. + Policy newPolicy = Policy.newBuilder() + .mergeFrom(iamPolicy) + .addBindings(newBinding) + .build(); + + // Set the new IAM Policy. + Policy policyResult = client.setIamPolicy(keyRingName, newPolicy); + + return policyResult; + } } // [END kms_add_member_to_keyring_policy] @@ -447,38 +399,42 @@ public static Policy removeMemberFromCryptoKeyPolicy( String projectId, String locationId, String keyRingId, String cryptoKeyId, String member, String role) throws IOException { - // Create the Cloud KMS client. - CloudKMS kms = createAuthorizedClient(); - // The resource name of the cryptoKey - String cryptoKey = String.format( - "projects/%s/locations/%s/keyRings/%s/cryptoKeys/%s", - projectId, locationId, keyRingId, cryptoKeyId); + // Create the Cloud KMS client. + try (KeyManagementServiceClient client = createClient()) { + + // The resource name of the cryptoKey version + String keyName = CryptoKeyName.format(projectId, locationId, keyRingId, cryptoKeyId); + + // Get the current IAM policy + Policy iamPolicy = client.getIamPolicy(keyName); + + // Create a bindings list that filters out the provided member + List newBindings = new ArrayList<>(); + for (Binding b : iamPolicy.getBindingsList()) { + if (!b.getRole().equals(role)) { + newBindings.add(b); + continue; + } + + Binding.Builder builder = Binding.newBuilder().setRole(b.getRole()); + for (String m : b.getMembersList()) { + if (!member.equals(m)) { + builder.addMembers(m); + } + } + newBindings.add(builder.build()); + } - // Get the current IAM policy and add the new account to it. - Policy iamPolicy = getCryptoKeyPolicy(projectId, locationId, keyRingId, cryptoKeyId); + Policy newIamPolicy = Policy.newBuilder() + .addAllBindings(newBindings) + .build(); - if (null == iamPolicy.getBindings()) { - // Nothing to remove - return null; - } + // Set the new IAM Policy. + Policy result = client.setIamPolicy(keyName, newIamPolicy); - // Filter out the given member - for (Binding b : iamPolicy.getBindings()) { - if (role.equals(b.getRole()) && b.getMembers().contains(member)) { - b.getMembers().removeAll(Collections.singletonList(member)); - break; - } + return result; } - - // Set the new IAM Policy. - Policy newIamPolicy = kms.projects().locations().keyRings() - .cryptoKeys() - .setIamPolicy(cryptoKey, new SetIamPolicyRequest().setPolicy(iamPolicy)) - .execute(); - - System.out.println("Response: " + newIamPolicy); - return newIamPolicy; } // [END kms_remove_member_from_cryptokey_policy] @@ -490,33 +446,41 @@ public static Policy removeMemberFromCryptoKeyPolicy( public static Policy removeMemberFromKeyRingPolicy( String projectId, String locationId, String keyRingId, String member, String role) throws IOException { + // Create the Cloud KMS client. - CloudKMS kms = createAuthorizedClient(); + try (KeyManagementServiceClient client = createClient()) { + + // The resource name of the cryptoKey version + String keyRingName = KeyRingName.format(projectId, locationId, keyRingId); + + // Get the current IAM policy + Policy iamPolicy = client.getIamPolicy(keyRingName); + + // Create a bindings list that filters out the provided member + List newBindings = new ArrayList<>(); + for (Binding b : iamPolicy.getBindingsList()) { + if (!b.getRole().equals(role)) { + newBindings.add(b); + } else { + Binding.Builder builder = Binding.newBuilder().setRole(b.getRole()); + for (String m : b.getMembersList()) { + if (!member.equals(m)) { + builder.addMembers(m); + } + } + newBindings.add(builder.build()); + } + } - // The resource name of the cryptoKey - String cryptoKey = String.format( - "projects/%s/locations/%s/keyRings/%s", - projectId, locationId, keyRingId); + Policy newIamPolicy = Policy.newBuilder() + .addAllBindings(newBindings) + .build(); - // Get the current IAM policy and add the new account to it. - Policy iamPolicy = getKeyRingPolicy(projectId, locationId, keyRingId); + // Set the new IAM Policy. + Policy result = client.setIamPolicy(keyRingName, newIamPolicy); - // Filter out the given member - for (Binding b : iamPolicy.getBindings()) { - if (role.equals(b.getRole()) && b.getMembers().contains(member)) { - b.getMembers().remove(member); - break; - } + return result; } - - // Set the new IAM Policy. - Policy newIamPolicy = kms.projects().locations() - .keyRings() - .setIamPolicy(cryptoKey, new SetIamPolicyRequest().setPolicy(iamPolicy)) - .execute(); - - System.out.println("Response: " + newIamPolicy); - return newIamPolicy; } // [END kms_remove_member_from_keyring_policy] @@ -524,32 +488,22 @@ public static Policy removeMemberFromKeyRingPolicy( * Lists all the key rings in the given project. */ public static List listKeyRings(String projectId, String locationId) throws IOException { + // Create the Cloud KMS client. - CloudKMS kms = createAuthorizedClient(); - - // The resource name of the cryptoKey - String keyRingPath = String.format( - "projects/%s/locations/%s", - projectId, locationId); - - // Make the RPC call - ListKeyRingsResponse response = kms.projects().locations() - .keyRings() - .list(keyRingPath) - .execute(); - - // Print the returned key rings - if (null != response.getKeyRings()) { - ArrayList result = new ArrayList<>(); - System.out.println("Key Rings: "); - for (KeyRing keyRing : response.getKeyRings()) { - result.add(keyRing); - System.out.println(keyRing.getName()); + try (KeyManagementServiceClient client = createClient()) { + + // The resource name of the location to search. + String parent = LocationName.format(projectId, locationId); + + // Retrieve a paginated list of KeyRings + ListKeyRingsPagedResponse response = client.listKeyRings(parent); + + ArrayList results = new ArrayList<>(); + // Iterate over all KeyRings (subsequent pages are retrieved automatically) + for (KeyRing keyRing : response.iterateAll()) { + results.add(keyRing); } - return result; - } else { - System.out.println("No keyrings defined."); - return Collections.emptyList(); + return results; } } @@ -559,30 +513,23 @@ public static List listKeyRings(String projectId, String locationId) th public static List listCryptoKeys( String projectId, String locationId, String keyRingId) throws IOException { + // Create the Cloud KMS client. - CloudKMS kms = createAuthorizedClient(); - - // The resource name of the cryptoKey - String keyRingPath = String.format( - "projects/%s/locations/%s/keyRings/%s", - projectId, locationId, keyRingId); - - ArrayList results = new ArrayList<>(); - ListCryptoKeysResponse cryptoKeys = null; - do { // Print every page of keys - cryptoKeys = kms.projects().locations().keyRings() - .cryptoKeys() - .list(keyRingPath) - .setPageToken(cryptoKeys != null ? cryptoKeys.getNextPageToken() : null) - .execute(); - - for (CryptoKey key : cryptoKeys.getCryptoKeys()) { - results.add(key); - System.out.println(key); - } - } while (cryptoKeys.getNextPageToken() != null); + try (KeyManagementServiceClient client = createClient()) { + + // The resource name of the KeyRing to search. + String parent = KeyRingName.format(projectId, locationId, keyRingId); - return results; + // Retrieve a paginated list of CryptoKeys + ListCryptoKeysPagedResponse response = client.listCryptoKeys(parent); + + ArrayList keys = new ArrayList<>(); + // Iterate over all CryptoKeys (subsequent pages are retrieved automatically) + for (CryptoKey cryptoKey : response.iterateAll()) { + keys.add(cryptoKey); + } + return keys; + } } /** @@ -591,27 +538,25 @@ public static List listCryptoKeys( public static List listCryptoKeyVersions( String projectId, String locationId, String keyRingId, String cryptoKeyId) throws IOException { + // Create the Cloud KMS client. - CloudKMS kms = createAuthorizedClient(); + try (KeyManagementServiceClient client = createClient()) { - // The resource name of the cryptoKey - String cryptoKeys = String.format( - "projects/%s/locations/%s/keyRings/%s/cryptoKeys/%s", - projectId, locationId, keyRingId, cryptoKeyId); + // The resource name of the CryptoKey to search. + String parent = CryptoKeyName.format(projectId, locationId, keyRingId, cryptoKeyId); + // Retrieve a paginated list of CryptoKeyVersions + ListCryptoKeyVersionsPagedResponse response = client.listCryptoKeyVersions(parent); - ListCryptoKeyVersionsResponse versions = kms.projects().locations().keyRings().cryptoKeys() - .cryptoKeyVersions() - .list(cryptoKeys) - .execute(); + ArrayList results = new ArrayList<>(); - ArrayList results = new ArrayList<>(); - for (CryptoKeyVersion version : versions.getCryptoKeyVersions()) { - System.out.println(version); - results.add(version); - } + // Iterate over all CryptoKeyVersions (subsequent pages are retrieved automatically) + for (CryptoKeyVersion version : response.iterateAll()) { + results.add(version); + } - return results; + return results; + } } /** @@ -619,20 +564,17 @@ public static List listCryptoKeyVersions( */ public static CryptoKey setPrimaryVersion(String projectId, String locationId, String keyRingId, String cryptoKeyId, String versionId) throws IOException { - // Create the Cloud KMS client. - CloudKMS kms = createAuthorizedClient(); - // Resource name of the key version. - String resourceName = String - .format("projects/%s/locations/%s/keyRings/%s/cryptoKeys/%s", - projectId, locationId, keyRingId, cryptoKeyId); + // Create the Cloud KMS client. + try (KeyManagementServiceClient client = createClient()) { - CryptoKey key = kms.projects().locations().keyRings().cryptoKeys() - .updatePrimaryVersion(resourceName, - new UpdateCryptoKeyPrimaryVersionRequest().setCryptoKeyVersionId(versionId)).execute(); + // The resource name of the CryptoKey to update. + String resourceName = CryptoKeyName.format(projectId, locationId, keyRingId, cryptoKeyId); - System.out.println(key); - return key; + // Update the primary CryptoKey version + CryptoKey key = client.updateCryptoKeyPrimaryVersion(resourceName, versionId); + return key; + } } diff --git a/kms/src/test/java/com/example/CryptFileIT.java b/kms/src/test/java/com/example/CryptFileIT.java index 4a09f6a792d..a1f38aa20ea 100644 --- a/kms/src/test/java/com/example/CryptFileIT.java +++ b/kms/src/test/java/com/example/CryptFileIT.java @@ -18,9 +18,9 @@ import static com.google.common.truth.Truth.assertThat; -import com.google.api.services.cloudkms.v1.model.CryptoKey; -import com.google.api.services.cloudkms.v1.model.CryptoKeyVersion; -import com.google.api.services.cloudkms.v1.model.KeyRing; +import com.google.cloud.kms.v1.CryptoKey; +import com.google.cloud.kms.v1.CryptoKeyVersion; +import com.google.cloud.kms.v1.KeyRing; import java.util.List; import java.util.UUID; @@ -66,10 +66,12 @@ public static void setUpClass() throws Exception { public static void tearDownClass() throws Exception { List versions = Snippets.listCryptoKeyVersions(PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID); - + for (CryptoKeyVersion v : versions) { - if (!v.getState().equals("DESTROY_SCHEDULED")) { - Snippets.destroyCryptoKeyVersion(v.getName()); + if (!v.getState().equals(CryptoKeyVersion.CryptoKeyVersionState.DESTROY_SCHEDULED)) { + Snippets.destroyCryptoKeyVersion( + PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID, + SnippetsIT.parseVersionId(v.getName())); } } } diff --git a/kms/src/test/java/com/example/QuickstartIT.java b/kms/src/test/java/com/example/QuickstartIT.java index 1cbf09fe87e..081d238470a 100644 --- a/kms/src/test/java/com/example/QuickstartIT.java +++ b/kms/src/test/java/com/example/QuickstartIT.java @@ -18,9 +18,9 @@ import static com.google.common.truth.Truth.assertThat; -import com.google.api.services.cloudkms.v1.model.CryptoKey; -import com.google.api.services.cloudkms.v1.model.CryptoKeyVersion; -import com.google.api.services.cloudkms.v1.model.KeyRing; +import com.google.cloud.kms.v1.CryptoKey; +import com.google.cloud.kms.v1.CryptoKeyVersion; +import com.google.cloud.kms.v1.KeyRing; import java.io.ByteArrayOutputStream; import java.io.PrintStream; @@ -66,10 +66,12 @@ public static void setUpClass() throws Exception { public static void tearDownClass() throws Exception { List versions = Snippets.listCryptoKeyVersions(PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID); - + for (CryptoKeyVersion v : versions) { - if (!v.getState().equals("DESTROY_SCHEDULED")) { - Snippets.destroyCryptoKeyVersion(v.getName()); + if (!v.getState().equals(CryptoKeyVersion.CryptoKeyVersionState.DESTROY_SCHEDULED)) { + Snippets.destroyCryptoKeyVersion( + PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID, + SnippetsIT.parseVersionId(v.getName())); } } } diff --git a/kms/src/test/java/com/example/SnippetsIT.java b/kms/src/test/java/com/example/SnippetsIT.java index 3b81adf0d25..26185af626c 100644 --- a/kms/src/test/java/com/example/SnippetsIT.java +++ b/kms/src/test/java/com/example/SnippetsIT.java @@ -19,11 +19,11 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertTrue; -import com.google.api.services.cloudkms.v1.model.Binding; -import com.google.api.services.cloudkms.v1.model.CryptoKey; -import com.google.api.services.cloudkms.v1.model.CryptoKeyVersion; -import com.google.api.services.cloudkms.v1.model.KeyRing; -import com.google.api.services.cloudkms.v1.model.Policy; +import com.google.cloud.kms.v1.CryptoKey; +import com.google.cloud.kms.v1.CryptoKeyVersion; +import com.google.cloud.kms.v1.KeyRing; +import com.google.iam.v1.Binding; +import com.google.iam.v1.Policy; import java.util.List; import java.util.UUID; @@ -72,10 +72,11 @@ public static void setUpClass() throws Exception { public static void tearDownClass() throws Exception { List versions = Snippets.listCryptoKeyVersions(PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID); - + for (CryptoKeyVersion v : versions) { - if (!v.getState().equals("DESTROY_SCHEDULED")) { - Snippets.destroyCryptoKeyVersion(v.getName()); + if (!v.getState().equals(CryptoKeyVersion.CryptoKeyVersionState.DESTROY_SCHEDULED)) { + Snippets.destroyCryptoKeyVersion( + PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID, parseVersionId(v.getName())); } } } @@ -104,7 +105,7 @@ public void listCryptoKeyVersions_retrievesVersions() throws Exception { assertThat(v.getName()).contains(String.format( "keyRings/%s/cryptoKeys/%s/cryptoKeyVersions/", KEY_RING_ID, CRYPTO_KEY_ID)); - if (v.getState().equals("ENABLED")) { + if (v.getState().equals(CryptoKeyVersion.CryptoKeyVersionState.ENABLED)) { return; } } @@ -122,7 +123,7 @@ public void disableCryptoKeyVersion_disables() throws Exception { CryptoKeyVersion disabled = Snippets.disableCryptoKeyVersion( PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID, versionId); - assertThat(disabled.getState()).isEqualTo("DISABLED"); + assertThat(disabled.getState()).isEqualTo(CryptoKeyVersion.CryptoKeyVersionState.DISABLED); } @Test @@ -135,12 +136,12 @@ public void enableCryptoKeyVersion_enables() throws Exception { // Disable the new key version CryptoKeyVersion disabled = Snippets.disableCryptoKeyVersion( PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID, versionId); - assertThat(disabled.getState()).isEqualTo("DISABLED"); + assertThat(disabled.getState()).isEqualTo(CryptoKeyVersion.CryptoKeyVersionState.DISABLED); // Enable the now-disabled key version CryptoKeyVersion enabled = Snippets.enableCryptoKeyVersion( PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID, versionId); - assertThat(enabled.getState()).isEqualTo("ENABLED"); + assertThat(enabled.getState()).isEqualTo(CryptoKeyVersion.CryptoKeyVersionState.ENABLED); } @Test @@ -153,7 +154,8 @@ public void destroyCryptoKeyVersion_destroys() throws Exception { // Destroy the new key version CryptoKeyVersion destroyScheduled = Snippets.destroyCryptoKeyVersion( PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID, versionId); - assertThat(destroyScheduled.getState()).isEqualTo("DESTROY_SCHEDULED"); + assertThat(destroyScheduled.getState()).isEqualTo( + CryptoKeyVersion.CryptoKeyVersionState.DESTROY_SCHEDULED); } @@ -168,12 +170,14 @@ public void restoreCryptoKeyVersion_restores() throws Exception { // version for destruction. CryptoKeyVersion destroyScheduled = Snippets.destroyCryptoKeyVersion( PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID, versionId); - assertThat(destroyScheduled.getState()).isEqualTo("DESTROY_SCHEDULED"); + assertThat(destroyScheduled.getState()).isEqualTo( + CryptoKeyVersion.CryptoKeyVersionState.DESTROY_SCHEDULED); // Now restore the key version. CryptoKeyVersion restored = Snippets.restoreCryptoKeyVersion( PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID, versionId); - assertThat(restored.getState()).isEqualTo("DISABLED"); + assertThat(restored.getState()).isEqualTo( + CryptoKeyVersion.CryptoKeyVersionState.DISABLED); } @Test @@ -182,7 +186,7 @@ public void setPrimaryVersion_createKeyAndSetPrimaryVersion() throws Exception { // caching. So we test that the call was successful. CryptoKeyVersion version = Snippets.createCryptoKeyVersion( PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID); - assertThat(version.getState()).isEqualTo("ENABLED"); + assertThat(version.getState()).isEqualTo(CryptoKeyVersion.CryptoKeyVersionState.ENABLED); String versionId = parseVersionId(version.getName()); @@ -198,11 +202,9 @@ public void addAndRemoveMemberToCryptoKeyPolicy_addsDisplaysAndRemoves() throws PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID); // Make sure the policy doesn't already have our test user - if (policy.getBindings() != null) { // TODO: remove when we use the GAPIC client - for (Binding binding : policy.getBindings()) { - for (String m : binding.getMembers()) { - assertThat(TEST_USER).isNotEqualTo(m); - } + for (Binding binding : policy.getBindingsList()) { + for (String m : binding.getMembersList()) { + assertThat(TEST_USER).isNotEqualTo(m); } } @@ -211,8 +213,8 @@ public void addAndRemoveMemberToCryptoKeyPolicy_addsDisplaysAndRemoves() throws Policy added = Snippets.addMemberToCryptoKeyPolicy( PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID, TEST_USER, TEST_ROLE); - for (Binding binding : added.getBindings()) { - for (String m : binding.getMembers()) { + for (Binding binding : added.getBindingsList()) { + for (String m : binding.getMembersList()) { if (TEST_USER.equals(m)) { return; } @@ -225,11 +227,9 @@ public void addAndRemoveMemberToCryptoKeyPolicy_addsDisplaysAndRemoves() throws // Now remove the test user, and make sure the policy no longer has it Policy removed = Snippets.removeMemberFromCryptoKeyPolicy( PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID, TEST_USER, TEST_ROLE); - if (policy.getBindings() != null) { // TODO: remove when we use the GAPIC client - for (Binding binding : removed.getBindings()) { - for (String m : binding.getMembers()) { - assertThat(TEST_USER).isNotEqualTo(m); - } + for (Binding binding : removed.getBindingsList()) { + for (String m : binding.getMembersList()) { + assertThat(TEST_USER).isNotEqualTo(m); } } } @@ -241,11 +241,9 @@ public void addAndRemoveMemberToKeyRingPolicy_addsDisplaysAndRemoves() throws Ex Policy policy = Snippets.getKeyRingPolicy(PROJECT_ID, LOCATION_ID, KEY_RING_ID); // Make sure the policy doesn't already have our test user - if (policy.getBindings() != null) { // TODO: remove when we use the GAPIC client - for (Binding binding : policy.getBindings()) { - for (String m : binding.getMembers()) { - assertThat(TEST_USER).isNotEqualTo(m); - } + for (Binding binding : policy.getBindingsList()) { + for (String m : binding.getMembersList()) { + assertThat(TEST_USER).isNotEqualTo(m); } } @@ -254,8 +252,8 @@ public void addAndRemoveMemberToKeyRingPolicy_addsDisplaysAndRemoves() throws Ex Policy added = Snippets.addMemberToKeyRingPolicy( PROJECT_ID, LOCATION_ID, KEY_RING_ID, TEST_USER, TEST_ROLE); - for (Binding binding : added.getBindings()) { - for (String m : binding.getMembers()) { + for (Binding binding : added.getBindingsList()) { + for (String m : binding.getMembersList()) { if (TEST_USER.equals(m)) { return; } @@ -268,11 +266,9 @@ public void addAndRemoveMemberToKeyRingPolicy_addsDisplaysAndRemoves() throws Ex // Now remove the test user, and make sure the policy no longer has it Policy removed = Snippets.removeMemberFromKeyRingPolicy( PROJECT_ID, LOCATION_ID, KEY_RING_ID, TEST_USER, TEST_ROLE); - if (policy.getBindings() != null) { // TODO: remove when we use the GAPIC client - for (Binding binding : removed.getBindings()) { - for (String m : binding.getMembers()) { - assertThat(TEST_USER).isNotEqualTo(m); - } + for (Binding binding : removed.getBindingsList()) { + for (String m : binding.getMembersList()) { + assertThat(TEST_USER).isNotEqualTo(m); } } } From 9468204b1215d6159967f88ced2771a12292121a Mon Sep 17 00:00:00 2001 From: Bradley Hess Date: Wed, 14 Nov 2018 09:37:15 -0500 Subject: [PATCH 07/15] Build CryptFile client from Snippets --- kms/src/main/java/com/example/CryptFile.java | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/kms/src/main/java/com/example/CryptFile.java b/kms/src/main/java/com/example/CryptFile.java index dfd615e1437..fd770e9dce3 100644 --- a/kms/src/main/java/com/example/CryptFile.java +++ b/kms/src/main/java/com/example/CryptFile.java @@ -28,18 +28,6 @@ public class CryptFile { - /** - * Creates a KeyManagementServiceClient using Application Default Credentials. - * - * @return an authorized KeyManagementServiceClient. - * @throws IOException if there's an error getting the default credentials. - */ - public static KeyManagementServiceClient createClient() throws IOException { - // GAP: missing ability to set application name - // see https://github.com/googleapis/gax-java/issues/614 - return KeyManagementServiceClient.create(); - } - // [START kms_encrypt] /** @@ -50,7 +38,7 @@ public static byte[] encrypt( throws IOException { // Create the KeyManagementServiceClient using try-with-resources to manage client cleanup. - try (KeyManagementServiceClient client = createClient()) { + try (KeyManagementServiceClient client = Snippets.createClient()) { // The resource name of the cryptoKey String resourceName = CryptoKeyName.format(projectId, locationId, keyRingId, cryptoKeyId); @@ -74,7 +62,7 @@ public static byte[] decrypt( throws IOException { // Create the KeyManagementServiceClient using try-with-resources to manage client cleanup. - try (KeyManagementServiceClient client = createClient()) { + try (KeyManagementServiceClient client = Snippets.createClient()) { // The resource name of the cryptoKey String resourceName = CryptoKeyName.format(projectId, locationId, keyRingId, cryptoKeyId); From 8cb9f98b9e7f655f4658ee99e3d0409ce281a1cd Mon Sep 17 00:00:00 2001 From: Bradley Hess Date: Wed, 14 Nov 2018 13:46:40 -0500 Subject: [PATCH 08/15] Port asymmetric tests --- kms/src/main/java/com/example/Asymmetric.java | 207 ++++++------------ .../test/java/com/example/AsymmetricIT.java | 156 +++++++------ 2 files changed, 147 insertions(+), 216 deletions(-) diff --git a/kms/src/main/java/com/example/Asymmetric.java b/kms/src/main/java/com/example/Asymmetric.java index e9902b31d1a..101d9e089b9 100644 --- a/kms/src/main/java/com/example/Asymmetric.java +++ b/kms/src/main/java/com/example/Asymmetric.java @@ -16,40 +16,26 @@ package com.example; -import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; -import com.google.api.client.http.HttpTransport; -import com.google.api.client.http.javanet.NetHttpTransport; -import com.google.api.client.json.JsonFactory; -import com.google.api.client.json.jackson2.JacksonFactory; -import com.google.api.services.cloudkms.v1.CloudKMS; -import com.google.api.services.cloudkms.v1.CloudKMSScopes; -import com.google.api.services.cloudkms.v1.model.AsymmetricDecryptRequest; -import com.google.api.services.cloudkms.v1.model.AsymmetricDecryptResponse; -import com.google.api.services.cloudkms.v1.model.AsymmetricSignRequest; -import com.google.api.services.cloudkms.v1.model.AsymmetricSignResponse; -import com.google.api.services.cloudkms.v1.model.Digest; -import com.google.api.services.cloudkms.v1.model.KeyRing; -import com.google.api.services.cloudkms.v1.model.ListKeyRingsResponse; +import com.google.cloud.kms.v1.AsymmetricDecryptResponse; +import com.google.cloud.kms.v1.AsymmetricSignRequest; +import com.google.cloud.kms.v1.AsymmetricSignResponse; +import com.google.cloud.kms.v1.Digest; +import com.google.cloud.kms.v1.KeyManagementServiceClient; +import com.google.common.io.BaseEncoding; +import com.google.protobuf.ByteString; + import java.io.IOException; -import java.io.StringReader; -import java.security.InvalidKeyException; +import java.security.GeneralSecurityException; import java.security.KeyFactory; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; import java.security.PublicKey; -import java.security.Security; import java.security.Signature; -import java.security.SignatureException; -import java.security.spec.InvalidKeySpecException; +import java.security.spec.MGF1ParameterSpec; import java.security.spec.X509EncodedKeySpec; -import java.util.Base64; -import javax.crypto.BadPaddingException; import javax.crypto.Cipher; -import javax.crypto.IllegalBlockSizeException; -import javax.crypto.NoSuchPaddingException; -import org.bouncycastle.jce.provider.BouncyCastleProvider; -import org.bouncycastle.util.io.pem.PemReader; +import javax.crypto.spec.OAEPParameterSpec; +import javax.crypto.spec.PSource; @SuppressWarnings("checkstyle:abbreviationaswordinname") public class Asymmetric { @@ -57,35 +43,28 @@ public class Asymmetric { // [START kms_get_asymmetric_public] /** * Retrieves the public key from a saved asymmetric key pair on Cloud KMS - * - * Requires: - * java.io.StringReader - * java.security.KeyFactory - * java.security.PublicKey - * java.security.Security - * java.security.spec.X509EncodedKeySpec - * org.bouncycastle.jce.provider.BouncyCastleProvider - * org.bouncycastle.util.io.pem.PemReader */ - public static PublicKey getAsymmetricPublicKey(CloudKMS client, String keyPath) - throws IOException, NoSuchAlgorithmException, InvalidKeySpecException, - NoSuchProviderException { - Security.addProvider(new BouncyCastleProvider()); - com.google.api.services.cloudkms.v1.model.PublicKey response; - response = client.projects() - .locations() - .keyRings() - .cryptoKeys() - .cryptoKeyVersions() - .getPublicKey(keyPath) - .execute(); - PemReader reader = new PemReader(new StringReader(response.getPem())); - byte[] pem = reader.readPemObject().getContent(); - X509EncodedKeySpec abstractKey = new X509EncodedKeySpec(pem); - try { - return KeyFactory.getInstance("RSA", "BC").generatePublic(abstractKey); - } catch (InvalidKeySpecException e) { - return KeyFactory.getInstance("ECDSA", "BC").generatePublic(abstractKey); + public static PublicKey getAsymmetricPublicKey(KeyManagementServiceClient client, String keyPath) + throws IOException, GeneralSecurityException { + + com.google.cloud.kms.v1.PublicKey pub = client.getPublicKey(keyPath); + + // Convert a PEM key to DER without taking a dependency on a third party library + String pemKey = pub.getPem(); + pemKey = pemKey.replaceFirst("-----BEGIN PUBLIC KEY-----", ""); + pemKey = pemKey.replaceFirst("-----END PUBLIC KEY-----", ""); + pemKey = pemKey.replaceAll("\\s", ""); + byte[] derKey = BaseEncoding.base64().decode(pemKey); + + X509EncodedKeySpec keySpec = new X509EncodedKeySpec(derKey); + + if (pub.getAlgorithm().name().contains("RSA")) { + return KeyFactory.getInstance("RSA").generatePublic(keySpec); + } else if (pub.getAlgorithm().name().contains("EC")) { + return KeyFactory.getInstance("EC").generatePublic(keySpec); + } else { + throw new UnsupportedOperationException(String.format( + "key at path '%s' is of unsupported type '%s'.", keyPath, pub.getAlgorithm())); } } // [END kms_get_asymmetric_public] @@ -95,17 +74,12 @@ public static PublicKey getAsymmetricPublicKey(CloudKMS client, String keyPath) * Decrypt a given ciphertext using an 'RSA_DECRYPT_OAEP_2048_SHA256' private key * stored on Cloud KMS */ - public static byte[] decryptRSA(byte[] ciphertext, CloudKMS client, String keyPath) + public static byte[] decryptRSA( + KeyManagementServiceClient client, String keyPath, byte[] ciphertext) throws IOException { - AsymmetricDecryptRequest request = new AsymmetricDecryptRequest().encodeCiphertext(ciphertext); - AsymmetricDecryptResponse response = client.projects() - .locations() - .keyRings() - .cryptoKeys() - .cryptoKeyVersions() - .asymmetricDecrypt(keyPath, request) - .execute(); - return response.decodePlaintext(); + AsymmetricDecryptResponse response = + client.asymmetricDecrypt(keyPath, ByteString.copyFrom(ciphertext)); + return response.getPlaintext().toByteArray(); } // [END kms_decrypt_rsa] @@ -113,72 +87,54 @@ public static byte[] decryptRSA(byte[] ciphertext, CloudKMS client, String keyPa /** * Encrypt data locally using an 'RSA_DECRYPT_OAEP_2048_SHA256' public key * retrieved from Cloud KMS - * - * Requires: - * java.security.PublicKey - * java.security.Security - * javax.crypto.Cipher - * org.bouncycastle.jce.provider.BouncyCastleProvider */ - public static byte[] encryptRSA(byte[] plaintext, CloudKMS client, String keyPath) - throws IOException, IllegalBlockSizeException, NoSuchPaddingException, - InvalidKeySpecException, NoSuchProviderException, BadPaddingException, - NoSuchAlgorithmException, InvalidKeyException { - Security.addProvider(new BouncyCastleProvider()); + public static byte[] encryptRSA( + KeyManagementServiceClient client, String keyPath, byte[] plaintext) + throws IOException, GeneralSecurityException { PublicKey rsaKey = getAsymmetricPublicKey(client, keyPath); - Cipher cipher = Cipher.getInstance("RSA/NONE/OAEPWITHSHA256ANDMGF1PADDING", "BC"); - cipher.init(Cipher.ENCRYPT_MODE, rsaKey); + Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding"); + OAEPParameterSpec oaepParams = new OAEPParameterSpec( + "SHA-256", "MGF1", MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT); + cipher.init(Cipher.ENCRYPT_MODE, rsaKey, oaepParams); + return cipher.doFinal(plaintext); } // [END kms_encrypt_rsa] // [START kms_sign_asymmetric] - /** Create a signature for a message using a private key stored on Cloud KMS - * - * Requires: - * java.security.MessageDigest - * java.util.Base64 - */ - public static byte[] signAsymmetric(byte[] message, CloudKMS client, String keyPath) + /** + * Create a signature for a message using a private key stored on Cloud KMS + */ + public static byte[] signAsymmetric( + KeyManagementServiceClient client, String keyPath, byte[] message) throws IOException, NoSuchAlgorithmException { - Digest digest = new Digest(); + // Note: some key algorithms will require a different hash function // For example, EC_SIGN_P384_SHA384 requires SHA-384 - digest.encodeSha256(MessageDigest.getInstance("SHA-256").digest(message)); - - AsymmetricSignRequest signRequest = new AsymmetricSignRequest(); - signRequest.setDigest(digest); - - AsymmetricSignResponse response = client.projects() - .locations() - .keyRings() - .cryptoKeys() - .cryptoKeyVersions() - .asymmetricSign(keyPath, signRequest) - .execute(); - return Base64.getMimeDecoder().decode(response.getSignature()); + byte[] messageHash = MessageDigest.getInstance("SHA-256").digest(message); + + AsymmetricSignRequest request = AsymmetricSignRequest.newBuilder() + .setName(keyPath) + .setDigest(Digest.newBuilder().setSha256(ByteString.copyFrom(messageHash))) + .build(); + + AsymmetricSignResponse response = client.asymmetricSign(request); + return response.getSignature().toByteArray(); } // [END kms_sign_asymmetric] // [START kms_verify_signature_rsa] /** - * Verify the validity of an 'RSA_SIGN_PSS_2048_SHA256' signature for the + * Verify the validity of an 'RSA_SIGN_PKCS1_2048_SHA256' signature for the * specified message - * - * Requires: - * java.security.PublicKey - * java.security.Security - * java.security.Signature - * org.bouncycastle.jce.provider.BouncyCastleProvider */ - public static boolean verifySignatureRSA(byte[] signature, byte[] message, CloudKMS client, - String keyPath) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException, - SignatureException, NoSuchProviderException, InvalidKeyException { - Security.addProvider(new BouncyCastleProvider()); - PublicKey rsaKey = getAsymmetricPublicKey(client, keyPath); + public static boolean verifySignatureRSA( + KeyManagementServiceClient client, String keyPath, byte[] message, byte[] signature) + throws IOException, GeneralSecurityException { - Signature rsaVerify = Signature.getInstance("SHA256withRSA/PSS"); + PublicKey rsaKey = getAsymmetricPublicKey(client, keyPath); + Signature rsaVerify = Signature.getInstance("SHA256withRSA"); rsaVerify.initVerify(rsaKey); rsaVerify.update(message); @@ -190,38 +146,17 @@ public static boolean verifySignatureRSA(byte[] signature, byte[] message, Cloud /** * Verify the validity of an 'EC_SIGN_P256_SHA256' signature for the * specified message - * - * Requires: - * java.security.PublicKey - * java.security.Security - * java.security.Signature - * org.bouncycastle.jce.provider.BouncyCastleProvider */ - public static boolean verifySignatureEC(byte[] signature, byte[] message, CloudKMS client, - String keyPath) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException, - SignatureException, NoSuchProviderException, InvalidKeyException { - Security.addProvider(new BouncyCastleProvider()); + public static boolean verifySignatureEC( + KeyManagementServiceClient client, String keyPath, byte[] message, byte[] signature) + throws IOException, GeneralSecurityException { PublicKey ecKey = getAsymmetricPublicKey(client, keyPath); - Signature ecVerify = Signature.getInstance("SHA256withECDSA", "BC"); - + Signature ecVerify = Signature.getInstance("SHA256withECDSA"); ecVerify.initVerify(ecKey); ecVerify.update(message); return ecVerify.verify(signature); } // [END kms_verify_signature_ec] - - public static CloudKMS createAuthorizedClient() throws IOException { - HttpTransport transport = new NetHttpTransport(); - JsonFactory jsonFactory = new JacksonFactory(); - GoogleCredential credential = GoogleCredential.getApplicationDefault(transport, jsonFactory); - if (credential.createScopedRequired()) { - credential = credential.createScoped(CloudKMSScopes.all()); - } - return new CloudKMS.Builder(transport, jsonFactory, credential) - .setApplicationName("CloudKMS snippets") - .build(); - } - } diff --git a/kms/src/test/java/com/example/AsymmetricIT.java b/kms/src/test/java/com/example/AsymmetricIT.java index e367d1c1966..21701269ec4 100644 --- a/kms/src/test/java/com/example/AsymmetricIT.java +++ b/kms/src/test/java/com/example/AsymmetricIT.java @@ -21,18 +21,20 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -import com.google.api.client.googleapis.json.GoogleJsonResponseException; -import com.google.api.services.cloudkms.v1.CloudKMS; -import com.google.api.services.cloudkms.v1.model.CryptoKey; -import com.google.api.services.cloudkms.v1.model.CryptoKeyVersionTemplate; -import com.google.api.services.cloudkms.v1.model.KeyRing; +import com.google.api.gax.rpc.AlreadyExistsException; +import com.google.api.gax.rpc.NotFoundException; +import com.google.cloud.kms.v1.CryptoKey; +import com.google.cloud.kms.v1.CryptoKey.CryptoKeyPurpose; +import com.google.cloud.kms.v1.CryptoKeyVersion.CryptoKeyVersionAlgorithm; +import com.google.cloud.kms.v1.CryptoKeyVersionName; +import com.google.cloud.kms.v1.CryptoKeyVersionTemplate; +import com.google.cloud.kms.v1.KeyManagementServiceClient; +import com.google.cloud.kms.v1.KeyRingName; import java.io.IOException; import java.nio.charset.StandardCharsets; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; +import java.security.GeneralSecurityException; import java.security.PublicKey; -import java.security.spec.InvalidKeySpecException; import java.util.Arrays; import org.junit.BeforeClass; @@ -46,65 +48,63 @@ @RunWith(JUnit4.class) @SuppressWarnings("checkstyle:abbreviationaswordinname") public class AsymmetricIT { - private static final String projectId = System.getenv("GOOGLE_CLOUD_PROJECT"); - private static final String parent = "projects/" + projectId + "/locations/global"; - private static final String keyRing = "kms-asymmetric-sample"; - private static final String message = "test message 123"; - private static final byte[] message_bytes = message.getBytes(StandardCharsets.UTF_8); + private static final String PROJECT_ID = System.getenv("GOOGLE_CLOUD_PROJECT"); + private static final String LOCATION = "global"; + private static final String KEY_RING = "kms-asymmetric-sample"; - private static final String rsaDecryptId = "rsa-decrypt"; - private static final String rsaSignId = "rsa-sign"; - private static final String ecSignId = "ec-sign"; + private static final String RSA_DECRYPT_ID = "rsa-decrypt"; + private static final String RSA_SIGN_ID = "rsa-pkcs-sign"; + private static final String EC_SIGN_ID = "ec-sign"; - private static final String keyParent = parent + "/keyRings/" + keyRing + "/cryptoKeys/"; - private static final String rsaDecrypt = keyParent + rsaDecryptId + "/cryptoKeyVersions/1"; - private static final String rsaSign = keyParent + rsaSignId + "/cryptoKeyVersions/1"; - private static final String ecSign = keyParent + ecSignId + "/cryptoKeyVersions/1"; + private static final String RSA_DECRYPT_PATH = + CryptoKeyVersionName.format(PROJECT_ID, LOCATION, KEY_RING, RSA_DECRYPT_ID, "1"); + private static final String RSA_SIGN_PATH = + CryptoKeyVersionName.format(PROJECT_ID, LOCATION, KEY_RING, RSA_SIGN_ID, "1"); + private static final String EC_SIGN_PATH = + CryptoKeyVersionName.format(PROJECT_ID, LOCATION, KEY_RING, EC_SIGN_ID, "1"); - private static CloudKMS client; + private static final byte[] MESSAGE = "test message 123".getBytes(StandardCharsets.UTF_8); + private static KeyManagementServiceClient client; - private static boolean createKeyHelper(String keyId, String purpose, String algorithm) - throws NoSuchAlgorithmException, InvalidKeySpecException, - NoSuchProviderException, IOException { + private static boolean createKeyHelper( + String keyId, CryptoKeyPurpose purpose, CryptoKeyVersionAlgorithm algorithm) + throws GeneralSecurityException, IOException { + + CryptoKey cryptoKey = CryptoKey.newBuilder() + .setPurpose(purpose) + .setVersionTemplate(CryptoKeyVersionTemplate.newBuilder().setAlgorithm(algorithm).build()) + .build(); - String keyPath = keyParent + keyId + "/cryptoKeyVersions/1"; try { - Asymmetric.getAsymmetricPublicKey(client, keyPath); - // got key; don't need to create one - return false; - } catch (GoogleJsonResponseException e) { - // key doesn't exist. Create it - CryptoKey cryptoKey = new CryptoKey(); - cryptoKey.setPurpose(purpose); - CryptoKeyVersionTemplate version = new CryptoKeyVersionTemplate(); - version.setAlgorithm(algorithm); - cryptoKey.setVersionTemplate(version); - - client.projects().locations().keyRings().cryptoKeys() - .create(parent + "/keyRings/" + keyRing, cryptoKey) - .setCryptoKeyId(keyId) - .execute(); + client.createCryptoKey( + KeyRingName.format(PROJECT_ID, LOCATION, KEY_RING), + keyId, + cryptoKey); return true; + } catch (AlreadyExistsException e) { + return false; } } @BeforeClass public static void setUpClass() throws Exception { - client = Asymmetric.createAuthorizedClient(); + // TODO: set application name + client = KeyManagementServiceClient.create(); + try { - // attempt to create keyRing - client.projects().locations().keyRings() - .create(parent, new KeyRing()) - .setKeyRingId(keyRing) - .execute(); - } catch (IOException e) { - // keyRing already exists. Skip + Snippets.createKeyRing(PROJECT_ID, LOCATION, KEY_RING); + } catch (AlreadyExistsException e) { + // If it already exists, we can just continue. } - boolean s1 = createKeyHelper(rsaDecryptId, "ASYMMETRIC_DECRYPT","RSA_DECRYPT_OAEP_2048_SHA256"); - boolean s2 = createKeyHelper(rsaSignId, "ASYMMETRIC_SIGN", "RSA_SIGN_PSS_2048_SHA256"); - boolean s3 = createKeyHelper(ecSignId, "ASYMMETRIC_SIGN", "EC_SIGN_P256_SHA256"); + boolean s1 = createKeyHelper(RSA_DECRYPT_ID, CryptoKeyPurpose.ASYMMETRIC_DECRYPT, + CryptoKeyVersionAlgorithm.RSA_DECRYPT_OAEP_2048_SHA256); + boolean s2 = createKeyHelper(RSA_SIGN_ID, CryptoKeyPurpose.ASYMMETRIC_SIGN, + CryptoKeyVersionAlgorithm.RSA_SIGN_PKCS1_2048_SHA256); + boolean s3 = createKeyHelper(EC_SIGN_ID, CryptoKeyPurpose.ASYMMETRIC_SIGN, + CryptoKeyVersionAlgorithm.EC_SIGN_P256_SHA256); + if (s1 || s2 || s3) { // leave time for keys to initialize Thread.sleep(20000); @@ -113,57 +113,53 @@ public static void setUpClass() throws Exception { @Test public void testGetPublicKey() throws Exception { - PublicKey rsaDecryptKey = Asymmetric.getAsymmetricPublicKey(client, rsaDecrypt); + PublicKey rsaDecryptKey = Asymmetric.getAsymmetricPublicKey(client, RSA_DECRYPT_PATH); assertEquals("invalid RSA key.", "RSA", rsaDecryptKey.getAlgorithm()); - PublicKey rsaSignKey = Asymmetric.getAsymmetricPublicKey(client, rsaSign); + PublicKey rsaSignKey = Asymmetric.getAsymmetricPublicKey(client, RSA_SIGN_PATH); assertEquals("invalid RSA key.", "RSA", rsaSignKey.getAlgorithm()); - PublicKey ecSignKey = Asymmetric.getAsymmetricPublicKey(client, ecSign); - assertEquals("invalid ECDSA key.", "ECDSA", ecSignKey.getAlgorithm()); - String fakeKeyPath = keyParent + "fake-key/cryptoKeyVersions/1"; + PublicKey ecSignKey = Asymmetric.getAsymmetricPublicKey(client, EC_SIGN_PATH); + assertEquals("invalid EC key.", "EC", ecSignKey.getAlgorithm()); + + String fakeKeyPath = CryptoKeyVersionName.format( + PROJECT_ID, LOCATION, KEY_RING, "FAKE", "1"); try { Asymmetric.getAsymmetricPublicKey(client, fakeKeyPath); - // should throw excpetion above - fail("GoogleJsonResponseException expected for non-existent key"); - } catch (GoogleJsonResponseException e) { + // should throw exception above + fail("NotFoundException expected for non-existent key"); + } catch (NotFoundException e) { // exception expected } } @Test public void testRSAEncryptDecrypt() throws Exception { - byte[] ciphertext = Asymmetric.encryptRSA(message_bytes, client, rsaDecrypt); + byte[] ciphertext = Asymmetric.encryptRSA(client, RSA_DECRYPT_PATH, MESSAGE); assertEquals("incorrect RSA ciphertext length.", 256, ciphertext.length); - byte[] plainbytes = Asymmetric.decryptRSA(ciphertext, client, rsaDecrypt); - assertTrue("decryption failed.", Arrays.equals(message_bytes, plainbytes)); - String plaintext = new String(plainbytes); - assertEquals("decryption failed.", message, plaintext); + byte[] plaintext = Asymmetric.decryptRSA(client, RSA_DECRYPT_PATH, ciphertext); + assertTrue("decryption failed.", Arrays.equals(plaintext, MESSAGE)); } @Test public void testRSASignVerify() throws Exception { - byte[] sig = Asymmetric.signAsymmetric(message_bytes, client, rsaSign); - assertEquals("invalid ciphertext length", 256, sig.length); + byte[] sig = Asymmetric.signAsymmetric(client, RSA_SIGN_PATH, MESSAGE); + assertEquals("invalid signature length", 256, sig.length); - boolean success = Asymmetric.verifySignatureRSA(sig, message_bytes, client, rsaSign); + boolean success = Asymmetric.verifySignatureRSA(client, RSA_SIGN_PATH, MESSAGE, sig); assertTrue("RSA verification failed. Valid message not accepted", success); - String changed = message + "."; - byte[] changedBytes = changed.getBytes(StandardCharsets.UTF_8); - boolean shouldFail = Asymmetric.verifySignatureRSA(sig, changedBytes, client, rsaSign); - assertFalse("RSA verification failed. Invalid message accepted", shouldFail); + byte[] alt = new byte[256]; + boolean verifiedInvalid = Asymmetric.verifySignatureRSA(client, RSA_SIGN_PATH, MESSAGE, alt); + assertFalse("RSA verification failed. Invalid message accepted", verifiedInvalid); } @Test public void testECSignVerify() throws Exception { - byte[] sig = Asymmetric.signAsymmetric(message_bytes, client, ecSign); - assertTrue("invalid ciphertext length", sig.length > 50 && sig.length < 300); - - boolean success = Asymmetric.verifySignatureEC(sig, message_bytes, client, ecSign); + byte[] sig = Asymmetric.signAsymmetric(client, EC_SIGN_PATH, MESSAGE); + boolean success = Asymmetric.verifySignatureEC(client, EC_SIGN_PATH, MESSAGE, sig); assertTrue("EC verification failed. Valid message not accepted", success); - String changed = message + "."; - byte[] changedBytes = changed.getBytes(StandardCharsets.UTF_8); - boolean shouldFail = Asymmetric.verifySignatureEC(sig, changedBytes, client, ecSign); - assertFalse("EC verification failed. Invalid message accepted", shouldFail); - } + byte[] alt = Asymmetric.signAsymmetric(client, EC_SIGN_PATH, new byte[16]); + boolean verifiedInvalid = Asymmetric.verifySignatureEC(client, EC_SIGN_PATH, MESSAGE, alt); + assertFalse("EC verification failed. Invalid message accepted", verifiedInvalid); + } } From a87f08caa53eaaa4ca7bd05c91720ba3d575f468 Mon Sep 17 00:00:00 2001 From: Bradley Hess Date: Wed, 14 Nov 2018 13:49:48 -0500 Subject: [PATCH 09/15] Remove old dependencies --- kms/pom.xml | 31 ------------------------------- 1 file changed, 31 deletions(-) diff --git a/kms/pom.xml b/kms/pom.xml index 0d567e75594..66b2f4e5cdd 100644 --- a/kms/pom.xml +++ b/kms/pom.xml @@ -27,42 +27,11 @@ google-cloud-kms 0.70.0-beta - - com.google.apis - google-api-services-cloudkms - v1-rev20181107-1.27.0 - - - com.google.guava - guava-jdk5 - - - - - com.google.guava - guava - 20.0 - - - com.google.api-client - google-api-client - 1.27.0 - - - com.google.http-client - google-http-client-jackson2 - 1.27.0 - args4j args4j 2.33 - - org.bouncycastle - bcpkix-jdk15on - 1.60 - junit From 7c8fd7739f4deac726f4b9bfaa213aa01d94cb47 Mon Sep 17 00:00:00 2001 From: Dan Sanche Date: Tue, 27 Nov 2018 10:05:26 -0800 Subject: [PATCH 10/15] removed dependency on helper functions --- kms/src/main/java/com/example/Asymmetric.java | 172 +++++++++++------- kms/src/main/java/com/example/Snippets.java | 34 ++-- 2 files changed, 123 insertions(+), 83 deletions(-) diff --git a/kms/src/main/java/com/example/Asymmetric.java b/kms/src/main/java/com/example/Asymmetric.java index 101d9e089b9..5ca36e940ac 100644 --- a/kms/src/main/java/com/example/Asymmetric.java +++ b/kms/src/main/java/com/example/Asymmetric.java @@ -44,27 +44,30 @@ public class Asymmetric { /** * Retrieves the public key from a saved asymmetric key pair on Cloud KMS */ - public static PublicKey getAsymmetricPublicKey(KeyManagementServiceClient client, String keyPath) - throws IOException, GeneralSecurityException { - - com.google.cloud.kms.v1.PublicKey pub = client.getPublicKey(keyPath); - - // Convert a PEM key to DER without taking a dependency on a third party library - String pemKey = pub.getPem(); - pemKey = pemKey.replaceFirst("-----BEGIN PUBLIC KEY-----", ""); - pemKey = pemKey.replaceFirst("-----END PUBLIC KEY-----", ""); - pemKey = pemKey.replaceAll("\\s", ""); - byte[] derKey = BaseEncoding.base64().decode(pemKey); - - X509EncodedKeySpec keySpec = new X509EncodedKeySpec(derKey); - - if (pub.getAlgorithm().name().contains("RSA")) { - return KeyFactory.getInstance("RSA").generatePublic(keySpec); - } else if (pub.getAlgorithm().name().contains("EC")) { - return KeyFactory.getInstance("EC").generatePublic(keySpec); - } else { - throw new UnsupportedOperationException(String.format( - "key at path '%s' is of unsupported type '%s'.", keyPath, pub.getAlgorithm())); + public static PublicKey getAsymmetricPublicKey(String keyPath) + throws IOException, GeneralSecurityException { + + // Create the Cloud KMS client. + try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) { + com.google.cloud.kms.v1.PublicKey pub = client.getPublicKey(keyPath); + + // Convert a PEM key to DER without taking a dependency on a third party library + String pemKey = pub.getPem(); + pemKey = pemKey.replaceFirst("-----BEGIN PUBLIC KEY-----", ""); + pemKey = pemKey.replaceFirst("-----END PUBLIC KEY-----", ""); + pemKey = pemKey.replaceAll("\\s", ""); + byte[] derKey = BaseEncoding.base64().decode(pemKey); + + X509EncodedKeySpec keySpec = new X509EncodedKeySpec(derKey); + + if (pub.getAlgorithm().name().contains("RSA")) { + return KeyFactory.getInstance("RSA").generatePublic(keySpec); + } else if (pub.getAlgorithm().name().contains("EC")) { + return KeyFactory.getInstance("EC").generatePublic(keySpec); + } else { + throw new UnsupportedOperationException(String.format( + "key at path '%s' is of unsupported type '%s'.", keyPath, pub.getAlgorithm())); + } } } // [END kms_get_asymmetric_public] @@ -74,12 +77,13 @@ public static PublicKey getAsymmetricPublicKey(KeyManagementServiceClient client * Decrypt a given ciphertext using an 'RSA_DECRYPT_OAEP_2048_SHA256' private key * stored on Cloud KMS */ - public static byte[] decryptRSA( - KeyManagementServiceClient client, String keyPath, byte[] ciphertext) - throws IOException { - AsymmetricDecryptResponse response = - client.asymmetricDecrypt(keyPath, ByteString.copyFrom(ciphertext)); - return response.getPlaintext().toByteArray(); + public static byte[] decryptRSA(String keyPath, byte[] ciphertext) throws IOException { + // Create the Cloud KMS client. + try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) { + AsymmetricDecryptResponse response = client.asymmetricDecrypt(keyPath, + ByteString.copyFrom(ciphertext)); + return response.getPlaintext().toByteArray(); + } } // [END kms_decrypt_rsa] @@ -88,17 +92,28 @@ public static byte[] decryptRSA( * Encrypt data locally using an 'RSA_DECRYPT_OAEP_2048_SHA256' public key * retrieved from Cloud KMS */ - public static byte[] encryptRSA( - KeyManagementServiceClient client, String keyPath, byte[] plaintext) - throws IOException, GeneralSecurityException { - PublicKey rsaKey = getAsymmetricPublicKey(client, keyPath); - - Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding"); - OAEPParameterSpec oaepParams = new OAEPParameterSpec( - "SHA-256", "MGF1", MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT); - cipher.init(Cipher.ENCRYPT_MODE, rsaKey, oaepParams); - - return cipher.doFinal(plaintext); + public static byte[] encryptRSA(String keyPath, byte[] plaintext) + throws IOException, GeneralSecurityException { + // Create the Cloud KMS client. + try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) { + // Get the public key + com.google.cloud.kms.v1.PublicKey pub = client.getPublicKey(keyPath); + String pemKey = pub.getPem(); + pemKey = pemKey.replaceFirst("-----BEGIN PUBLIC KEY-----", ""); + pemKey = pemKey.replaceFirst("-----END PUBLIC KEY-----", ""); + pemKey = pemKey.replaceAll("\\s", ""); + byte[] derKey = BaseEncoding.base64().decode(pemKey); + X509EncodedKeySpec keySpec = new X509EncodedKeySpec(derKey); + PublicKey rsaKey = KeyFactory.getInstance("RSA").generatePublic(keySpec); + + // Encrypt the plaintext + Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding"); + OAEPParameterSpec oaepParams = new OAEPParameterSpec( + "SHA-256", "MGF1", MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT); + cipher.init(Cipher.ENCRYPT_MODE, rsaKey, oaepParams); + + return cipher.doFinal(plaintext); + } } // [END kms_encrypt_rsa] @@ -106,21 +121,23 @@ public static byte[] encryptRSA( /** * Create a signature for a message using a private key stored on Cloud KMS */ - public static byte[] signAsymmetric( - KeyManagementServiceClient client, String keyPath, byte[] message) + public static byte[] signAsymmetric(String keyPath, byte[] message) throws IOException, NoSuchAlgorithmException { + // Create the Cloud KMS client. + try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) { - // Note: some key algorithms will require a different hash function - // For example, EC_SIGN_P384_SHA384 requires SHA-384 - byte[] messageHash = MessageDigest.getInstance("SHA-256").digest(message); - - AsymmetricSignRequest request = AsymmetricSignRequest.newBuilder() - .setName(keyPath) - .setDigest(Digest.newBuilder().setSha256(ByteString.copyFrom(messageHash))) - .build(); - - AsymmetricSignResponse response = client.asymmetricSign(request); - return response.getSignature().toByteArray(); + // Note: some key algorithms will require a different hash function + // For example, EC_SIGN_P384_SHA384 requires SHA-384 + byte[] messageHash = MessageDigest.getInstance("SHA-256").digest(message); + + AsymmetricSignRequest request = AsymmetricSignRequest.newBuilder() + .setName(keyPath) + .setDigest(Digest.newBuilder().setSha256(ByteString.copyFrom(messageHash))) + .build(); + + AsymmetricSignResponse response = client.asymmetricSign(request); + return response.getSignature().toByteArray(); + } } // [END kms_sign_asymmetric] @@ -129,16 +146,27 @@ public static byte[] signAsymmetric( * Verify the validity of an 'RSA_SIGN_PKCS1_2048_SHA256' signature for the * specified message */ - public static boolean verifySignatureRSA( - KeyManagementServiceClient client, String keyPath, byte[] message, byte[] signature) + public static boolean verifySignatureRSA(String keyPath, byte[] message, byte[] signature) throws IOException, GeneralSecurityException { - PublicKey rsaKey = getAsymmetricPublicKey(client, keyPath); - Signature rsaVerify = Signature.getInstance("SHA256withRSA"); - - rsaVerify.initVerify(rsaKey); - rsaVerify.update(message); - return rsaVerify.verify(signature); + // Create the Cloud KMS client. + try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) { + // Get the public key + com.google.cloud.kms.v1.PublicKey pub = client.getPublicKey(keyPath); + String pemKey = pub.getPem(); + pemKey = pemKey.replaceFirst("-----BEGIN PUBLIC KEY-----", ""); + pemKey = pemKey.replaceFirst("-----END PUBLIC KEY-----", ""); + pemKey = pemKey.replaceAll("\\s", ""); + byte[] derKey = BaseEncoding.base64().decode(pemKey); + X509EncodedKeySpec keySpec = new X509EncodedKeySpec(derKey); + PublicKey rsaKey = KeyFactory.getInstance("RSA").generatePublic(keySpec); + + // Verify the signature + Signature rsaVerify = Signature.getInstance("SHA256withRSA"); + rsaVerify.initVerify(rsaKey); + rsaVerify.update(message); + return rsaVerify.verify(signature); + } } // [END kms_verify_signature_rsa] @@ -147,15 +175,27 @@ public static boolean verifySignatureRSA( * Verify the validity of an 'EC_SIGN_P256_SHA256' signature for the * specified message */ - public static boolean verifySignatureEC( - KeyManagementServiceClient client, String keyPath, byte[] message, byte[] signature) + public static boolean verifySignatureEC(String keyPath, byte[] message, byte[] signature) throws IOException, GeneralSecurityException { - PublicKey ecKey = getAsymmetricPublicKey(client, keyPath); - Signature ecVerify = Signature.getInstance("SHA256withECDSA"); - ecVerify.initVerify(ecKey); - ecVerify.update(message); - return ecVerify.verify(signature); + // Create the Cloud KMS client. + try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) { + // Get the public key + com.google.cloud.kms.v1.PublicKey pub = client.getPublicKey(keyPath); + String pemKey = pub.getPem(); + pemKey = pemKey.replaceFirst("-----BEGIN PUBLIC KEY-----", ""); + pemKey = pemKey.replaceFirst("-----END PUBLIC KEY-----", ""); + pemKey = pemKey.replaceAll("\\s", ""); + byte[] derKey = BaseEncoding.base64().decode(pemKey); + X509EncodedKeySpec keySpec = new X509EncodedKeySpec(derKey); + PublicKey ecKey = KeyFactory.getInstance("EC").generatePublic(keySpec); + + // Verify the signature + Signature ecVerify = Signature.getInstance("SHA256withECDSA"); + ecVerify.initVerify(ecKey); + ecVerify.update(message); + return ecVerify.verify(signature); + } } // [END kms_verify_signature_ec] } diff --git a/kms/src/main/java/com/example/Snippets.java b/kms/src/main/java/com/example/Snippets.java index d88ecab9094..74a2f9e189c 100644 --- a/kms/src/main/java/com/example/Snippets.java +++ b/kms/src/main/java/com/example/Snippets.java @@ -63,7 +63,7 @@ public static KeyManagementServiceClient createClient() throws IOException { public static KeyRing createKeyRing(String projectId, String locationId, String keyRingId) throws IOException { // Create the Cloud KMS client. - try (KeyManagementServiceClient client = createClient()) { + try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) { // The resource name of the location associated with the KeyRing. String parent = LocationName.format(projectId, locationId); @@ -86,7 +86,7 @@ public static CryptoKey createCryptoKey(String projectId, String locationId, Str throws IOException { // Create the Cloud KMS client. - try (KeyManagementServiceClient client = createClient()) { + try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) { // The resource name of the location associated with the KeyRing. String parent = KeyRingName.format(projectId, locationId, keyRingId); @@ -112,7 +112,7 @@ public static CryptoKeyVersion createCryptoKeyVersion( String projectId, String locationId, String keyRingId, String cryptoKeyId) throws IOException { // Create the Cloud KMS client. - try (KeyManagementServiceClient client = createClient()) { + try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) { // The resource name of the cryptoKey String cryptoKey = CryptoKeyName.format(projectId, locationId, keyRingId, cryptoKeyId); @@ -134,7 +134,7 @@ public static CryptoKeyVersion disableCryptoKeyVersion( String projectId, String locationId, String keyRingId, String cryptoKeyId, String version) throws IOException { // Create the Cloud KMS client. - try (KeyManagementServiceClient client = createClient()) { + try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) { // The resource name of the cryptoKey version String versionName = CryptoKeyVersionName.format( @@ -169,7 +169,7 @@ public static CryptoKeyVersion enableCryptoKeyVersion( throws IOException { // Create the Cloud KMS client. - try (KeyManagementServiceClient client = createClient()) { + try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) { // The resource name of the cryptoKey version String versionName = CryptoKeyVersionName.format( @@ -205,7 +205,7 @@ public static CryptoKeyVersion destroyCryptoKeyVersion( throws IOException { // Create the Cloud KMS client. - try (KeyManagementServiceClient client = createClient()) { + try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) { // The resource name of the cryptoKey version String versionName = CryptoKeyVersionName.format( @@ -229,7 +229,7 @@ public static CryptoKeyVersion restoreCryptoKeyVersion( throws IOException { // Create the Cloud KMS client. - try (KeyManagementServiceClient client = createClient()) { + try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) { // The resource name of the cryptoKey version String versionName = CryptoKeyVersionName.format( @@ -252,7 +252,7 @@ public static Policy getCryptoKeyPolicy( throws IOException { // Create the Cloud KMS client. - try (KeyManagementServiceClient client = createClient()) { + try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) { // The resource name of the cryptoKey version String keyName = CryptoKeyName.format(projectId, locationId, keyRingId, cryptoKeyId); @@ -273,7 +273,7 @@ public static Policy getCryptoKeyPolicy( public static Policy getKeyRingPolicy(String projectId, String locationId, String keyRingId) throws IOException { // Create the Cloud KMS client. - try (KeyManagementServiceClient client = createClient()) { + try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) { // The resource name of the cryptoKey version String keyRingName = KeyRingName.format(projectId, locationId, keyRingId); @@ -311,7 +311,7 @@ public static Policy addMemberToCryptoKeyPolicy( throws IOException { // Create the Cloud KMS client. - try (KeyManagementServiceClient client = createClient()) { + try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) { // The resource name of the cryptoKey version String keyName = CryptoKeyName.format(projectId, locationId, keyRingId, cryptoKeyId); @@ -362,7 +362,7 @@ public static Policy addMemberToKeyRingPolicy( throws IOException { // Create the Cloud KMS client. - try (KeyManagementServiceClient client = createClient()) { + try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) { // The resource name of the cryptoKey version String keyRingName = KeyRingName.format(projectId, locationId, keyRingId); @@ -401,7 +401,7 @@ public static Policy removeMemberFromCryptoKeyPolicy( throws IOException { // Create the Cloud KMS client. - try (KeyManagementServiceClient client = createClient()) { + try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) { // The resource name of the cryptoKey version String keyName = CryptoKeyName.format(projectId, locationId, keyRingId, cryptoKeyId); @@ -448,7 +448,7 @@ public static Policy removeMemberFromKeyRingPolicy( throws IOException { // Create the Cloud KMS client. - try (KeyManagementServiceClient client = createClient()) { + try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) { // The resource name of the cryptoKey version String keyRingName = KeyRingName.format(projectId, locationId, keyRingId); @@ -490,7 +490,7 @@ public static Policy removeMemberFromKeyRingPolicy( public static List listKeyRings(String projectId, String locationId) throws IOException { // Create the Cloud KMS client. - try (KeyManagementServiceClient client = createClient()) { + try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) { // The resource name of the location to search. String parent = LocationName.format(projectId, locationId); @@ -515,7 +515,7 @@ public static List listCryptoKeys( throws IOException { // Create the Cloud KMS client. - try (KeyManagementServiceClient client = createClient()) { + try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) { // The resource name of the KeyRing to search. String parent = KeyRingName.format(projectId, locationId, keyRingId); @@ -540,7 +540,7 @@ public static List listCryptoKeyVersions( throws IOException { // Create the Cloud KMS client. - try (KeyManagementServiceClient client = createClient()) { + try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) { // The resource name of the CryptoKey to search. String parent = CryptoKeyName.format(projectId, locationId, keyRingId, cryptoKeyId); @@ -566,7 +566,7 @@ public static CryptoKey setPrimaryVersion(String projectId, String locationId, S String cryptoKeyId, String versionId) throws IOException { // Create the Cloud KMS client. - try (KeyManagementServiceClient client = createClient()) { + try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) { // The resource name of the CryptoKey to update. String resourceName = CryptoKeyName.format(projectId, locationId, keyRingId, cryptoKeyId); From 80a02b4826c97c37e7780e076a81a5f48049651b Mon Sep 17 00:00:00 2001 From: Dan Sanche Date: Tue, 27 Nov 2018 11:03:34 -0800 Subject: [PATCH 11/15] added comments explaining keyName --- kms/src/main/java/com/example/Asymmetric.java | 50 +++++++++++++------ 1 file changed, 34 insertions(+), 16 deletions(-) diff --git a/kms/src/main/java/com/example/Asymmetric.java b/kms/src/main/java/com/example/Asymmetric.java index 5ca36e940ac..faeb604f5a1 100644 --- a/kms/src/main/java/com/example/Asymmetric.java +++ b/kms/src/main/java/com/example/Asymmetric.java @@ -42,14 +42,17 @@ public class Asymmetric { // [START kms_get_asymmetric_public] /** - * Retrieves the public key from a saved asymmetric key pair on Cloud KMS + * Retrieves the public key from a saved asymmetric key pair on Cloud KMS + * + * Example keyName: + * "projects/PROJECT_ID/locations/global/keyRings/RING_ID/cryptoKeys/KEY_ID/cryptoKeyVersions/1" */ - public static PublicKey getAsymmetricPublicKey(String keyPath) + public static PublicKey getAsymmetricPublicKey(String keyName) throws IOException, GeneralSecurityException { // Create the Cloud KMS client. try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) { - com.google.cloud.kms.v1.PublicKey pub = client.getPublicKey(keyPath); + com.google.cloud.kms.v1.PublicKey pub = client.getPublicKey(keyName); // Convert a PEM key to DER without taking a dependency on a third party library String pemKey = pub.getPem(); @@ -66,7 +69,7 @@ public static PublicKey getAsymmetricPublicKey(String keyPath) return KeyFactory.getInstance("EC").generatePublic(keySpec); } else { throw new UnsupportedOperationException(String.format( - "key at path '%s' is of unsupported type '%s'.", keyPath, pub.getAlgorithm())); + "key at path '%s' is of unsupported type '%s'.", keyName, pub.getAlgorithm())); } } } @@ -74,13 +77,16 @@ public static PublicKey getAsymmetricPublicKey(String keyPath) // [START kms_decrypt_rsa] /** - * Decrypt a given ciphertext using an 'RSA_DECRYPT_OAEP_2048_SHA256' private key + * Decrypt a given ciphertext using an 'RSA_DECRYPT_OAEP_2048_SHA256' private key * stored on Cloud KMS + * + * Example keyName: + * "projects/PROJECT_ID/locations/global/keyRings/RING_ID/cryptoKeys/KEY_ID/cryptoKeyVersions/1" */ - public static byte[] decryptRSA(String keyPath, byte[] ciphertext) throws IOException { + public static byte[] decryptRSA(String keyName, byte[] ciphertext) throws IOException { // Create the Cloud KMS client. try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) { - AsymmetricDecryptResponse response = client.asymmetricDecrypt(keyPath, + AsymmetricDecryptResponse response = client.asymmetricDecrypt(keyName, ByteString.copyFrom(ciphertext)); return response.getPlaintext().toByteArray(); } @@ -91,13 +97,16 @@ public static byte[] decryptRSA(String keyPath, byte[] ciphertext) throws IOExce /** * Encrypt data locally using an 'RSA_DECRYPT_OAEP_2048_SHA256' public key * retrieved from Cloud KMS + * + * Example keyName: + * "projects/PROJECT_ID/locations/global/keyRings/RING_ID/cryptoKeys/KEY_ID/cryptoKeyVersions/1" */ - public static byte[] encryptRSA(String keyPath, byte[] plaintext) + public static byte[] encryptRSA(String keyName, byte[] plaintext) throws IOException, GeneralSecurityException { // Create the Cloud KMS client. try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) { // Get the public key - com.google.cloud.kms.v1.PublicKey pub = client.getPublicKey(keyPath); + com.google.cloud.kms.v1.PublicKey pub = client.getPublicKey(keyName); String pemKey = pub.getPem(); pemKey = pemKey.replaceFirst("-----BEGIN PUBLIC KEY-----", ""); pemKey = pemKey.replaceFirst("-----END PUBLIC KEY-----", ""); @@ -119,9 +128,12 @@ public static byte[] encryptRSA(String keyPath, byte[] plaintext) // [START kms_sign_asymmetric] /** - * Create a signature for a message using a private key stored on Cloud KMS + * Create a signature for a message using a private key stored on Cloud KMS + * + * Example keyName: + * "projects/PROJECT_ID/locations/global/keyRings/RING_ID/cryptoKeys/KEY_ID/cryptoKeyVersions/1" */ - public static byte[] signAsymmetric(String keyPath, byte[] message) + public static byte[] signAsymmetric(String keyName, byte[] message) throws IOException, NoSuchAlgorithmException { // Create the Cloud KMS client. try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) { @@ -131,7 +143,7 @@ public static byte[] signAsymmetric(String keyPath, byte[] message) byte[] messageHash = MessageDigest.getInstance("SHA-256").digest(message); AsymmetricSignRequest request = AsymmetricSignRequest.newBuilder() - .setName(keyPath) + .setName(keyName) .setDigest(Digest.newBuilder().setSha256(ByteString.copyFrom(messageHash))) .build(); @@ -145,14 +157,17 @@ public static byte[] signAsymmetric(String keyPath, byte[] message) /** * Verify the validity of an 'RSA_SIGN_PKCS1_2048_SHA256' signature for the * specified message + * + * Example keyName: + * "projects/PROJECT_ID/locations/global/keyRings/RING_ID/cryptoKeys/KEY_ID/cryptoKeyVersions/1" */ - public static boolean verifySignatureRSA(String keyPath, byte[] message, byte[] signature) + public static boolean verifySignatureRSA(String keyName, byte[] message, byte[] signature) throws IOException, GeneralSecurityException { // Create the Cloud KMS client. try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) { // Get the public key - com.google.cloud.kms.v1.PublicKey pub = client.getPublicKey(keyPath); + com.google.cloud.kms.v1.PublicKey pub = client.getPublicKey(keyName); String pemKey = pub.getPem(); pemKey = pemKey.replaceFirst("-----BEGIN PUBLIC KEY-----", ""); pemKey = pemKey.replaceFirst("-----END PUBLIC KEY-----", ""); @@ -174,14 +189,17 @@ public static boolean verifySignatureRSA(String keyPath, byte[] message, byte[] /** * Verify the validity of an 'EC_SIGN_P256_SHA256' signature for the * specified message + * + * Example keyName: + * "projects/PROJECT_ID/locations/global/keyRings/RING_ID/cryptoKeys/KEY_ID/cryptoKeyVersions/1" */ - public static boolean verifySignatureEC(String keyPath, byte[] message, byte[] signature) + public static boolean verifySignatureEC(String keyName, byte[] message, byte[] signature) throws IOException, GeneralSecurityException { // Create the Cloud KMS client. try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) { // Get the public key - com.google.cloud.kms.v1.PublicKey pub = client.getPublicKey(keyPath); + com.google.cloud.kms.v1.PublicKey pub = client.getPublicKey(keyName); String pemKey = pub.getPem(); pemKey = pemKey.replaceFirst("-----BEGIN PUBLIC KEY-----", ""); pemKey = pemKey.replaceFirst("-----END PUBLIC KEY-----", ""); From 78e8f73e14f1966e510ce35e5a898f99599478f3 Mon Sep 17 00:00:00 2001 From: Dan Sanche Date: Tue, 27 Nov 2018 15:32:58 -0800 Subject: [PATCH 12/15] removed client from asymmetric tests --- .../test/java/com/example/AsymmetricIT.java | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/kms/src/test/java/com/example/AsymmetricIT.java b/kms/src/test/java/com/example/AsymmetricIT.java index 21701269ec4..c60eba5ae95 100644 --- a/kms/src/test/java/com/example/AsymmetricIT.java +++ b/kms/src/test/java/com/example/AsymmetricIT.java @@ -113,17 +113,17 @@ public static void setUpClass() throws Exception { @Test public void testGetPublicKey() throws Exception { - PublicKey rsaDecryptKey = Asymmetric.getAsymmetricPublicKey(client, RSA_DECRYPT_PATH); + PublicKey rsaDecryptKey = Asymmetric.getAsymmetricPublicKey(RSA_DECRYPT_PATH); assertEquals("invalid RSA key.", "RSA", rsaDecryptKey.getAlgorithm()); - PublicKey rsaSignKey = Asymmetric.getAsymmetricPublicKey(client, RSA_SIGN_PATH); + PublicKey rsaSignKey = Asymmetric.getAsymmetricPublicKey(RSA_SIGN_PATH); assertEquals("invalid RSA key.", "RSA", rsaSignKey.getAlgorithm()); - PublicKey ecSignKey = Asymmetric.getAsymmetricPublicKey(client, EC_SIGN_PATH); + PublicKey ecSignKey = Asymmetric.getAsymmetricPublicKey(EC_SIGN_PATH); assertEquals("invalid EC key.", "EC", ecSignKey.getAlgorithm()); String fakeKeyPath = CryptoKeyVersionName.format( PROJECT_ID, LOCATION, KEY_RING, "FAKE", "1"); try { - Asymmetric.getAsymmetricPublicKey(client, fakeKeyPath); + Asymmetric.getAsymmetricPublicKey(fakeKeyPath); // should throw exception above fail("NotFoundException expected for non-existent key"); } catch (NotFoundException e) { @@ -133,33 +133,33 @@ public void testGetPublicKey() throws Exception { @Test public void testRSAEncryptDecrypt() throws Exception { - byte[] ciphertext = Asymmetric.encryptRSA(client, RSA_DECRYPT_PATH, MESSAGE); + byte[] ciphertext = Asymmetric.encryptRSA(RSA_DECRYPT_PATH, MESSAGE); assertEquals("incorrect RSA ciphertext length.", 256, ciphertext.length); - byte[] plaintext = Asymmetric.decryptRSA(client, RSA_DECRYPT_PATH, ciphertext); + byte[] plaintext = Asymmetric.decryptRSA(RSA_DECRYPT_PATH, ciphertext); assertTrue("decryption failed.", Arrays.equals(plaintext, MESSAGE)); } @Test public void testRSASignVerify() throws Exception { - byte[] sig = Asymmetric.signAsymmetric(client, RSA_SIGN_PATH, MESSAGE); + byte[] sig = Asymmetric.signAsymmetric(RSA_SIGN_PATH, MESSAGE); assertEquals("invalid signature length", 256, sig.length); - boolean success = Asymmetric.verifySignatureRSA(client, RSA_SIGN_PATH, MESSAGE, sig); + boolean success = Asymmetric.verifySignatureRSA(RSA_SIGN_PATH, MESSAGE, sig); assertTrue("RSA verification failed. Valid message not accepted", success); byte[] alt = new byte[256]; - boolean verifiedInvalid = Asymmetric.verifySignatureRSA(client, RSA_SIGN_PATH, MESSAGE, alt); + boolean verifiedInvalid = Asymmetric.verifySignatureRSA(RSA_SIGN_PATH, MESSAGE, alt); assertFalse("RSA verification failed. Invalid message accepted", verifiedInvalid); } @Test public void testECSignVerify() throws Exception { - byte[] sig = Asymmetric.signAsymmetric(client, EC_SIGN_PATH, MESSAGE); - boolean success = Asymmetric.verifySignatureEC(client, EC_SIGN_PATH, MESSAGE, sig); + byte[] sig = Asymmetric.signAsymmetric(EC_SIGN_PATH, MESSAGE); + boolean success = Asymmetric.verifySignatureEC(EC_SIGN_PATH, MESSAGE, sig); assertTrue("EC verification failed. Valid message not accepted", success); - byte[] alt = Asymmetric.signAsymmetric(client, EC_SIGN_PATH, new byte[16]); - boolean verifiedInvalid = Asymmetric.verifySignatureEC(client, EC_SIGN_PATH, MESSAGE, alt); + byte[] alt = Asymmetric.signAsymmetric(EC_SIGN_PATH, new byte[16]); + boolean verifiedInvalid = Asymmetric.verifySignatureEC(EC_SIGN_PATH, MESSAGE, alt); assertFalse("EC verification failed. Invalid message accepted", verifiedInvalid); } } From cd15274d2e34dc47a697c36ff3d901cc9f0f2ee0 Mon Sep 17 00:00:00 2001 From: Dan Sanche Date: Wed, 28 Nov 2018 16:41:48 -0800 Subject: [PATCH 13/15] added sample for creating asymmetric key --- kms/src/main/java/com/example/Asymmetric.java | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/kms/src/main/java/com/example/Asymmetric.java b/kms/src/main/java/com/example/Asymmetric.java index faeb604f5a1..f33792c3b8d 100644 --- a/kms/src/main/java/com/example/Asymmetric.java +++ b/kms/src/main/java/com/example/Asymmetric.java @@ -19,8 +19,13 @@ import com.google.cloud.kms.v1.AsymmetricDecryptResponse; import com.google.cloud.kms.v1.AsymmetricSignRequest; import com.google.cloud.kms.v1.AsymmetricSignResponse; +import com.google.cloud.kms.v1.CryptoKey; +import com.google.cloud.kms.v1.CryptoKey.CryptoKeyPurpose; +import com.google.cloud.kms.v1.CryptoKeyVersion.CryptoKeyVersionAlgorithm; +import com.google.cloud.kms.v1.CryptoKeyVersionTemplate; import com.google.cloud.kms.v1.Digest; import com.google.cloud.kms.v1.KeyManagementServiceClient; +import com.google.cloud.kms.v1.KeyRingName; import com.google.common.io.BaseEncoding; import com.google.protobuf.ByteString; @@ -40,6 +45,42 @@ @SuppressWarnings("checkstyle:abbreviationaswordinname") public class Asymmetric { + // [START kms_create_asymmetric_key] + /** + * Creates an RSA encrypt/decrypt key pair with the given id. + */ + public static CryptoKey createAsymmetricKey(String projectId, String locationId, String keyRingId, + String cryptoKeyId) + throws IOException { + + // Create the Cloud KMS client. + try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) { + // The resource name of the location associated with the KeyRing. + String parent = KeyRingName.format(projectId, locationId, keyRingId); + + // Choose a purpose (ASYMMETRIC_DECRYPT or ASYMMETRIC_SIGN). + CryptoKeyPurpose purpose = CryptoKeyPurpose.ASYMMETRIC_DECRYPT; + + // Choose an algorithm. + CryptoKeyVersionAlgorithm algorithm = CryptoKeyVersionAlgorithm.RSA_DECRYPT_OAEP_2048_SHA256; + CryptoKeyVersionTemplate version = CryptoKeyVersionTemplate.newBuilder() + .setAlgorithm(algorithm) + .build(); + + // Build the key template + CryptoKey cryptoKey = CryptoKey.newBuilder() + .setPurpose(purpose) + .setVersionTemplate(version) + .build(); + + // Create the CryptoKey for your project. + CryptoKey createdKey = client.createCryptoKey(parent, cryptoKeyId, cryptoKey); + + return createdKey; + } + } + // [END kms_create_asymmetric_key] + // [START kms_get_asymmetric_public] /** * Retrieves the public key from a saved asymmetric key pair on Cloud KMS From f7630f5a9882ecc570259c74f108cde42d5fac86 Mon Sep 17 00:00:00 2001 From: Dan Sanche Date: Wed, 5 Dec 2018 16:32:08 -0800 Subject: [PATCH 14/15] fixed checkstyle issues --- kms/src/main/java/com/example/Asymmetric.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/kms/src/main/java/com/example/Asymmetric.java b/kms/src/main/java/com/example/Asymmetric.java index f33792c3b8d..96ff1b82ce4 100644 --- a/kms/src/main/java/com/example/Asymmetric.java +++ b/kms/src/main/java/com/example/Asymmetric.java @@ -89,7 +89,7 @@ public static CryptoKey createAsymmetricKey(String projectId, String locationId, * "projects/PROJECT_ID/locations/global/keyRings/RING_ID/cryptoKeys/KEY_ID/cryptoKeyVersions/1" */ public static PublicKey getAsymmetricPublicKey(String keyName) - throws IOException, GeneralSecurityException { + throws IOException, GeneralSecurityException { // Create the Cloud KMS client. try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) { @@ -127,8 +127,8 @@ public static PublicKey getAsymmetricPublicKey(String keyName) public static byte[] decryptRSA(String keyName, byte[] ciphertext) throws IOException { // Create the Cloud KMS client. try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) { - AsymmetricDecryptResponse response = client.asymmetricDecrypt(keyName, - ByteString.copyFrom(ciphertext)); + AsymmetricDecryptResponse response = client.asymmetricDecrypt( + keyName, ByteString.copyFrom(ciphertext)); return response.getPlaintext().toByteArray(); } } @@ -143,7 +143,7 @@ public static byte[] decryptRSA(String keyName, byte[] ciphertext) throws IOExce * "projects/PROJECT_ID/locations/global/keyRings/RING_ID/cryptoKeys/KEY_ID/cryptoKeyVersions/1" */ public static byte[] encryptRSA(String keyName, byte[] plaintext) - throws IOException, GeneralSecurityException { + throws IOException, GeneralSecurityException { // Create the Cloud KMS client. try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) { // Get the public key From 44704f063c0b9968d6edcb106572b13b3ce2dea2 Mon Sep 17 00:00:00 2001 From: Dan Sanche Date: Mon, 7 Jan 2019 16:16:33 -0800 Subject: [PATCH 15/15] addressed PR comments --- kms/pom.xml | 2 +- kms/src/main/java/com/example/Asymmetric.java | 23 +++++----- kms/src/main/java/com/example/CryptFile.java | 6 +-- .../java/com/example/CryptFileCommands.java | 2 +- kms/src/main/java/com/example/Quickstart.java | 4 +- .../java/com/example/SnippetCommands.java | 2 +- kms/src/main/java/com/example/Snippets.java | 42 +++++++------------ .../test/java/com/example/AsymmetricIT.java | 4 +- .../test/java/com/example/CryptFileIT.java | 8 ++-- .../test/java/com/example/QuickstartIT.java | 2 +- kms/src/test/java/com/example/SnippetsIT.java | 14 +++---- 11 files changed, 47 insertions(+), 62 deletions(-) diff --git a/kms/pom.xml b/kms/pom.xml index 66b2f4e5cdd..989d636d05c 100644 --- a/kms/pom.xml +++ b/kms/pom.xml @@ -12,7 +12,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.10 diff --git a/kms/src/main/java/com/example/Asymmetric.java b/kms/src/main/java/com/example/Asymmetric.java index 96ff1b82ce4..c582210dbab 100644 --- a/kms/src/main/java/com/example/Asymmetric.java +++ b/kms/src/main/java/com/example/Asymmetric.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 Google Inc. + * Copyright 2018 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -53,27 +53,20 @@ public static CryptoKey createAsymmetricKey(String projectId, String locationId, String cryptoKeyId) throws IOException { - // Create the Cloud KMS client. try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) { - // The resource name of the location associated with the KeyRing. String parent = KeyRingName.format(projectId, locationId, keyRingId); - // Choose a purpose (ASYMMETRIC_DECRYPT or ASYMMETRIC_SIGN). CryptoKeyPurpose purpose = CryptoKeyPurpose.ASYMMETRIC_DECRYPT; - - // Choose an algorithm. CryptoKeyVersionAlgorithm algorithm = CryptoKeyVersionAlgorithm.RSA_DECRYPT_OAEP_2048_SHA256; + CryptoKeyVersionTemplate version = CryptoKeyVersionTemplate.newBuilder() .setAlgorithm(algorithm) .build(); - - // Build the key template CryptoKey cryptoKey = CryptoKey.newBuilder() .setPurpose(purpose) .setVersionTemplate(version) .build(); - // Create the CryptoKey for your project. CryptoKey createdKey = client.createCryptoKey(parent, cryptoKeyId, cryptoKey); return createdKey; @@ -156,7 +149,9 @@ public static byte[] encryptRSA(String keyName, byte[] plaintext) X509EncodedKeySpec keySpec = new X509EncodedKeySpec(derKey); PublicKey rsaKey = KeyFactory.getInstance("RSA").generatePublic(keySpec); - // Encrypt the plaintext + // Encrypt plaintext for the 'RSA_DECRYPT_OAEP_2048_SHA256' key. + // For other key algorithms: + // https://docs.oracle.com/javase/7/docs/api/javax/crypto/Cipher.html Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding"); OAEPParameterSpec oaepParams = new OAEPParameterSpec( "SHA-256", "MGF1", MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT); @@ -217,7 +212,9 @@ public static boolean verifySignatureRSA(String keyName, byte[] message, byte[] X509EncodedKeySpec keySpec = new X509EncodedKeySpec(derKey); PublicKey rsaKey = KeyFactory.getInstance("RSA").generatePublic(keySpec); - // Verify the signature + // Verify the 'RSA_SIGN_PKCS1_2048_SHA256' signature. + // For other key algorithms: + // http://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#Signature Signature rsaVerify = Signature.getInstance("SHA256withRSA"); rsaVerify.initVerify(rsaKey); rsaVerify.update(message); @@ -249,7 +246,9 @@ public static boolean verifySignatureEC(String keyName, byte[] message, byte[] s X509EncodedKeySpec keySpec = new X509EncodedKeySpec(derKey); PublicKey ecKey = KeyFactory.getInstance("EC").generatePublic(keySpec); - // Verify the signature + // Verify the 'EC_SIGN_P256_SHA256' signature + // For other key algorithms: + // http://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#Signature Signature ecVerify = Signature.getInstance("SHA256withECDSA"); ecVerify.initVerify(ecKey); ecVerify.update(message); diff --git a/kms/src/main/java/com/example/CryptFile.java b/kms/src/main/java/com/example/CryptFile.java index fd770e9dce3..4a97bd7a903 100644 --- a/kms/src/main/java/com/example/CryptFile.java +++ b/kms/src/main/java/com/example/CryptFile.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 Google Inc. + * Copyright 2018 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -38,7 +38,7 @@ public static byte[] encrypt( throws IOException { // Create the KeyManagementServiceClient using try-with-resources to manage client cleanup. - try (KeyManagementServiceClient client = Snippets.createClient()) { + try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) { // The resource name of the cryptoKey String resourceName = CryptoKeyName.format(projectId, locationId, keyRingId, cryptoKeyId); @@ -62,7 +62,7 @@ public static byte[] decrypt( throws IOException { // Create the KeyManagementServiceClient using try-with-resources to manage client cleanup. - try (KeyManagementServiceClient client = Snippets.createClient()) { + try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) { // The resource name of the cryptoKey String resourceName = CryptoKeyName.format(projectId, locationId, keyRingId, cryptoKeyId); diff --git a/kms/src/main/java/com/example/CryptFileCommands.java b/kms/src/main/java/com/example/CryptFileCommands.java index 42a415bcec2..7a418e37b7a 100644 --- a/kms/src/main/java/com/example/CryptFileCommands.java +++ b/kms/src/main/java/com/example/CryptFileCommands.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 Google Inc. + * Copyright 2017 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/kms/src/main/java/com/example/Quickstart.java b/kms/src/main/java/com/example/Quickstart.java index 95d28408488..bdadb770424 100644 --- a/kms/src/main/java/com/example/Quickstart.java +++ b/kms/src/main/java/com/example/Quickstart.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 Google Inc. + * Copyright 2018 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -38,8 +38,6 @@ public static void main(String... args) throws Exception { String location = args[1]; // Create the KeyManagementServiceClient using try-with-resources to manage client cleanup. - // GAP: missing ability to set application name - // see https://github.com/googleapis/gax-java/issues/614 try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) { // The resource name of the location to search diff --git a/kms/src/main/java/com/example/SnippetCommands.java b/kms/src/main/java/com/example/SnippetCommands.java index 50d4e527ea1..81a862a44aa 100644 --- a/kms/src/main/java/com/example/SnippetCommands.java +++ b/kms/src/main/java/com/example/SnippetCommands.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 Google Inc. + * Copyright 2017 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/kms/src/main/java/com/example/Snippets.java b/kms/src/main/java/com/example/Snippets.java index 74a2f9e189c..30f6f2875bf 100644 --- a/kms/src/main/java/com/example/Snippets.java +++ b/kms/src/main/java/com/example/Snippets.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 Google Inc. + * Copyright 2017 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -43,18 +43,6 @@ public class Snippets { - /** - * Creates a KeyManagementServiceClient using Application Default Credentials. - * - * @return an authorized KeyManagementServiceClient. - * @throws IOException if there's an error getting the default credentials. - */ - public static KeyManagementServiceClient createClient() throws IOException { - // GAP: missing ability to set application name - // see https://github.com/googleapis/gax-java/issues/614 - return KeyManagementServiceClient.create(); - } - // [START kms_create_keyring] /** @@ -411,16 +399,16 @@ public static Policy removeMemberFromCryptoKeyPolicy( // Create a bindings list that filters out the provided member List newBindings = new ArrayList<>(); - for (Binding b : iamPolicy.getBindingsList()) { - if (!b.getRole().equals(role)) { - newBindings.add(b); + for (Binding binding : iamPolicy.getBindingsList()) { + if (!binding.getRole().equals(role)) { + newBindings.add(binding); continue; } - Binding.Builder builder = Binding.newBuilder().setRole(b.getRole()); - for (String m : b.getMembersList()) { - if (!member.equals(m)) { - builder.addMembers(m); + Binding.Builder builder = Binding.newBuilder().setRole(binding.getRole()); + for (String bindingMember : binding.getMembersList()) { + if (!member.equals(bindingMember)) { + builder.addMembers(bindingMember); } } newBindings.add(builder.build()); @@ -458,14 +446,14 @@ public static Policy removeMemberFromKeyRingPolicy( // Create a bindings list that filters out the provided member List newBindings = new ArrayList<>(); - for (Binding b : iamPolicy.getBindingsList()) { - if (!b.getRole().equals(role)) { - newBindings.add(b); + for (Binding binding : iamPolicy.getBindingsList()) { + if (!binding.getRole().equals(role)) { + newBindings.add(binding); } else { - Binding.Builder builder = Binding.newBuilder().setRole(b.getRole()); - for (String m : b.getMembersList()) { - if (!member.equals(m)) { - builder.addMembers(m); + Binding.Builder builder = Binding.newBuilder().setRole(binding.getRole()); + for (String bindingMember : binding.getMembersList()) { + if (!member.equals(bindingMember)) { + builder.addMembers(bindingMember); } } newBindings.add(builder.build()); diff --git a/kms/src/test/java/com/example/AsymmetricIT.java b/kms/src/test/java/com/example/AsymmetricIT.java index c60eba5ae95..4a8c950c609 100644 --- a/kms/src/test/java/com/example/AsymmetricIT.java +++ b/kms/src/test/java/com/example/AsymmetricIT.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 Google Inc. + * Copyright 2018 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -89,7 +89,7 @@ private static boolean createKeyHelper( @BeforeClass public static void setUpClass() throws Exception { - // TODO: set application name + // TODO: set application name. https://github.com/googleapis/gax-java/issues/614 client = KeyManagementServiceClient.create(); try { diff --git a/kms/src/test/java/com/example/CryptFileIT.java b/kms/src/test/java/com/example/CryptFileIT.java index a1f38aa20ea..1d98676831d 100644 --- a/kms/src/test/java/com/example/CryptFileIT.java +++ b/kms/src/test/java/com/example/CryptFileIT.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 Google Inc. + * Copyright 2018 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -67,11 +67,11 @@ public static void tearDownClass() throws Exception { List versions = Snippets.listCryptoKeyVersions(PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID); - for (CryptoKeyVersion v : versions) { - if (!v.getState().equals(CryptoKeyVersion.CryptoKeyVersionState.DESTROY_SCHEDULED)) { + for (CryptoKeyVersion version : versions) { + if (!version.getState().equals(CryptoKeyVersion.CryptoKeyVersionState.DESTROY_SCHEDULED)) { Snippets.destroyCryptoKeyVersion( PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID, - SnippetsIT.parseVersionId(v.getName())); + SnippetsIT.parseVersionId(version.getName())); } } } diff --git a/kms/src/test/java/com/example/QuickstartIT.java b/kms/src/test/java/com/example/QuickstartIT.java index 081d238470a..d59271af378 100644 --- a/kms/src/test/java/com/example/QuickstartIT.java +++ b/kms/src/test/java/com/example/QuickstartIT.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 Google Inc. + * Copyright 2017 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/kms/src/test/java/com/example/SnippetsIT.java b/kms/src/test/java/com/example/SnippetsIT.java index 26185af626c..01f256c8ae8 100644 --- a/kms/src/test/java/com/example/SnippetsIT.java +++ b/kms/src/test/java/com/example/SnippetsIT.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 Google Inc. + * Copyright 2017 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -73,10 +73,10 @@ public static void tearDownClass() throws Exception { List versions = Snippets.listCryptoKeyVersions(PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID); - for (CryptoKeyVersion v : versions) { - if (!v.getState().equals(CryptoKeyVersion.CryptoKeyVersionState.DESTROY_SCHEDULED)) { + for (CryptoKeyVersion version : versions) { + if (!version.getState().equals(CryptoKeyVersion.CryptoKeyVersionState.DESTROY_SCHEDULED)) { Snippets.destroyCryptoKeyVersion( - PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID, parseVersionId(v.getName())); + PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID, parseVersionId(version.getName())); } } } @@ -101,11 +101,11 @@ public void listCryptoKeyVersions_retrievesVersions() throws Exception { List versions = Snippets.listCryptoKeyVersions(PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID); - for (CryptoKeyVersion v : versions) { - assertThat(v.getName()).contains(String.format( + for (CryptoKeyVersion version : versions) { + assertThat(version.getName()).contains(String.format( "keyRings/%s/cryptoKeys/%s/cryptoKeyVersions/", KEY_RING_ID, CRYPTO_KEY_ID)); - if (v.getState().equals(CryptoKeyVersion.CryptoKeyVersionState.ENABLED)) { + if (version.getState().equals(CryptoKeyVersion.CryptoKeyVersionState.ENABLED)) { return; } }