Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #46 from maxlambrecht/spire-api
* Refactor repository: new `spiffe` folder, new `spire-api` crate, and `spire-api-sdk` submodule (#42) Signed-off-by: Max Lambrecht <maxlambrecht@gmail.com> * Add delegated identity API support to spire-api package (#43) Signed-off-by: Eitan Yarmush <eitan.yarmush@solo.io> * Refactoring `spiffe` crate: Introducing `spiffe-types` and `workload-api` features (#44) Signed-off-by: Max Lambrecht <maxlambrecht@gmail.com> * Add Releasing Process Documentation for Crates (#45) Signed-off-by: Max Lambrecht <maxlambrecht@gmail.com> --------- Signed-off-by: Max Lambrecht <maxlambrecht@gmail.com> Co-authored-by: Eitan Yarmush <eitan.yarmush@solo.io>
- Loading branch information
Showing
67 changed files
with
2,254 additions
and
361 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
[submodule "spire-api-sdk"] | ||
path = spire-api-sdk | ||
url = https://github.com/spiffe/spire-api-sdk.git |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,52 +1,5 @@ | ||
[package] | ||
edition = "2018" | ||
name = "spiffe" | ||
# When releasing to crates.io: | ||
# - Update CHANGELOG.md. | ||
# - Create a new tag | ||
version = "0.3.1" | ||
authors = ["Max Lambrecht <maxlambrecht@gmail.com>"] | ||
description = "Rust client library implementation for SPIFFE" | ||
license = "Apache-2.0" | ||
repository = "https://github.com/maxlambrecht/rust-spiffe" | ||
documentation = "https://docs.rs/spiffe" | ||
readme = "README.md" | ||
categories = ["cryptography"] | ||
keywords = ["SPIFFE", "X509", "JWT"] | ||
|
||
[dependencies] | ||
tonic = { version = "0.9", default-features = false, features = ["prost", "codegen", "transport"]} | ||
prost = { version = "0.11"} | ||
prost-types = {version = "0.11"} | ||
tokio = { "version" = "1", features = ["net", "test-util"]} | ||
tokio-stream = "0.1" | ||
tower = { version = "0.4", features = ["util"] } | ||
thiserror = "1.0" | ||
url = "2.2" | ||
asn1 = { package = "simple_asn1", version = "0.6" } | ||
x509-parser = "0.15" | ||
pkcs8 = "0.10" | ||
jsonwebtoken = "8.3" | ||
jsonwebkey = { version = "0.3", features = ["jsonwebtoken", "jwt-convert"] } | ||
serde = { version = "1.0", features = ["derive"] } | ||
serde_json = "1.0" | ||
zeroize = { version = "1.6", features = ["zeroize_derive"] } | ||
time = "0.3" | ||
|
||
|
||
[dev-dependencies] | ||
jsonwebkey = { version = "0.3", features = ["generate"] } | ||
tokio-test = "0.4" | ||
once_cell = "1.18" | ||
|
||
# used to verify in tests that the certificates bytes from the X.509 SVIDs and bundle authorities | ||
# are parseable as OpenSSL X.509 certificates. | ||
openssl = { version = "0.10", features = ["vendored"] } | ||
|
||
[build-dependencies] | ||
tonic-build = { version = "0.9", default-features = false, features = ["prost"] } | ||
prost-build = "0.11" | ||
anyhow = "1.0.65" | ||
|
||
[features] | ||
integration-tests = [] | ||
[workspace] | ||
members = [ | ||
"spiffe", | ||
"spire-api", | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,134 +1,27 @@ | ||
# Rust SPIFFE Library | ||
# Rust SPIRE Libraries | ||
|
||
This utility library enables interaction with the [SPIFFE Workload API](https://github.com/spiffe/spiffe/blob/main/standards/SPIFFE_Workload_API.md). It allows fetching of X.509 and JWT SVIDs, bundles and supports watch/stream updates. The types in the library are in compliance with [SPIFFE standards](https://github.com/spiffe/spiffe/tree/main/standards). More about SPIFFE can be found at [spiffe.io](https://spiffe.io/). | ||
This repository contains two distinct Rust libraries focused on supporting SPIRE functionalities: | ||
|
||
[![crates.io](https://img.shields.io/crates/v/spiffe.svg)](https://crates.io/crates/spiffe) | ||
[![docs.rs](https://docs.rs/spiffe/badge.svg)](https://docs.rs/spiffe) | ||
![CI](https://github.com/maxlambrecht/rust-spiffe/workflows/Continuous%20Integration/badge.svg) | ||
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/maxlambrecht/rust-spiffe/blob/main/LICENSE) | ||
## [spiffe](./spiffe) | ||
|
||
## Getting Started | ||
|
||
Include `spiffe` in your `Cargo.toml` dependencies: | ||
|
||
```toml | ||
[dependencies] | ||
spiffe = "0.3.1" | ||
``` | ||
|
||
## Examples of Usage | ||
|
||
### Creating a `WorkloadApiClient` | ||
|
||
Create client using the endpoint socket path: | ||
|
||
```rust | ||
let mut client = WorkloadApiClient::new_from_path("unix:/tmp/spire-agent/public/api.sock").await?; | ||
``` | ||
|
||
Or by using the `SPIFFE_ENDPOINT_SOCKET` environment variable: | ||
|
||
```rust | ||
let mut client = WorkloadApiClient::default().await?; | ||
``` | ||
|
||
### Fetching X.509 Materials | ||
|
||
Fetch the default X.509 SVID, a set of X.509 bundles, all X.509 materials, or watch for updates on the X.509 context and bundles. | ||
|
||
```rust | ||
// fetch the default X.509 SVID | ||
let x509_svid: X509Svid = client.fetch_x509_svid().await?; | ||
|
||
// fetch a set of X.509 bundles (X.509 public key authorities) | ||
let x509_bundles: X509BundleSet = client.fetch_x509_bundles().await?; | ||
The `spiffe` crate enables interaction with | ||
the [SPIFFE Workload API](https://github.com/spiffe/spiffe/blob/main/standards/SPIFFE_Workload_API.md). It allows | ||
fetching of X.509 and JWT SVIDs, bundles, and supports watch/stream updates. The types in the library are in compliance | ||
with [SPIFFE standards](https://github.com/spiffe/spiffe/tree/main/standards). More about SPIFFE can be found | ||
at [spiffe.io](https://spiffe.io/). | ||
|
||
// fetch all the X.509 materials (SVIDs and bundles) | ||
let x509_context: X509Context = client.fetch_x509_context().await?; | ||
- [Read the README](./spiffe/README.md) for more information. | ||
|
||
// get the X.509 chain of certificates from the SVID | ||
let cert_chain: &Vec<Certificate> = x509_svid.cert_chain(); | ||
## [spire-api](./spire-api) | ||
|
||
// get the private key from the SVID | ||
let private_key: &PrivateKey = x509_svid.private_key(); | ||
The `spire-api` crate provides support for SPIRE specific APIs, including the Delegated Identity API. | ||
|
||
// parse a SPIFFE trust domain | ||
let trust_domain = TrustDomain::try_from("example.org")?; | ||
- [Read the README](./spire-api/README.md) for more information. | ||
|
||
// get the X.509 bundle associated to the trust domain | ||
let x509_bundle: &X509Bundle = x509_bundles.get_bundle(&trust_domain)?; | ||
|
||
// get the X.509 authorities (public keys) in the bundle | ||
let x509_authorities: &Vec<Certificate> = x509_bundle.authorities(); | ||
|
||
// watch for updates on the X.509 context | ||
let mut x509_context_stream = client.watch_x509_context_stream().await?; | ||
while let Some(x509_context_update) = x509_context_stream.next().await { | ||
match x509_context_update { | ||
Ok(update) => { | ||
// handle the updated X509Context | ||
} | ||
Err(e) => { | ||
// handle the error | ||
} | ||
} | ||
} | ||
|
||
// watch for updates on the X.509 bundles | ||
let mut x509_bundle_stream = client.watch_x509_bundles_stream().await?; | ||
while let Some(x509_bundle_update) = x509_bundle_stream.next().await { | ||
match x509_bundle_update { | ||
Ok(update) => { | ||
// handle the updated X509 bundle | ||
} | ||
Err(e) => { | ||
// handle the error | ||
} | ||
} | ||
} | ||
``` | ||
|
||
### Fetching and Validating JWT Tokens and Bundles | ||
|
||
Fetch JWT tokens, parse and validate them, fetch JWT bundles, or watch for updates on the JWT bundles. | ||
|
||
```rust | ||
// parse a SPIFFE ID to ask a token for | ||
let spiffe_id = SpiffeId::try_from("spiffe://example.org/my-service")?; | ||
|
||
// fetch a jwt token for the provided SPIFFE-ID and with the target audience `service1.com` | ||
let jwt_token = client.fetch_jwt_token(&["audience1", "audience2"], Some(&spiffe_id)).await?; | ||
|
||
// fetch the jwt token and parses it as a `JwtSvid` | ||
let jwt_svid = client.fetch_jwt_svid(&["audience1", "audience2"], Some(&spiffe_id)).await?; | ||
|
||
// fetch a set of jwt bundles (public keys for validating jwt token) | ||
let jwt_bundles = client.fetch_jwt_bundles().await?; | ||
|
||
// parse a SPIFFE trust domain | ||
let trust_domain = TrustDomain::try_from("example.org")?; | ||
|
||
// get the JWT bundle associated to the trust domain | ||
let jwt_bundle: &JwtBundle = jwt_bundles.get_bundle(&trust_domain)?; | ||
|
||
// get the JWT authorities (public keys) in the bundle | ||
let jwt_authority: &JwtAuthority = jwt_bundle.find_jwt_authority("a_key_id")?; | ||
## Getting Started | ||
|
||
// parse a `JwtSvid` validating the token signature with a JWT bundle source. | ||
let validated_jwt_svid = JwtSvid::parse_and_validate(&jwt_token, &jwt_bundles_set, &["service1.com"])?; | ||
Follow the links above to the individual README files for detailed information on how to use each library. | ||
|
||
// watch for updates on the JWT bundles | ||
let mut jwt_bundle_stream = client.watch_jwt_bundles_stream().await?; | ||
while let Some(jwt_bundle_update) = jwt_bundle_stream.next().await { | ||
match jwt_bundle_update { | ||
Ok(update) => { | ||
// handle the updated JWT bundle | ||
} | ||
Err(e) => { | ||
// handle the error | ||
} | ||
} | ||
} | ||
``` | ||
## License | ||
|
||
For more detailed examples and additional features, refer to the [documentation](https://docs.rs/spiffe). | ||
This project is licensed under [LICENSE NAME](./LICENSE). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
# Releasing Crates | ||
|
||
Follow these steps to create a new release for a specific crate in the repository. | ||
|
||
## 1. Prepare the Release | ||
|
||
- Determine the crate you are releasing and the new version number. | ||
- Update the crate's `Cargo.toml` file with the new version number on a dedicated branch. | ||
- Update the CHANGELOG.md file with detailed notes about the new release. Include any new features, bug fixes, and other | ||
relevant information. | ||
- Update any relevant documentation, including README files and any public-facing documents related to the crate. | ||
|
||
## 2. Create a Pull Request (PR) for Preparing the Release | ||
|
||
- Push the branch and create a pull request to merge the changes into the main branch. | ||
- Include the changes to the `Cargo.toml`, CHANGELOG.md, and documentation files in the PR. | ||
- Engage the maintainers for a thorough review of the changes. | ||
|
||
## 3. Merge the PR | ||
|
||
- Once the PR is approved, merge it into the main branch. | ||
|
||
## 4. Create the Release Branch | ||
|
||
- Checkout the main branch. | ||
- Create a new branch for the release, named with the pattern `release/CRATE-NAME-VERSION`. | ||
|
||
For example: | ||
```sh | ||
git checkout -b release/spiffe-v0.3.2 | ||
``` | ||
|
||
## 5. Create a Git Tag | ||
|
||
- Create a Git tag for the new release, using the same pattern `CRATE-NAME-VERSION`. | ||
|
||
For example: | ||
```sh | ||
git tag spiffe-v0.3.2 | ||
``` | ||
|
||
- Push the tag and the branch to the repository. | ||
|
||
## 6. Publish the Crate | ||
|
||
For example: | ||
```sh | ||
cargo publish --manifest-path spiffe/Cargo.toml | ||
``` | ||
|
||
## 7 Create a GitHub Release | ||
|
||
Navigate to the "Releases" section in the repository on GitHub. | ||
Draft a new release using the tag created earlier, and include the notes from the CHANGELOG.md. | ||
Publish the release. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
agent { | ||
data_dir = "./data/agent" | ||
log_level = "DEBUG" | ||
trust_domain = "example.org" | ||
server_address = "localhost" | ||
server_port = 8081 | ||
|
||
# Insecure bootstrap is NOT appropriate for production use but is ok for | ||
# simple testing/evaluation purposes. | ||
insecure_bootstrap = true | ||
|
||
admin_socket_path = "$STRIPPED_SPIRE_ADMIN_ENDPOINT_SOCKET" | ||
authorized_delegates = [ | ||
"spiffe://example.org/myservice", | ||
] | ||
} | ||
|
||
plugins { | ||
KeyManager "disk" { | ||
plugin_data { | ||
directory = "./data/agent" | ||
} | ||
} | ||
|
||
NodeAttestor "join_token" { | ||
plugin_data {} | ||
} | ||
|
||
WorkloadAttestor "unix" { | ||
plugin_data {} | ||
} | ||
} |
Oops, something went wrong.