diff --git a/.classpath b/.classpath new file mode 100644 index 0000000..76d6555 --- /dev/null +++ b/.classpath @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b83d222 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target/ diff --git a/.project b/.project new file mode 100644 index 0000000..f9bc3ce --- /dev/null +++ b/.project @@ -0,0 +1,23 @@ + + + java-client-example + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..809653a --- /dev/null +++ b/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,6 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.release=disabled +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/.settings/org.eclipse.m2e.core.prefs b/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 0000000..14b697b --- /dev/null +++ b/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/EaaSPolicy.hcl b/EaaSPolicy.hcl new file mode 100644 index 0000000..7797e1c --- /dev/null +++ b/EaaSPolicy.hcl @@ -0,0 +1,24 @@ +/* + * to create a token using this policy: + * vault token create -policy=eaas + */ + +# Enable transit secrets engine +path "sys/mounts/transit" { + capabilities = [ "create", "read", "update", "delete", "list" ] +} + +# To read enabled secrets engines +path "sys/mounts" { + capabilities = [ "read" ] +} + +# Manage the transit secrets engine +path "transit/*" { + capabilities = [ "create", "read", "update", "delete", "list" ] +} + +#access secrets +path "secret/*" { + capabilities = ["create", "read", "update", "delete", "list", "sudo"] +} diff --git a/EaaSPolicy2.hcl b/EaaSPolicy2.hcl new file mode 100644 index 0000000..40f7e33 --- /dev/null +++ b/EaaSPolicy2.hcl @@ -0,0 +1,20 @@ + +path "/transit/encrypt/MyKey"{ + capabilities = ["create", "read", "update", "delete", "list"] + } + + +path "/transit/decrypt/MyKey"{ + capabilities = ["create", "read", "update", "delete", "list"] + } + +path "secret/*" { + capabilities = ["create", "read", "update", "delete", "list"] +} + +path "/transit/keys/*"{ + capabilities = ["create", "read", "update", "delete", "list"] + allowed_parameters = { + "type" = ["aes256-gcm96", "rsa-2048"] + } + } diff --git a/admin_policy.hcl b/admin_policy.hcl new file mode 100644 index 0000000..c1cf486 --- /dev/null +++ b/admin_policy.hcl @@ -0,0 +1,124 @@ +path "transit/*" { + capabilities = ["create", "read", "update", "delete", "list", "sudo"] +} + + +# This section grants all access on "secret/*". Further restrictions can be +# applied to this broad policy, as shown below. + +path "pki/*" { + capabilities = ["create", "read", "update", "delete", "list", "sudo"] +} + +path "secret/*" { + capabilities = ["create", "read", "update", "delete", "list", "sudo"] +} + + +path "aws/*" { + capabilities = ["create", "read", "update", "delete", "list", "sudo"] +} + +path "aws/creds/*" { + capabilities = ["create", "read", "update", "delete", "list", "sudo"] +} + + +# Even though we allowed secret/*, this line explicitly denies +# secret/super-secret. This takes precedence. +path "secret/super-secret" { + capabilities = ["deny"] +} + +# Policies can also specify allowed, disallowed, and required parameters. Here +# the key "secret/restricted" can only contain "foo" (any value) and "bar" (one +# of "zip" or "zap"). +path "secret/restricted" { + capabilities = ["create"] + allowed_parameters = { + "foo" = [] + "bar" = ["zip", "zap"] + } + +} + +path "auth/*" +{ + capabilities = ["create", "read", "update", "delete", "list", "sudo"] +} + +# List, create, update, and delete auth methods +path "sys/auth/*" +{ + capabilities = ["create", "read", "update", "delete", "list", "sudo"] +} + +# policies +path "sys/policy" +{ + capabilities = ["create", "update", "delete"] + control_group = { + factor "ops_manager" { + identity { + group_names = ["managers"] + approvals = 1 + } + } + } +} + + +# List, create, update, and delete key/value secrets +path "secret/*" +{ + capabilities = ["create", "read", "update", "delete", "list", "sudo"] +} + +# Manage and manage secret engines broadly across Vault. +path "sys/mounts/*" +{ + capabilities = ["create", "read", "update", "delete", "list", "sudo"] +} + +# Read health checks +path "sys/health" +{ + capabilities = ["read", "sudo"] +} + +# To perform Step 4 +path "sys/capabilities-self" +{ + capabilities = ["create", "update"] +} + +path "sys/*" +{ + capabilities = ["create", "read", "update", "delete", "list", "sudo"] +} + +path "sys/control-group" +{ + capabilities = ["create", "read", "update", "delete", "list", "sudo"] +} + + +path "identity/*" +{ + capabilities = ["create", "read", "update", "delete", "list", "sudo"] +} + +path "ssh/*" +{ + capabilities = ["create", "read", "update", "delete", "list", "sudo"] +} + +path "ssh/my-role/*" +{ + capabilities = ["create", "read", "update", "delete", "list", "sudo"] +} + +path "sys/capabilities-self/*" +{ + capabilities = ["create", "read", "update", "delete", "list", "sudo"] +} diff --git a/java-client-example-1.0-SNAPSHOT-jar-with-dependencies.jar b/java-client-example-1.0-SNAPSHOT-jar-with-dependencies.jar index 3873668..e65281a 100644 Binary files a/java-client-example-1.0-SNAPSHOT-jar-with-dependencies.jar and b/java-client-example-1.0-SNAPSHOT-jar-with-dependencies.jar differ diff --git a/java-client-example-1.0-SNAPSHOT.jar b/java-client-example-1.0-SNAPSHOT.jar new file mode 100644 index 0000000..f7cdf60 Binary files /dev/null and b/java-client-example-1.0-SNAPSHOT.jar differ diff --git a/pom.xml b/pom.xml index 5b8049e..9f15773 100644 --- a/pom.xml +++ b/pom.xml @@ -1,64 +1,78 @@ - - 4.0.0 - io.vaultproject.javaclientexample - java-client-example - jar - 1.0-SNAPSHOT - java-client-example - http://maven.apache.org - - - junit - junit - 3.8.1 - test - - - com.bettercloud - vault-java-driver - 2.0.0 - - - - - - org.apache.maven.plugins - maven-assembly-plugin - - - package - - single - - - - - io.vaultproject.javaclientexample.App - - - - jar-with-dependencies - - - - - - - - org.apache.maven.plugins - maven-jar-plugin - 3.0.2 - - - - true - lib/ - io.vaultproject.javaclientexample.App - - - - - - - + + 4.0.0 + io.vaultproject.javaclientexample + java-client-example + jar + 1.0-SNAPSHOT + java-client-example + http://maven.apache.org + + 1.8 + 1.8 + + + + junit + junit + 4.13 + test + + + com.bettercloud + vault-java-driver + 5.1.0 + + + + + + org.apache.maven.plugins + maven-site-plugin + 3.9.1 + + + org.apache.maven.plugins + maven-project-info-reports-plugin + 3.1.0 + + + org.apache.maven.plugins + maven-assembly-plugin + + + package + + single + + + + + io.vaultproject.javaclientexample.App + + + + jar-with-dependencies + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.2.0 + + + + true + lib/ + io.vaultproject.javaclientexample.App + + + + + + + diff --git a/src/main/java/io/vaultproject/javaclientexample/App.java b/src/main/java/io/vaultproject/javaclientexample/App.java index cd30158..7fb78b0 100644 --- a/src/main/java/io/vaultproject/javaclientexample/App.java +++ b/src/main/java/io/vaultproject/javaclientexample/App.java @@ -1,37 +1,84 @@ -package io.vaultproject.javaclientexample; -import com.bettercloud.vault.*; - -/** - * Hello world from Vault! - * - */ -public class App -{ - public static void main( String[] args ) throws VaultException - { - /* The com.bettercloud.vault driver automatically reads a - * a number of Environment Variables like VAULT_TOKEN or - * VAULT_ADDR, you should ensure those are set properly - * These are displayed just to ensure you have the - * right ones for demo purposes. - */ - - String vaulttoken = System.getenv("VAULT_TOKEN"); - String vaulthost = System.getenv("VAULT_ADDR"); - System.out.format( "Using Vault Host %s\n", vaulthost); - System.out.format( "With Vault Token %s\n", vaulttoken ); - /* This should be a separate method called from Main, then - * again for simplicity... - */ - final VaultConfig config = new VaultConfig().build(); - final Vault vault = new Vault(config); - try { - final String value = vault.logical() - .read("secret/hello") - .getData().get("value"); - System.out.format( "value key in secret/hello is " + value +"\n"); - } catch(VaultException e) { - System.out.println("Exception thrown: " + e); - } - } -} +package io.vaultproject.javaclientexample; +import java.util.HashMap; +import java.util.Map; + +import com.bettercloud.vault.*; +import com.bettercloud.vault.response.LogicalResponse; + +/** + * Hello world from Vault! + * + */ +public class App +{ + + /* For Reference check out the Hashicorp Vault EaaS learn page: + https://learn.hashicorp.com/vault/encryption-as-a-service/eaas-transit + */ + + public static void main( String[] args ) throws VaultException + { + /* The com.bettercloud.vault driver automatically reads a + * a number of Environment Variables like VAULT_TOKEN or + * VAULT_ADDR, you should ensure those are set properly + * These are displayed just to ensure you have the + * right ones for demo purposes. + */ + + + //Create secrets to save + Map secrets = new HashMap(); + secrets.put("value", "from java"); + + + try { + VaultSecret vault = new VaultSecret(); + + //Write KV Secret + LogicalResponse writeResponse = vault.setKvSecret("secret/hello", secrets); + System.out.format( "Write request response : " + writeResponse.getRestResponse().getStatus() +"\n"); + + //read KV Secret + System.out.format( "value secret in secret/hello is " + vault.getKvSecret() +"\n"); + + ////////////////////////////////////////////////////////////////////////////////////////////////////// + //Create Encryption Keys + String encryptionKey = "testKey"; + vault.createKeys(encryptionKey); + + //Encrypt plaintext + + String plainText = "test input"; + + Map ciphertext = vault.encryptSecret(encryptionKey, plainText); + + System.out.format( "the encrypted Value is " + ciphertext.get("ciphertext") +"\n"); + + + //Decrypt ciphertext + String plainTextResponse = vault.decryptSecret(encryptionKey, ciphertext.get("ciphertext")); + System.out.format( "the decrypted Value is " + plainTextResponse +"\n"); + + + //Rotate Keys + vault.rotateKeys(encryptionKey); + + //Encrypt plaintext after key rotate + plainText = "test 2"; + + Map ciphertext2 = vault.encryptSecret(encryptionKey, plainText); + + System.out.format( "the encrypted Value is " + ciphertext2.get("ciphertext") +"\n"); + + //Decrypt ciphertext + plainTextResponse = vault.decryptSecret(encryptionKey, ciphertext.get("ciphertext")); + System.out.format( "the decrypted Value is " + plainTextResponse +"\n"); + + + } catch(VaultException e) { + System.out.println("Exception thrown: " + e); + } + + + } +} diff --git a/src/main/java/io/vaultproject/javaclientexample/VaultSecret.java b/src/main/java/io/vaultproject/javaclientexample/VaultSecret.java new file mode 100644 index 0000000..2c40dd7 --- /dev/null +++ b/src/main/java/io/vaultproject/javaclientexample/VaultSecret.java @@ -0,0 +1,155 @@ +/** + * + */ +package io.vaultproject.javaclientexample; + +import java.util.Base64; +import java.util.HashMap; +import java.util.Map; + +import com.bettercloud.vault.Vault; +import com.bettercloud.vault.VaultConfig; +import com.bettercloud.vault.VaultException; +import com.bettercloud.vault.response.LogicalResponse; + +/** + * @author phatb + * + */ +public class VaultSecret { + Vault vault; + + public VaultSecret() throws VaultException { + String vaulttoken = System.getenv("VAULT_TOKEN"); + String vaulthost = System.getenv("VAULT_ADDR"); + System.out.format( "Using Vault Host %s\n", vaulthost); + System.out.format( "With Vault Token %s\n", vaulttoken ); + /* This should be a separate method called from Main, then + * again for simplicity... + */ + final VaultConfig config = new VaultConfig() + .address(vaulthost) + .token(vaulttoken) + .build(); + vault = new Vault(config,1); + } + + public LogicalResponse setKvSecret(String path, Map secrets){ + LogicalResponse writeResponse = null; + try { + + // Write operation + writeResponse = vault.logical().write("secret/hello", secrets); + + } catch(VaultException e) { + System.out.println("Exception thrown: " + e); + } + return writeResponse; + + + } + + public String getKvSecret(){ + String value = ""; + try { + value = vault.logical() + .read("secret/hello") + .getData().get("value"); + + } catch(VaultException e) { + System.out.println("Exception thrown: " + e); + } + return value; + + + } + + public Map encryptSecret(String key, String plainText){ + String transit = "transit/encrypt/"+key; + String encodedString = Base64.getEncoder().encodeToString(plainText.getBytes()); + + Map toEncrypt = new HashMap(); + toEncrypt.put("plaintext", encodedString); + + LogicalResponse writeResponse = null; + try { + + // Write operation + writeResponse = vault.logical().write(transit, toEncrypt); + + } catch(Exception e) { + System.out.println("Exception thrown: " + e); + } + return writeResponse.getData(); + + + } + + public String decryptSecret(String key, String cipherText){ + String transit = "transit/decrypt/"+key; + String plainText = null; + + Map toDecrypt = new HashMap(); + toDecrypt.put("ciphertext", cipherText); + + LogicalResponse writeResponse = null; + try { + + // Write operation + writeResponse = vault.logical().write(transit, toDecrypt); + + byte[] decodedBytes = Base64.getDecoder().decode(writeResponse.getData().get("plaintext")); + plainText = new String(decodedBytes); + + } catch(Exception e) { + System.out.println("Exception thrown: " + e); + } + return plainText; + + + } + + public void rotateKeys(String key) { + String transit = "transit/keys/"+key+"/rotate"; + + Map empty = new HashMap(); + + LogicalResponse writeResponse = null; + try { + + // Write operation + writeResponse = vault.logical().write(transit, empty); + + System.out.println("keys rotated: " + writeResponse.getRestResponse().getStatus() ); + + } catch(VaultException e) { + System.out.println("Exception thrown: " + e); + } + + + + + } + + public void createKeys(String key) { + String transit = "transit/keys/"+key; + + Map empty = new HashMap(); + + LogicalResponse writeResponse = null; + try { + + // Write operation + writeResponse = vault.logical().write(transit, empty); + + System.out.println("keys created: " + writeResponse.getRestResponse().getStatus() ); + + } catch(Exception e) { + System.out.println("Exception thrown: " + e); + } + + + } + + +} diff --git a/src/test/java/io/vaultproject/javaclientexample/AppTest.java b/src/test/java/io/vaultproject/javaclientexample/AppTest.java index f98f95c..f712593 100644 --- a/src/test/java/io/vaultproject/javaclientexample/AppTest.java +++ b/src/test/java/io/vaultproject/javaclientexample/AppTest.java @@ -1,38 +1,38 @@ -package io.vaultproject.javaclientexample; - -import junit.framework.Test; -import junit.framework.TestCase; -import junit.framework.TestSuite; - -/** - * Unit test for simple App. - */ -public class AppTest - extends TestCase -{ - /** - * Create the test case - * - * @param testName name of the test case - */ - public AppTest( String testName ) - { - super( testName ); - } - - /** - * @return the suite of tests being tested - */ - public static Test suite() - { - return new TestSuite( AppTest.class ); - } - - /** - * Rigourous Test :-) - */ - public void testApp() - { - assertTrue( true ); - } -} +package io.vaultproject.javaclientexample; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +/** + * Unit test for simple App. + */ +public class AppTest + extends TestCase +{ + /** + * Create the test case + * + * @param testName name of the test case + */ + public AppTest( String testName ) + { + super( testName ); + } + + /** + * @return the suite of tests being tested + */ + public static Test suite() + { + return new TestSuite( AppTest.class ); + } + + /** + * Rigourous Test :-) + */ + public void testApp() + { + assertTrue( true ); + } +}