PlayFab/consuldotnet

Setting token after creating client

Closed this issue · 6 comments

We are using consul in a singleton context in our IOC container. I am trying to move to dynamic ACLs utilizing vault (Hashicorp's secret management tool). In this case, we use a default Consul client to find our vault instance, get a dynamcially created ACL token from vault, and want to reset the consul client with the new token. This is currently not possible.

I can help out with submitting a PR to support this but looking for feedback on how you would like to see it done (and if you think it is a good idea). I could create a simple SetToken method but not sure if that would be the best way to go.

Hi, thanks for submitting this.

If possible I'd say the "best correct option" in my opinion would be to create a "bootstrap" ConsulClient during your IOC construction (I have no idea how you're doing this, though, and it's quite awkward in reality since a constructor can't be async) rather than using the global singleton and re-configuring the singleton after you've managed to obtain a token.

There was a reason I made the ConsulClient's configuration post-creation immutable a few versions ago: because there are so many moving parts in a multithreaded environment I've attempted to make the ConsulClient as immutable as possible so as to not add locks to common code paths through it. Additionally, I can guarantee each request from a specific client object uses the same properties unless an explicit QueryOptions or WriteOptions gets passed in. It's a weird debugging situation to start a request that blocks with token A and then change the token before starting a request with token B, since the first request will continue to use token A.

I just spent a couple hours tearing the config code apart and it looks like the main problem is that there are a bunch of janky properties for the old-style config that are obsolete but not removed, e.g. ConsulClientConfiguration.DisableServerCertificateValidation which actually sets a callback on the HttpHandler of the HttpClient. 😞

Since old-style config mutates the HttpHandler and/or HttpClient, I have to call a method to update them if the config is changed, and thus I can't just rely on the fact that reference assignment is atomic and say "oh yeah just go ahead and swap out the ConsulClientConfiguration I guess."

I think I've got a working thing though it's a bit rough around the edges because reconfiguring in a safe manner has to dispose of the existing HttpClient, and thus means that all current connections over that HttpClient throw a TaskCancelledException.

I've made an alpha package: https://www.nuget.org/packages/Consul/0.7.2.1-alpha1

Let me know if the ConsulClient's Reconfigure method works for you.

Oh yeah one addendum: there's now a saveOverrides argument on the ConsulClient constructor that you might find useful when constructing your base case. It keeps a reference to the delegates that you use to configure the constructor and re-runs them when you Reconfigure, otherwise everything has to be Reconfigured from a fresh state.

Also feel free to suggest a better way to do this. That's why I made it an alpha package - so I can twiddle the API before releasing it for real.

Thanks for the work! I will check it out and let you know in the next day or two how it works out.

Did you ever get a chance to check this out @chrishoffman ?

Sorry for the delay. I did and immediately got concerned that it added additional complexity to the maintenance of this library. I took your advice and worked in creating bootstrap instances of all my default clients and binding my singleton instance to the authenticated client. Thanks for taking the time to work out this solution.

Awesome, thanks for letting me know.

This exercise actually let me find and fix a couple of other bugs, which I'm going to cherry-pick into main and update but good to hear you figured out the bootstrap instance stuff.