securitydept_token_set_context/access_token_substrate/propagation/
config.rs1use regex::Regex;
2use serde::{Deserialize, Serialize};
3use typed_builder::TypedBuilder;
4
5#[cfg_attr(feature = "config-schema", derive(schemars::JsonSchema))]
7#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
8#[serde(rename_all = "snake_case")]
9pub enum BearerPropagationPolicy {
10 ValidateThenForward,
13 ExchangeForDownstreamToken,
19}
20
21pub(crate) fn default_bearer_propagation_policy() -> BearerPropagationPolicy {
22 BearerPropagationPolicy::ValidateThenForward
23}
24
25fn default_true() -> bool {
26 true
27}
28
29#[cfg_attr(feature = "config-schema", derive(schemars::JsonSchema))]
31#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, TypedBuilder)]
32pub struct TokenPropagatorConfig {
33 #[builder(default = BearerPropagationPolicy::ValidateThenForward)]
35 #[serde(default = "default_bearer_propagation_policy")]
36 pub default_policy: BearerPropagationPolicy,
37 #[builder(default)]
39 #[serde(default)]
40 pub destination_policy: PropagationDestinationPolicy,
41 #[builder(default)]
43 #[serde(default)]
44 pub token_validation: PropagatedTokenValidationConfig,
45}
46
47impl Default for TokenPropagatorConfig {
48 fn default() -> Self {
49 Self {
50 default_policy: default_bearer_propagation_policy(),
51 destination_policy: PropagationDestinationPolicy::default(),
52 token_validation: PropagatedTokenValidationConfig::default(),
53 }
54 }
55}
56
57#[cfg_attr(feature = "config-schema", derive(schemars::JsonSchema))]
59#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default, TypedBuilder)]
60pub struct PropagationDestinationPolicy {
61 #[builder(default)]
63 #[serde(default)]
64 pub allowed_node_ids: Vec<String>,
65 #[builder(default)]
67 #[serde(default)]
68 pub allowed_targets: Vec<AllowedPropagationTarget>,
69 #[builder(default = true)]
73 #[serde(default = "default_true")]
74 pub deny_sensitive_ip_literals: bool,
75 #[builder(default = true)]
78 #[serde(default = "default_true")]
79 pub require_explicit_port: bool,
80}
81
82#[cfg_attr(feature = "config-schema", derive(schemars::JsonSchema))]
84#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
85#[serde(rename_all = "snake_case")]
86pub enum PropagationScheme {
87 Https,
88 Http,
89}
90
91impl PropagationScheme {
92 pub fn as_str(&self) -> &'static str {
93 match self {
94 Self::Https => "https",
95 Self::Http => "http",
96 }
97 }
98}
99
100#[cfg_attr(feature = "config-schema", derive(schemars::JsonSchema))]
102#[derive(Debug, Clone, Serialize, Deserialize)]
103#[serde(tag = "kind", rename_all = "snake_case")]
104pub enum AllowedPropagationTarget {
105 ExactOrigin {
107 scheme: PropagationScheme,
108 hostname: String,
109 port: u16,
110 },
111 DomainSuffix {
113 scheme: PropagationScheme,
114 domain_suffix: String,
115 port: u16,
116 },
117 DomainRegex {
119 scheme: PropagationScheme,
120 #[serde(with = "serde_regex")]
121 #[cfg_attr(feature = "config-schema", schemars(with = "String"))]
122 domain_regex: Regex,
123 port: u16,
124 },
125 Cidr {
127 scheme: PropagationScheme,
128 cidr: String,
129 port: u16,
130 },
131}
132
133impl PartialEq for AllowedPropagationTarget {
134 fn eq(&self, other: &Self) -> bool {
135 match (self, other) {
136 (
137 Self::ExactOrigin {
138 scheme: left_scheme,
139 hostname: left_hostname,
140 port: left_port,
141 },
142 Self::ExactOrigin {
143 scheme: right_scheme,
144 hostname: right_hostname,
145 port: right_port,
146 },
147 ) => {
148 left_scheme == right_scheme
149 && left_hostname == right_hostname
150 && left_port == right_port
151 }
152 (
153 Self::DomainSuffix {
154 scheme: left_scheme,
155 domain_suffix: left_suffix,
156 port: left_port,
157 },
158 Self::DomainSuffix {
159 scheme: right_scheme,
160 domain_suffix: right_suffix,
161 port: right_port,
162 },
163 ) => {
164 left_scheme == right_scheme
165 && left_suffix == right_suffix
166 && left_port == right_port
167 }
168 (
169 Self::DomainRegex {
170 scheme: left_scheme,
171 domain_regex: left_regex,
172 port: left_port,
173 },
174 Self::DomainRegex {
175 scheme: right_scheme,
176 domain_regex: right_regex,
177 port: right_port,
178 },
179 ) => {
180 left_scheme == right_scheme
181 && left_regex.as_str() == right_regex.as_str()
182 && left_port == right_port
183 }
184 (
185 Self::Cidr {
186 scheme: left_scheme,
187 cidr: left_cidr,
188 port: left_port,
189 },
190 Self::Cidr {
191 scheme: right_scheme,
192 cidr: right_cidr,
193 port: right_port,
194 },
195 ) => left_scheme == right_scheme && left_cidr == right_cidr && left_port == right_port,
196 _ => false,
197 }
198 }
199}
200
201impl Eq for AllowedPropagationTarget {}
202
203#[cfg_attr(feature = "config-schema", derive(schemars::JsonSchema))]
206#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default, TypedBuilder)]
207pub struct PropagatedTokenValidationConfig {
208 #[builder(default)]
210 #[serde(default)]
211 pub required_issuers: Vec<String>,
212 #[builder(default)]
214 #[serde(default)]
215 pub allowed_audiences: Vec<String>,
216 #[builder(default)]
218 #[serde(default)]
219 pub required_scopes: Vec<String>,
220 #[builder(default)]
222 #[serde(default)]
223 pub allowed_azp: Vec<String>,
224}