1use crate::error::Result;
2use crate::resolve::MaterialWatcher;
3use crate::types::{authorize_any, AuthorizeSpiffeId};
4use crate::verifier::SpiffeClientCertVerifier;
5use rustls::server::ResolvesServerCert;
6use rustls::ServerConfig;
7use spiffe::{TrustDomain, X509Source};
8use std::sync::Arc;
9
10#[derive(Clone)]
14pub struct ServerConfigOptions {
15 pub trust_domain: TrustDomain,
17
18 pub authorize_client: AuthorizeSpiffeId,
23}
24
25impl std::fmt::Debug for ServerConfigOptions {
26 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
27 f.debug_struct("ServerConfigOptions")
28 .field("trust_domain", &self.trust_domain)
29 .field("authorize_client", &"<authorize_fn>")
30 .finish()
31 }
32}
33
34impl ServerConfigOptions {
35 pub fn allow_any(trust_domain: TrustDomain) -> Self {
40 Self {
41 trust_domain,
42 authorize_client: authorize_any(),
43 }
44 }
45}
46
47#[derive(Debug)]
55pub struct ServerConfigBuilder {
56 source: Arc<X509Source>,
57 opts: ServerConfigOptions,
58}
59
60impl ServerConfigBuilder {
61 pub fn new(source: Arc<X509Source>, opts: ServerConfigOptions) -> Self {
63 Self { source, opts }
64 }
65
66 pub fn build(self) -> Result<ServerConfig> {
77 crate::crypto::ensure_crypto_provider_installed();
78
79 let watcher = MaterialWatcher::new(self.source, self.opts.trust_domain)?;
80
81 let resolver: Arc<dyn ResolvesServerCert> =
82 Arc::new(resolve_server::SpiffeServerCertResolver {
83 watcher: watcher.clone(),
84 });
85
86 let verifier = Arc::new(SpiffeClientCertVerifier::from_watcher(
87 watcher.clone(),
88 self.opts.authorize_client,
89 ));
90
91 let cfg = ServerConfig::builder()
92 .with_client_cert_verifier(verifier)
93 .with_cert_resolver(resolver);
94
95 Ok(cfg)
96 }
97}
98
99mod resolve_server {
100 use crate::resolve::MaterialWatcher;
101 use rustls::server::ResolvesServerCert;
102 use rustls::sign::CertifiedKey;
103 use std::sync::Arc;
104
105 #[derive(Clone, Debug)]
106 pub(crate) struct SpiffeServerCertResolver {
107 pub watcher: MaterialWatcher,
108 }
109
110 impl ResolvesServerCert for SpiffeServerCertResolver {
111 fn resolve(
112 &self,
113 _client_hello: rustls::server::ClientHello<'_>,
114 ) -> Option<Arc<CertifiedKey>> {
115 Some(self.watcher.current().certified_key.clone())
116 }
117 }
118}