use regex::Regex;
use serde::{Deserialize, Serialize};
use typed_builder::TypedBuilder;
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum BearerPropagationPolicy {
ValidateThenForward,
ExchangeForDownstreamToken,
}
pub(crate) fn default_bearer_propagation_policy() -> BearerPropagationPolicy {
BearerPropagationPolicy::ValidateThenForward
}
fn default_true() -> bool {
true
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, TypedBuilder)]
pub struct TokenPropagatorConfig {
#[builder(default = BearerPropagationPolicy::ValidateThenForward)]
#[serde(default = "default_bearer_propagation_policy")]
pub default_policy: BearerPropagationPolicy,
#[builder(default)]
#[serde(default)]
pub destination_policy: PropagationDestinationPolicy,
#[builder(default)]
#[serde(default)]
pub token_validation: PropagatedTokenValidationConfig,
}
impl Default for TokenPropagatorConfig {
fn default() -> Self {
Self {
default_policy: default_bearer_propagation_policy(),
destination_policy: PropagationDestinationPolicy::default(),
token_validation: PropagatedTokenValidationConfig::default(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default, TypedBuilder)]
pub struct PropagationDestinationPolicy {
#[builder(default)]
#[serde(default)]
pub allowed_node_ids: Vec<String>,
#[builder(default)]
#[serde(default)]
pub allowed_targets: Vec<AllowedPropagationTarget>,
#[builder(default = true)]
#[serde(default = "default_true")]
pub deny_sensitive_ip_literals: bool,
#[builder(default = true)]
#[serde(default = "default_true")]
pub require_explicit_port: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum PropagationScheme {
Https,
Http,
}
impl PropagationScheme {
pub fn as_str(&self) -> &'static str {
match self {
Self::Https => "https",
Self::Http => "http",
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "kind", rename_all = "snake_case")]
pub enum AllowedPropagationTarget {
ExactOrigin {
scheme: PropagationScheme,
hostname: String,
port: u16,
},
DomainSuffix {
scheme: PropagationScheme,
domain_suffix: String,
port: u16,
},
DomainRegex {
scheme: PropagationScheme,
#[serde(with = "serde_regex")]
domain_regex: Regex,
port: u16,
},
Cidr {
scheme: PropagationScheme,
cidr: String,
port: u16,
},
}
impl PartialEq for AllowedPropagationTarget {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(
Self::ExactOrigin {
scheme: left_scheme,
hostname: left_hostname,
port: left_port,
},
Self::ExactOrigin {
scheme: right_scheme,
hostname: right_hostname,
port: right_port,
},
) => {
left_scheme == right_scheme
&& left_hostname == right_hostname
&& left_port == right_port
}
(
Self::DomainSuffix {
scheme: left_scheme,
domain_suffix: left_suffix,
port: left_port,
},
Self::DomainSuffix {
scheme: right_scheme,
domain_suffix: right_suffix,
port: right_port,
},
) => {
left_scheme == right_scheme
&& left_suffix == right_suffix
&& left_port == right_port
}
(
Self::DomainRegex {
scheme: left_scheme,
domain_regex: left_regex,
port: left_port,
},
Self::DomainRegex {
scheme: right_scheme,
domain_regex: right_regex,
port: right_port,
},
) => {
left_scheme == right_scheme
&& left_regex.as_str() == right_regex.as_str()
&& left_port == right_port
}
(
Self::Cidr {
scheme: left_scheme,
cidr: left_cidr,
port: left_port,
},
Self::Cidr {
scheme: right_scheme,
cidr: right_cidr,
port: right_port,
},
) => left_scheme == right_scheme && left_cidr == right_cidr && left_port == right_port,
_ => false,
}
}
}
impl Eq for AllowedPropagationTarget {}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default, TypedBuilder)]
pub struct PropagatedTokenValidationConfig {
#[builder(default)]
#[serde(default)]
pub required_issuers: Vec<String>,
#[builder(default)]
#[serde(default)]
pub allowed_audiences: Vec<String>,
#[builder(default)]
#[serde(default)]
pub required_scopes: Vec<String>,
#[builder(default)]
#[serde(default)]
pub allowed_azp: Vec<String>,
}