Skip to content

Commit 363ceb1

Browse files
authored
Merge pull request #496 from GoogleCloudPlatform/kms
Kms samples
2 parents 48b8f12 + 961c51a commit 363ceb1

File tree

7 files changed

+1062
-0
lines changed

7 files changed

+1062
-0
lines changed

kms/README.md

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Cloud Key Management Service
2+
3+
Google [Cloud Key Management Service](https://cloud.google.com/kms/) is a
4+
cloud-hosted key management service that lets you manage encryption for your
5+
cloud services the same way you do on-premise. You can generate, use, rotate and
6+
destroy AES256 encryption keys. These sample Java applications demonstrate
7+
how to access the KMS API using the Google Java API Client Libraries.
8+
9+
## Quickstart
10+
11+
Install [Maven](http://maven.apache.org/).
12+
13+
Build your project with:
14+
15+
mvn clean compile assembly:single
16+
17+
You can run the quickstart with:
18+
19+
java -cp target/kms-samples-1.0.0-jar-with-dependencies.jar \
20+
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
26+
27+
For example:
28+
29+
java -cp target/kms-samples-1.0.0-jar-with-dependencies.jar \
30+
com.example.Snippets createKeyRing -p <your-project-id> myFirstKeyRing

kms/pom.xml

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
2+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
3+
<modelVersion>4.0.0</modelVersion>
4+
<groupId>com.google.cloud.kms.samples</groupId>
5+
<artifactId>kms-samples</artifactId>
6+
<packaging>jar</packaging>
7+
8+
<parent>
9+
<artifactId>doc-samples</artifactId>
10+
<groupId>com.google.cloud</groupId>
11+
<version>1.0.0</version>
12+
<relativePath>..</relativePath>
13+
</parent>
14+
15+
<dependencies>
16+
<dependency>
17+
<groupId>com.google.apis</groupId>
18+
<artifactId>google-api-services-cloudkms</artifactId>
19+
<version>v1beta1-rev51-1.18.0-rc</version>
20+
</dependency>
21+
<dependency>
22+
<groupId>com.google.api-client</groupId>
23+
<artifactId>google-api-client</artifactId>
24+
<version>1.22.0</version>
25+
</dependency>
26+
<dependency>
27+
<groupId>com.google.http-client</groupId>
28+
<artifactId>google-http-client-jackson2</artifactId>
29+
<version>1.22.0</version>
30+
</dependency>
31+
<dependency>
32+
<groupId>args4j</groupId>
33+
<artifactId>args4j</artifactId>
34+
<version>2.33</version>
35+
</dependency>
36+
37+
<!-- test dependencies -->
38+
<dependency>
39+
<groupId>junit</groupId>
40+
<artifactId>junit</artifactId>
41+
<version>4.12</version>
42+
<scope>test</scope>
43+
</dependency>
44+
<dependency>
45+
<groupId>com.google.truth</groupId>
46+
<artifactId>truth</artifactId>
47+
<version>0.31</version>
48+
<scope>test</scope>
49+
</dependency>
50+
</dependencies>
51+
52+
<properties>
53+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
54+
</properties>
55+
56+
<build>
57+
<sourceDirectory>src/main/java</sourceDirectory>
58+
<plugins>
59+
<plugin>
60+
<groupId>org.apache.maven.plugins</groupId>
61+
<artifactId>maven-compiler-plugin</artifactId>
62+
<version>3.2</version>
63+
<configuration>
64+
<source>5</source>
65+
<target>5</target>
66+
</configuration>
67+
</plugin>
68+
<plugin>
69+
<artifactId>maven-assembly-plugin</artifactId>
70+
<configuration>
71+
<descriptorRefs>
72+
<descriptorRef>jar-with-dependencies</descriptorRef>
73+
</descriptorRefs>
74+
</configuration>
75+
</plugin>
76+
</plugins>
77+
</build>
78+
79+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
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 com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
18+
import com.google.api.client.http.HttpTransport;
19+
import com.google.api.client.http.javanet.NetHttpTransport;
20+
import com.google.api.client.json.JsonFactory;
21+
import com.google.api.client.json.jackson2.JacksonFactory;
22+
import com.google.api.services.cloudkms.v1beta1.CloudKMS;
23+
import com.google.api.services.cloudkms.v1beta1.CloudKMSScopes;
24+
import com.google.api.services.cloudkms.v1beta1.model.DecryptRequest;
25+
import com.google.api.services.cloudkms.v1beta1.model.DecryptResponse;
26+
import com.google.api.services.cloudkms.v1beta1.model.EncryptRequest;
27+
import com.google.api.services.cloudkms.v1beta1.model.EncryptResponse;
28+
29+
import org.kohsuke.args4j.CmdLineException;
30+
import org.kohsuke.args4j.CmdLineParser;
31+
32+
import java.io.IOException;
33+
34+
public class CryptFile {
35+
36+
/**
37+
* Creates an authorized CloudKMS client service using Application Default Credentials.
38+
*
39+
* @return an authorized CloudKMS client
40+
* @throws IOException if there's an error getting the default credentials.
41+
*/
42+
public static CloudKMS createAuthorizedClient() throws IOException {
43+
// Create the credential
44+
HttpTransport transport = new NetHttpTransport();
45+
JsonFactory jsonFactory = new JacksonFactory();
46+
// Authorize the client using Application Default Credentials
47+
// @see https://g.co/dv/identity/protocols/application-default-credentials
48+
GoogleCredential credential = GoogleCredential.getApplicationDefault(transport, jsonFactory);
49+
50+
// Depending on the environment that provides the default credentials (e.g. Compute Engine, App
51+
// Engine), the credentials may require us to specify the scopes we need explicitly.
52+
// Check for this case, and inject the scope if required.
53+
if (credential.createScopedRequired()) {
54+
credential = credential.createScoped(CloudKMSScopes.all());
55+
}
56+
57+
return new CloudKMS.Builder(transport, jsonFactory, credential)
58+
.setApplicationName("CloudKMS CryptFile")
59+
.build();
60+
}
61+
62+
/**
63+
* Encrypts the given bytes, using the specified crypto key.
64+
*/
65+
public static byte[] encrypt(String projectId, String ringId, String keyId, byte[] plaintext)
66+
throws IOException {
67+
String location = "global";
68+
// The resource name of the cryptoKey
69+
String cryptoKeyName = String.format(
70+
"projects/%s/locations/%s/keyRings/%s/cryptoKeys/%s",
71+
projectId, location, ringId, keyId);
72+
// Create the Cloud KMS client.
73+
CloudKMS kms = createAuthorizedClient();
74+
75+
EncryptRequest request = new EncryptRequest().encodePlaintext(plaintext);
76+
EncryptResponse response = kms.projects().locations().keyRings().cryptoKeys()
77+
.encrypt(cryptoKeyName, request)
78+
.execute();
79+
80+
return response.decodeCiphertext();
81+
}
82+
83+
/**
84+
* Decrypts the given encrypted bytes, using the specified crypto key.
85+
*/
86+
public static byte[] decrypt(String projectId, String ringId, String keyId, byte[] encrypted)
87+
throws IOException {
88+
String location = "global";
89+
// Create the Cloud KMS client.
90+
CloudKMS kms = createAuthorizedClient();
91+
92+
// The resource name of the cryptoKey
93+
String cryptoKeyName = String.format(
94+
"projects/%s/locations/%s/keyRings/%s/cryptoKeys/%s",
95+
projectId, location, ringId, keyId);
96+
97+
DecryptRequest request = new DecryptRequest().encodeCiphertext(encrypted);
98+
DecryptResponse response = kms.projects().locations().keyRings().cryptoKeys()
99+
.decrypt(cryptoKeyName, request)
100+
.execute();
101+
102+
return response.decodePlaintext();
103+
}
104+
105+
public static void main(String[] args) throws IOException {
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);
116+
}
117+
commands.command.run();
118+
}
119+
}
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+
}

0 commit comments

Comments
 (0)