diff --git a/kms/src/main/java/com/example/SnippetCommands.java b/kms/src/main/java/com/example/SnippetCommands.java index 53cb04fa182..8d8b85b1022 100644 --- a/kms/src/main/java/com/example/SnippetCommands.java +++ b/kms/src/main/java/com/example/SnippetCommands.java @@ -109,6 +109,13 @@ public void run() throws IOException { } } + public static class SetPrimaryVersionCommand extends KeyVersionArgs implements Command { + + public void run() throws IOException { + Snippets.setPrimaryVersion(projectId, locationId, keyRingId, cryptoKeyId, version); + } + } + public static class GetKeyRingPolicyCommand extends KeyRingArgs implements Command { public void run() throws IOException { Snippets.getKeyRingPolicy(projectId, locationId, keyRingId); @@ -124,12 +131,12 @@ public void run() throws IOException { public static class AddMemberToKeyRingPolicyCommand extends KeyRingArgs implements Command { @Argument(metaVar = "member", required = true, index = 1, usage = "The member to add.\n" - + "See https://g.co/cloud/kms/docs/reference/rest/v1/Policy#binding " - + "for valid values.") + + "See https://g.co/cloud/kms/docs/reference/rest/v1/Policy#binding " + + "for valid values.") String member; @Argument(metaVar = "role", required = true, index = 2, usage = "The role for the member.\n" - + "See https://g.co/cloud/iam/docs/understanding-roles for valid values.") + + "See https://g.co/cloud/iam/docs/understanding-roles for valid values.") String role; public void run() throws IOException { @@ -140,28 +147,29 @@ public void run() throws IOException { public static class AddMemberToCryptoKeyPolicyCommand extends KeyArgs implements Command { @Argument(metaVar = "member", required = true, index = 2, usage = "The member to add.\n" - + "See https://g.co/cloud/kms/docs/reference/rest/v1/Policy#binding " - + "for valid values.") + + "See https://g.co/cloud/kms/docs/reference/rest/v1/Policy#binding " + + "for valid values.") String member; @Argument(metaVar = "role", required = true, index = 3, usage = "The role for the member.\n" - + "See https://g.co/cloud/iam/docs/understanding-roles for valid values.") + + "See https://g.co/cloud/iam/docs/understanding-roles for valid values.") String role; public void run() throws IOException { - Snippets.addMemberToCryptoKeyPolicy(projectId, locationId, keyRingId, cryptoKeyId, member, role); + Snippets + .addMemberToCryptoKeyPolicy(projectId, locationId, keyRingId, cryptoKeyId, member, role); } } public static class RemoveMemberFromKeyRingPolicyCommand extends KeyRingArgs implements Command { @Argument(metaVar = "member", required = true, index = 1, usage = "The member to add.\n" - + "See https://g.co/cloud/kms/docs/reference/rest/v1/Policy#binding " - + "for valid values.") + + "See https://g.co/cloud/kms/docs/reference/rest/v1/Policy#binding " + + "for valid values.") String member; @Argument(metaVar = "role", required = true, index = 2, usage = "The role for the member.\n" - + "See https://g.co/cloud/iam/docs/understanding-roles for valid values.") + + "See https://g.co/cloud/iam/docs/understanding-roles for valid values.") String role; public void run() throws IOException { @@ -172,16 +180,18 @@ public void run() throws IOException { public static class RemoveMemberFromCryptoKeyPolicyCommand extends KeyArgs implements Command { @Argument(metaVar = "member", required = true, index = 2, usage = "The member to add.\n" - + "See https://g.co/cloud/kms/docs/reference/rest/v1/Policy#binding " - + "for valid values.") + + "See https://g.co/cloud/kms/docs/reference/rest/v1/Policy#binding " + + "for valid values.") String member; @Argument(metaVar = "role", required = true, index = 3, usage = "The role for the member.\n" - + "See https://g.co/cloud/iam/docs/understanding-roles for valid values.") + + "See https://g.co/cloud/iam/docs/understanding-roles for valid values.") String role; public void run() throws IOException { - Snippets.removeMemberFromCryptoKeyPolicy(projectId, locationId, keyRingId, cryptoKeyId, member, role); + Snippets + .removeMemberFromCryptoKeyPolicy(projectId, locationId, keyRingId, cryptoKeyId, member, + role); } } @@ -198,6 +208,7 @@ public void run() throws IOException { @SubCommand(name = "destroyCryptoKeyVersion", impl = DestroyCryptoKeyVersionCommand.class), @SubCommand(name = "getKeyRingPolicy", impl = GetKeyRingPolicyCommand.class), @SubCommand(name = "getCryptoKeyPolicy", impl = GetCryptoKeyPolicyCommand.class), + @SubCommand(name = "setPrimaryVersion", impl = SetPrimaryVersionCommand.class), @SubCommand(name = "addMemberToKeyRingPolicy", impl = AddMemberToKeyRingPolicyCommand.class), @SubCommand(name = "addMemberToCryptoKeyPolicy", impl = AddMemberToCryptoKeyPolicyCommand.class), @@ -205,6 +216,6 @@ public void run() throws IOException { impl = RemoveMemberFromKeyRingPolicyCommand.class), @SubCommand(name = "removeMemberFromCryptoKeyPolicy", impl = RemoveMemberFromCryptoKeyPolicyCommand.class) - }) + }) Command command; } diff --git a/kms/src/main/java/com/example/Snippets.java b/kms/src/main/java/com/example/Snippets.java index e862e0befe1..cacda5dc343 100644 --- a/kms/src/main/java/com/example/Snippets.java +++ b/kms/src/main/java/com/example/Snippets.java @@ -20,6 +20,7 @@ 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.CloudKMS.Projects.Locations.KeyRings.CryptoKeys.UpdatePrimaryVersion; 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; @@ -31,6 +32,7 @@ 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.SetIamPolicyRequest; +import com.google.api.services.cloudkms.v1.model.UpdateCryptoKeyPrimaryVersionRequest; import java.io.IOException; import java.util.Collections; import java.util.List; @@ -525,6 +527,27 @@ public static void listCryptoKeyVersions( } } + /** + * Sets a version as the primary version for a crypto key. + */ + public static void 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); + + CryptoKey key = kms.projects().locations().keyRings().cryptoKeys() + .updatePrimaryVersion(resourceName, + new UpdateCryptoKeyPrimaryVersionRequest().setCryptoKeyVersionId(versionId)).execute(); + + System.out.println(key); + + } + public static void main(String[] args) throws IOException, CmdLineException { SnippetCommands commands = new SnippetCommands(); diff --git a/kms/src/test/java/com/example/SnippetsIT.java b/kms/src/test/java/com/example/SnippetsIT.java index a36b0a7033f..301a55cde40 100644 --- a/kms/src/test/java/com/example/SnippetsIT.java +++ b/kms/src/test/java/com/example/SnippetsIT.java @@ -19,7 +19,11 @@ 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 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; @@ -28,11 +32,6 @@ import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -import java.io.ByteArrayOutputStream; -import java.io.PrintStream; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - /** * Integration (system) tests for {@link Snippets}. */ @@ -43,7 +42,7 @@ 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 = "test-snippets-crypto-key"; + static final String CRYPTO_KEY_ID = UUID.randomUUID().toString(); static final String TEST_USER = "serviceAccount:" + "131304031188-compute@developer.gserviceaccount.com"; static final String TEST_ROLE = "roles/viewer"; @@ -64,7 +63,7 @@ public static void setUpClass() throws Exception { // 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); + 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 @@ -90,6 +89,17 @@ public static void setUpClass() throws Exception { 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); } /** @@ -121,7 +131,8 @@ public static void tearDownClass() throws Exception { } String version = matcher.group(1); - Snippets.destroyCryptoKeyVersion(PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID, version); + Snippets + .destroyCryptoKeyVersion(PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID, version); } } @@ -130,8 +141,6 @@ public void setUp() throws Exception { bout = new ByteArrayOutputStream(); out = new PrintStream(bout); System.setOut(out); - - Snippets.createCryptoKeyVersion(PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID); } @After @@ -165,7 +174,7 @@ public void listCryptoKeyVersions_printsVersions() throws Exception { @Test public void disableCryptoKeyVersion_disables() throws Exception { - Snippets.listCryptoKeyVersions(PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID); + 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()); @@ -180,7 +189,7 @@ public void disableCryptoKeyVersion_disables() throws Exception { @Test public void destroyCryptoKeyVersion_destroys() throws Exception { - Snippets.listCryptoKeyVersions(PROJECT_ID, LOCATION_ID, KEY_RING_ID, CRYPTO_KEY_ID); + 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()); @@ -195,6 +204,24 @@ public void destroyCryptoKeyVersion_destroys() throws Exception { KEY_RING_ID, CRYPTO_KEY_ID, version)); } + @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()); + + String version = matcher.group(1); + + 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)); + } + @Test public void addAndRemoveMemberToCryptoKeyPolicy_addsDisplaysAndRemoves() throws Exception { // Make sure the policy doesn't already have our test user