-
-
Notifications
You must be signed in to change notification settings - Fork 53
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
Provide keyutils with persistence-after-reboot using secret-service #222
Provide keyutils with persistence-after-reboot using secret-service #222
Conversation
Requires #220 for the CI not to complain about dual keystores. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi Clément, thanks for this! It's a very interesting idea. I have reactions at three levels:
At the highest level, I think this captures very nicely the idea you were talking about in one of your comments, where you talked about having one credential store be primary and then another be fallback. That idea is really independent of credential store, and could be a separate crate that uses keyring to provide the credential stores.
At an intermediate level, this feels like it should be structured as a separate credential store module (and feature) that relies on (and requires) both secret-service and keyutils. Rather than thinking of it as "secret-service with keyutils cache," I tend to think of it as "keyutils with fallback to secret-service for persistence across reboots," because that's how it would work in practice (as has been noted in a number of closed issues against this crate, for example see #168).
At the lowest level, I think there are some logic changes that would be needed to really make this robust, in particular one would need to guard against the two stores going "out of sync" with one another as a result of separate access.
If you are willing to turn this into a separate credential module, and fix the out-of-sync issues, I would be delighted to include it as part of keyring.
I thought about it, I hesitated between the actual simpler (naive) solution and this one. What stopped me to implement the late one is the complexity around: how to name such store? how to deal with cargo features (sync/async secret service with/without keyring)? it brings even more conditions etc. I am not against, but knowing the low need of such feature we could start simpler, by just adding cache to secret service. It can be put behind a feature gate as well.
Same here. While I am not against (because it makes sense), I find overkill to fine-tune the feature now knowing that it's an edge case of an edge case. IMHO, better to start simpler and improve over time with users' feedback. What do you think? |
After all, both ideas can be complementary, as they serve different purposes:
Since nobody needed both secret service and keyutils (nor such cache feature) before, it makes sense to start first with the light one. |
Thanks for your thoughtful comments; they make a lot of sense. I absolutely agree that keeping things simple to begin with is the way to go. It doesn't need to be super robust as long as we document what the behavior is. I agree there's a real need to have a standard way for keyring to support backing the keyutils with persistence. And I think that fills a real need for people who have systems they run as headless servers for the most part (relying on keyutils) but then can log into via UI to configure (via secret-service). I still think this is best modeled as a separate linux-only keystore (perhaps called "linux-native-persistent") that is an exclusive alternative to both keyutils and secret-service. Because both the keyutils and dbus-secret-service modules are optional dependencies, we can have the "linux-native-persistent" feature enable both of those modules, and then simply use them as a client (using the pattern you've established in your existing PR). That way we don't complicate the existing keystore code and we give all users an easy way to use the double-keystore pattern that you are using. Is this an approach that might work for you? |
Maybe |
17b2e8e
to
cce6436
Compare
daf92f3
to
87aacd7
Compare
87aacd7
to
e08aeaa
Compare
I had hard time to deal with this new keystore with the actual cargo features management. As I expected, it became a mess of conditions in order to make default keystore exclusive. I also discovered the potential reason behind the default keystore confusion: the word In order to go forward, I suggest the following ideas:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is starting to look very good, thanks for working on it! Some notes:
- WRT your suggested feature renames, changing existing feature behavior is a SemVer-incompatible change, and I would like to keep this change to a backwards-compatible enhancement (dot) release. So for now let's pick a new name for the feature controlling this keystore and just add it alongside the existing ones as an exclusive option. I know this makes the
cfg
logic even deeper on the*nix
side, but that's purely an internal issue that we can manage and doesn't show to clients. - I like where you're going with the idea about
-default
vs-native
features, and will keep track of it for the next major release. It also suggests to me that we don't need the-native
feature set at all, because we can just include those keystores based on platform rather than feature, so maybe this will all get a lot simpler in v4 :). After all, there is only 1 platform (*nix) where there's a choice of keystores... - I don't see any reason to support both sync and async secret-service usage in this brand new keystore. Just supporting the
dbus-secret-service
will provide a lot of advantages: (a) no need to conditionalize a bunch of code, (b) much simpler feature logic (just have this feature rely onkeyutils-rs
anddbus-secret-service
directly and prevent use of other *nix keystores), (c) much slimmer dependency footprint. - I think we should consider altering (or allowing the client to alter) one or more of the target, user, and service values that this code passes to keyutils and secret-service in order to avoid conflicts with legacy code that was already using those services for their passwords. But then again maybe we want this code just to overtake all those old entries if they exist?
- When get_secret gets a miss in keyutils and then a hit in secret-service, it should repair the cache with set_password on the keyutils entry. If we do decide to overtake old entries with the same values, then perhaps the same should be done if we get a hit in keyutils but a miss in secret-service.
And what if someone already relies on zbus (it may be my case within my app, I need to check) and want to have
I think it's fine to overtake old entries, at least for now. Let's wait for users feedback?
Nice catch, I take care of it tomorrow morning. I don't get the reason of the CI failure, nothing changed except for cargo features. Any idea? |
Wrt using dbus-secret-service with tokio and zbus: I have tested that thoroughly and there's no issue there. I'd really like to keep the footprint as light as possible and I don't want to have multiple features for this new store, so let's stay with just the one. Not sure about the test failures, often they fail once randomly but when I ran them again they failed at the same test. Once you finish your changes we can take a closer look. |
- Removed `default-*` features as breaking semver compat is not planned - Added `keyutils` cargo feature - Adjusted compilation condition for default stores - Replaced `keyutils: Option<KeyutilsCredential>` by `KeyutilsCredential` in `SsKeyutilsCredential`
I just pushed changes. Somehow, by keeping the
I thought about this, but native features are still convenient for testing purpose (for example to force the mock store). It joins a bit the idea I proposed last time about having the whole default keystore system behind a feature gate (on by default). Native features also allow apps to choose on which OS they want to be compatible: if you have an app that works only on Linux and MacOS, you can omit the
If we get a hit in keyutils then it returns straight without hitting secret service: the role if this cache is to prevent as much as possible to call the slower secret service. It's part of the opportunistic approach I was explaining, it's fine (at least with this particular store) if keys are not sync. |
ce2bc07
to
d9ec382
Compare
f7883a7
to
827fd6e
Compare
The cargo feature condition you were proposing did not work, so I adjusted them. Ready for the next review! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Excellent! One last feature name change (or three if you like my suggested change to the top-level features names) and adding logging and the content is done!
Now we need documentation and unit tests. You should pretty much be able to crib the tests from the keyring crate. If you can take a first pass at the docs - I suggest keeping them simple and just referring to the docs of the other crates if necessary - I am happy to do copy editing in a review.
3bbe95d
to
b41fafc
Compare
Sure, maybe it is better this way as I may not word properly things. You can also push a commit directly on my branch, as you wish. Ready for another review. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Almost! You lost a config test that's required for non-linux systems. I've called it out. (actually, I didn't before, I will add it below.)
What do you think about adding logging for all the error conditions that aren't returned. For example, when you miss in keyutils we would log that happened even if you then hit in secret-service. As long as we have logging I think it would be good to be transparent in this way.
28ddd04
to
d09aff3
Compare
Not sure to understand what's wrong with the CI. Feel free to push commits on the branch if needed for the merge, I will check tomorrow morning. |
d09aff3
to
160ad9f
Compare
Don't worry about the test failures until we have unit tests and docs. Then, if necessary, I'll pull it and look at it. |
I initiated doc and unit tests, feel free to adjust at your convenience. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great, thank you!! I will be making tweaks for a while by pushing commits to your repo - feel free to review them. Then once we agree it's done I'll merge it.
Also updated feature descriptions in the library docs, and the readme. Updated the cross-platform doc builder script to know about the new keystore.
OK, I've updated docs and tweaked a few things. Please take a look and try it out and let me know if you think we are ready to pull this. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for fixing typos. Looks good to me, ready to merge!
Could I ask you to release a new version as soon as you merge? It will allow me to release my versions as well. |
This PR makes both async and sync secret service keystores using keyutils as cache, when available (on Linux only).
Since you mentioned that rare are users needing both secret service and keyutils, I assume the following statement: if a user enables both secret service and keyring, it implies that the user wants to benefit from the Linux secure cache. To disable cache, just remove the feature.