Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@ derivative = "2.1.1"
zeroize = "1.1.0"
users = "0.10.0"
url = "2.2.0"
spiffe = { version = "0.1.1", optional = true }

[dev-dependencies]
mockstream = "0.0.3"

[features]
default = []
spiffe-auth = ["spiffe"]
testing = ["parsec-interface/testing"]
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
This repository contains a Rust client for consuming the API provided by the [Parsec service](https://github.com/parallaxsecond/parsec).
The low-level functionality that this library uses for IPC is implemented in the [interface crate](https://github.com/parallaxsecond/parsec-interface-rs).

Check out the `spiffe` branch for JWT SVID authentication feature.
When using the JWT-SVID authentication method, the client will expect the `SPIFFE_ENDPOINT_SOCKET` environment variable to contain the path of the Workload API endpoint.
See the [SPIFFE Workload Endpoint](https://github.com/spiffe/spiffe/blob/master/standards/SPIFFE_Workload_Endpoint.md#4-locating-the-endpoint) for more information.

## Locating the Parsec endpoint

Expand Down
23 changes: 23 additions & 0 deletions src/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ pub enum Authentication {
/// Used for authentication via Peer Credentials provided by Unix
/// operating systems for Domain Socket connections.
UnixPeerCredentials,
/// Authentication using JWT SVID tokens. The will fetch its JWT-SVID and pass it in the
/// Authentication field. The socket endpoint is found through the SPIFFE_ENDPOINT_SOCKET
/// environment variable.
#[cfg(feature = "spiffe-auth")]
JwtSvid,
}

impl Authentication {
Expand All @@ -30,6 +35,8 @@ impl Authentication {
Authentication::None => AuthType::NoAuth,
Authentication::Direct(_) => AuthType::Direct,
Authentication::UnixPeerCredentials => AuthType::UnixPeerCredentials,
#[cfg(feature = "spiffe-auth")]
Authentication::JwtSvid => AuthType::JwtSvid,
}
}
}
Expand All @@ -45,6 +52,20 @@ impl TryFrom<&Authentication> for RequestAuth {
let current_uid = users::get_current_uid();
Ok(RequestAuth::new(current_uid.to_le_bytes().to_vec()))
}
#[cfg(feature = "spiffe-auth")]
Authentication::JwtSvid => {
use crate::error::ClientErrorKind;
use log::error;
use spiffe::workload_api::client::WorkloadApiClient;

let client = WorkloadApiClient::default().unwrap();
let token = client.fetch_jwt_token(&["parsec"], None).map_err(|e| {
error!("Error while fetching the JWT-SVID ({}).", e);
Error::Client(ClientErrorKind::Spiffe(e))
})?;

Ok(RequestAuth::new(token.as_bytes().into()))
}
}
}
}
Expand All @@ -57,6 +78,8 @@ impl PartialEq for Authentication {
(Authentication::Direct(app_name), Authentication::Direct(other_app_name)) => {
app_name == other_app_name
}
#[cfg(feature = "spiffe-auth")]
(Authentication::JwtSvid, Authentication::JwtSvid) => true,
_ => false,
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/core/basic_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,8 @@ impl BasicClient {
AuthType::UnixPeerCredentials => {
self.auth_data = Authentication::UnixPeerCredentials
}
#[cfg(feature = "spiffe-auth")]
AuthType::JwtSvid => self.auth_data = Authentication::JwtSvid,
auth => {
warn!(
"Authenticator of type \"{:?}\" not supported by this client library",
Expand Down
5 changes: 5 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ pub enum ClientErrorKind {
InvalidSocketAddress,
/// The socket URL is invalid
InvalidSocketUrl,
/// Error while using the SPIFFE Workload API
#[cfg(feature = "spiffe-auth")]
Spiffe(spiffe::workload_api::client::ClientError),
}

impl From<ClientErrorKind> for Error {
Expand Down Expand Up @@ -80,6 +83,8 @@ impl fmt::Display for ClientErrorKind {
ClientErrorKind::NotFound => write!(f, "one of the resources required in the operation was not found"),
ClientErrorKind::InvalidSocketAddress => write!(f, "the socket address provided in the URL is not valid"),
ClientErrorKind::InvalidSocketUrl => write!(f, "the socket URL is invalid"),
#[cfg(feature = "spiffe-auth")]
ClientErrorKind::Spiffe(error) => error.fmt(f),
}
}
}
Expand Down
1 change: 1 addition & 0 deletions tests/ci.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ set -euf -o pipefail
################
RUST_BACKTRACE=1 cargo build
RUST_BACKTRACE=1 cargo build --features testing
RUST_BACKTRACE=1 cargo build --features spiffe-auth
RUST_BACKTRACE=1 cargo build --no-default-features

#################
Expand Down