Skip to content
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

FreeBSD: use of undeclared crate or module secret_service #148

Closed
soywod opened this issue Nov 23, 2023 · 6 comments · Fixed by #154
Closed

FreeBSD: use of undeclared crate or module secret_service #148

soywod opened this issue Nov 23, 2023 · 6 comments · Fixed by #154
Assignees

Comments

@soywod
Copy link
Contributor

soywod commented Nov 23, 2023

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 #36, could it be related?

@brotskydotcom
Copy link
Collaborator

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
Copy link
Collaborator

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
Copy link
Contributor Author

soywod commented Dec 10, 2023

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
Copy link
Collaborator

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
Copy link
Collaborator

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 brotskydotcom reopened this Dec 26, 2023
@brotskydotcom brotskydotcom self-assigned this Dec 26, 2023
brotskydotcom added a commit to brotskydotcom/keyring-rs that referenced this issue Dec 26, 2023
This fixes hwchen#153 by making all platform dependencies be features and including them as default features, so now you can suppress building all platform dependencies by suppressing default features.

This also fixes hwchen#148 by having the code check to see if there is platform support and, if not, using the mock keystore as the default.

While this change is not fully backward compatible for people who were suppressing default features on macOS, iOS, Win, or FreeBSD, doing so was undefined behavior on those platforms and so changing it does not break the semantics of the API.
brotskydotcom added a commit to brotskydotcom/keyring-rs that referenced this issue Dec 26, 2023
This fixes hwchen#153 by making all platform dependencies be features and including them as default features, so now you can suppress building all platform dependencies by suppressing default features.

This also fixes hwchen#148 by having the code check to see if there is platform support and, if not, using the mock keystore as the default.

While this change is not fully backward compatible for people who were suppressing default features on macOS, iOS, Win, or FreeBSD, doing so was undefined behavior on those platforms and so changing it does not break the semantics of the API.
@brotskydotcom
Copy link
Collaborator

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants