hwchen / keyring-rs

Cross-platform library and utility to manage passwords
Apache License 2.0
450 stars 49 forks source link

FreeBSD: use of undeclared crate or module `secret_service` #148

Closed soywod closed 6 months ago

soywod commented 7 months ago

Someone reported the following issue on my project:

error[E0433]: failed to resolve: use of undeclared crate or module `secret_service`
  --> /home/fc/.cargo/registry/src/index.crates.io-6f17d22bba15001f/keyring-2.0.4/src/secret_service.rs:82:5
   |
82 | use secret_service::blocking::{Collection, Item, SecretService};
   |     ^^^^^^^^^^^^^^ use of undeclared crate or module `secret_service`

error[E0432]: unresolved import `secret_service`
  --> /home/fc/.cargo/registry/src/index.crates.io-6f17d22bba15001f/keyring-2.0.4/src/secret_service.rs:83:5
   |
83 | use secret_service::{EncryptionType, Error};
   |     ^^^^^^^^^^^^^^ help: a similar path exists: `crate::secret_service`
   |
   = note: `use` statements changed in Rust 2018; read more at <https://doc.rust-lang.org/edition-guide/rust-2018/module-system/path-clarity.html>

error[E0282]: type annotations needed
   --> /home/fc/.cargo/registry/src/index.crates.io-6f17d22bba15001f/keyring-2.0.4/src/secret_service.rs:158:14
    |
158 |         self.map_matching_items(delete_item, true)?;
    |              ^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the method `map_matching_items`
    |
help: consider specifying the generic arguments
    |
158 |         self.map_matching_items::<_, T>(delete_item, true)?;
    |                                ++++++++

error[E0282]: type annotations needed for `Vec<T>`
   --> /home/fc/.cargo/registry/src/index.crates.io-6f17d22bba15001f/keyring-2.0.4/src/secret_service.rs:216:13
    |
216 |         let credentials = self.map_matching_items(Self::new_from_item, true)?;
    |             ^^^^^^^^^^^
217 |         Ok(credentials[0].clone())
    |            -------------- type must be known at this point
    |
help: consider giving `credentials` an explicit type, where the placeholders `_` are specified
    |
216 |         let credentials: Vec<T> = self.map_matching_items(Self::new_from_item, true)?;
    |                        ++++++++

error[E0282]: type annotations needed
   --> /home/fc/.cargo/registry/src/index.crates.io-6f17d22bba15001f/keyring-2.0.4/src/secret_service.rs:233:14
    |
233 |         self.map_matching_items(delete_item, true)?;
    |              ^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the method `map_matching_items`
    |
help: consider specifying the generic arguments
    |
233 |         self.map_matching_items::<_, T>(delete_item, true)?;
    |                                ++++++++

error[E0618]: expected function, found `F`
   --> /home/fc/.cargo/registry/src/index.crates.io-6f17d22bba15001f/keyring-2.0.4/src/secret_service.rs:273:26
    |
247 |     pub fn map_matching_items<F, T>(&self, f: F, require_unique: bool) -> Result<Vec<T>>
    |                                            - `f` has type `F`
...
273 |             results.push(f(item)?);
    |                          ^------
    |                          |
    |                          call expression requires function

error[E0618]: expected function, found `F`
   --> /home/fc/.cargo/registry/src/index.crates.io-6f17d22bba15001f/keyring-2.0.4/src/secret_service.rs:277:26
    |
247 |     pub fn map_matching_items<F, T>(&self, f: F, require_unique: bool) -> Result<Vec<T>>
    |                                            - `f` has type `F`
...
277 |             results.push(f(item)?);
    |                          ^------
    |                          |
    |                          call expression requires function

Some errors have detailed explanations: E0282, E0432, E0433, E0618.
For more information about an error, try `rustc --explain E0282`.
    Checking serde_path_to_error v0.1.11
error: could not compile `keyring` (lib) due to 7 previous errors
warning: build failed, waiting for other jobs to finish...

Your crate is used like this in my project:

[dependencies.keyring_native]
package = "keyring"
version = "2.0.4"
default-features = false
features = ["linux-no-secret-service"]

I read https://github.com/hwchen/keyring-rs/issues/36, could it be related?

brotskydotcom commented 7 months ago

Hi @soywod, it looks like the secret-service is not installed on your user's build machine. Since the secret service is the only supported keystore on FreeBSD, it's not possible to use features to disable its use. The linux-... features only apply to Linux builds, not to FreeBSD builds. On FreeBSD, the secret service is always required.

Thinking about this, I suppose there might be users on FreeBSD who are bringing their own keystore and thus need this crate to compile without installing the secret service. We could allow disabling the secret service on FreeBSD by using the mock keystore as the default. But I'd like to hear from you about whether your user needs this (because they are, in fact, bringing their own keystore) or whether they simply need to install the secret service on their machine (e.g., by running pkg install libgnome-keyring as root).

brotskydotcom commented 7 months ago

Hi @soywod, I'm going to close this as resolved. Happy to reopen it if in fact your users have written their own credential store.

soywod commented 6 months ago

Thank you for your reply and sorry for the late mine.

But I'd like to hear from you about whether your user needs this (because they are, in fact, bringing their own keystore) or whether they simply need to install the secret service on their machine (e.g., by running pkg install libgnome-keyring as root).

My users are not necessarily developers, so I would bet on the second option.

But I have a question related to your Cargo.toml: why is secret-service optional for FreeBSD? To force lib-consumers to have secret-service in their dependencies? For example, I have a lib called secret-lib that consumes your lib, and secret-lib is consumed by a bigger project called Himalaya, a CLI to manage emails (the user who reported the issue tried to build this project). What is the impact of having secret-service as a required dependency in your lib VS secret-lib VS Himalaya?

brotskydotcom commented 6 months ago

Hi Clément, to answer your question, I need to draw a careful distinction between the secret-service, which is a Rust crate, the gnome-keyring, which is native FreeBSD software maintained by the Gnome project, and the secret service API, which is a public API maintained by the Gnome project.

Currently, the keyring crate has the secret-service crate as a required dependency on FreeBSD systems. (This is because it's the only FreeBSD module we support that implements a secure credential store.) Because the secret-service crate itself requires the host system to have an installation of a native library which implements the secret service API in order to compile correctly, users on BSD who try to build/link the keyring crate without having installed libgnome-keyring (or an equivalent) will get the error reported by your user.

Because the secret-service crate is actually usable against a number of different native libraries (all of which implement the secret service API), neither the keyring crate nor the secret-service crate attempt to install a specific native module: those are assumed to be installed either by the OS or the user.

So, as I see it, you have three options for secret-lib/Himalaya:

  1. You can warn users of Himalya on FreeBSD that they need to install libgnome-keyring themselves.
  2. You can have the FreeBSD Himalaya installer (if there is one) check for the existence a compatible library and, failing to find one, install libgnome-keyring itself.
  3. You can ask me to enhance the feature set of the keyring crate to make the secret-service crate be an optional dependency on FreeBSD (which would make the non-persistent mock credential store be the default). However, that would leave Himalaya without any persistent credential storage, which probably wouldn't work very well.

I hope you find this answer useful! Please get back to me here with any further questions.

brotskydotcom commented 6 months ago

So I'm reopening this because #153 has made me realize that people may really want to compile this crate with no underlying platform support on all platforms.

brotskydotcom commented 6 months ago

Version 2.2 (just released) fixes this. If you don't want to use secret service on FreeBSD, you can build with no default features. At that point you will be using the mock keystore by default.