Are vault credentials refreshed? #72
Replies: 47 comments 2 replies
-
yes there is. see secret-config-cache-period |
Beta Was this translation helpful? Give feedback.
-
no that property does not work. First, it's applied to only to a kv store (which arguably does not have the problem of short-lived credentials), secondly, it's secret store wide, while each secret can have a different TTL. Normally non-kv secret engines produce short lived credentials. As an example let's take the database/postgresql engine as featured in the quarkus guide for [dynamic credentials](https://quarkiverse.github.io/quarkiverse-docs/quarkus-vault/dev/vault-datasource.html#_dynamic_database_credentials.
the lease duration is 1h. The quarkus-vault library should be aware of that and schedule a refresh of this property in a bit less 1h. Beyond that time the credential will be revoked and attempting to connect/or run sql statements with a stale credentials will result in an error. |
Beta Was this translation helpful? Give feedback.
-
the way I'd design this feature is:
|
Beta Was this translation helpful? Give feedback.
-
This is not possible in Quarkus and would be an extremely complicated thing to attempt. Even in dev mode Quarkus is just restart, using the static build time config as the beginning state. Using your database example, Quarkus does expire the database credentials in the appropriate time but waits until the database driver requests the credentials again to perform the actual refresh. It's the database's job to disconnect the driver when credentials are stale, and they'll be refreshed if/when that happens. Given that... using a secret-config-cache-period smaller than your smallest KV temporary credential lease time will achieve nearly the exact same expiration functionality as we provide for "proper" temporary credentials. |
Beta Was this translation helpful? Give feedback.
-
@kdubb I'm a bit confused by your answer. I suggest to try to break the conversation into two pieces:
On the 1. Vault exposes a contract (it tells you when you should refresh) and I think the quarkus-vault plugin should honor that contract. |
Beta Was this translation helpful? Give feedback.
-
1 - With regard to propery temporary credentials, Vault tells you when the credentials expire not when to refresh. If a set of credentials expire, but are never needed again, what would be the use of refreshing them over and over as they expire each time? This Vault extension honors that contract properly. The extension will not allow the use of expired temporary credentials. Once they expire, any request for that set of credentials will trigger a refresh before the credentials are returned to the requestor. 1b - Vault's KV secrets are not expired based on a time-to-live or some equivalent lease duration. The KV2 engine doesn't report a lease duration at all for its entries see here and while the KV1 engine allowed setting a time-to-live and reported it as So, we are offering the best we can with regard to KV secrets and we are refreshing them periodically; which is all we can really do for them. 2 - Reloading a bean because a configuration value changed is not a Quarkus feature that I know of. Either way, support would be through Quarkus main not through this extension. |
Beta Was this translation helpful? Give feedback.
-
for what it is worth, here is a conversation we had with Luis with respect to caching credentials for the db use case. it is worth mentioning the renew-grace-period property as well. do you think something is still missing? |
Beta Was this translation helpful? Give feedback.
-
@vsevel I think the conversation link you share goes exactly in the same direction as the question I am posing.
@kdubb
|
Beta Was this translation helpful? Give feedback.
-
correct. it is being used in the login use case, and dynamic credentials |
Beta Was this translation helpful? Give feedback.
-
Vault itself operates exactly like It is your job to ensure your database connections are reconnecting often enough that your temporary credentials are refreshed or they will be forcefully terminated (if the database enforces that) and upon the reconnection they will receive new credentials. Many connection pools have a max connection lifetime to ensure your connections are reconnected at a regular interval. For example, we use pgBouncer and its With regard to RabbitMQ, which we also use (FYI, I made the Quarkus RabbitMQ connector and added Vault's temporary credential supports for it), it's the same situation. We cycle through connections quite regularly, way more often than the credentials. To my eyes, this is how it is supposed to work because that's how Vault works. |
Beta Was this translation helpful? Give feedback.
-
I am ignoring manual lease renewals here. A request for credentials from Vault automatically renews the lease on your current credentials, if they exist and are not expired, instead of creating new credentials. So essentially a request for renewed credentials is either a manual lease renewal or new credential creation in one request. |
Beta Was this translation helpful? Give feedback.
-
@raffaelespazzoli Would it be correct to say that what you are looking for is for the extension to allow you to request/create a set of credentials and have the extension keep renewing the leases proactively until either the application is terminated or the credentials are deleted from the extension. Is that a correct assessment? |
Beta Was this translation helpful? Give feedback.
-
@kdubb yes, but I'm open to options. There seems to be two approaches:
I think that ultimately both would work and if today 1. is what is supported so be it. Perhaps let's include some considerations in the docs about this issue so everyone is aware. Option 2. seems like a better experience for developers though. So, if technically possible, it would be perhaps worth investing in it. |
Beta Was this translation helpful? Give feedback.
-
I can see the appeal of (2) but it may require changes to the way other extensions work. With (1) you request credentials whenever you need them and they are always valid for that attempt. Nothing else needs to be done to ensure credentials expire; which is kind of how things work in general. For (2) some extensions would need to add calls to manually expire the credentials, lest they be refreshed for as long as the application is alive. |
Beta Was this translation helpful? Give feedback.
-
The appeal of (2) that I see currently is specifically for other users of RabbitMQ. Our app cycles connections fairly often, but that's a function of our app. RabbitMQ encourages a small number of very long lived connections. RabbitMQ doesn't generally use connection pools and doesn't have a connection lifetime to automatically cause stable reconnection. This use case would particularly benefit from an automatic lease renewal. |
Beta Was this translation helpful? Give feedback.
-
exactly. my understanding was that you get an object valid for some time (lease ttl), that you can extend up to a maximum (max ttl). at that point, you will not be able to extend it further, and you will be forced to go through the re-acquisition process. the same logic applies to the dynamic credentials. it does require the app to ask for credentials on a regular basis, and may be that is something we can do in a background thread. but if the purpose is to deactivate credentials after some max amount of time, it must be the responsibility for the app to know when to stop using the credentials and re-ask for them. so the pool has to honor the "expires-at" property that we provide through the quarkus credentials provider (the cheap solution is to configure a fixed recycle period smaller than the lease ttl on the pool, to make sure a call will be made in time to extend the lease). with the auto-extend, let's say that the lease ttl is 1 hour, and the max ttl is 1 day, we could extend automatically the credentials every hour, and let the pool expire its connections once a day, as opposed to every hour. I do agree with you @raffaelespazzoli that security teams want several extensions within a limited max ttl to force apps to go through re-acquisition. |
Beta Was this translation helpful? Give feedback.
-
I was under the impression I also agree that credentials should be short lived but I also see the value in refreshing the credentials automatically for clients that do not have that capability. This just may not be possible though. |
Beta Was this translation helpful? Give feedback.
-
@kdubb that depends on the secret engine. The database secret engine will mint new credentials every time a credentials are read (there is no way for it to know if it's a refresh to a new request). secret engines that create bearer tokens credentials such a jwt tokens also cannot be extended they have to be re-minted. |
Beta Was this translation helpful? Give feedback.
-
from what I remember and what I see in the code, no. if you approach the expiration time, you can renew/extend the lease. this will give a new expiration time, and again the flag after some time (when you approach the max ttl), this will give a new expiration time and that is why I think we could renew/extend on behalf of the app, but not go beyond the max ttl. |
Beta Was this translation helpful? Give feedback.
-
I'm fairly sure this is not true. Renewing a lease is done via |
Beta Was this translation helpful? Give feedback.
-
Credentials are not affected by lease renewals... verified in Vault. Generating new credentials with a read: $ vault read database/creds/readonly
The role verified in PG: $ docker exec learn-postgres psql -c "SELECT rolname FROM pg_roles;"
Renew the lease (notice it doesn't provide any new credentials): $ vault lease renew database/creds/readonly/$LEASE_ID
Same role still exists in PG: docker exec learn-postgres psql -c "SELECT rolname FROM pg_roles;"
|
Beta Was this translation helpful? Give feedback.
-
Max TTL is confirmed to be the maximum a lease can exist. Generate new credentials with a read (1m ttl and 2m max_ttl): vault read database/creds/readonly
Renew lease after 1m 19s: vault lease renew database/creds/readonly/kMFToBm8g8lI3jRpaeUBM6RR
|
Beta Was this translation helpful? Give feedback.
-
I don't think there's much to do in the We should document this better and maybe propose changes to Agroal & the Vert.x reactive clients. |
Beta Was this translation helpful? Give feedback.
-
@vsevel One thing to notice is that you can't trust the |
Beta Was this translation helpful? Give feedback.
-
@vsevel setting Agroal also has a way to flush connections that see an exception that is considered to be non-recoverable. As far as I can't tell, that is not triggered at the moment because a permission issue is not considered to be in that category. |
Beta Was this translation helpful? Give feedback.
-
@barreiro thanks for your input. the easiest solution (for the vault extension and quarkus) would be that the agroal credentials carry the expiration date, then the pool would be autonomous to handle the lifecycle of the connections. |
Beta Was this translation helpful? Give feedback.
-
@raffaelespazzoli in summary are you suggesting that the vault extension auto-extends automatically on behalf of the app any lease associated with all objects that were fetched by the app, without the app needing to interact the vault extension. |
Beta Was this translation helpful? Give feedback.
-
@raffaelespazzoli Quarkus now supports recycling connections in both Reactive and JDBC datasources. Setting one of: quarkus.datasource.reactive.max-lifetime=<some division of your Vault lease time>
quarkus.datasource.jdbc.max-lifetime=<some division of your Vault lease time> Currently this is the solution. FYI, there is a DX change I would like to PR in Quarkus soon, to attempt to automatically derive these settings from Vault's credentials data (which already passes the expiration). This is Quarkus change though, not a Vault change. |
Beta Was this translation helpful? Give feedback.
-
should this discussion be closed? |
Beta Was this translation helpful? Give feedback.
-
I found "pinning", closing the issue now that it's pinned in General |
Beta Was this translation helpful? Give feedback.
-
one of the most powerful feature of Vault is the idea of secret engines: component that generate new credentials for a subsystem that needs authentication. Normally these credentials are short lived. the kv secret engine is somewhat of an exception to this rule as the key value store have unlimited lifetime.
When reading a secret from a path backed by a secret engine, vault returns the associated TTL (lease duration).
does the
quarkus-vault
library honors this behavior?The expectation would be that as the TTL deadline approaches, the quarkus-vault library re-reads the secret (obtaining a new credential) and refreshes all of the beans using that property. This may involve some complicated logic in cases when for example the property are used by a datasource.
Beta Was this translation helpful? Give feedback.
All reactions