-
Notifications
You must be signed in to change notification settings - Fork 22
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[question] are vault credentials refreshed? #65
Comments
yes there is. see secret-config-cache-period |
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. |
the way I'd design this feature is:
|
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. |
@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. |
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. |
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? |
@vsevel I think the conversation link you share goes exactly in the same direction as the question I am posing.
@kdubb
|
correct. it is being used in the login use case, and dynamic credentials |
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. |
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. |
@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? |
@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. |
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. |
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. |
The confusion I was having initially is that none of this helps the KV case. |
apparently this is not fully working: #66 |
I'm gonna play with this today. I think renewing the lease automatically should be relatively simple. My only issue is that we might need a flag to determine if auto-renewal should happen or somehow base it on the type of credentials. I'm concerned about a situations where a consumer might request a "one off" set of credentials (e.g. migration?) that shouldn't be auto-renewed until the app exits. |
As it stands, the "one-off" scenario might not be a huge deal because Quarkus's dynamic credentials support is based around long-lived credentials. |
@raffaelespazzoli may be to get out of the generalities, may be we could focus on a particular use case that is useful to you. what would it be? |
@vsevel I think it would be enabling the use case with the data base / datasource credentials obtained via Vault. So understating when Vault is suggesting to refresh the credentials and having a way to roll out a new set of connections within a connection pool which use the new set of credentials. Ideally the rollout is incremental, that is: a new connection is created then an old one that is not being used is removed. and so on until no more old connection exists. This would minimize the impact to the code. |
@raffaelespazzoli I am just wondering how much this discussion is relevant to the vault extension vs agroal. |
What do you see as the issue with renewing expiring credentials automatically in the vault extension? If we think this is a worthy change over current behavior, then we're either going to implement it once in the extension or have every client implement it themselves. |
don't we need the connection pool to expire the connection and recreate it? or may be we can just extend the lease? is this what we are talking about? |
cc @barreiro |
I actually forgot the reason I added expires-at was because the RabbitMQ library supports expiring credentials itself. For that implementation it needs to know when the vended credentials expire. It recreates the connection exactly as we are talking about.
I'm talking about extending the lease. The current implementation already extends the lease falling back to creating new credentials when it cannot do that. The nice thing about this there is no connection expiration required. Vault won't update/delete the credentials as long as we extend the leases. |
Additionally, with auto-renewal in the extension, we could possibly treat all requests for credentials as a "create". E.g. Any configured connection expiration in connections pools would ask for new credentials on each new connection. This would ensure fresh credentials for correctly configured pools but allow other non-expiring configurations to work without changes. |
The only case this would be true is if lease renewal fails. Which I guess we have to think about. |
I guess I do not see the flow entirely. can we create a connection, add it to the pool and use it forever (e.g. for a longer time than the max-ttl on vault)? |
According to the docs, leases can be renewed forever.
So we should be able to extend the leases indefinitely. Also, reading through that made me realize we should be revoking our authentication token on shutdown, which will in turn revoke all leases issues with it immediately. |
|
Well the docs specifically use the phrase "valid for eternity" 🤷♂️... It's pretty easy to test though. If leases cannot be extended indefinitely then this discussion is moot. If credentials are required to be invalidated then the connection pools have to check in periodically to get new credentials, which is the current behavior. |
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. |
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. |
@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. |
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. |
I'm fairly sure this is not true. Renewing a lease is done via |
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;"
|
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
|
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. |
@vsevel One thing to notice is that you can't trust the |
@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. |
@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. |
@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. |
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
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.
The text was updated successfully, but these errors were encountered: