gomplate icon indicating copy to clipboard operation
gomplate copied to clipboard

Support Vault's secrets engine v2

Open jbialy opened this issue 4 years ago • 19 comments

Currently the vault datasource will not work with v2 version of Vault's secret engine. Extending the datasource to support this would allow for the use of versioned secrets!

https://www.vaultproject.io/api/secret/kv/kv-v2

jbialy avatar Jun 04 '20 14:06 jbialy

I second this request and would be glad to help if any is needed.

McShauno avatar Jun 08 '20 13:06 McShauno

@McShauno thanks! Any help would be appreciated 🙂

I suppose the big question is how do we determine which kv version to use? Also it's a bit unclear if the Go client is any different between v1/v2 - I suspect the path is meant to be the API path, not the CLI path (for v2, the API path is /secret/data/foo, whereas for the CLI, and for v1 it's just /secret/foo).

In fact, it could work with kv v2 right now if you just use /secret/data/foo instead of /secret/foo 🤔... But that's also clearly not the best user interface.

hairyhenderson avatar Jun 09 '20 13:06 hairyhenderson

@hairyhenderson I think getting exact version is only missing, as getting latest version of v2 secret can be done even now:

gomplate --version
gomplate version 3.7.0
vault --version
Vault v1.4.2
  1. start vault in dev mode (with k/v "secrets" engine enabled by default)
VAULT_DEV_ROOT_TOKEN_ID="root-token" vault server -dev
  1. create secret with vault binary
VAULT_DEV_ROOT_TOKEN_ID="root-token" VAULT_ADDR="http://localhost:8200" vault kv put secret/foo/bar/baz hello=world
Key              Value
---              -----
created_time     2020-06-10T20:05:10.00293551Z
deletion_time    n/a
destroyed        false
version          1
  1. get secret with vault binary
VAULT_DEV_ROOT_TOKEN_ID="root-token" VAULT_ADDR="http://localhost:8200" vault kv get secret/foo/bar/baz
====== Metadata ======
Key              Value
---              -----
created_time     2020-06-10T20:05:10.00293551Z
deletion_time    n/a
destroyed        false
version          1

==== Data ====
Key      Value
---      -----
hello    world
  1. get secret with gomplate
VAULT_TOKEN="root-token" VAULT_ADDR="http://localhost:8200" gomplate --datasource vault=vault:// -i '{{ (datasource "vault" "secret/data/foo/bar/baz").data.hello }}'
world

But what would be really nice, if one could select exact version of secret:

VAULT_DEV_ROOT_TOKEN_ID="root-token" VAULT_ADDR="http://localhost:8200" vault kv put secret/foo/bar/baz hello=doot
Key              Value
---              -----
created_time     2020-06-10T20:16:18.559436096Z
deletion_time    n/a
destroyed        false
version          2

VAULT_DEV_ROOT_TOKEN_ID="root-token" VAULT_ADDR="http://localhost:8200" vault kv get secret/foo/bar/baz
====== Metadata ======
Key              Value
---              -----
created_time     2020-06-10T20:16:18.559436096Z
deletion_time    n/a
destroyed        false
version          2

==== Data ====
Key      Value
---      -----
hello    doot
VAULT_TOKEN="root-token" VAULT_ADDR="http://localhost:8200" gomplate --datasource vault=vault:// -i '{{ (datasource "vault" "secret/data/foo/bar/baz").data.hello }}'                                                                                                                             
doot

Basically looking for gomplate equivalent of

VAULT_DEV_ROOT_TOKEN_ID="root-token" VAULT_ADDR="http://localhost:8200" vault kv get -version=1 secret/foo/bar/baz 
====== Metadata ======
Key              Value
---              -----
created_time     2020-06-10T20:12:37.876472509Z
deletion_time    n/a
destroyed        false
version          1

==== Data ====
Key      Value
---      -----
hello    world

With current implementation of vault datasource, query parameters will invoke PUT request

VAULT_TOKEN="root-token" VAULT_ADDR="http://localhost:8200" gomplate --datasource vault=vault:// -i '{{ (datasource "vault" "secret/data/foo/bar/baz?version=1").data.hello }}'

22:19:54 FTL  error="template: <arg>:1:4: executing \"<arg>\" at <datasource \"vault\" \"secret/data/foo/bar/baz?version=1\">: error calling datasource: Couldn't read datasource 'vault': Error making API request.\n\nURL: PUT http://localhost:8200/v1/secret/data/foo/bar/baz\nCode: 400. Errors:\n\n* no data provided"

Vault API reference for getting exact version of v2 secret: https://www.vaultproject.io/api/secret/kv/kv-v2.html#read-secret-version

petrjurasek avatar Jun 10 '20 20:06 petrjurasek

@petrjurasek I'm not sure if this'll work, but maybe try this instead:

VAULT_TOKEN="root-token" VAULT_ADDR="http://localhost:8200" gomplate --datasource 'vault=vault://?version=1' -i '{{ (datasource "vault" "secret/data/foo/bar/baz").data.hello }}'

If neither of those work (and they should be equivalent), then I think the key is to just handle the version query parameter properly.

hairyhenderson avatar Jun 10 '20 20:06 hairyhenderson

@hairyhenderson - same result

VAULT_TOKEN="root-token" VAULT_ADDR="http://localhost:8200" gomplate --datasource 'vault=vault://?version=1' -i '{{ (datasource "vault" "secret/data/foo/bar/baz").data.hello }}'

06:08:13 FTL  error="template: <arg>:1:4: executing \"<arg>\" at <datasource \"vault\" \"secret/data/foo/bar/baz\">: error calling datasource: Couldn't read datasource 'vault': Error making API request.\n\nURL: PUT http://localhost:8200/v1/secret/data/foo/bar/baz\nCode: 400. Errors:\n\n* no data provided"

petrjurasek avatar Jun 13 '20 04:06 petrjurasek

Thanks @petrjurasek, that makes sense.

Looks like adding the version param is causing the PUT API to be used which isn't quite what we want. Also I'd really rather not have to use the API path, since it's different than what would be provided to vault kv get.

I'll try and find some time this weekend to dig into this a bit more.

hairyhenderson avatar Jun 13 '20 16:06 hairyhenderson

We have been using gomplate for several years now and it has been working great. We too have a need to use v2 of the secrets engine to be able to version secrets. Looks like this request has gone a bit stale.

carltonmason avatar Jun 02 '21 19:06 carltonmason

Thanks for the bump @carltonmason - indeed this has gone stale... I'd love if someone could take this on if possible! 🙂

hairyhenderson avatar Jun 03 '21 20:06 hairyhenderson

@hairyhenderson any hints where to start digging in the code?

I guess the PUT method is part of gomplate(?) logic, rather than vault library itself.

petrjurasek avatar Jun 22 '21 19:06 petrjurasek

Also found this might be helpful to determine version of kv

https://github.com/hashicorp/vault/blob/v1.7.3/command/kv_helpers.go#L99

petrjurasek avatar Jun 22 '21 20:06 petrjurasek

Probably relevant to this whole discussion: at some point I'll be updating gomplate to use my new go-fsimpl library for datasource support.

Currently go-fsimpl is missing Vault support however, and I've been working on it for a little while (still a few days from a PR for it though).

hairyhenderson avatar Jun 26 '21 23:06 hairyhenderson

@hairyhenderson, would be happy about KV2 support also - we have a mixed Vault setup with multiple tenant spaces in there and some have KV1, others have already KV2. The secrets are used for K8S deployments in multiple stages/branches and with Gomplate we were able to reduce the complexity dramatically :) Thank you for this nice templating engine!

pkovtunov avatar Jul 21 '21 13:07 pkovtunov

Currently go-fsimpl is missing Vault support however, and I've been working on it for a little while (still a few days from a PR for it though).

Update: go-fsimpl just got Vault support, though it doesn't yet support KV2 - that's tracked in https://github.com/hairyhenderson/go-fsimpl/issues/24.

I'm not totally opposed to KV2 support going into gomplate prior to moving to go-fsimpl, but I won't have the time to do that myself - I'll be focusing on the go-fsimpl support instead.

hairyhenderson avatar Oct 11 '21 16:10 hairyhenderson

I know I am a little late to the party, but for future reference: I found a way to use the v2 kv-engine with gomplate.

You have to add an extra "/data" between the name of the secret-engine (general) and the path of the secret (secretpath): gomplate -d vault=vault:///general/data/secretpath instead of gomplate -d vault=vault:///general/secretpath.

You can then use {{ (datasource "vault" ).data.keyinsidesecret }} in your templates. Notice the extra ".data" there. (In addition to .data there are also some other keys in the struct that may be interesting)

It's a bit strange, but seems to work just fine.

@hairyhenderson Maybe it would be worth it to add this piece of info to the documentation?

dbaumgarten avatar May 10 '22 11:05 dbaumgarten

Thanks @dbaumgarten - this is good information. Once kv2 is supported this will break, but it's at least worth noting with that caveat!

hairyhenderson avatar May 18 '22 12:05 hairyhenderson

Wouldn't it be possible do design the v2-support in a way that it at least emits a warning when it detects that you are using a (now broken) workaround. Looking for path's of the form "secretengine/data/*" should work well enough.

dbaumgarten avatar May 19 '22 12:05 dbaumgarten

@dbaumgarten perhaps? It wouldn't be as simple though... Besides, what if someone is using the literal prefix data/ in their path?

If it's documented (I am open to PRs for this!!), I think that's enough. If someone's done this workaround and things break with a future version of gomplate, it should be relatively obvious why.

hairyhenderson avatar May 20 '22 17:05 hairyhenderson

kv2 would be something that I'm interested in having. I haven't had a look in how to implement it though, not by any means a golang expert.

Perhaps looking at how chezmoi handles vault would be worthwhile?

dngray avatar Sep 01 '22 23:09 dngray

@dngray interesting! Never heard of chezmoi, thanks for the tip!

kv2 support will come probably in gomplate 4.0, when it moves to use go-fsimpl in the backend. I would accept a PR to document the workaround, as mentioned above 😉

hairyhenderson avatar Sep 02 '22 00:09 hairyhenderson

This issue is stale because it has been open for 60 days with no activity. Remove stale label or comment or this will be automatically closed in a few days.

github-actions[bot] avatar Apr 10 '23 04:04 github-actions[bot]

@hairyhenderson are you still considering this?

AndrewSav avatar Apr 10 '23 05:04 AndrewSav

Remove stale label or comment or this will be automatically closed in a few days.

I find it interesting that this issue is still marked stale, despite me commenting on it.

AndrewSav avatar Apr 10 '23 08:04 AndrewSav

Remove stale label or comment or this will be automatically closed in a few days.

I find it interesting that this issue is still marked stale, despite me commenting on it.

I think that's because the stale workflow only runs weekly (I can increase frequency though).

hairyhenderson avatar Apr 11 '23 16:04 hairyhenderson

@hairyhenderson are you still considering this?

Yep. My latest comment in https://github.com/hairyhenderson/gomplate/issues/862#issuecomment-1234936678 still stands.

To put it more concretely, #1336 will fix this issue.

hairyhenderson avatar Apr 11 '23 16:04 hairyhenderson

This issue is stale because it has been open for 60 days with no activity. Remove stale label or comment or this will be automatically closed in a few days.

github-actions[bot] avatar Jun 12 '23 04:06 github-actions[bot]

Go team ;)

AndrewSav avatar Jun 13 '23 09:06 AndrewSav

@hairyhenderson

I think that's because the stale workflow only runs weekly (I can increase frequency though).

This is quite unusual comparing to any other repo that does this. Hourly seems like a good schedule, some run every 5 minutes.

AndrewSav avatar Jun 13 '23 20:06 AndrewSav

I would still like to see this feature.

dngray avatar Jun 20 '23 15:06 dngray

Me too. I'm stalling on one of my projects for this feature.

zachfi avatar Jun 23 '23 01:06 zachfi

Thanks for commenting folks.

To re-iterate, this will be implemented by #1336. Once that makes it (which could very well take a while yet - I have limited time), this issue will auto-close.

I think that's because the stale workflow only runs weekly (I can increase frequency though). This is quite unusual comparing to any other repo that does this. Hourly seems like a good schedule, some run every 5 minutes.

I have a limited number of GitHub Actions minutes available to me per month, so I'm not really interested in running the workflow that often.

I have assigned this issue to a new v4.0.0 milestone, and configured the workflow to no longer consider milestone-assigned issues as stale.

In other words: rest assured - this one'll make it in to 4.0.

hairyhenderson avatar Jun 24 '23 16:06 hairyhenderson