summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStuart Clark <stuart.clark@Jahingo.com>2017-08-06 03:20:34 +0100
committerDave Henderson <dhenderson@gmail.com>2017-08-05 22:20:34 -0400
commit7a16088eeb7490977a41390ec93e9eeafa2eec8b (patch)
tree4fa21358ee0e4b6c7bc326fe7040d17157eae576
parentbe871892fb11fcf13f882da9cfa074cafbcc7c39 (diff)
Vault write support (#183)
* Add write support for Vault to enable the use of dynamic secrets
-rw-r--r--data.go29
-rw-r--r--docs/content/functions/general.md10
-rw-r--r--test/integration/datasources_vault.bats19
-rw-r--r--vault/vault.go14
4 files changed, 70 insertions, 2 deletions
diff --git a/data.go b/data.go
index 6ecb5e53..7f41d2ec 100644
--- a/data.go
+++ b/data.go
@@ -321,12 +321,37 @@ func readVault(source *Source, args ...string) ([]byte, error) {
addCleanupHook(source.VC.Logout)
}
+ params := make(map[string]interface{})
+
p := source.URL.Path
+
+ for key, val := range source.URL.Query() {
+ params[key] = strings.Join(val, " ")
+ }
+
if len(args) == 1 {
- p = p + "/" + args[0]
+ parsed, err := url.Parse(args[0])
+ if err != nil {
+ return nil, err
+ }
+
+ if parsed.Path != "" {
+ p = p + "/" + parsed.Path
+ }
+
+ for key, val := range parsed.Query() {
+ params[key] = strings.Join(val, " ")
+ }
}
- data, err := source.VC.Read(p)
+ var data []byte
+ var err error
+
+ if len(params) > 0 {
+ data, err = source.VC.Write(p, params)
+ } else {
+ data, err = source.VC.Read(p)
+ }
if err != nil {
return nil, err
}
diff --git a/docs/content/functions/general.md b/docs/content/functions/general.md
index d04e8cc6..8a8802a1 100644
--- a/docs/content/functions/general.md
+++ b/docs/content/functions/general.md
@@ -627,6 +627,16 @@ $ echo 'db_password={{(datasource "vault" "db/pass").value}}' \
db_password=prodsecret
```
+It is also possible to use dynamic secrets by using the write capibility of the datasource. To use
+add an additional query string style section to the optional key name (i.e.
+`"key?name=value&name=value"`). These values are then included within the JSON body of the request.
+
+```console
+$ echo 'otp={{(datasource "vault" "ssh/creds/test?ip=10.1.2.3&username=user").key}}' \
+ | gomplate -d vault=vault:///
+otp=604a4bd5-7afd-30a2-d2d8-80c4aebc6183
+```
+
## `datasourceExists`
Tests whether or not a given datasource was defined on the commandline (with the
diff --git a/test/integration/datasources_vault.bats b/test/integration/datasources_vault.bats
index 08c5b61e..e4fa6b1e 100644
--- a/test/integration/datasources_vault.bats
+++ b/test/integration/datasources_vault.bats
@@ -29,6 +29,7 @@ function teardown () {
vault auth-disable app-id2
vault policy-delete writepol
vault policy-delete readpol
+ vault unmount ssh
}
@test "Testing token vault auth" {
@@ -121,6 +122,24 @@ function teardown () {
[[ "${output}" == "$BATS_TEST_DESCRIPTION" ]]
}
+@test "Testing vault auth with dynamic secret" {
+ vault mount ssh
+ vault write ssh/roles/test key_type=otp default_user=user cidr_list=10.0.0.0/8
+ VAULT_TOKEN=$(vault token-create -format=json -policy=writepol -use-limit=2 -ttl=1m | jq -j .auth.client_token)
+ VAULT_TOKEN=$VAULT_TOKEN gomplate -d vault=vault:/// -i '{{(datasource "vault" "ssh/creds/test?ip=10.1.2.3&username=user").ip}}'
+ [ "$status" -eq 0 ]
+ [[ "${output}" == "10.1.2.3" ]]
+}
+
+@test "Testing vault auth with dynamic secret using prefix" {
+ vault mount ssh
+ vault write ssh/roles/test key_type=otp default_user=user cidr_list=10.0.0.0/8
+ VAULT_TOKEN=$(vault token-create -format=json -policy=writepol -use-limit=2 -ttl=1m | jq -j .auth.client_token)
+ VAULT_TOKEN=$VAULT_TOKEN gomplate -d vault=vault:///ssh/creds/test -i '{{(datasource "vault" "?ip=10.1.2.3&username=user").ip}}'
+ [ "$status" -eq 0 ]
+ [[ "${output}" == "10.1.2.3" ]]
+}
+
# TODO: test the github auth backend at some point... this needs a github token though, so...
# vault write auth/github/config organization=DockerOttawaMeetup
# vault write auth/github/map/teams/organizers value=pol
diff --git a/vault/vault.go b/vault/vault.go
index 20a259d8..3b18167f 100644
--- a/vault/vault.go
+++ b/vault/vault.go
@@ -55,3 +55,17 @@ func (v *Vault) Read(path string) ([]byte, error) {
}
return buf.Bytes(), nil
}
+
+func (v *Vault) Write(path string, data map[string]interface{}) ([]byte, error) {
+ secret, err := v.client.Logical().Write(path, data)
+ if err != nil {
+ return nil, err
+ }
+
+ var buf bytes.Buffer
+ enc := json.NewEncoder(&buf)
+ if err := enc.Encode(secret.Data); err != nil {
+ return nil, err
+ }
+ return buf.Bytes(), nil
+}