How to use Hashicorp Vault's AppRole in production?
Asked Answered
N

4

9

We have installed and configured Hashicorp Vault AppRole authentication for one server, by storing the role_id and secret_id in a local file on the server, and we're able to have code on the server read the values from file, authenticate to Vault, receive a token and then read the secrets it needs from Vault. So far so good. However, the secret_id expires after 31 days, and so the process fails.

I've read up on the concepts of using AppRoles, and they seem like the perfect fit for our use case, but for this expiration. We don't want to have to re-generate the secret_id every month.

From what I've read, if you create the role without setting secret_id_ttl it should be non-expiring, but that isn't the case. This may be due to how the AppRole auth method is configured, but I haven't seen anything solid on this.

So I found an article on the Hashicorp website where AppRoles are discussed in detail. The article gives good arguments for expiring secret_id's in a CI/CD environment, even illustrating how this works in 8 simple steps. I understand how this works, but the article fails to mention how the CI/CD and Orchestrator systems themselves are authenticated to Vault? Or am I missing something?

In the end, I want to have the secret_id not expire. Ever.

Neeley answered 21/8, 2019 at 12:57 Comment(3)
I think the fundamental misunderstanding here is that Vault wants secrets to be dynamic -- meaning generated on-demand and short-lived for security purposes. If you don't want to rotate secrets frequently, Vault is not a good fit for that.Teleplay
No, you're not missing something! See Alan Thatcher's blog on approle authentication for a reasonable approach to the initial Vault authentication: blog.alanthatcher.io/vault-approle-authenticationOozy
Above link has gone stale, wayback machine to the rescue at web.archive.org/web/20200813074640/https://blog.alanthatcher.io/…Endorsed
A
3

Without additional support from your environment you will have to write some logic in your installer, and have a service manager of some sort to start your services. In many cloud environments, you may already have the equivalent entities (Terraform, Cloud Formation, etc.) and you should leverage their secrets management capabilities where needed.

For custom installations, here is a workflow that I have used.

  1. Have an installation manager process that can be invoked to perform installation / upgrade. Make sure installation / upgrade of services is always through this process.
  2. Have a service manager process that is responsible for starting individual services and monitoring them / restarting them. Make sure service start-ups are always via this service manager.
  3. During installation, generate self-signed certificates for Vault, installation manager and service manager. Vault certificates should trust the certs for the installation manager and the service manager. Store these with limited permission (600) in directories owned by the installation user or the service manager user as the case may be. Set up certificate-based authentication in Vault using these certs.
  4. These credentials should have limited capabilities associated with them. The installation manager should only be able to create new roles and not delete anything. The service manager should only be able to create secrets for the named roles created by the installation manager, and delete nothing.
  5. During installation / upgrade, the installation manager should connect to Vault and create all necessary service-specific roles. It should also be able to set role ids for individual services in per-service config files that the services may read on start-up.
  6. During each service's start-up, the service manager should connect to Vault and create secret ids corresponding to each service's role. It should set the secret id in an environment variable and start the service. The secret id should have time-bound validity (by setting TTLs) so that they cannot be used for much beyond the creation of the auth token (see #7).
  7. Each service should read the role id from the config file, and the secret id from the environment variable. It should then generate the auth token using these two, and use the token to authenticate itself with vault for its lifetime.
Absorber answered 16/12, 2019 at 3:24 Comment(1)
So basically this boils down to "use a long-lived cert as your root of trust" (for the installation and service managers)?Respirator
R
1

It is possible to create a Vault AppRole with a secret_id that essentially never expires. However, this should be limited to use on a Vault development server -- one that does not contain any production credentials -- and for use in a development environment.

That being said, here's the procedure I used based on several articles in the Vault documentation, but primarily AppRole Pull Authentication.

This assumes that the Vault approle authentication method is already installed at approle/ and that you are logged in to Vault, have root or admin privileges on the Vault server and have a valid, non-expired token.

Note: For the values supplied for the fields below, the maximum value that vault seems to accept is 999,999,999. For the TTL fields, that is the number of seconds which comes out to more than 31 years. That's not forever, but it is long enough that renewing the secret_id will probably be somebody else's problem (SEP).

# Vault server address to be used by the Vault CLI.

export VAULT_ADDR="https://vault-dev.example.com:8200/"

# Vault namespace to be used by the CLI. 
#   Required for Cloud and Enterprise editions
#   Not applicable for Open Source edition

export VAULT_NAMESPACE="admin"

# The name of the Vault AppRole

export VAULT_ROLE=my-approle

# Override defaults on the approle authentication method

#   NOTE: In this command, the field names, default-lease-ttl
#         and max-lease-ttl contain dashes ('-'), NOT 
#         underscores ('_'), and are preceded by a single
#         dash ('-').

vault auth tune \
  -default-lease-ttl=999999999 \
  -max-lease-ttl=999999999 approle/

# Override defaults on the approle

#   NOTE: In this command, the field names, secret_id_ttl and 
#         secret_id_num contain underscores ('_'), NOT
#         dashes ('-'), and are NOT preceded by a single
#         dash ('-'). 

vault write auth/approle/role/my-approle \
  secret_id_ttl=999999999 \
  secret_id_num_uses=999999999

# Create a new secret_id for the approle which uses the new defaults

vault write -f auth/approle/role/my-approle/secret-id

Update the server config file to use the new secret_id and you are ready to go.

Rajkot answered 21/7, 2021 at 13:39 Comment(0)
O
1

As the OP has noted, the Hashicorp Vault documentation assumes that the application is able to authenticate, somehow, to the vault and then retrieve the secret ID (possibly wrapped) from the vault and then, use that to authenticate and fetch a token used to actually work with secrets. The answers here are posing alternative approaches to retrieving that initial token.

Alan Thatcher wrote a blog article, Vault AppRole Authentication, that provides another well thought out approach:

  1. Create a policy that allows the user to retrieve the secret-id and role-id, but nothing else.
  2. Create a long lived, periodic/renewable token based on that policy.
  3. Store the long lived token securely, e.g. as a Kubernetes secret
  4. At runtime, use the long-lived token to:
    • acquire the secret-id and role-id,
    • authenticate to vault using these and acquire short-lived token
    • use current short-lived token to work with secrets

For Java applications, the Spring Vault project supports this approach if you configure the long-lived token as the "initial token" and the approle authencation name, e.g. chef-ro in the blog case.

My personal feeling is that this approach is about as secure but a bit simpler than the mutual TLS approach. I agree that using an infinite TTL for the secret-id is a less secure practice for Production environments.

Thanks to Mr. Thatcher for thinking this one through.

Oozy answered 5/12, 2022 at 18:22 Comment(2)
What's the practical justification that an ~infinite-lifespan token is more secure than an infinite TTL secret-id? I guess the token needs to be renewed, so if the process even shuts down for a while, it automatically loses value??Respirator
@AlexDehnert I take your point. The long lived role-id and secret-id values are perhaps comparable to client ID and secret in the OAuth2 Client Credentials flow.Oozy
L
0

This is probably not the canonnical answer, but I found it empty so decided to add some pointers.

As per Hashicorp Vault AppRole: role-id and secret-id:

Additional brownie information: Ideally, it's best practice to keep the TTL low, 30 minutes max - if your application is stateful, or maybe even less if it's a stateless application. The secret key of Vault approle should also be rotated every 90 days. Please note by default, Vault approle backend has 31 days of TTL, so if you want to set it to 90 days, you need to increase TTL of the approle backend as well.

However (in the same question):

You can generate secret-id with indefinite validity. But doing so will be as good as keeping your secrets in the configuration file.

For ephemeral instances you can use configuration management to pass in secrets via a third (broker) role. With regard to a server that exists indefinitely, i'm still working that out...

Ideas:

  • TLS certificates might work well on Windows, don't know about Linux.
  • GitHub Personal Access Tokens, but this is not org. friendly.
  • Review the other auth methods available to see if there's one that fits your requirements (e.g. AWS).
Liman answered 6/9, 2019 at 6:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.