Your application needs a TOKEN
in order to access your Vault server. How do you get the TOKEN
to the application server?
From here on we will be calling your Vault-server-in-the-cloud simply 'Vault'
Vault is a tool for managing secrets. Vault act as a key/value store where the keys are paths and the values are dictionaries written at those paths. Vault allows for auditing, roles, authentication, and much more.
Vault application access your secrets through a TOKEN
. A TOKEN
is built from a tuple of (ROLE_ID, SECRET_NONCE)
. You likely have a single ROLE_ID
per application. Your SECRET_NONCE
is a cryptographic nonce that is exchanged with the ROLE_ID
to get a TOKEN
. As a nonce, your SECRET_NONCE
may only be exchanged for a TOKEN
at most one time.
Once you application has a TOKEN
it may then make request to your Vault server. A TOKEN
will expire N
minutes from its last refresh or initialization. So to keep a TOKEN
valid, the application will need to tell Vault at least once every N minutes to refresh (extend) the TOKEN
. Your Token will always have a lifetime of (last refresh time) + N
. If your server goes down, the TOKEN
will soon expire as the application will no longer extend the TOKEN
lifetime.
We have all done it, it is not a good idea. There definitely should be no secrets in your source code. Secrets in your source code means you cannot share your code without a full audit. Ugh
Environment variables are better. It still requires that you ask questions about what secrets exist at what locations when you are considering your infrastructure. Contrast this to having secrets in one place (Vault). If you are considering Vault then you have likely decided that environment variables are not a good enough solution, so I will not spend any more time attacking them.
TOKEN
as part of your deploymentThe equivalent of putting ALL your secrets in your application. Anyone who gets access to the TOKEN
(through source or environment variables) can access Vault as the application.
(ROLE_ID,SECRET_NONCE)
as part of your deploymentThis is sound under some strictly ordered conditions. We must be certain that the application is the first to exchange (ROLE_ID, SECRET_NONCE)
for the TOKEN
. Because SECRET_NONCE
is a nonce, we don't need to worry about subsequent request, only the first one wins. However, if Alice is able to get the SECRET_NONCE
and exchange it for a TOKEN
before our application, Alice would now have access to all of the applications secrets. Dependent order in security does not sound like a good idea.
(ROLE_ID,SECRET_NONCE)
in a application endpointAfter deployment of your app, call an endpoint on it and pass in a (ROLE_ID,SECRET_NONCE)
. Your application will then exchange your (ROLE_ID,SECRET_NONCE)
for a TOKEN
. This alleviates the timing concerns of the previous solution while still having zero secrets in code or environment variables. This endpoint can be entirely open. Vault will refuse to provide a TOKEN
for a (ROLE_ID, SECRET_NONCE)
that it did not issue.
I have written a demo project that implements a (ROLE_ID,SECRET_NONCE)
endpoint. After the very first deployment of the app, it requires that you "light the pilot light" by posting a (ROLE_ID, SECRET_NONCE)
that may be use to access Vault. So, the steps are.
/vault
with your (ROLE_ID, SECRET_NONCE)
.TOKEN
, make another curl POST request with a new secret, expire the old TOKEN
.Instructions are provided in the README.