18 releases

0.3.3 Jun 18, 2024
0.3.0 Feb 18, 2024
0.2.1 Aug 12, 2023
0.1.2 Apr 16, 2023
0.1.0-alpha.5 Jun 3, 2022

#56 in Unix APIs

Download history 1538/week @ 2024-08-18 1875/week @ 2024-08-25 2021/week @ 2024-09-01 1757/week @ 2024-09-08 2135/week @ 2024-09-15 4148/week @ 2024-09-22 2528/week @ 2024-09-29 2155/week @ 2024-10-06 1958/week @ 2024-10-13 1370/week @ 2024-10-20 1758/week @ 2024-10-27 1889/week @ 2024-11-03 1786/week @ 2024-11-10 1985/week @ 2024-11-17 1866/week @ 2024-11-24 2297/week @ 2024-12-01

8,050 downloads per month
Used in 2 crates

MIT license

175KB
4K SLoC

OO7

docs crates.io CI

James Bond went on a new mission and this time as a Secret Service provider.

The library consists of two modules:

  • An implementation of the Secret Service specifications using zbus. Which sends the secrets to a DBus implementation of the org.freedesktop.Secrets interface that stores them somewhere safe.

  • A file backend using the org.freedesktop.portal.Secrets portal to retrieve the service's key to encrypt the file with. The file format is compatible with libsecret.

Sandboxed applications should prefer using the file backend as it doesn't expose the application secrets to other sandboxed applications if they can talk to the org.freedesktop.Secrets service.

The library provides helper methods to store and retrieve secrets and uses either the DBus interface or the file backend based on whether the application is sandboxed or not.

Goals

  • Async only API
  • Ease to use
  • Integration with the Secret portal if sandboxed
  • Provide API to migrate from host secrets to sandboxed ones

Examples

Basic usage

use std::collections::HashMap;

async fn run() -> oo7::Result<()> {
    let keyring = oo7::Keyring::new().await?;
    let attributes = HashMap::from([("attribute", "attribute_value")]);

    // Store a secret
    keyring
        .create_item("Item Label", &attributes, b"secret", true).await?;

    // Find a stored secret
    let items = keyring.search_items(&attributes).await?;

    // Delete a stored secret
    keyring.delete(&attributes).await?;

    // Unlock the collection if the Secret Service is used
    keyring.unlock().await?;

    // Lock the collection if the Secret Service is used
    keyring.lock().await?;
    Ok(())
}

If your application makes heavy usage of the keyring like a password manager. You could store an instance of the Keyring in a OnceCell / OnceLock / Lazy

use std::sync::OnceLock;
use std::collections::HashMap;

static KEYRING: OnceLock<oo7::Keyring> = OnceLock::new();

fn main() {
    // SOME_RUNTIME could be a tokio/async-std/glib runtime
    SOME_RUNTIME.block_on(async {
        let keyring = oo7::Keyring::new()
            .await
            .expect("Failed to start Secret Service");
        KEYRING.set(keyring);
    });

    // Then to use it
    SOME_RUNTIME.spawn(async {
        let items = KEYRING
            .get()
            .unwrap()
            .search_items(&HashMap::from([("attribute", "attribute_value")]))
            .await;
    });
}

Migrating your secrets to the file backend

The library also comes with API to migrate your secrets from the host Secret Service to the sandboxed file backend. Note that the items are removed from the host keyring if they are migrated successfully.

use std::collections::HashMap;

// SOME_RUNTIME could be a tokio/async-std/glib runtime
SOME_RUNTIME.block_on(async {
    match oo7::migrate(vec![HashMap::from([("attribute", "attribute_value")])], true).await {
        Ok(_) => {
            // Store somewhere the migration happened, to avoid re-doing it at every startup
        }
        Err(err) => log::error!("Failed to migrate secrets {err}"),
    }
});

Optional features

Feature Description Default
tracing Record various debug information using the tracing library No
async-std Use async-std APIs for IO/filesystem operations Yes
tokio Use tokio APIs for IO/Filesystem operations No
native_crypto Use Rust Crypto crates for cryptographic primitives Yes
openssl_crypto Use openssl crate for cryptographic primitives No
unstable Unlock internal APIs No

How does it compare to other libraries?

  • libsecret-rs provides Rust bindings of the C library libsecret. The current main pain point with it is that it does assume things for you so it will either use the host or the sandbox file-based keyring which makes migrating your secrets to inside the sandbox a probably impossible task. There are also issues like https://gitlab.gnome.org/GNOME/libsecret/-/issues/58 that makes it not usable inside the Flatpak sandbox.

  • secret-service-rs uses zbus internally as well but does provide a sync only API, hasn't seen an update in a while, doesn't integrate with Secret portal if sandboxed.

License

The project is released under the MIT license.

Credits

Dependencies

~7–19MB
~292K SLoC