Skip to content

Commit

Permalink
Refactor repository: new spiffe folder, new spire-api crate, and …
Browse files Browse the repository at this point in the history
…`spire-api-sdk` submodule (#42)

Signed-off-by: Max Lambrecht <maxlambrecht@gmail.com>
  • Loading branch information
maxlambrecht committed Aug 14, 2023
1 parent 25a44c7 commit 8b74f1a
Show file tree
Hide file tree
Showing 59 changed files with 1,211 additions and 179 deletions.
6 changes: 5 additions & 1 deletion .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ updates:
schedule:
interval: "daily"
- package-ecosystem: "cargo"
directory: "/" # Location of the Cargo.toml file
directory: "/spiffe" # Location of the Cargo.toml file for spiffe crate
schedule:
interval: "daily"
- package-ecosystem: "cargo"
directory: "/spire-api" # Location of the Cargo.toml file for spire-api crate
schedule:
interval: "daily"
17 changes: 16 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ jobs:
steps:
- name: Check out code
uses: actions/checkout@v3
with:
submodules: recursive
- name: Install dependencies and common setup
uses: ./.github/actions/setup-env
- name: Lint Rust code with rustfmt and clippy
Expand All @@ -23,25 +25,38 @@ jobs:
steps:
- name: Check out code
uses: actions/checkout@v3
with:
submodules: recursive
- name: Install dependencies and common setup
uses: ./.github/actions/setup-env
- name: Build Rust project
run: cargo build

test:
name: Run SPIFFE Integration Tests
name: Run spiffe and spire-api Integration Tests
runs-on: ubuntu-latest
env:
SPIFFE_ENDPOINT_SOCKET: unix:/tmp/spire-agent/public/api.sock
needs: build
steps:
- name: Check out code
uses: actions/checkout@v3
with:
submodules: recursive

- name: Install dependencies and common setup
uses: ./.github/actions/setup-env

- name: Start SPIRE
run: ./scripts/run-spire.sh &

- name: Execute spiffe Integration Tests
run: RUST_BACKTRACE=1 cargo test --features integration-tests
working-directory: spiffe

- name: Execute spire-api Integration Tests
run: RUST_BACKTRACE=1 cargo test --features integration-tests
working-directory: spire-api

- name: Clean up SPIRE
run: ./scripts/cleanup-spire.sh
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
Cargo.lock
**/Cargo.lock

# These are backup files generated by rustfmt
**/*.rs.bk
Expand Down
3 changes: 3 additions & 0 deletions .gitmodules
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
57 changes: 5 additions & 52 deletions Cargo.toml
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",
]
139 changes: 16 additions & 123 deletions README.md
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).
File renamed without changes.
52 changes: 52 additions & 0 deletions spiffe/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
[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 = []

0 comments on commit 8b74f1a

Please sign in to comment.