1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg))]
#![doc = include_str!("../README.md")]
// @@ begin lint list maintained by maint/add_warning @@
#![allow(renamed_and_removed_lints)] // @@REMOVE_WHEN(ci_arti_stable)
#![allow(unknown_lints)] // @@REMOVE_WHEN(ci_arti_nightly)
#![warn(missing_docs)]
#![warn(noop_method_call)]
#![warn(unreachable_pub)]
#![warn(clippy::all)]
#![deny(clippy::await_holding_lock)]
#![deny(clippy::cargo_common_metadata)]
#![deny(clippy::cast_lossless)]
#![deny(clippy::checked_conversions)]
#![warn(clippy::cognitive_complexity)]
#![deny(clippy::debug_assert_with_mut_call)]
#![deny(clippy::exhaustive_enums)]
#![deny(clippy::exhaustive_structs)]
#![deny(clippy::expl_impl_clone_on_copy)]
#![deny(clippy::fallible_impl_from)]
#![deny(clippy::implicit_clone)]
#![deny(clippy::large_stack_arrays)]
#![warn(clippy::manual_ok_or)]
#![deny(clippy::missing_docs_in_private_items)]
#![warn(clippy::needless_borrow)]
#![warn(clippy::needless_pass_by_value)]
#![warn(clippy::option_option)]
#![deny(clippy::print_stderr)]
#![deny(clippy::print_stdout)]
#![warn(clippy::rc_buffer)]
#![deny(clippy::ref_option_ref)]
#![warn(clippy::semicolon_if_nothing_returned)]
#![warn(clippy::trait_duplication_in_bounds)]
#![deny(clippy::unchecked_duration_subtraction)]
#![deny(clippy::unnecessary_wraps)]
#![warn(clippy::unseparated_literal_suffix)]
#![deny(clippy::unwrap_used)]
#![allow(clippy::let_unit_value)] // This can reasonably be done for explicitness
#![allow(clippy::uninlined_format_args)]
#![allow(clippy::significant_drop_in_scrutinee)] // arti/-/merge_requests/588/#note_2812945
#![allow(clippy::result_large_err)] // temporary workaround for arti#587
#![allow(clippy::needless_raw_string_hashes)] // complained-about code is fine, often best
//! <!-- @@ end lint list maintained by maint/add_warning @@ -->

// TODO: write more comprehensive documentation when the API is a bit more
// stable

mod arti_path;
pub mod config;
mod err;
mod key_specifier;
pub(crate) mod ssh;
#[cfg(any(test, feature = "testing"))]
pub mod test_utils;

#[cfg(feature = "keymgr")]
mod key_type;
#[cfg(feature = "keymgr")]
mod keystore;
#[cfg(feature = "keymgr")]
mod mgr;

#[cfg(not(feature = "keymgr"))]
mod dummy;

pub use arti_path::{ArtiPath, DENOTATOR_SEP};
pub use err::{ArtiPathSyntaxError, Error, KeystoreCorruptionError, KeystoreError};
pub use key_specifier::{
    ArtiPathUnavailableError, CTorPath, InvalidKeyPathComponentValue, KeyPath, KeyPathError,
    KeyPathInfo, KeyPathInfoBuilder, KeyPathInfoExtractor, KeyPathPattern, KeyPathRange,
    KeySpecifier, KeySpecifierComponent, KeySpecifierComponentViaDisplayFromStr,
    KeySpecifierPattern,
};
pub use ssh::SshKeyAlgorithm;

#[cfg(feature = "keymgr")]
#[cfg_attr(docsrs, doc(cfg(feature = "keymgr")))]
pub use {
    key_type::{KeyType, UnknownKeyTypeError},
    keystore::arti::ArtiNativeKeystore,
    keystore::ephemeral::ArtiEphemeralKeystore,
    keystore::{EncodableKey, ErasedKey, Keygen, KeygenRng, Keystore, SshKeyData, ToEncodableKey},
    mgr::{KeyMgr, KeyMgrBuilder, KeyMgrBuilderError, KeystoreEntry},
    ssh_key,
};

#[doc(hidden)]
pub use key_specifier::derive as key_specifier_derive;

derive_deftly::template_export_semver_check! { "0.12.1" }

#[cfg(not(feature = "keymgr"))]
#[cfg_attr(docsrs, doc(cfg(not(feature = "keymgr"))))]
pub use dummy::*;

/// A boxed [`Keystore`].
pub(crate) type BoxedKeystore = Box<dyn Keystore>;

#[doc(hidden)]
pub use {derive_deftly, inventory};

use derive_more::{AsRef, Display, From};
use serde::{Deserialize, Serialize};
use std::str::FromStr;

/// A Result type for this crate.
pub type Result<T> = std::result::Result<T, Error>;

/// An identifier for a particular [`Keystore`] instance.
//
// TODO (#1193): restrict the charset of this ID
#[derive(
    Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize, Display, AsRef,
)]
#[serde(transparent)]
#[non_exhaustive]
pub struct KeystoreId(String);

impl FromStr for KeystoreId {
    type Err = Error;

    fn from_str(s: &str) -> Result<Self> {
        Ok(Self(s.into()))
    }
}

/// Specifies which keystores a [`KeyMgr`] operation should apply to.
#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, Hash, From)]
#[non_exhaustive]
pub enum KeystoreSelector<'a> {
    /// Try to use the keystore with the specified ID.
    Id(&'a KeystoreId),
    /// Use the default key store.
    #[default]
    Default,
}