Skip to content

Commit

Permalink
Initial implementation of the library (#1)
Browse files Browse the repository at this point in the history
* Initial commit defining and implementing the basic interface and SPIFFE types:

- Workload API client with one-shot call methods
- Certificate and PrivateKey types
- X.509 SVID and bundle types
- JWT SVID and bundle types
- TrustDomain and SpiffeId types

Signed-off-by: Max Lambrecht <maxlambrecht@gmail.com>
  • Loading branch information
Max Lambrecht authored Jun 15, 2021
1 parent 91479ed commit dabc35e
Showing 44 changed files with 5,671 additions and 2 deletions.
1 change: 1 addition & 0 deletions .clippy.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
msrv = "1.47"
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -8,3 +8,5 @@ Cargo.lock

# These are backup files generated by rustfmt
**/*.rs.bk

.idea
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

## 0.1.0
- Initial release
38 changes: 38 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
[package]
name = "spiffe"
version = "0.1.0"
authors = ["Max Lambrecht <maxlambrecht@gmail.com>"]
edition = "2018"
license = "Apache-2.0"
categories = ["crytography"]
keywords = ["SPIFFE", "X509", "JWT"]
readme = "README.md"
repository = "https://github.com/maxlambrecht/rust-spiffe"
description = "Rust client library implementation for SPIFFE"

[dependencies]
grpcio = { version = "0.9", default-features = false, features = ["protobuf-codec"] }
protobuf = "2.24.1"
futures = "0.3.15"
thiserror = "1.0.25"
url = "2.2.2"
asn1 = { package = "simple_asn1", version = "0.5.3" }
x509-parser = "0.9.2"
pkcs8 = "0.6.1"
jsonwebtoken = "7.2.0"
jsonwebkey = { version = "0.3.2", features = ["jsonwebtoken", "jwt-convert"] }
serde = { version = "1.0.126", features = ["derive"] }
serde_json = "1.0.64"
chrono = { version = "0.4.19", features = ["serde"] }
zeroize = { version = "1.3.0", features = ["zeroize_derive"] }

[build-dependencies]
protoc-grpcio = "3.0.0"
grpcio-sys = "0.9.0"

[dev-dependencies]
jsonwebkey = { version = "0.3.2", features = ["generate"] }

# 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"] }
81 changes: 79 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,84 @@
# rust-spiffe

[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/maxlambrecht/rust-spiffe/blob/main/LICENSE)

Rust client library implementation for SPIFFE, to interact with the Workload API to fetch and verify JWT and X.509 SVIDs.
## Overview

This library provides functions to interact with the [SPIFFE Workload API](https://github.com/spiffe/spiffe/blob/main/standards/SPIFFE_Workload_API.md)
to fetch X.509 and JWT SVIDs and Bundles. It also provides types that comply with the [SPIFFE standards](https://github.com/spiffe/spiffe/tree/main/standards).

Under development.

## Examples

### Create a `WorkloadApiClient`

Providing the endpoint socket path as parameter:

```rust
let client = WorkloadApiClient::new("unix:/tmp/spire-agent/api/public.sock")?;
```

Providing the endpoint socket path through the environment variable `SPIFFE_ENDPOINT_SOCKET`:

```rust
let client = WorkloadApiClient::default()?;
```

### Fetching X.509 materials

```rust

// fetch the default X.509 SVID
let x509_svid: X509Svid = client.fetch_x509_svid()?;

// fetch a set of X.509 bundles (X.509 public key authorities)
let x509_bundles: X509BundleSet = client.fetch_x509_bundles()?;

// fetch all the X.509 materials (SVIDs and bundles)
let x509_context: X509Context = client.fetch_x509_context()?;

// get the X.509 chain of certificates from the SVID
let cert_chain: &Vec<Certificate> = x509_svid.cert_chain();

// get the private key from the SVID
let private_key: &PrivateKey = x509_svid.private_key();

// parse a SPIFFE trust domain
let trust_domain = TrustDomain::try_from("example.org")?;

// get the X.509 bundle associated to the trust domain
let x509_bundle: &X509Bundle = x509_bundles.get_bundle(&trust_domain).unwrap();

// get the X.509 authorities (public keys) in the bundle
let x509_authorities: &Vec<Certificate> = x509_bundle.authorities();
```


### Fetching JWT tokens and bundles and validating tokens

```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))?;

// fetch the jwt token and parses it as a `JwtSvid`
let jwt_svid = client.fetch_jwt_svid(&["audience1", "audience2"], Some(&spiffe_id))?;

// fetch a set of jwt bundles (public keys for validating jwt token)
let jwt_bundles = client.fetch_jwt_bundles()?;

// 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).unwrap();

// get the JWT authorities (public keys) in the bundle
let jwt_authority: &JwtAuthority = jwt_bundle.find_jwt_authority("a_key_id").unwrap();

// 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"])?;
```
6 changes: 6 additions & 0 deletions rustfmt.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# unstable features, use nightly: `rustup run nightly cargo fmt`
reorder_imports = true
imports_granularity = "Module"
format_code_in_doc_comments = true
format_macro_bodies = true
format_strings = true
Loading

0 comments on commit dabc35e

Please sign in to comment.