diff options
| author | Stuart Clark <stuart.clark@Jahingo.com> | 2017-08-06 03:20:34 +0100 |
|---|---|---|
| committer | Dave Henderson <dhenderson@gmail.com> | 2017-08-05 22:20:34 -0400 |
| commit | 7a16088eeb7490977a41390ec93e9eeafa2eec8b (patch) | |
| tree | 4fa21358ee0e4b6c7bc326fe7040d17157eae576 | |
| parent | be871892fb11fcf13f882da9cfa074cafbcc7c39 (diff) | |
Vault write support (#183)
* Add write support for Vault to enable the use of dynamic secrets
| -rw-r--r-- | data.go | 29 | ||||
| -rw-r--r-- | docs/content/functions/general.md | 10 | ||||
| -rw-r--r-- | test/integration/datasources_vault.bats | 19 | ||||
| -rw-r--r-- | vault/vault.go | 14 |
4 files changed, 70 insertions, 2 deletions
@@ -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 +} |
