Skip to content

Commit 37621da

Browse files
author
Jerjou Cheng
committed
Add command-line handling.
1 parent 44bc9de commit 37621da

File tree

6 files changed

+335
-141
lines changed

6 files changed

+335
-141
lines changed

kms/README.md

+5
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,8 @@ You can run the quickstart with:
1818

1919
java -cp target/kms-samples-1.0.0-jar-with-dependencies.jar \
2020
com.example.Quickstart [your-project-id]
21+
22+
and can see the available snippet commands with:
23+
24+
java -cp target/kms-samples-1.0.0-jar-with-dependencies.jar \
25+
com.example.Snippets

kms/src/main/java/com/example/CryptFile.java

+16-53
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,13 @@
2626
import com.google.api.services.cloudkms.v1beta1.model.EncryptRequest;
2727
import com.google.api.services.cloudkms.v1beta1.model.EncryptResponse;
2828

29-
import java.io.FileOutputStream;
29+
import org.kohsuke.args4j.CmdLineException;
30+
import org.kohsuke.args4j.CmdLineParser;
31+
3032
import java.io.IOException;
31-
import java.nio.file.Files;
32-
import java.nio.file.Paths;
3333

3434
public class CryptFile {
3535

36-
String projectId;
37-
38-
public CryptFile(String projectId) {
39-
this.projectId = projectId;
40-
}
41-
4236
/**
4337
* Creates an authorized CloudKMS client service using Application Default Credentials.
4438
*
@@ -68,7 +62,7 @@ public static CloudKMS createAuthorizedClient() throws IOException {
6862
/**
6963
* Encrypts the given bytes, using the specified crypto key.
7064
*/
71-
public byte[] encrypt(String ringId, String keyId, byte[] plaintext)
65+
public static byte[] encrypt(String projectId, String ringId, String keyId, byte[] plaintext)
7266
throws IOException {
7367
String location = "global";
7468
// The resource name of the cryptoKey
@@ -89,7 +83,7 @@ public byte[] encrypt(String ringId, String keyId, byte[] plaintext)
8983
/**
9084
* Decrypts the given encrypted bytes, using the specified crypto key.
9185
*/
92-
public byte[] decrypt(String ringId, String keyId, byte[] encrypted)
86+
public static byte[] decrypt(String projectId, String ringId, String keyId, byte[] encrypted)
9387
throws IOException {
9488
String location = "global";
9589
// Create the Cloud KMS client.
@@ -109,48 +103,17 @@ public byte[] decrypt(String ringId, String keyId, byte[] encrypted)
109103
}
110104

111105
public static void main(String[] args) throws IOException {
112-
// Your Google Cloud Platform project ID
113-
String projectId = args[0];
114-
String command = args[1];
115-
116-
CryptFile cryptFile = new CryptFile(projectId);
117-
118-
if ("encrypt".equals(command)) {
119-
String ringId = args[2];
120-
String keyId = args[3];
121-
String inFile = args[4];
122-
String outFile = args[5];
123-
124-
byte[] encrypted = cryptFile.encrypt(
125-
ringId, keyId,
126-
Files.readAllBytes(Paths.get(inFile)));
127-
128-
FileOutputStream stream = new FileOutputStream(outFile);
129-
try {
130-
stream.write(encrypted);
131-
} finally {
132-
stream.close();
133-
}
134-
135-
} else if ("decrypt".equals(command)) {
136-
String ringId = args[2];
137-
String keyId = args[3];
138-
String inFile = args[4];
139-
String outFile = args[5];
140-
141-
byte[] decrypted = cryptFile.decrypt(
142-
ringId, keyId,
143-
Files.readAllBytes(Paths.get(inFile)));
144-
145-
FileOutputStream stream = new FileOutputStream(outFile);
146-
try {
147-
stream.write(decrypted);
148-
} finally {
149-
stream.close();
150-
}
151-
152-
} else {
153-
throw new RuntimeException("Unrecognized command: " + command);
106+
CryptFileCommands commands = new CryptFileCommands();
107+
CmdLineParser parser = new CmdLineParser(commands);
108+
109+
try {
110+
parser.parseArgument(args);
111+
} catch (CmdLineException e) {
112+
System.out.println(e);
113+
System.out.println();
114+
e.getParser().printUsage(System.out);
115+
System.exit(1);
154116
}
117+
commands.command.run();
155118
}
156119
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
/*
2+
* Copyright (c) 2017 Google Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5+
* in compliance with the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License
10+
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11+
* or implied. See the License for the specific language governing permissions and limitations under
12+
* the License.
13+
*/
14+
15+
package com.example;
16+
17+
import org.kohsuke.args4j.Argument;
18+
import org.kohsuke.args4j.Option;
19+
import org.kohsuke.args4j.spi.SubCommand;
20+
import org.kohsuke.args4j.spi.SubCommandHandler;
21+
import org.kohsuke.args4j.spi.SubCommands;
22+
23+
import java.io.FileOutputStream;
24+
import java.io.IOException;
25+
import java.nio.file.Files;
26+
import java.nio.file.Paths;
27+
28+
/**
29+
* Defines the different sub-commands and their parameters, for command-line invocation.
30+
*/
31+
class CryptFileCommands {
32+
/**
33+
* An interface for a command-line sub-command.
34+
*/
35+
interface Command {
36+
public void run() throws IOException;
37+
}
38+
39+
// Most of the commands take some subset of the same arguments, so specify groups of arguments
40+
// as classes for greater code reuse.
41+
static class Args {
42+
@Option(name = "--project-id", aliases = "-p", required = true, usage = "Your GCP project ID")
43+
String projectId;
44+
@Argument(metaVar = "ringId", required = true, index = 0, usage = "The ring id")
45+
String ringId;
46+
@Argument(metaVar = "keyId", required = true, index = 1, usage = "The key id")
47+
String keyId;
48+
@Argument(metaVar = "inFile", required = true, index = 1, usage = "The source file")
49+
String inFile;
50+
@Argument(metaVar = "outFile", required = true, index = 1, usage = "The destination file")
51+
String outFile;
52+
}
53+
54+
public static class EncryptCommand extends Args implements Command {
55+
public void run() throws IOException {
56+
byte[] encrypted = CryptFile.encrypt(
57+
projectId, ringId, keyId,
58+
Files.readAllBytes(Paths.get(inFile)));
59+
60+
FileOutputStream stream = new FileOutputStream(outFile);
61+
try {
62+
stream.write(encrypted);
63+
} finally {
64+
stream.close();
65+
}
66+
}
67+
}
68+
69+
public static class DecryptCommand extends Args implements Command {
70+
public void run() throws IOException {
71+
byte[] decrypted = CryptFile.decrypt(
72+
projectId, ringId, keyId,
73+
Files.readAllBytes(Paths.get(inFile)));
74+
75+
FileOutputStream stream = new FileOutputStream(outFile);
76+
try {
77+
stream.write(decrypted);
78+
} finally {
79+
stream.close();
80+
}
81+
}
82+
}
83+
84+
@Argument(metaVar = "command", required = true, handler = SubCommandHandler.class,
85+
usage = "The subcommand to run")
86+
@SubCommands({
87+
@SubCommand(name = "encrypt", impl = EncryptCommand.class),
88+
@SubCommand(name = "decrypt", impl = DecryptCommand.class)
89+
})
90+
Command command;
91+
}

kms/src/main/java/com/example/Quickstart.java

+6
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,14 @@ public static CloudKMS createAuthorizedClient() throws IOException {
5555
}
5656

5757
public static void main(String[] args) throws IOException {
58+
if (args.length != 1) {
59+
System.err.println("Usage: Quickstart <project-id>");
60+
System.exit(1);
61+
}
62+
5863
// Your Google Cloud Platform project ID
5964
String projectId = args[0];
65+
6066
// Lists keys in the "global" location.
6167
String location = "global";
6268
// The resource name of the location associated with the KeyRings
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
/*
2+
* Copyright (c) 2017 Google Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5+
* in compliance with the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License
10+
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11+
* or implied. See the License for the specific language governing permissions and limitations under
12+
* the License.
13+
*/
14+
15+
package com.example;
16+
17+
import org.kohsuke.args4j.Argument;
18+
import org.kohsuke.args4j.Option;
19+
import org.kohsuke.args4j.spi.SubCommand;
20+
import org.kohsuke.args4j.spi.SubCommandHandler;
21+
import org.kohsuke.args4j.spi.SubCommands;
22+
23+
import java.io.IOException;
24+
25+
/**
26+
* Defines the different sub-commands and their parameters, for command-line invocation.
27+
*/
28+
class SnippetCommands {
29+
/**
30+
* An interface for a command-line sub-command.
31+
*/
32+
interface Command {
33+
public void run() throws IOException;
34+
}
35+
36+
// Most of the commands take some subset of the same arguments, so specify groups of arguments
37+
// as classes for greater code reuse.
38+
static class ProjectIdArgs {
39+
@Option(name = "--project-id", aliases = "-p", required = true, usage = "Your GCP project ID")
40+
String projectId;
41+
}
42+
43+
static class KeyRingArgs extends ProjectIdArgs {
44+
@Argument(metaVar = "ringId", required = true, index = 0, usage = "The ring id")
45+
String ringId;
46+
}
47+
48+
static class KeyArgs extends KeyRingArgs {
49+
@Argument(metaVar = "keyId", required = true, index = 1, usage = "The key id")
50+
String keyId;
51+
}
52+
53+
static class KeyVersionArgs extends KeyArgs {
54+
@Argument(metaVar = "version", required = true, index = 2, usage = "The key version")
55+
String version;
56+
}
57+
58+
59+
public static class CreateKeyRingCommand extends KeyRingArgs implements Command {
60+
public void run() throws IOException {
61+
Snippets.createKeyRing(projectId, ringId);
62+
}
63+
}
64+
65+
public static class CreateKeyCommand extends KeyArgs implements Command {
66+
public void run() throws IOException {
67+
Snippets.createCryptoKey(projectId, ringId, keyId);
68+
}
69+
}
70+
71+
public static class ListVersionsCommand extends KeyArgs implements Command {
72+
public void run() throws IOException {
73+
Snippets.listCryptoKeyVersions(projectId, ringId, keyId);
74+
}
75+
}
76+
77+
public static class DisableKeyCommand extends KeyVersionArgs implements Command {
78+
public void run() throws IOException {
79+
Snippets.disableCryptoKeyVersion(projectId, ringId, keyId, version);
80+
}
81+
}
82+
83+
public static class DestroyCommand extends KeyVersionArgs implements Command {
84+
public void run() throws IOException {
85+
Snippets.destroyCryptoKeyVersion(projectId, ringId, keyId, version);
86+
}
87+
}
88+
89+
public static class GetKeyRingPolicyCommand extends KeyRingArgs implements Command {
90+
public void run() throws IOException {
91+
Snippets.getKeyRingPolicy(projectId, ringId);
92+
}
93+
}
94+
95+
public static class GetKeyPolicyCommand extends KeyArgs implements Command {
96+
public void run() throws IOException {
97+
Snippets.getCryptoKeyPolicy(projectId, ringId, keyId);
98+
}
99+
}
100+
101+
public static class AddMemberToKeyRingPolicy extends KeyRingArgs implements Command {
102+
@Argument(metaVar = "member", required = true, index = 2,
103+
usage = "The member to add.\n"
104+
+ "See https://g.co/cloud/kms/docs/reference/rest/v1beta1/Policy#binding "
105+
+ "for valid values.")
106+
String member;
107+
@Argument(metaVar = "role", required = true, index = 3,
108+
usage = "The role for the member.\n"
109+
+ "See https://g.co/cloud/iam/docs/understanding-roles for valid values.")
110+
String role;
111+
112+
public void run() throws IOException {
113+
Snippets.addToKeyRingPolicy(projectId, ringId, member, role);
114+
}
115+
}
116+
117+
public static class AddMemberToKeyPolicy extends KeyArgs implements Command {
118+
@Argument(metaVar = "member", required = true, index = 3,
119+
usage = "The member to add.\n"
120+
+ "See https://g.co/cloud/kms/docs/reference/rest/v1beta1/Policy#binding "
121+
+ "for valid values.")
122+
String member;
123+
@Argument(metaVar = "role", required = true, index = 4,
124+
usage = "The role for the member.\n"
125+
+ "See https://g.co/cloud/iam/docs/understanding-roles for valid values.")
126+
String role;
127+
128+
public void run() throws IOException {
129+
Snippets.addToCryptokeyPolicy(projectId, ringId, keyId, member, role);
130+
}
131+
}
132+
133+
public static class RemoveMemberFromKeyRingPolicy extends KeyRingArgs implements Command {
134+
@Argument(metaVar = "member", required = true, index = 2,
135+
usage = "The member to add.\n"
136+
+ "See https://g.co/cloud/kms/docs/reference/rest/v1beta1/Policy#binding "
137+
+ "for valid values.")
138+
String member;
139+
@Argument(metaVar = "role", required = true, index = 3,
140+
usage = "The role for the member.\n"
141+
+ "See https://g.co/cloud/iam/docs/understanding-roles for valid values.")
142+
String role;
143+
144+
public void run() throws IOException {
145+
Snippets.removeFromKeyRingPolicy(projectId, ringId, member, role);
146+
}
147+
}
148+
149+
public static class RemoveMemberFromKeyPolicy extends KeyArgs implements Command {
150+
@Argument(metaVar = "member", required = true, index = 3,
151+
usage = "The member to add.\n"
152+
+ "See https://g.co/cloud/kms/docs/reference/rest/v1beta1/Policy#binding "
153+
+ "for valid values.")
154+
String member;
155+
@Argument(metaVar = "role", required = true, index = 4,
156+
usage = "The role for the member.\n"
157+
+ "See https://g.co/cloud/iam/docs/understanding-roles for valid values.")
158+
String role;
159+
160+
public void run() throws IOException {
161+
Snippets.removeFromCryptokeyPolicy(projectId, ringId, keyId, member, role);
162+
}
163+
}
164+
165+
@Argument(metaVar = "command", required = true, handler = SubCommandHandler.class,
166+
usage = "The subcommand to run")
167+
@SubCommands({
168+
@SubCommand(name = "createKeyRing", impl = CreateKeyRingCommand.class),
169+
@SubCommand(name = "createKey", impl = CreateKeyCommand.class),
170+
@SubCommand(name = "listVersions", impl = ListVersionsCommand.class),
171+
@SubCommand(name = "disableKey", impl = DisableKeyCommand.class),
172+
@SubCommand(name = "destroyKey", impl = DestroyCommand.class),
173+
@SubCommand(name = "getKeyRingPolicy", impl = GetKeyRingPolicyCommand.class),
174+
@SubCommand(name = "getKeyPolicy", impl = GetKeyPolicyCommand.class),
175+
@SubCommand(name = "addMemberToKeyRing", impl = AddMemberToKeyRingPolicy.class),
176+
@SubCommand(name = "addMemberToKey", impl = AddMemberToKeyPolicy.class),
177+
@SubCommand(name = "removeMemberFromKeyRing", impl = RemoveMemberFromKeyRingPolicy.class),
178+
@SubCommand(name = "removeMemberFromKey", impl = RemoveMemberFromKeyPolicy.class)
179+
})
180+
Command command;
181+
}

0 commit comments

Comments
 (0)