Skip to content

Commit

Permalink
Add command-line handling.
Browse files Browse the repository at this point in the history
  • Loading branch information
Jerjou Cheng committed Jan 31, 2017
1 parent 44bc9de commit 37621da
Show file tree
Hide file tree
Showing 6 changed files with 335 additions and 141 deletions.
5 changes: 5 additions & 0 deletions kms/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,8 @@ You can run the quickstart with:

java -cp target/kms-samples-1.0.0-jar-with-dependencies.jar \
com.example.Quickstart [your-project-id]

and can see the available snippet commands with:

java -cp target/kms-samples-1.0.0-jar-with-dependencies.jar \
com.example.Snippets
69 changes: 16 additions & 53 deletions kms/src/main/java/com/example/CryptFile.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,13 @@
import com.google.api.services.cloudkms.v1beta1.model.EncryptRequest;
import com.google.api.services.cloudkms.v1beta1.model.EncryptResponse;

import java.io.FileOutputStream;
import org.kohsuke.args4j.CmdLineException;
import org.kohsuke.args4j.CmdLineParser;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

public class CryptFile {

String projectId;

public CryptFile(String projectId) {
this.projectId = projectId;
}

/**
* Creates an authorized CloudKMS client service using Application Default Credentials.
*
Expand Down Expand Up @@ -68,7 +62,7 @@ public static CloudKMS createAuthorizedClient() throws IOException {
/**
* Encrypts the given bytes, using the specified crypto key.
*/
public byte[] encrypt(String ringId, String keyId, byte[] plaintext)
public static byte[] encrypt(String projectId, String ringId, String keyId, byte[] plaintext)
throws IOException {
String location = "global";
// The resource name of the cryptoKey
Expand All @@ -89,7 +83,7 @@ public byte[] encrypt(String ringId, String keyId, byte[] plaintext)
/**
* Decrypts the given encrypted bytes, using the specified crypto key.
*/
public byte[] decrypt(String ringId, String keyId, byte[] encrypted)
public static byte[] decrypt(String projectId, String ringId, String keyId, byte[] encrypted)
throws IOException {
String location = "global";
// Create the Cloud KMS client.
Expand All @@ -109,48 +103,17 @@ public byte[] decrypt(String ringId, String keyId, byte[] encrypted)
}

public static void main(String[] args) throws IOException {
// Your Google Cloud Platform project ID
String projectId = args[0];
String command = args[1];

CryptFile cryptFile = new CryptFile(projectId);

if ("encrypt".equals(command)) {
String ringId = args[2];
String keyId = args[3];
String inFile = args[4];
String outFile = args[5];

byte[] encrypted = cryptFile.encrypt(
ringId, keyId,
Files.readAllBytes(Paths.get(inFile)));

FileOutputStream stream = new FileOutputStream(outFile);
try {
stream.write(encrypted);
} finally {
stream.close();
}

} else if ("decrypt".equals(command)) {
String ringId = args[2];
String keyId = args[3];
String inFile = args[4];
String outFile = args[5];

byte[] decrypted = cryptFile.decrypt(
ringId, keyId,
Files.readAllBytes(Paths.get(inFile)));

FileOutputStream stream = new FileOutputStream(outFile);
try {
stream.write(decrypted);
} finally {
stream.close();
}

} else {
throw new RuntimeException("Unrecognized command: " + command);
CryptFileCommands commands = new CryptFileCommands();
CmdLineParser parser = new CmdLineParser(commands);

try {
parser.parseArgument(args);
} catch (CmdLineException e) {
System.out.println(e);
System.out.println();
e.getParser().printUsage(System.out);
System.exit(1);
}
commands.command.run();
}
}
91 changes: 91 additions & 0 deletions kms/src/main/java/com/example/CryptFileCommands.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
* Copyright (c) 2017 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 org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.Option;
import org.kohsuke.args4j.spi.SubCommand;
import org.kohsuke.args4j.spi.SubCommandHandler;
import org.kohsuke.args4j.spi.SubCommands;

import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

/**
* Defines the different sub-commands and their parameters, for command-line invocation.
*/
class CryptFileCommands {
/**
* An interface for a command-line sub-command.
*/
interface Command {
public void run() throws IOException;
}

// Most of the commands take some subset of the same arguments, so specify groups of arguments
// as classes for greater code reuse.
static class Args {
@Option(name = "--project-id", aliases = "-p", required = true, usage = "Your GCP project ID")
String projectId;
@Argument(metaVar = "ringId", required = true, index = 0, usage = "The ring id")
String ringId;
@Argument(metaVar = "keyId", required = true, index = 1, usage = "The key id")
String keyId;
@Argument(metaVar = "inFile", required = true, index = 1, usage = "The source file")
String inFile;
@Argument(metaVar = "outFile", required = true, index = 1, usage = "The destination file")
String outFile;
}

public static class EncryptCommand extends Args implements Command {
public void run() throws IOException {
byte[] encrypted = CryptFile.encrypt(
projectId, ringId, keyId,
Files.readAllBytes(Paths.get(inFile)));

FileOutputStream stream = new FileOutputStream(outFile);
try {
stream.write(encrypted);
} finally {
stream.close();
}
}
}

public static class DecryptCommand extends Args implements Command {
public void run() throws IOException {
byte[] decrypted = CryptFile.decrypt(
projectId, ringId, keyId,
Files.readAllBytes(Paths.get(inFile)));

FileOutputStream stream = new FileOutputStream(outFile);
try {
stream.write(decrypted);
} finally {
stream.close();
}
}
}

@Argument(metaVar = "command", required = true, handler = SubCommandHandler.class,
usage = "The subcommand to run")
@SubCommands({
@SubCommand(name = "encrypt", impl = EncryptCommand.class),
@SubCommand(name = "decrypt", impl = DecryptCommand.class)
})
Command command;
}
6 changes: 6 additions & 0 deletions kms/src/main/java/com/example/Quickstart.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,14 @@ public static CloudKMS createAuthorizedClient() throws IOException {
}

public static void main(String[] args) throws IOException {
if (args.length != 1) {
System.err.println("Usage: Quickstart <project-id>");
System.exit(1);
}

// Your Google Cloud Platform project ID
String projectId = args[0];

// Lists keys in the "global" location.
String location = "global";
// The resource name of the location associated with the KeyRings
Expand Down
181 changes: 181 additions & 0 deletions kms/src/main/java/com/example/SnippetCommands.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
/*
* Copyright (c) 2017 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 org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.Option;
import org.kohsuke.args4j.spi.SubCommand;
import org.kohsuke.args4j.spi.SubCommandHandler;
import org.kohsuke.args4j.spi.SubCommands;

import java.io.IOException;

/**
* Defines the different sub-commands and their parameters, for command-line invocation.
*/
class SnippetCommands {
/**
* An interface for a command-line sub-command.
*/
interface Command {
public void run() throws IOException;
}

// Most of the commands take some subset of the same arguments, so specify groups of arguments
// as classes for greater code reuse.
static class ProjectIdArgs {
@Option(name = "--project-id", aliases = "-p", required = true, usage = "Your GCP project ID")
String projectId;
}

static class KeyRingArgs extends ProjectIdArgs {
@Argument(metaVar = "ringId", required = true, index = 0, usage = "The ring id")
String ringId;
}

static class KeyArgs extends KeyRingArgs {
@Argument(metaVar = "keyId", required = true, index = 1, usage = "The key id")
String keyId;
}

static class KeyVersionArgs extends KeyArgs {
@Argument(metaVar = "version", required = true, index = 2, usage = "The key version")
String version;
}


public static class CreateKeyRingCommand extends KeyRingArgs implements Command {
public void run() throws IOException {
Snippets.createKeyRing(projectId, ringId);
}
}

public static class CreateKeyCommand extends KeyArgs implements Command {
public void run() throws IOException {
Snippets.createCryptoKey(projectId, ringId, keyId);
}
}

public static class ListVersionsCommand extends KeyArgs implements Command {
public void run() throws IOException {
Snippets.listCryptoKeyVersions(projectId, ringId, keyId);
}
}

public static class DisableKeyCommand extends KeyVersionArgs implements Command {
public void run() throws IOException {
Snippets.disableCryptoKeyVersion(projectId, ringId, keyId, version);
}
}

public static class DestroyCommand extends KeyVersionArgs implements Command {
public void run() throws IOException {
Snippets.destroyCryptoKeyVersion(projectId, ringId, keyId, version);
}
}

public static class GetKeyRingPolicyCommand extends KeyRingArgs implements Command {
public void run() throws IOException {
Snippets.getKeyRingPolicy(projectId, ringId);
}
}

public static class GetKeyPolicyCommand extends KeyArgs implements Command {
public void run() throws IOException {
Snippets.getCryptoKeyPolicy(projectId, ringId, keyId);
}
}

public static class AddMemberToKeyRingPolicy extends KeyRingArgs implements Command {
@Argument(metaVar = "member", required = true, index = 2,
usage = "The member to add.\n"
+ "See https://g.co/cloud/kms/docs/reference/rest/v1beta1/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.")
String role;

public void run() throws IOException {
Snippets.addToKeyRingPolicy(projectId, ringId, member, role);
}
}

public static class AddMemberToKeyPolicy extends KeyArgs implements Command {
@Argument(metaVar = "member", required = true, index = 3,
usage = "The member to add.\n"
+ "See https://g.co/cloud/kms/docs/reference/rest/v1beta1/Policy#binding "
+ "for valid values.")
String member;
@Argument(metaVar = "role", required = true, index = 4,
usage = "The role for the member.\n"
+ "See https://g.co/cloud/iam/docs/understanding-roles for valid values.")
String role;

public void run() throws IOException {
Snippets.addToCryptokeyPolicy(projectId, ringId, keyId, member, role);
}
}

public static class RemoveMemberFromKeyRingPolicy extends KeyRingArgs implements Command {
@Argument(metaVar = "member", required = true, index = 2,
usage = "The member to add.\n"
+ "See https://g.co/cloud/kms/docs/reference/rest/v1beta1/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.")
String role;

public void run() throws IOException {
Snippets.removeFromKeyRingPolicy(projectId, ringId, member, role);
}
}

public static class RemoveMemberFromKeyPolicy extends KeyArgs implements Command {
@Argument(metaVar = "member", required = true, index = 3,
usage = "The member to add.\n"
+ "See https://g.co/cloud/kms/docs/reference/rest/v1beta1/Policy#binding "
+ "for valid values.")
String member;
@Argument(metaVar = "role", required = true, index = 4,
usage = "The role for the member.\n"
+ "See https://g.co/cloud/iam/docs/understanding-roles for valid values.")
String role;

public void run() throws IOException {
Snippets.removeFromCryptokeyPolicy(projectId, ringId, keyId, member, role);
}
}

@Argument(metaVar = "command", required = true, handler = SubCommandHandler.class,
usage = "The subcommand to run")
@SubCommands({
@SubCommand(name = "createKeyRing", impl = CreateKeyRingCommand.class),
@SubCommand(name = "createKey", impl = CreateKeyCommand.class),
@SubCommand(name = "listVersions", impl = ListVersionsCommand.class),
@SubCommand(name = "disableKey", impl = DisableKeyCommand.class),
@SubCommand(name = "destroyKey", impl = DestroyCommand.class),
@SubCommand(name = "getKeyRingPolicy", impl = GetKeyRingPolicyCommand.class),
@SubCommand(name = "getKeyPolicy", impl = GetKeyPolicyCommand.class),
@SubCommand(name = "addMemberToKeyRing", impl = AddMemberToKeyRingPolicy.class),
@SubCommand(name = "addMemberToKey", impl = AddMemberToKeyPolicy.class),
@SubCommand(name = "removeMemberFromKeyRing", impl = RemoveMemberFromKeyRingPolicy.class),
@SubCommand(name = "removeMemberFromKey", impl = RemoveMemberFromKeyPolicy.class)
})
Command command;
}
Loading

0 comments on commit 37621da

Please sign in to comment.