mirror of https://github.com/dapr/java-sdk.git
replace vault to local (#719)
* replace vault to local Signed-off-by: zjx244729 <zjx244729@alibaba-inc.com> * change secret store name style Signed-off-by: zjx244729 <zjx244729@alibaba-inc.com> * delete vault token file Signed-off-by: zjx244729 <zjx244729@alibaba-inc.com> * remove vault int validate.yml Signed-off-by: zjx244729 <zjx244729@alibaba-inc.com> * fix it secret case Signed-off-by: zjx244729 <zjx244729@alibaba-inc.com> * replace vault to local Signed-off-by: zjx244729 <zjx244729@alibaba-inc.com> * change secret store name style Signed-off-by: zjx244729 <zjx244729@alibaba-inc.com> * delete vault token file Signed-off-by: zjx244729 <zjx244729@alibaba-inc.com> * remove vault int validate.yml Signed-off-by: zjx244729 <zjx244729@alibaba-inc.com> * fix it secret case Signed-off-by: zjx244729 <zjx244729@alibaba-inc.com> * fix it dead loop Signed-off-by: zjx244729 <zjx244729@alibaba-inc.com> Co-authored-by: zjx244729 <zjx244729@alibaba-inc.com> Co-authored-by: Mukundan Sundararajan <65565396+mukundansundar@users.noreply.github.com>
This commit is contained in:
parent
65936ee963
commit
e2d4d1e1ea
|
@ -87,10 +87,6 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
docker-compose -f ./sdk-tests/deploy/local-test-kafka.yml up -d
|
docker-compose -f ./sdk-tests/deploy/local-test-kafka.yml up -d
|
||||||
docker ps
|
docker ps
|
||||||
- name: Install Local Hashicorp Vault using docker-compose
|
|
||||||
run: |
|
|
||||||
docker-compose -f ./sdk-tests/deploy/local-test-vault.yml up -d
|
|
||||||
docker ps
|
|
||||||
- name: Install Local mongo database using docker-compose
|
- name: Install Local mongo database using docker-compose
|
||||||
run: |
|
run: |
|
||||||
docker-compose -f ./sdk-tests/deploy/local-test-mongo.yml up -d
|
docker-compose -f ./sdk-tests/deploy/local-test-mongo.yml up -d
|
||||||
|
|
|
@ -99,15 +99,6 @@ jobs:
|
||||||
echo "PATH=$PATH:$HOME/.local/bin" >> $GITHUB_ENV
|
echo "PATH=$PATH:$HOME/.local/bin" >> $GITHUB_ENV
|
||||||
pip3 install setuptools wheel
|
pip3 install setuptools wheel
|
||||||
pip3 install mechanical-markdown
|
pip3 install mechanical-markdown
|
||||||
- name: Install Vault CLI
|
|
||||||
run: |
|
|
||||||
# From the installtion page of vault https://learn.hashicorp.com/tutorials/vault/getting-started-install?in=vault/getting-started
|
|
||||||
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
|
|
||||||
sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install vault
|
|
||||||
# Verify vault is installed
|
|
||||||
vault -h
|
|
||||||
- name: Install Local mongo database using docker-compose
|
- name: Install Local mongo database using docker-compose
|
||||||
run: |
|
run: |
|
||||||
docker-compose -f ./sdk-tests/deploy/local-test-mongo.yml up -d
|
docker-compose -f ./sdk-tests/deploy/local-test-mongo.yml up -d
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
myroot
|
|
|
@ -1,16 +0,0 @@
|
||||||
apiVersion: dapr.io/v1alpha1
|
|
||||||
kind: Component
|
|
||||||
metadata:
|
|
||||||
name: vault
|
|
||||||
spec:
|
|
||||||
type: secretstores.hashicorp.vault
|
|
||||||
version: v1
|
|
||||||
metadata:
|
|
||||||
- name: vaultAddr
|
|
||||||
value: "http://127.0.0.1:8200"
|
|
||||||
- name: skipVerify
|
|
||||||
value : true
|
|
||||||
- name: vaultTokenMountPath
|
|
||||||
value : ".hashicorp_vault_token"
|
|
||||||
- name: vaultKVPrefix
|
|
||||||
value : "dapr"
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
apiVersion: dapr.io/v1alpha1
|
||||||
|
kind: Component
|
||||||
|
metadata:
|
||||||
|
name: localSecretStore
|
||||||
|
namespace: default
|
||||||
|
spec:
|
||||||
|
type: secretstores.local.file
|
||||||
|
version: v1
|
||||||
|
metadata:
|
||||||
|
- name: secretsFile
|
||||||
|
value: "./components/secrets/secret.json"
|
||||||
|
- name: nestedSeparator
|
||||||
|
value: ":"
|
||||||
|
- name: multiValued
|
||||||
|
value: "false"
|
|
@ -1,31 +1,28 @@
|
||||||
# Dapr's Secret Store Sample
|
# Dapr's Secret Store Sample
|
||||||
|
|
||||||
In this sample, we'll see how to retrieve a secret using Dapr's Java SDK.
|
In this sample, we'll see how to retrieve a secret using Dapr's Java SDK.
|
||||||
This sample includes two files:
|
This sample includes two files:
|
||||||
|
|
||||||
* docker-compose-vault.yml (Starts Hashicorp's Vault as a container)
|
|
||||||
* SecretClient.java (Reads a secret from Dapr's Secret Store)
|
* SecretClient.java (Reads a secret from Dapr's Secret Store)
|
||||||
* Existing Dapr component file in `< repo dir >/examples/components/hashicorp_vault.yaml`
|
* Existing Dapr component file in `< repo dir >/examples/components/local_file.yaml`
|
||||||
* Existing token file in `< repo dir >/examples/.hashicorp_vault_token` (Consumed by `daprd`'s vault component above)
|
|
||||||
|
|
||||||
Visit [this](https://docs.dapr.io/developing-applications/building-blocks/secrets/secrets-overview/) link for more information about secret stores in Dapr.
|
Visit [this](https://docs.dapr.io/developing-applications/building-blocks/secrets/secrets-overview/) link for more information about secret stores in Dapr.
|
||||||
|
|
||||||
## Secret store sample using the Java-SDK
|
## Secret store sample using the Java-SDK
|
||||||
|
|
||||||
In this example, the component used is Hashicorp Vault, but others are also available.
|
In this example, the component used is local file(not recommended for production use), but others are also available.
|
||||||
|
|
||||||
Visit [this](https://github.com/dapr/components-contrib/tree/master/secretstores) link for more information about secret stores implementations.
|
Visit [this](https://github.com/dapr/components-contrib/tree/master/secretstores) link for more information about secret store implementations.
|
||||||
|
|
||||||
|
|
||||||
## Pre-requisites
|
## Pre-requisites
|
||||||
|
|
||||||
* [Dapr and Dapr Cli](https://docs.dapr.io/getting-started/install-dapr/).
|
* [Dapr and Dapr Cli](https://docs.dapr.io/getting-started/install-dapr/).
|
||||||
* Java JDK 11 (or greater):
|
* Java JDK 11 (or greater):
|
||||||
* [Microsoft JDK 11](https://docs.microsoft.com/en-us/java/openjdk/download#openjdk-11)
|
* [Microsoft JDK 11](https://docs.microsoft.com/en-us/java/openjdk/download#openjdk-11)
|
||||||
* [Oracle JDK 11](https://www.oracle.com/technetwork/java/javase/downloads/index.html#JDK11)
|
* [Oracle JDK 11](https://www.oracle.com/technetwork/java/javase/downloads/index.html#JDK11)
|
||||||
* [OpenJDK 11](https://jdk.java.net/11/)
|
* [OpenJDK 11](https://jdk.java.net/11/)
|
||||||
* [Apache Maven](https://maven.apache.org/install.html) version 3.x.
|
* [Apache Maven](https://maven.apache.org/install.html) version 3.x.
|
||||||
* Hashicorp's vault client [installed](https://www.vaultproject.io/docs/install/).
|
|
||||||
|
|
||||||
### Checking out the code
|
### Checking out the code
|
||||||
|
|
||||||
|
@ -49,157 +46,80 @@ Then get into the examples directory:
|
||||||
cd examples
|
cd examples
|
||||||
```
|
```
|
||||||
|
|
||||||
### Setting Vault locally
|
### Creating a JSON secret file locally
|
||||||
|
|
||||||
Before getting into the application code, follow these steps in order to set up a local instance of Vault. This is needed for the local instances. Steps are:
|
Dapr's API for secret store only support read operations. For this sample to run, we will first create a secret file with a JSON string that contains two keys: `redisPassword` and `randomKey`.
|
||||||
|
|
||||||
1. To run the vault container locally run:
|
|
||||||
<!-- Docker is writing output to stderr ... -->
|
|
||||||
|
|
||||||
<!-- STEP
|
<!-- STEP
|
||||||
name: Start vault
|
name: create local file
|
||||||
expected_stderr_lines:
|
|
||||||
- 'Creating network "secrets_default" with the default driver'
|
|
||||||
sleep: 10
|
|
||||||
-->
|
-->
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker-compose -f ./src/main/java/io/dapr/examples/secrets/docker-compose-vault.yml up -d
|
echo '{"redisPassword":"root123","randomKey":"value"}' > ./components/secrets/secret.json
|
||||||
```
|
|
||||||
|
|
||||||
<!-- END_STEP -->
|
|
||||||
|
|
||||||
2. Run `docker ps` to see the container running locally:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
342d3522ca14 vault "docker-entrypoint.s…" 34 seconds ago Up About
|
|
||||||
a minute 0.0.0.0:8200->8200/tcp secrets_hashicorp_vault_1
|
|
||||||
```
|
|
||||||
Click [here](https://hub.docker.com/_/vault/) for more information about the container image for Hashicorp's Vault.
|
|
||||||
|
|
||||||
### Create a secret in Vault
|
|
||||||
Dapr's API for secret store only support read operations. For this sample to run, we will first create a secret via the Vault's cli commands:
|
|
||||||
|
|
||||||
Export the `VAULT_ADDR` for vault CLI:
|
|
||||||
```bash
|
|
||||||
export VAULT_ADDR=http://127.0.0.1:8200/
|
|
||||||
```
|
|
||||||
|
|
||||||
Login to Hashicorp's Vault:
|
|
||||||
|
|
||||||
<!-- STEP
|
|
||||||
name: Vault login
|
|
||||||
expected_stdout_lines:
|
|
||||||
- "Success! You are now authenticated. The token information displayed below"
|
|
||||||
- "token myroot"
|
|
||||||
env:
|
|
||||||
VAULT_ADDR: "http://127.0.0.1:8200/"
|
|
||||||
-->
|
|
||||||
|
|
||||||
```bash
|
|
||||||
vault login myroot
|
|
||||||
```
|
```
|
||||||
|
|
||||||
<!-- END_STEP -->
|
<!-- END_STEP -->
|
||||||
|
|
||||||
Create secret (replace `$MY_FAVORITE_MOVIE` with a title of our choice):
|
|
||||||
|
|
||||||
<!-- STEP
|
|
||||||
name: Create movie vault secret
|
|
||||||
expected_stdout_lines:
|
|
||||||
- "version 1"
|
|
||||||
env:
|
|
||||||
VAULT_ADDR: "http://127.0.0.1:8200/"
|
|
||||||
MY_FAVORITE_MOVIE: "Star Wars"
|
|
||||||
-->
|
|
||||||
|
|
||||||
```bash
|
|
||||||
vault kv put secret/dapr/movie title="$MY_FAVORITE_MOVIE"
|
|
||||||
```
|
|
||||||
|
|
||||||
<!-- END_STEP -->
|
|
||||||
|
|
||||||
Create random secret:
|
|
||||||
|
|
||||||
<!-- STEP
|
|
||||||
name: Create random vault secret
|
|
||||||
expected_stdout_lines:
|
|
||||||
- "version 1"
|
|
||||||
env:
|
|
||||||
VAULT_ADDR: "http://127.0.0.1:8200/"
|
|
||||||
-->
|
|
||||||
|
|
||||||
```bash
|
|
||||||
vault kv put secret/dapr/randomKey testVal="value"
|
|
||||||
```
|
|
||||||
|
|
||||||
<!-- END_STEP -->
|
|
||||||
|
|
||||||
In the command above, `secret` means the secret engine in Hashicorp's Vault.
|
|
||||||
Then, `dapr` is the prefix as defined in `< repo dir >/examples/components/hashicorp_vault.yaml`.
|
|
||||||
Finally, `movie` and `randomKey` are the secret names with the value set in the form of `key=value` pair.
|
|
||||||
|
|
||||||
A secret in Dapr is a dictionary.
|
|
||||||
|
|
||||||
### Running the secret store sample
|
### Running the secret store sample
|
||||||
|
|
||||||
The example's main function is in `SecretClient.java`.
|
The example's main function is in `SecretClient.java`.
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public class SecretClient {
|
public class SecretClient {
|
||||||
/**
|
|
||||||
* Identifier in Dapr for the secret store.
|
|
||||||
*/
|
|
||||||
private static final String SECRET_STORE_NAME = "vault";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JSON Serializer to print output.
|
* JSON Serializer to print output.
|
||||||
*/
|
*/
|
||||||
private static final ObjectMapper JSON_SERIALIZER = new ObjectMapper();
|
private static final ObjectMapper JSON_SERIALIZER = new ObjectMapper();
|
||||||
|
|
||||||
///...
|
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
/**
|
||||||
if (args.length != 1) {
|
* Client to read a secret.
|
||||||
throw new IllegalArgumentException("Use one argument: secret's key to be retrieved.");
|
*
|
||||||
}
|
* @param args Unused arguments.
|
||||||
|
*/
|
||||||
String secretKey = args[0];
|
public static void main(String[] args) throws Exception {
|
||||||
try (DaprClient client = (new DaprClientBuilder()).build()) {
|
if (args.length < 2) {
|
||||||
Map<String, String> secret = client.getSecret(SECRET_STORE_NAME, secretKey).block();
|
throw new IllegalArgumentException("Required two argument at least: "
|
||||||
System.out.println(JSON_SERIALIZER.writeValueAsString(secret));
|
+ "one's the secret store name, and the others are secret keys.");
|
||||||
|
}
|
||||||
try {
|
|
||||||
secret = client.getSecret(SECRET_STORE_NAME, "randomKey").block();
|
final String secretStoreName = args[0];
|
||||||
System.out.println(JSON_SERIALIZER.writeValueAsString(secret));
|
try (DaprClient client = (new DaprClientBuilder()).build()) {
|
||||||
} catch (Exception ex) {
|
|
||||||
System.out.println(ex.getMessage());
|
for (int i = 1; i < args.length; i++) {
|
||||||
|
String secretKey = args[i];
|
||||||
|
|
||||||
|
try {
|
||||||
|
Map<String, String> secret = client.getSecret(secretStoreName, secretKey).block();
|
||||||
|
System.out.println(JSON_SERIALIZER.writeValueAsString(secret));
|
||||||
|
} catch (Exception ex) {
|
||||||
|
System.out.println(ex.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception ex) {
|
||||||
|
System.out.println(ex.getMessage());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
///...
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
The program receives one and only one argument: the secret's key to be fetched.
|
The program receives two arguments at least: one's the secret store name and the others are secret's keys to be fetched.
|
||||||
After identifying the key to be fetched, it will retrieve it from the pre-defined secret store: `vault`.
|
After identifying the secret store name that created and the keys to be fetched, it will retrieve them from the pre-defined secret store: `< repo dir >/examples/components/secrets/secret.json`.
|
||||||
The secret store's name **must** match the component's name defined in `< repo dir >/examples/components/hashicorp_vault.yaml`.
|
The secret store's name **must** match the component's name defined in `< repo dir >/examples/components/secrets/local_file.yaml`.
|
||||||
The Dapr client is also within a try-with-resource block to properly close the client at the end.
|
The Dapr client is also within a try-with-resource block to properly close the client at the end.
|
||||||
|
|
||||||
Execute the following script in order to run the example:
|
Execute the following script in order to run the example:
|
||||||
|
|
||||||
<!-- STEP
|
<!-- STEP
|
||||||
name: Validate normal run
|
name: Validate normal run
|
||||||
expected_stdout_lines:
|
expected_stdout_lines:
|
||||||
- '== APP == {"title":"Star Wars"}'
|
- '== APP == {"redisPassword":"root123"}'
|
||||||
- '== APP == {"testVal":"value"}'
|
- '== APP == {"randomKey":"value"}'
|
||||||
env:
|
|
||||||
VAULT_ADDR: "http://127.0.0.1:8200/"
|
|
||||||
background: true
|
background: true
|
||||||
sleep: 5
|
sleep: 5
|
||||||
-->
|
-->
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
dapr run --components-path ./components/secrets --app-id secrets1 -- java -jar target/dapr-java-sdk-examples-exec.jar io.dapr.examples.secrets.SecretClient movie
|
dapr run --components-path ./components/secrets --app-id secrets1 -- java -jar target/dapr-java-sdk-examples-exec.jar io.dapr.examples.secrets.SecretClient localSecretStore redisPassword randomKey
|
||||||
```
|
```
|
||||||
|
|
||||||
<!-- END_STEP -->
|
<!-- END_STEP -->
|
||||||
|
@ -207,9 +127,8 @@ dapr run --components-path ./components/secrets --app-id secrets1 -- java -jar t
|
||||||
Once running, the program should print the output as follows:
|
Once running, the program should print the output as follows:
|
||||||
|
|
||||||
```
|
```
|
||||||
== APP == {"title":"$MY_FAVORITE_MOVIE"}
|
== APP == {"redisPassword":"root123"}
|
||||||
|
== APP == {"randomKey":"value"}
|
||||||
== APP == {"testVal":"value"}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
To close the app either press `CTRL+C` or run
|
To close the app either press `CTRL+C` or run
|
||||||
|
@ -225,7 +144,7 @@ dapr stop --app-id secrets1
|
||||||
<!-- END_STEP -->
|
<!-- END_STEP -->
|
||||||
|
|
||||||
|
|
||||||
The example's `config.yaml` is as follows:
|
The example's `config.yaml` is as follows:
|
||||||
```yaml
|
```yaml
|
||||||
apiVersion: dapr.io/v1alpha1
|
apiVersion: dapr.io/v1alpha1
|
||||||
kind: Configuration
|
kind: Configuration
|
||||||
|
@ -234,28 +153,26 @@ metadata:
|
||||||
spec:
|
spec:
|
||||||
secrets:
|
secrets:
|
||||||
scopes:
|
scopes:
|
||||||
- storeName: "vault"
|
- storeName: "localSecretStore"
|
||||||
defaultAccess: "deny"
|
defaultAccess: "deny"
|
||||||
allowedSecrets: ["movie",]
|
allowedSecrets: ["redisPassword",]
|
||||||
```
|
```
|
||||||
|
|
||||||
The configuration defines, that the only allowed secret is `movie` and all other secrets are denied.
|
The configuration defines, that the only allowed secret is `redisPassword` and all other secrets are denied.
|
||||||
|
|
||||||
Execute the following script in order to run this example with additional secret scoping:
|
Execute the following script in order to run this example with additional secret scoping:
|
||||||
|
|
||||||
<!-- STEP
|
<!-- STEP
|
||||||
name: Validate error on querying random secret
|
name: Validate error on querying random secret
|
||||||
expected_stdout_lines:
|
expected_stdout_lines:
|
||||||
- '== APP == {"title":"Star Wars"}'
|
- '== APP == {"redisPassword":"root123"}'
|
||||||
- '== APP == PERMISSION_DENIED: access denied by policy to get "randomKey" from "vault"'
|
- '== APP == PERMISSION_DENIED: access denied by policy to get "randomKey" from "localSecretStore"'
|
||||||
env:
|
|
||||||
VAULT_ADDR: "http://127.0.0.1:8200/"
|
|
||||||
background: true
|
background: true
|
||||||
sleep: 5
|
sleep: 5
|
||||||
-->
|
-->
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
dapr run --components-path ./components/secrets --config ./src/main/java/io/dapr/examples/secrets/config.yaml --app-id secrets2 -- java -jar target/dapr-java-sdk-examples-exec.jar io.dapr.examples.secrets.SecretClient movie
|
dapr run --components-path ./components/secrets --config ./src/main/java/io/dapr/examples/secrets/config.yaml --app-id secrets2 -- java -jar target/dapr-java-sdk-examples-exec.jar io.dapr.examples.secrets.SecretClient localSecretStore redisPassword randomKey
|
||||||
```
|
```
|
||||||
|
|
||||||
<!-- END_STEP -->
|
<!-- END_STEP -->
|
||||||
|
@ -263,9 +180,8 @@ dapr run --components-path ./components/secrets --config ./src/main/java/io/dapr
|
||||||
Once running, the program should print the output as follows:
|
Once running, the program should print the output as follows:
|
||||||
|
|
||||||
```
|
```
|
||||||
== APP == {"title":"$MY_FAVORITE_MOVIE"}
|
== APP == {"redisPassword":"root123"}
|
||||||
|
== APP == PERMISSION_DENIED: access denied by policy to get "randomKey" from "localSecretStore"
|
||||||
== APP == PERMISSION_DENIED: access denied by policy to get "randomKey" from "vault"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
To close the app either press `CTRL+C` or run
|
To close the app either press `CTRL+C` or run
|
||||||
|
@ -281,14 +197,14 @@ dapr stop --app-id secrets2
|
||||||
<!-- END_STEP -->
|
<!-- END_STEP -->
|
||||||
|
|
||||||
|
|
||||||
To clean up and bring the vault container down, run
|
To clean up the local secret file
|
||||||
|
|
||||||
<!-- STEP
|
<!-- STEP
|
||||||
name: Cleanup vault container
|
name: Cleanup local secret file
|
||||||
-->
|
-->
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
docker-compose -f ./src/main/java/io/dapr/examples/secrets/docker-compose-vault.yml down
|
rm -rf ./components/secrets/secret.json
|
||||||
```
|
```
|
||||||
|
|
||||||
<!-- END_STEP -->
|
<!-- END_STEP -->
|
||||||
|
|
|
@ -21,21 +21,16 @@ import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 1. Build and install jars:
|
* 1. Build and install jars:
|
||||||
* mvn clean install
|
* mvn clean install
|
||||||
* 2. cd to [repo-root]/examples
|
* 2. cd to [repo-root]/examples
|
||||||
* 3. Add secret to vault:
|
* 3. Creating a JSON secret file that contains two keys: redisPassword and randomKey locally:
|
||||||
* vault kv put secret/dapr/movie title="[my favorite movie]"
|
|
||||||
* 4. Read secret from example:
|
* 4. Read secret from example:
|
||||||
* dapr run --components-path ./components/secrets -- \
|
* dapr run --components-path ./components/secrets -- \
|
||||||
* java -jar target/dapr-java-sdk-examples-exec.jar io.dapr.examples.secrets.SecretClient movie
|
* java -jar target/dapr-java-sdk-examples-exec.jar io.dapr.examples.secrets.SecretClient \
|
||||||
|
* localSecretStore redisPassword randomKey
|
||||||
*/
|
*/
|
||||||
public class SecretClient {
|
public class SecretClient {
|
||||||
|
|
||||||
/**
|
|
||||||
* Identifier in Dapr for the secret store.
|
|
||||||
*/
|
|
||||||
private static final String SECRET_STORE_NAME = "vault";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JSON Serializer to print output.
|
* JSON Serializer to print output.
|
||||||
*/
|
*/
|
||||||
|
@ -47,21 +42,26 @@ public class SecretClient {
|
||||||
* @param args Unused arguments.
|
* @param args Unused arguments.
|
||||||
*/
|
*/
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
if (args.length != 1) {
|
if (args.length < 2) {
|
||||||
throw new IllegalArgumentException("Use one argument: secret's key to be retrieved.");
|
throw new IllegalArgumentException("Required two argument at least: "
|
||||||
|
+ "one's the secret store name, and the others are secret keys.");
|
||||||
}
|
}
|
||||||
|
|
||||||
String secretKey = args[0];
|
final String secretStoreName = args[0];
|
||||||
try (DaprClient client = (new DaprClientBuilder()).build()) {
|
try (DaprClient client = (new DaprClientBuilder()).build()) {
|
||||||
Map<String, String> secret = client.getSecret(SECRET_STORE_NAME, secretKey).block();
|
|
||||||
System.out.println(JSON_SERIALIZER.writeValueAsString(secret));
|
|
||||||
|
|
||||||
try {
|
for (int i = 1; i < args.length; i++) {
|
||||||
secret = client.getSecret(SECRET_STORE_NAME, "randomKey").block();
|
String secretKey = args[i];
|
||||||
System.out.println(JSON_SERIALIZER.writeValueAsString(secret));
|
|
||||||
} catch (Exception ex) {
|
try {
|
||||||
System.out.println(ex.getMessage());
|
Map<String, String> secret = client.getSecret(secretStoreName, secretKey).block();
|
||||||
|
System.out.println(JSON_SERIALIZER.writeValueAsString(secret));
|
||||||
|
} catch (Exception ex) {
|
||||||
|
System.out.println(ex.getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} catch (Exception ex) {
|
||||||
|
System.out.println(ex.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,6 @@ metadata:
|
||||||
spec:
|
spec:
|
||||||
secrets:
|
secrets:
|
||||||
scopes:
|
scopes:
|
||||||
- storeName: "vault"
|
- storeName: "localSecretStore"
|
||||||
defaultAccess: "deny"
|
defaultAccess: "deny"
|
||||||
allowedSecrets: ["movie",]
|
allowedSecrets: ["redisPassword"]
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
version: '2'
|
|
||||||
services:
|
|
||||||
hashicorp_vault:
|
|
||||||
image: vault
|
|
||||||
ports:
|
|
||||||
- "8200:8200"
|
|
||||||
cap_add:
|
|
||||||
- IPC_LOCK
|
|
||||||
environment:
|
|
||||||
VAULT_DEV_ROOT_TOKEN_ID: "myroot"
|
|
|
@ -0,0 +1 @@
|
||||||
|
{}
|
|
@ -0,0 +1,14 @@
|
||||||
|
apiVersion: dapr.io/v1alpha1
|
||||||
|
kind: Component
|
||||||
|
metadata:
|
||||||
|
name: localSecretStore
|
||||||
|
spec:
|
||||||
|
type: secretstores.local.file
|
||||||
|
version: v1
|
||||||
|
metadata:
|
||||||
|
- name: secretsFile
|
||||||
|
value: "./components/secret.json"
|
||||||
|
- name: nestedSeparator
|
||||||
|
value: ":"
|
||||||
|
- name: multiValued
|
||||||
|
value: "true"
|
|
@ -1,16 +0,0 @@
|
||||||
apiVersion: dapr.io/v1alpha1
|
|
||||||
kind: Component
|
|
||||||
metadata:
|
|
||||||
name: vault
|
|
||||||
spec:
|
|
||||||
type: secretstores.hashicorp.vault
|
|
||||||
version: v1
|
|
||||||
metadata:
|
|
||||||
- name: vaultAddr
|
|
||||||
value: "http://127.0.0.1:8200"
|
|
||||||
- name: skipVerify
|
|
||||||
value : true
|
|
||||||
- name: vaultTokenMountPath
|
|
||||||
value : ".hashicorp_vault_token"
|
|
||||||
- name: vaultKVPrefix
|
|
||||||
value : "dapr"
|
|
|
@ -1,10 +0,0 @@
|
||||||
version: '2'
|
|
||||||
services:
|
|
||||||
hashicorp_vault:
|
|
||||||
image: vault
|
|
||||||
ports:
|
|
||||||
- "8200:8200"
|
|
||||||
cap_add:
|
|
||||||
- IPC_LOCK
|
|
||||||
environment:
|
|
||||||
VAULT_DEV_ROOT_TOKEN_ID: "myroot"
|
|
|
@ -116,13 +116,6 @@
|
||||||
<artifactId>json-path</artifactId>
|
<artifactId>json-path</artifactId>
|
||||||
<version>2.4.0</version>
|
<version>2.4.0</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<!-- This is need for us to programmatically add secrets in integration tests. -->
|
|
||||||
<groupId>com.bettercloud</groupId>
|
|
||||||
<artifactId>vault-java-driver</artifactId>
|
|
||||||
<version>5.1.0</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.projectreactor</groupId>
|
<groupId>io.projectreactor</groupId>
|
||||||
|
|
|
@ -13,12 +13,12 @@ limitations under the License.
|
||||||
|
|
||||||
package io.dapr.it.secrets;
|
package io.dapr.it.secrets;
|
||||||
|
|
||||||
import com.bettercloud.vault.Vault;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.bettercloud.vault.VaultConfig;
|
|
||||||
import io.dapr.client.DaprClient;
|
import io.dapr.client.DaprClient;
|
||||||
import io.dapr.client.DaprClientBuilder;
|
import io.dapr.client.DaprClientBuilder;
|
||||||
import io.dapr.it.BaseIT;
|
import io.dapr.it.BaseIT;
|
||||||
import io.dapr.it.DaprRun;
|
import io.dapr.it.DaprRun;
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
|
@ -26,9 +26,11 @@ import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.junit.runners.Parameterized;
|
import org.junit.runners.Parameterized;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
@ -37,28 +39,28 @@ import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test Secrets Store APIs using Harshicorp's vault.
|
* Test Secrets Store APIs using local file.
|
||||||
*
|
*
|
||||||
* 1. Start harshicorp vault locally:
|
* 1. create secret file locally:
|
||||||
* docker run --cap-add=IPC_LOCK -e 'VAULT_DEV_ROOT_TOKEN_ID=myroot' --name=dev-vault -p 8200:8200 -d vault
|
|
||||||
* 2. Create token file (path defined in integration test's vault.yaml):
|
|
||||||
* echo myroot > /tmp/.hashicorp_vault_token
|
|
||||||
*/
|
*/
|
||||||
@RunWith(Parameterized.class)
|
@RunWith(Parameterized.class)
|
||||||
public class SecretsClientIT extends BaseIT {
|
public class SecretsClientIT extends BaseIT {
|
||||||
|
|
||||||
private static final String LOCAL_VAULT_ADDRESS = "http://127.0.0.1:8200";
|
/**
|
||||||
|
* JSON Serializer to print output.
|
||||||
|
*/
|
||||||
|
private static final ObjectMapper JSON_SERIALIZER = new ObjectMapper();
|
||||||
|
|
||||||
private static final String LOCAL_VAULT_TOKEN = "myroot";
|
private static final String SECRETS_STORE_NAME = "localSecretStore";
|
||||||
|
|
||||||
private static final String PREFIX = "dapr";
|
private static final String LOCAL_SECRET_FILE_PATH = "./components/secret.json";
|
||||||
|
|
||||||
private static final String SECRETS_STORE_NAME = "vault";
|
private static final String KEY1 = UUID.randomUUID().toString();
|
||||||
|
|
||||||
|
private static final String KYE2 = UUID.randomUUID().toString();
|
||||||
|
|
||||||
private static DaprRun daprRun;
|
private static DaprRun daprRun;
|
||||||
|
|
||||||
private static Vault vault;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parameters for this test.
|
* Parameters for this test.
|
||||||
* Param #1: useGrpc.
|
* Param #1: useGrpc.
|
||||||
|
@ -70,20 +72,21 @@ public class SecretsClientIT extends BaseIT {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Parameterized.Parameter
|
@Parameterized.Parameter
|
||||||
public boolean useGrpc;
|
public boolean useGrpc = true;
|
||||||
|
|
||||||
private DaprClient daprClient;
|
private DaprClient daprClient;
|
||||||
|
|
||||||
|
private static File localSecretFile;
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void init() throws Exception {
|
public static void init() throws Exception {
|
||||||
daprRun = startDaprApp(SecretsClientIT.class.getSimpleName(), 5000);
|
|
||||||
|
|
||||||
VaultConfig vaultConfig = new VaultConfig()
|
localSecretFile = new File(LOCAL_SECRET_FILE_PATH);
|
||||||
.address(LOCAL_VAULT_ADDRESS)
|
boolean existed = localSecretFile.exists();
|
||||||
.token(LOCAL_VAULT_TOKEN)
|
assertTrue(existed);
|
||||||
.prefixPath(PREFIX)
|
initSecretFile();
|
||||||
.build();
|
|
||||||
vault = new Vault(vaultConfig);
|
daprRun = startDaprApp(SecretsClientIT.class.getSimpleName(), 5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
|
@ -100,38 +103,29 @@ public class SecretsClientIT extends BaseIT {
|
||||||
@After
|
@After
|
||||||
public void tearDown() throws Exception {
|
public void tearDown() throws Exception {
|
||||||
daprClient.close();
|
daprClient.close();
|
||||||
|
clearSecretFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getSecret() throws Exception {
|
public void getSecret() throws Exception {
|
||||||
String key = UUID.randomUUID().toString();
|
|
||||||
String attributeKey = "title";
|
|
||||||
String attributeValue = "The Metrics IV";
|
|
||||||
writeSecret(key, attributeKey, attributeValue);
|
|
||||||
|
|
||||||
Map<String, String> data = daprClient.getSecret(SECRETS_STORE_NAME, key).block();
|
Map<String, String> data = daprClient.getSecret(SECRETS_STORE_NAME, KEY1).block();
|
||||||
assertEquals(1, data.size());
|
assertEquals(2, data.size());
|
||||||
assertEquals("The Metrics IV", data.get("title"));
|
assertEquals("The Metrics IV", data.get("title"));
|
||||||
|
assertEquals("2020", data.get("year"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getBulkSecret() throws Exception {
|
public void getBulkSecret() throws Exception {
|
||||||
String key1 = UUID.randomUUID().toString();
|
|
||||||
writeSecret(key1, new HashMap<>() {{
|
|
||||||
put("title", "The Metrics IV");
|
|
||||||
put("year", "2020");
|
|
||||||
}});
|
|
||||||
String key2 = UUID.randomUUID().toString();
|
|
||||||
writeSecret(key2, "name", "Jon Doe");
|
|
||||||
|
|
||||||
Map<String, Map<String, String>> data = daprClient.getBulkSecret(SECRETS_STORE_NAME).block();
|
Map<String, Map<String, String>> data = daprClient.getBulkSecret(SECRETS_STORE_NAME).block();
|
||||||
// There can be other keys from other runs or test cases, so we are good with at least two.
|
// There can be other keys from other runs or test cases, so we are good with at least two.
|
||||||
assertTrue(data.size() >= 2);
|
assertTrue(data.size() >= 2);
|
||||||
assertEquals(2, data.get(key1).size());
|
assertEquals(2, data.get(KEY1).size());
|
||||||
assertEquals("The Metrics IV", data.get(key1).get("title"));
|
assertEquals("The Metrics IV", data.get(KEY1).get("title"));
|
||||||
assertEquals("2020", data.get(key1).get("year"));
|
assertEquals("2020", data.get(KEY1).get("year"));
|
||||||
assertEquals(1, data.get(key2).size());
|
assertEquals(1, data.get(KYE2).size());
|
||||||
assertEquals("Jon Doe", data.get(key2).get("name"));
|
assertEquals("Jon Doe", data.get(KYE2).get("name"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = RuntimeException.class)
|
@Test(expected = RuntimeException.class)
|
||||||
|
@ -144,12 +138,26 @@ public class SecretsClientIT extends BaseIT {
|
||||||
daprClient.getSecret("unknownStore", "unknownKey").block();
|
daprClient.getSecret("unknownStore", "unknownKey").block();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void writeSecret(String secretName, String key, String value) throws Exception {
|
private static void initSecretFile() throws Exception {
|
||||||
writeSecret(secretName, Collections.singletonMap(key, value));
|
Map<String, Object> key2 = new HashMap(){{
|
||||||
|
put("name", "Jon Doe");
|
||||||
|
}};
|
||||||
|
Map<String, Object> key1 = new HashMap(){{
|
||||||
|
put("title", "The Metrics IV");
|
||||||
|
put("year", "2020");
|
||||||
|
}};
|
||||||
|
Map<String, Map<String, Object>> secret = new HashMap<>(){{
|
||||||
|
put(KEY1, key1);
|
||||||
|
put(KYE2, key2);
|
||||||
|
}};
|
||||||
|
try (FileOutputStream fos = new FileOutputStream(localSecretFile)) {
|
||||||
|
JSON_SERIALIZER.writeValue(fos, secret);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void writeSecret(String secretName, Map<String, Object> secrets) throws Exception {
|
private static void clearSecretFile() throws IOException {
|
||||||
vault.logical().write("secret/" + PREFIX + "/" + secretName, secrets);
|
try (FileOutputStream fos = new FileOutputStream(localSecretFile)) {
|
||||||
|
IOUtils.write("{}", fos);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue