hashicorp / vault

A tool for secrets management, encryption as a service, and privileged access management
https://www.vaultproject.io/
Other
31.23k stars 4.21k forks source link

Allow API client to read token from file #11270

Open JasonN3 opened 3 years ago

JasonN3 commented 3 years ago

Is your feature request related to a problem? Please describe. This is related to https://github.com/hashicorp/boundary/issues/987 When Boundary connects to Transit it uses https://github.com/hashicorp/go-kms-wrapping, which uses the api client in this repo. As of right now, the only way to access the token is to include it in the configuration file or set it as an environment variable. If you are using Boundary within Kubernetes and using the Vault Agent sidecar to generate/manage the token, the environment variable isn't available and it's excessive to need to rewrite the configuration file.

Describe the solution you'd like I would like if the API client could read the token from a file. At that point, I could point the configuration to that file and it would be able to read the token that the sidecar generated. In addition, the lifetime watcher could be modified so if there's a token file, it will re-read the file whenever the token expires. That way when the token reaches its max TTL and the sidecar generates a new token, it is automatically read in.

Describe alternatives you've considered After digging through the code, it doesn't make sense for this to be a modification to Boundary since that project doesn't interact with Transit directly. This feature could be in go-kms-wrapping, however, it makes more sense for it to be a feature of the api client itself. If it was added to go-kms-wrapping, they would need to write their own lifetime watcher to re-read the file. Putting it in the api client just means adding a condition around line 280 of https://github.com/hashicorp/vault/blob/master/api/lifetime_watcher.go that will check if a token file was used and then re-read the file instead of calling renewFunc.

Explain any additional use-cases This will allow the token to be managed by the vault agent sidecar and it will allow the token to change without restarting the application that is using the API.

Once this feature is added to the API client, I'll submit a feature request with go-kms-wrapping to update their use of the API client.

jefferai commented 3 years ago

See https://github.com/hashicorp/boundary/blob/main/internal/cmd/config/config.go#L368 -- it'd probably be good to move that into shared-secure-libs (please coordinate with Boundary on this), then it can easily be read directly, or from a file or env var. cc @briankassouf

briankassouf commented 3 years ago

How about a client.SetTokenSource(string) function that accepts a file:// or env:// string that @jefferai linked to?

JasonN3 commented 3 years ago

Creating a client.SetTokenSource(string) function to store the source could work. You could then internally call ParseAddress whenever the token needs to be refreshed.

jefferai commented 3 years ago

FWIW given that no actual tokens would start with file:// or env:// I think you don't need a separate function. SetToken could just call ParseAddress.

JasonN3 commented 3 years ago

@jefferai, that is an option as well. You would need to modify ParseAddress so it returns whether it found an address so you know whether it's a source or a token since the lifetime watcher will need to treat them differently. Alternatively, you could check if the returned token is the same as the input, which would also tell you if it's a source or a token.

jefferai commented 3 years ago

It already does this -- if what's come in is not a URL, it returns the same string back (after trimming) and ErrNotAUrl.

JasonN3 commented 3 years ago

Nice catch. I overlooked those lines and was looking at the return at the bottom of the function with a nil error.

You could use that error to determine whether the lifetime watcher should reload the source or renew the token.