|
1 | 1 | //! This crate implements the [OmniBOR][omnibor] specification, so you can |
2 | 2 | //! __identify artifacts__ like binaries and source code files and __track |
3 | | -//! build dependencies__ in compilers and other build tools. |
| 3 | +//! build dependencies__ used to create them. |
4 | 4 | //! |
5 | 5 | //! You can identify a file like so: |
6 | 6 | //! |
|
48 | 48 | //! Artifact ID in the "target artifact" whose build input it's describing. |
49 | 49 | //! |
50 | 50 | //! With Input Manifests, you get a [Merkle tree]-like record of build inputs, |
51 | | -//! describing the full Artifact Dependency Graph (ADG)—every input used to build |
52 | | -//! the final artifact. Any time a build input changes, all the Artifact IDs |
53 | | -//! of anything derived from it change too! This enables easy detection of |
| 51 | +//! describing the full Artifact Dependency Graph (ADG)—every input used to |
| 52 | +//! build the final artifact. Any time a build input changes, all the Artifact |
| 53 | +//! IDs of anything derived from it change too! This enables easy detection of |
54 | 54 | //! build differences, arbitrarily deep in an ADG. |
55 | 55 | //! |
56 | 56 | //! There are three ways to use the Rust OmniBOR implementation: |
|
59 | 59 | //! - The [`omnibor` crate Foreign Function Interface (FFI)][ffi] |
60 | 60 | //! - The [OmniBOR CLI][cli] |
61 | 61 | //! |
62 | | -//! # Creating Artifact IDs |
| 62 | +//! # Concepts |
| 63 | +//! |
| 64 | +//! In addition to [`ArtifactId`], [`InputManifest`], and |
| 65 | +//! [`InputManifestBuilder`], there are some key traits and types to know: |
| 66 | +//! |
| 67 | +//! - __[Identify and IdentifyAsync](#identify-and-identifyasync)__: Traits for |
| 68 | +//! types that can produce an [`ArtifactId`], synchronously or asynchronously. |
| 69 | +//! - __[Hash Algorithms](#hash-algorithms)__: Types implementing |
| 70 | +//! [`HashAlgorithm`](crate::hash_algorithm::HashAlgorithm), currently only |
| 71 | +//! [`Sha256`](crate::hash_algorithm::Sha256). |
| 72 | +//! - __[Hash Providers](#hash-providers)__: Types implementing |
| 73 | +//! [`HashProvider`](crate::hash_provider::HashProvider), currently |
| 74 | +//! [`RustCrypto`](crate::hash_provider::RustCrypto), |
| 75 | +//! [`OpenSsl`](crate::hash_provider::OpenSsl), and |
| 76 | +//! [`BoringSsl`](crate::hash_provider::BoringSsl). |
| 77 | +//! - __[Storage](#storage)__: Types implementing |
| 78 | +//! [`Storage`](crate::storage::Storage), currently |
| 79 | +//! [`FileSystemStorage`](crate::storage::FileSystemStorage) or |
| 80 | +//! [`InMemoryStorage`](crate::storage::InMemoryStorage). |
| 81 | +//! - __[Embedding](#embedding)__: Types implementing |
| 82 | +//! [`Embed`](crate::embed::Embed), currently |
| 83 | +//! [`NoEmbed`](crate::embed::NoEmbed), |
| 84 | +//! [`AutoEmbed`](crate::embed::AutoEmbed), |
| 85 | +//! and [`CustomEmbed`](crate::embed::CustomEmbed). |
| 86 | +//! |
| 87 | +//! ## Identify and IdentifyAsync |
| 88 | +//! |
| 89 | +//! There are two traits for types that can produce an [`ArtifactId`]: |
| 90 | +//! |
| 91 | +//! - [`Identify`]: Can produce an Artifact ID synchronously. |
| 92 | +//! - [`IdentifyAsync`]: Can produce an Artifact ID asynchronously. |
| 93 | +//! |
| 94 | +//! These traits are used as bounds on functions throughout the crate that |
| 95 | +//! expect an [`ArtifactId`]. |
| 96 | +//! |
| 97 | +//! The full list of "identifiable" types, with an explanation of how they're |
| 98 | +//! processed, is as follows: |
| 99 | +//! |
| 100 | +//! | Type | `impl Identify` | `impl IdentifyAsync` | Explanation | |
| 101 | +//! |:-----------------------------------------------------------------|:----------------|:---------------------|:-------------------------------------------------------------| |
| 102 | +//! | `&[u8]` | ✅ | | Hash the bytes. | |
| 103 | +//! | `[u8; N]` | ✅ | | Hash the bytes. | |
| 104 | +//! | `&[u8; N]` | ✅ | | Hash the bytes. | |
| 105 | +//! | `&str` | ✅ | ✅ | Treat as a path, hash the contents of the file at that path. | |
| 106 | +//! | `&String` | ✅ | ✅ | Treat as a path, hash the contents of the file at that path. | |
| 107 | +//! | `&OsStr` | ✅ | ✅ | Treat as a path, hash the contents of the file at that path. | |
| 108 | +//! | `&OsString` | ✅ | ✅ | Treat as a path, hash the contents of the file at that path. | |
| 109 | +//! | `&Path` | ✅ | ✅ | Hash the contents of the file at that path. | |
| 110 | +//! | `&PathBuf` | ✅ | ✅ | Hash the contents of the file at that path. | |
| 111 | +//! | `File` | ✅ | | Hash the contents of the file. | |
| 112 | +//! | `&File` | ✅ | | Hash the contents of the file. | |
| 113 | +//! | `Box<File>` | ✅ | | Hash the contents of the file. | |
| 114 | +//! | `Rc<File>` | ✅ | | Hash the contents of the file. | |
| 115 | +//! | `Arc<File>` | ✅ | | Hash the contents of the file. | |
| 116 | +//! | `&mut tokio::fs::File` | | ✅ | Hash the contents of the file. | |
| 117 | +//! | `tokio::fs::File` | | ✅ | Hash the contents of the file. | |
| 118 | +//! | `BufReader<R> where R: Read + Seek` | ✅ | | Hash the bytes read off the reader. | |
| 119 | +//! | `tokio::io::BufReader<R> where R: AsyncRead + AsyncSync + Unpin` | | ✅ | Hash the bytes read off the reader. | |
| 120 | +//! | `&mut R where R: Read + Seek` | ✅ | | Hash the bytes read off the reader. | |
| 121 | +//! | `Cursor<T> where T: AsRef<[u8]>` | ✅ | | Hash the bytes read off the cursor. | |
| 122 | +//! | `InputManifest<H>` | ✅ | | Hash the on-disk representation of the manifest. | |
| 123 | +//! | `&InputManifest<H>` | ✅ | | Hash the on-disk representation of the manifest. | |
| 124 | +//! | `ArtifactId<H>` | ✅ | | Copy the Artifact ID. | |
| 125 | +//! | `&ArtifactId<H>` | ✅ | | Copy the Artifact ID. | |
| 126 | +//! |
| 127 | +//! ## Hash Algorithms |
| 128 | +//! |
| 129 | +//! Artifact IDs and Input Manifests are based on a hash algorithm. |
| 130 | +//! Today, OmniBOR only supports SHA-256, though alternatives may be added in |
| 131 | +//! the future if SHA-256's cryptographic properties are broken. |
63 | 132 | //! |
64 | | -//! Artifact IDs can be made from many different kinds of input types, and |
65 | | -//! both synchronously and asynchronously, using the |
66 | | -//! [`ArtifactId::new`] and [`ArtifactId::new_async`] |
67 | | -//! methods, which take types that implement the [`Identify`] and |
68 | | -//! [`IdentifyAsync`] traits, respectively. |
| 133 | +//! The [`HashAlgorithm`](crate::hash_algorithm::HashAlgorithm) trait is |
| 134 | +//! implemented by the [`Sha256`](crate::hash_algorithm::Sha256) type, and most |
| 135 | +//! types in this crate are parameterized over the hash algorithm. |
69 | 136 | //! |
70 | | -//! # Creating Input Manifests |
| 137 | +//! ## Hash Providers |
71 | 138 | //! |
72 | | -//! [`InputManifest`]s are created with an [`InputManifestBuilder`]. This type |
73 | | -//! is parameterized over three things: the hash algorithm to use, the hash |
74 | | -//! provider to use, and the storage to use. The usual flow of constructing |
75 | | -//! an [`InputManifest`] is to create a new [`InputManifestBuilder`], add |
76 | | -//! entries with [`InputManifestBuilder::add_relation`], and complete |
77 | | -//! the build with [`InputManifestBuilder::build_for_target`]. |
| 139 | +//! Hashes are produced by "hash providers," which implement the |
| 140 | +//! [`HashProvider`](crate::hash_provider::HashProvider) trait. Today we |
| 141 | +//! support [RustCrypto], [OpenSSL], and [BoringSSL], which you can turn on or |
| 142 | +//! off at compile time using features: |
78 | 143 | //! |
79 | | -//! # Hash Algorithms and Hash Providers |
| 144 | +//! | Feature | Provider | Type | |
| 145 | +//! |:----------------------|:-----------|:-------------------------------------------------| |
| 146 | +//! | `provider-rustcrypto` | RustCrypto | [`RustCrypto`](crate::hash_provider::RustCrypto) | |
| 147 | +//! | `provider-openssl` | OpenSSL | [`OpenSsl`](crate::hash_provider::OpenSsl) | |
| 148 | +//! | `provider-boringssl` | BoringSSL | [`BoringSsl`](crate::hash_provider::BoringSsl) | |
80 | 149 | //! |
81 | | -//! Artifact IDs and Input Manifests are based on a chosen hash algorithm. |
82 | | -//! Today, OmniBOR only supports SHA-256, though alternatives may be added in |
83 | | -//! the future if SHA-256's cryptographic properties are broken. |
84 | | -//! |
85 | | -//! The [`HashAlgorithm`](crate::hash_algorithm::HashAlgorithm) trait is |
86 | | -//! implemented by the [`Sha256`](crate::hash_algorithm::Sha256) type, and |
87 | | -//! both [`ArtifactId`]s and [`InputManifest`]s |
88 | | -//! are parameterized over their [`HashAlgorithm`](crate::hash_algorithm::HashAlgorithm). |
89 | | -//! |
90 | | -//! We also support plugging in arbitrary "hash providers," libraries which |
91 | | -//! provide implementations of cryptographic hashes. Today, we support |
92 | | -//! [RustCrypto](https://github.com/rustcrypto), [OpenSSL](https://www.openssl.org/), |
93 | | -//! and [BoringSSL](https://boringssl.googlesource.com/boringssl). |
94 | | -//! |
95 | | -//! All hash providers are represented by a type implementing the |
96 | | -//! [`HashProvider`](crate::hash_provider::HashProvider) trait; so we have |
97 | | -//! [`RustCrypto`](crate::hash_provider::RustCrypto), |
98 | | -//! [`OpenSsl`](crate::hash_provider::OpenSsl), and |
99 | | -//! [`BoringSsl`](crate::hash_provider::BoringSsl), respectively. |
100 | | -//! All APIs in the crate for creating [`ArtifactId`]s or |
101 | | -//! [`InputManifest`]s are |
102 | | -//! parameterized over the [`HashProvider`](crate::hash_provider::HashProvider). |
103 | | -//! We also provide convenience methods to choose one of the built-in providers. |
104 | | -//! |
105 | | -//! Providers are conditionally compiled in based on crate features. By default, |
106 | | -//! only the `provider-rustcrypto` feature is turned on. Any combination of |
107 | | -//! these may be included. In all cases, they are vendored in and do not link |
108 | | -//! to any system instances of these libraries. |
109 | | -//! |
110 | | -//! In the future we plan to support linking to system instances of OpenSSL and |
111 | | -//! BoringSSL. |
112 | | -//! |
113 | | -//! # Storing Input Manifests |
| 150 | +//! ## Storage |
114 | 151 | //! |
115 | 152 | //! We expose a [`Storage`](crate::storage::Storage) trait, representing the |
116 | 153 | //! abstract interface needed for interacting with Input Manifests in memory or |
|
126 | 163 | //! If you do not need to persist Input Manifests, use |
127 | 164 | //! [`InMemoryStorage`](crate::storage::InMemoryStorage). |
128 | 165 | //! |
129 | | -//! # Specification Compliance |
| 166 | +//! ## Embedding |
| 167 | +//! |
| 168 | +//! When [`InputManifest`]s are built with [`InputManifestBuilder`], you pass |
| 169 | +//! in an embedding choice to select whether and how to embed the Artifact ID |
| 170 | +//! of the Input Manifest into the target artifact the manifest is describing. |
| 171 | +//! |
| 172 | +//! If you _do_ embed the manifest's Artifact ID, you ensure changes to the |
| 173 | +//! build inputs are reflected in the Artifact ID of the target artifact. |
| 174 | +//! |
| 175 | +//! There are currently three options, all implementing the |
| 176 | +//! [`Embed`](crate::embed::Embed) trait: |
| 177 | +//! |
| 178 | +//! - [`NoEmbed`](crate::embed::NoEmbed): Do not do embedding. The resulting |
| 179 | +//! manifest is considered "detached." |
| 180 | +//! - [`AutoEmbed`](crate::embed::AutoEmbed): Do embedding, with the `omnibor` |
| 181 | +//! crate inferring the filetype of the target artifact to determine how to |
| 182 | +//! embed in it. Requires the `infer-filetypes` feature is on. |
| 183 | +//! - [`CustomEmbed`](crate::embed::CustomEmbed): Do embedding, providing your |
| 184 | +//! own embedding function which takes the path to the target artifact, and |
| 185 | +//! an [`EmbedProvider`](crate::embed::EmbedProvider) which gives a hex string |
| 186 | +//! or bytes to embed, as appropriate. |
| 187 | +//! |
| 188 | +//! # Meta |
| 189 | +//! |
| 190 | +//! ## Specification Compliance |
130 | 191 | //! |
131 | 192 | //! OmniBOR is a [draft specification][omnibor_spec], and this implementation |
132 | 193 | //! is the primary implementation of it. |
|
140 | 201 | //! All differences from the specification and this library are in the process |
141 | 202 | //! of being resolved through specification updates. |
142 | 203 | //! |
143 | | -//! # Comparison with other Software Identifiers |
| 204 | +//! ## Comparison with other Software Identifiers |
144 | 205 | //! |
145 | 206 | //! OmniBOR Artifact IDs are just one scheme for identifying software. Others |
146 | 207 | //! include the [Common Platform Enumeration (CPE)][cpe], |
|
222 | 283 | //! same inputs is not guaranteed, and will not be detectable by Derivation |
223 | 284 | //! Store Path alone). |
224 | 285 | //! |
225 | | -//! # Contribute |
| 286 | +//! ## Contribute |
226 | 287 | //! |
227 | 288 | //! The following items are things we'd want to complete before committing to |
228 | 289 | //! stability in this crate with a 1.0.0 release: |
|
231 | 292 | //! - [ ] Support for auto-embedding in ELF files |
232 | 293 | //! - [ ] Support for auto-embedding in Mach-O binary files |
233 | 294 | //! - [ ] Support for auto-embedding in Portable Executable files |
| 295 | +//! - [ ] ADG Support |
| 296 | +//! - [ ] Support creating an Artifact Dependency Graph |
234 | 297 | //! - [ ] FFI Support |
235 | 298 | //! - [ ] Exposing the `InputManifestBuilder` API over FFI |
236 | 299 | //! - [ ] Exposing the `InputManifest` API over FFI |
|
264 | 327 | //! [swhid]: https://www.swhid.org/ |
265 | 328 | //! [Issue Tracker]: https://github.com/omnibor/omnibor-rs/issues |
266 | 329 | //! [Contributor Guide]: https://github.com/omnibor/omnibor-rs/blob/main/CONTRIBUTING.md |
| 330 | +//! [RustCrypto]: https://github.com/rustcrypto |
| 331 | +//! [OpenSSL]: https://www.openssl.org/ |
| 332 | +//! [BoringSSL]: https://boringssl.googlesource.com/boringssl |
267 | 333 |
|
268 | 334 | /*=============================================================================================== |
269 | 335 | * Lint Configuration |
|
0 commit comments