Skip to content

Commit 9e5a1f6

Browse files
Merge pull request #114 from brotskydotcom/doc-updates
Revamp the docs for v2. Also tweaked visibility of a few classes for documentation purposes. This brings us to 2.0.0-rc.3, and will likely be promoted to our 2.0 release.
2 parents 09527c7 + b053fa3 commit 9e5a1f6

11 files changed

+662
-232
lines changed

Cargo.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@ keywords = ["password", "credential", "keychain", "keyring", "cross-platform"]
66
license = "MIT OR Apache-2.0"
77
name = "keyring"
88
repository = "https://github.com/hwchen/keyring-rs.git"
9-
version = "2.0.0-rc.2"
9+
version = "2.0.0-rc.3"
1010
edition = "2021"
1111
exclude = [".github/"]
12+
readme = "README.md"
1213

1314
[features]
1415
default = ["linux-secret-service"]

README.md

+66-43
Original file line numberDiff line numberDiff line change
@@ -3,78 +3,94 @@
33
[![Crates.io](https://img.shields.io/crates/v/keyring.svg?style=flat-square)](https://crates.io/crates/keyring)
44
[![API Documentation on docs.rs](https://docs.rs/keyring/badge.svg)](https://docs.rs/keyring)
55

6-
A cross-platform library to manage storage and retrieval of passwords (and other credential-like secrets) in the underlying platform secure store, with a fully-developed example that provides a command-line interface.
7-
8-
Published on [crates.io](https://crates.io/crates/keyring)
6+
A cross-platform library to manage storage and retrieval of passwords
7+
(and other secrets) in the underlying platform secure store,
8+
with a fully-developed example that provides a command-line interface.
99

1010
## Usage
1111

12-
__Currently supports Linux, iOS, macOS, and Windows.__ Please file issues if you have any problems or bugs!
12+
**Currently supports Linux, iOS, macOS, and Windows.**
13+
Please file issues if you have have questions or problems.
1314

1415
To use this library in your project add the following to your `Cargo.toml` file:
1516

1617
```toml
1718
[dependencies]
18-
keyring = "1"
19+
keyring = "2"
1920
```
2021

21-
This will give you access to the `keyring` crate in your code. Now you can use the `Entry::new` function to create a new keyring entry. The `new` function expects a non-empty `service` name and a non-empty `username` which together identify the entry.
22+
This will give you access to the `keyring` crate in your code.
23+
Now you can use the `Entry::new` function to create a new keyring entry.
24+
The `new` function takes a service name
25+
and a user name which together identify the entry.
2226

23-
Passwords can be added to an entry using its `set_password` method. They can then be read back using the `get_password` method, and deleted using the `delete_password` method. (The persistence of the `Entry` is determined via Rust rules, so deleting the password doesn't delete the entry, but it does delete the underlying platform credential which was used to store the password.)
27+
Passwords can be added to an entry using its `set_password` method.
28+
They can then be read back using the `get_password` method,
29+
and removed using the `delete_password` method.
30+
(The persistence of the `Entry` is determined via Rust rules,
31+
so deleting the password doesn't delete the entry,
32+
but it does delete the underlying platform credential
33+
which is used to store the password.)
2434

2535
```rust
26-
extern crate keyring;
27-
28-
use std::error::Error;
29-
30-
fn main() -> Result<(), Box<dyn Error>> {
31-
let service = "my_application";
32-
let username = "my_name";
33-
let entry = keyring::Entry::new(&service, &username);
34-
35-
let password = "topS3cr3tP4$$w0rd";
36-
entry.set_password(&password)?;
36+
use keyring::{Entry, Result};
3737

38+
fn main() -> Result<()> {
39+
let entry = Entry::new("my_service", "my_name");
40+
entry.set_password("topS3cr3tP4$$w0rd")?;
3841
let password = entry.get_password()?;
3942
println!("My password is '{}'", password);
40-
4143
entry.delete_password()?;
42-
println!("My password has been deleted");
43-
4444
Ok(())
4545
}
4646
```
4747

4848
## Errors
4949

50-
Creating and operating on entries can yield a `keyring::Error` which provides both a platform-independent code that classifies the error and, where available, underlying platform errors and/or more information about what went wrong.
50+
Creating and operating on entries can yield a `keyring::Error`
51+
which provides both a platform-independent code
52+
that classifies the error and, where relevant,
53+
underlying platform errors or more information about what went wrong.
5154

5255
## Examples
5356

54-
The keychain-rs project contains a sample application (`cli`) and a sample library (`ios`).
55-
56-
The application is a command-line interface to the keyring. This can be a great way to explore how the library is used, and it allows experimentation with the use of different service names, usernames, and targets. When run in "singly verbose" mode (-v), it outputs the retrieved credentials on each `get` run. When run in "doubly verbose" mode (-vv), it also outputs any errors returned. This can be a great way to see which errors result from which conditions on each platform.
57-
58-
The sample library is a full exercise of all the iOS functionality; it's meant to be loaded into an iOS test harness such as the one found in [this project](https://github.com/brotskydotcom/rust-on-ios). While the library can be compiled and linked to on macOS as well, doing so doesn't provide any advantages over the standard macOS tests.
57+
The keychain-rs project contains a sample application (`cli`)
58+
and a sample library (`ios`).
59+
60+
The application is a command-line interface to the keyring.
61+
It can be used to explore how the library is used.
62+
It can also be used in debugging keyring-based applications
63+
to probe the contents of the credential store.
64+
When run in "singly verbose" mode (-v),
65+
it outputs the retrieved credentials on each `get` run.
66+
When run in "doubly verbose" mode (-vv),
67+
it also outputs any errors returned.
68+
69+
The sample library is a full exercise of all the iOS functionality;
70+
it's meant to be loaded into an iOS test harness
71+
such as the one found in
72+
[this project](https://github.com/brotskydotcom/rust-on-ios).
73+
While the library can be compiled and linked to on macOS as well,
74+
doing so doesn't provide any advantages over the standard macOS tests.
5975

6076
## Client Testing
6177

62-
This crate comes with a "mock" credential store that can be used by clients who want to test without accessing the native platform store. The mock store is cross-platform and allows mocking errors as well as successes.
78+
This crate comes with a "mock" credential store
79+
that can be used by clients who want to test
80+
without accessing the native platform store.
81+
The mock store is cross-platform
82+
and allows mocking errors as well as successes.
6383

6484
## Extensibility
6585

66-
This crate comes with built-in support for the keychain on Mac, the credential manager on Windows, and both secret-service and the kernel keyring on Linux. But it's also designed to allow clients to "bring their own credential stores" by providing traits that clients can implement. See the [developer docs](https://docs.rs/keyring/latest/keyring/) for details.
67-
68-
## Dev Notes
69-
70-
* We build using GitHub CI.
71-
* Each tag is built on Ubuntu x64, Win 10 x64, and Mac intel x64. The `cli` example executable is posted for all platforms with the tag.
72-
73-
### Headless Linux
74-
75-
If you are trying to use keyring on a headless linux box, be aware that there are known issues with getting dbus and secret-service and the gnome keyring to work properly in headless environments. For a quick workaround, look at how this project's [CI workflow](https://github.com/hwchen/keyring-rs/blob/master/.github/workflows/build.yaml) uses the [linux-test.sh](https://github.com/hwchen/keyring-rs/blob/master/linux-test.sh) script; a similar solution is also documented in the [Python Keyring docs](https://pypi.org/project/keyring/) (search for "Using Keyring on headless Linux systems"). For an excellent treatment of all the headless dbus issues, see [this answer on ServerFault](https://serverfault.com/a/906224/79617).
76-
77-
Note that you can build this crate without secret-service support; this makes the Linux keyring (which works normally on headless linux) the default credential store on Linux platforms.
86+
This crate comes with built-in support for the keychain on Mac,
87+
the credential manager on Windows,
88+
and both secret-service and the kernel keyutils on Linux.
89+
But it's also designed to allow clients
90+
to "bring their own credential stores"
91+
by providing traits that clients can implement.
92+
See the [developer docs](https://docs.rs/keyring/latest/keyring/)
93+
for details.
7894

7995
## License
8096

@@ -87,7 +103,8 @@ at your option.
87103

88104
## Contributors
89105

90-
Thanks to the following for helping make this library better, whether through contributing code, discussion, or bug reports!
106+
Thanks to the following for helping make this library better,
107+
whether through contributing code, discussion, or bug reports!
91108

92109
- @Alexei-Barnes
93110
- @bhkaminski
@@ -111,8 +128,14 @@ Thanks to the following for helping make this library better, whether through co
111128
- @steveatinfincia
112129
- @Sytten
113130

114-
If you should be on this list, but don't find yourself, please contact @brotskydotcom.
131+
If you should be on this list, but don't find yourself,
132+
please contact @brotskydotcom.
115133

116134
### Contribution
117135

118-
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
136+
Unless you explicitly state otherwise,
137+
any contribution intentionally submitted
138+
for inclusion in the work by you,
139+
as defined in the Apache-2.0 license,
140+
shall be dual licensed as above,
141+
without any additional terms or conditions.

build-xplat-docs.sh

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#!/bin/bash
2+
cargo doc --no-deps --target x86_64-unknown-linux-musl $OPEN_DOCS
3+
cargo doc --no-deps --target x86_64-pc-windows-gnu $OPEN_DOCS
4+
cargo doc --no-deps --target aarch64-apple-darwin $OPEN_DOCS
5+
cargo doc --no-deps --target aarch64-apple-ios $OPEN_DOCS

src/credential.rs

+36-18
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,38 @@
11
/*!
2+
3+
# Platorm-independent secure storage model
4+
25
This module defines a plug and play model for platform-specific credential stores.
3-
The model comprises two traits: `CredentialBuilder` for the store service
4-
and `Credential` for the credentials produced by the service.
6+
The model comprises two traits: [CredentialBuilderApi] for the underlying store
7+
and [CredentialApi] for the entries in the store. These traits must be implemented
8+
in a thread-safe way, a requirement captured in the [CredentialBuilder] and
9+
[CredentialApi] types that wrap them.
510
*/
611
use super::Result;
712
use std::any::Any;
813

9-
/// This trait defines the API that all credentials must implement.
14+
/// The API that [credentials](Credential) implement.
1015
pub trait CredentialApi {
11-
/// Set a password in the underlying store
16+
/// Set the credential's password.
17+
///
18+
/// This will persist the password in the underlying store.
1219
fn set_password(&self, password: &str) -> Result<()>;
13-
/// Retrieve a password from the underlying store
20+
/// Retrieve a password from the credential, if one has been set.
21+
///
22+
/// This has no effect on the underlying store.
1423
fn get_password(&self) -> Result<String>;
15-
/// Delete a password from the underlying store
24+
/// Forget the credential's password, if one has been set.
25+
///
26+
/// This will also remove the credential from the underlying store,
27+
/// so a second call to delete_password will return
28+
/// a [NoEntry](crate::Error::NoEntry) error.
1629
fn delete_password(&self) -> Result<()>;
17-
/// Cast the credential object to Any. This allows clients
30+
/// Return the underlying concrete object cast to [Any](std::any::Any).
31+
///
32+
/// This allows clients
1833
/// to downcast the credential to its concrete type so they
19-
/// can do platform-specific things with it (e.g, unlock it)
34+
/// can do platform-specific things with it (e.g.,
35+
/// query its attributes in the underlying store).
2036
fn as_any(&self) -> &dyn Any;
2137
}
2238

@@ -26,16 +42,21 @@ impl std::fmt::Debug for Credential {
2642
}
2743
}
2844

29-
/// Credentials must be usable from multiple threads, and they must
30-
/// be movable from thread to thread, so they must be Send and Sync.
45+
/// A thread-safe implementation of the [Credential API](CredentialApi).
3146
pub type Credential = dyn CredentialApi + Send + Sync;
3247

33-
/// This trait defines the API that Credential Builders must implement.
48+
/// The API that [credential builders](CredentialBuilder) implement.
3449
pub trait CredentialBuilderApi {
35-
/// Build a platform credential for the given parameters
50+
/// Create a credential identified by the given target, service, and user.
51+
///
52+
/// This typically has no effect on the content of the underlying store.
53+
/// A credential need not be persisted until its password is set.
3654
fn build(&self, target: Option<&str>, service: &str, user: &str) -> Result<Box<Credential>>;
37-
/// Cast the builder as type Any. This is not so much for clients.
38-
/// as it is to allow us to derive a Debug trait for builders.
55+
/// Return the underlying concrete object cast to [Any](std::any::Any).
56+
///
57+
/// Because credential builders need not have any internal structure,
58+
/// this call is not so much for clients
59+
/// as it is to allow automatic derivation of a Debug trait for builders.
3960
fn as_any(&self) -> &dyn Any;
4061
}
4162

@@ -45,8 +66,5 @@ impl std::fmt::Debug for CredentialBuilder {
4566
}
4667
}
4768

48-
/// Credential Builders must be Sync so they can be invoked from
49-
/// multiple threads simultaneously. Although no one expects a
50-
/// Credential Builder to be passed from one thread to another,
51-
/// they are usually objects, so Send should be easy.
69+
/// A thread-safe implementation of the [CredentialBuilder API](CredentialBuilderApi).
5270
pub type CredentialBuilder = dyn CredentialBuilderApi + Send + Sync;

0 commit comments

Comments
 (0)