spiffe-rs 0.1.0

Rust port of spiffe-go with SPIFFE IDs, bundles, SVIDs, Workload API client, federation helpers, and rustls-based SPIFFE TLS utilities.
Documentation
use crate::logger;
use crate::workloadapi::{backoff, client::Client, LoggerRef};
use std::sync::Arc;

pub trait ClientOption: Send + Sync {
    fn configure_client(&self, config: &mut ClientConfig);
}

pub trait SourceOption: Send + Sync {
    fn configure_x509_source(&self, config: &mut X509SourceConfig);
    fn configure_jwt_source(&self, config: &mut JWTSourceConfig);
    fn configure_bundle_source(&self, config: &mut BundleSourceConfig);
}

pub trait X509SourceOption: Send + Sync {
    fn configure_x509_source(&self, config: &mut X509SourceConfig);
}

pub trait JWTSourceOption: Send + Sync {
    fn configure_jwt_source(&self, config: &mut JWTSourceConfig);
}

pub trait BundleSourceOption: Send + Sync {
    fn configure_bundle_source(&self, config: &mut BundleSourceConfig);
}

pub trait DialOption: Send + Sync {
    fn apply(&self, endpoint: tonic::transport::Endpoint) -> tonic::transport::Endpoint;
}

pub fn with_addr(addr: impl Into<String>) -> Arc<dyn ClientOption> {
    Arc::new(WithAddr {
        addr: addr.into(),
    })
}

pub fn with_dial_options(options: Vec<Arc<dyn DialOption>>) -> Arc<dyn ClientOption> {
    Arc::new(WithDialOptions { options })
}

pub fn with_logger(log: LoggerRef) -> Arc<dyn ClientOption> {
    Arc::new(WithLogger { log })
}

pub fn with_backoff_strategy(strategy: Arc<dyn backoff::BackoffStrategy>) -> Arc<dyn ClientOption> {
    Arc::new(WithBackoffStrategy { strategy })
}

pub fn with_client(client: Arc<Client>) -> Arc<dyn SourceOption> {
    Arc::new(WithClient { client })
}

pub fn with_client_options(options: Vec<Arc<dyn ClientOption>>) -> Arc<dyn SourceOption> {
    Arc::new(WithClientOptions { options })
}

pub fn with_default_x509_svid_picker(
    picker: Arc<dyn Fn(&[crate::svid::x509svid::SVID]) -> crate::svid::x509svid::SVID + Send + Sync>,
) -> Arc<dyn X509SourceOption> {
    Arc::new(WithDefaultX509SVIDPicker { picker })
}

pub fn with_default_jwt_svid_picker(
    picker: Arc<dyn Fn(&[crate::svid::jwtsvid::SVID]) -> crate::svid::jwtsvid::SVID + Send + Sync>,
) -> Arc<dyn JWTSourceOption> {
    Arc::new(WithDefaultJWTSVIDPicker { picker })
}

#[derive(Clone)]
pub struct ClientConfig {
    pub address: Option<String>,
    pub dial_options: Vec<Arc<dyn DialOption>>,
    pub log: LoggerRef,
    pub backoff_strategy: Arc<dyn backoff::BackoffStrategy>,
}

impl Default for ClientConfig {
    fn default() -> Self {
        Self {
            address: None,
            dial_options: Vec::new(),
            log: Arc::new(logger::null_logger()),
            backoff_strategy: Arc::new(backoff::LinearBackoffStrategy::default()),
        }
    }
}

pub struct WatcherConfig {
    pub client: Option<Arc<Client>>,
    pub client_options: Vec<Arc<dyn ClientOption>>,
}

impl Default for WatcherConfig {
    fn default() -> Self {
        Self {
            client: None,
            client_options: Vec::new(),
        }
    }
}

pub struct X509SourceConfig {
    pub watcher: WatcherConfig,
    pub picker: Option<
        Arc<dyn Fn(&[crate::svid::x509svid::SVID]) -> crate::svid::x509svid::SVID + Send + Sync>,
    >,
}

impl Default for X509SourceConfig {
    fn default() -> Self {
        Self {
            watcher: WatcherConfig::default(),
            picker: None,
        }
    }
}

pub struct JWTSourceConfig {
    pub watcher: WatcherConfig,
    pub picker:
        Option<Arc<dyn Fn(&[crate::svid::jwtsvid::SVID]) -> crate::svid::jwtsvid::SVID + Send + Sync>>,
}

impl Default for JWTSourceConfig {
    fn default() -> Self {
        Self {
            watcher: WatcherConfig::default(),
            picker: None,
        }
    }
}

pub struct BundleSourceConfig {
    pub watcher: WatcherConfig,
}

impl Default for BundleSourceConfig {
    fn default() -> Self {
        Self {
            watcher: WatcherConfig::default(),
        }
    }
}

struct WithAddr {
    addr: String,
}

impl ClientOption for WithAddr {
    fn configure_client(&self, config: &mut ClientConfig) {
        config.address = Some(self.addr.clone());
    }
}

struct WithDialOptions {
    options: Vec<Arc<dyn DialOption>>,
}

impl ClientOption for WithDialOptions {
    fn configure_client(&self, config: &mut ClientConfig) {
        config.dial_options.extend(self.options.iter().cloned());
    }
}

struct WithLogger {
    log: LoggerRef,
}

impl ClientOption for WithLogger {
    fn configure_client(&self, config: &mut ClientConfig) {
        config.log = self.log.clone();
    }
}

struct WithBackoffStrategy {
    strategy: Arc<dyn backoff::BackoffStrategy>,
}

impl ClientOption for WithBackoffStrategy {
    fn configure_client(&self, config: &mut ClientConfig) {
        config.backoff_strategy = self.strategy.clone();
    }
}

struct WithClient {
    client: Arc<Client>,
}

impl SourceOption for WithClient {
    fn configure_x509_source(&self, config: &mut X509SourceConfig) {
        config.watcher.client = Some(self.client.clone());
    }

    fn configure_jwt_source(&self, config: &mut JWTSourceConfig) {
        config.watcher.client = Some(self.client.clone());
    }

    fn configure_bundle_source(&self, config: &mut BundleSourceConfig) {
        config.watcher.client = Some(self.client.clone());
    }
}

struct WithClientOptions {
    options: Vec<Arc<dyn ClientOption>>,
}

impl SourceOption for WithClientOptions {
    fn configure_x509_source(&self, config: &mut X509SourceConfig) {
        config.watcher.client_options = self.options.clone();
    }

    fn configure_jwt_source(&self, config: &mut JWTSourceConfig) {
        config.watcher.client_options = self.options.clone();
    }

    fn configure_bundle_source(&self, config: &mut BundleSourceConfig) {
        config.watcher.client_options = self.options.clone();
    }
}

struct WithDefaultX509SVIDPicker {
    picker: Arc<dyn Fn(&[crate::svid::x509svid::SVID]) -> crate::svid::x509svid::SVID + Send + Sync>,
}

impl X509SourceOption for WithDefaultX509SVIDPicker {
    fn configure_x509_source(&self, config: &mut X509SourceConfig) {
        config.picker = Some(self.picker.clone());
    }
}

impl SourceOption for WithDefaultX509SVIDPicker {
    fn configure_x509_source(&self, config: &mut X509SourceConfig) {
        X509SourceOption::configure_x509_source(self, config);
    }

    fn configure_jwt_source(&self, _config: &mut JWTSourceConfig) {}

    fn configure_bundle_source(&self, _config: &mut BundleSourceConfig) {}
}

struct WithDefaultJWTSVIDPicker {
    picker: Arc<dyn Fn(&[crate::svid::jwtsvid::SVID]) -> crate::svid::jwtsvid::SVID + Send + Sync>,
}

impl JWTSourceOption for WithDefaultJWTSVIDPicker {
    fn configure_jwt_source(&self, config: &mut JWTSourceConfig) {
        config.picker = Some(self.picker.clone());
    }
}

impl SourceOption for WithDefaultJWTSVIDPicker {
    fn configure_x509_source(&self, _config: &mut X509SourceConfig) {}

    fn configure_jwt_source(&self, config: &mut JWTSourceConfig) {
        JWTSourceOption::configure_jwt_source(self, config);
    }

    fn configure_bundle_source(&self, _config: &mut BundleSourceConfig) {}
}