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)]
12pub struct ServerConfigOptions {
13 pub trust_domain: TrustDomain,
15
16 pub authorize_client: AuthorizeSpiffeId,
20}
21
22impl ServerConfigOptions {
23 pub fn allow_any(trust_domain: TrustDomain) -> Self {
27 Self {
28 trust_domain,
29 authorize_client: authorize_any(),
30 }
31 }
32}
33
34pub struct ServerConfigBuilder {
43 source: Arc<X509Source>,
44 opts: ServerConfigOptions,
45}
46
47impl ServerConfigBuilder {
48 pub fn new(source: Arc<X509Source>, opts: ServerConfigOptions) -> Self {
50 Self { source, opts }
51 }
52
53 pub async fn build(self) -> Result<ServerConfig> {
55 crate::crypto::ensure_crypto_provider_installed();
56
57 let watcher = MaterialWatcher::new(self.source, self.opts.trust_domain).await?;
58
59 let resolver: Arc<dyn ResolvesServerCert> =
60 Arc::new(resolve_server::SpiffeServerCertResolver {
61 watcher: watcher.clone(),
62 });
63
64 let verifier = Arc::new(SpiffeClientCertVerifier::new(
65 Arc::new(watcher.clone()),
66 self.opts.authorize_client,
67 )?);
68
69 let cfg = ServerConfig::builder()
70 .with_client_cert_verifier(verifier)
71 .with_cert_resolver(resolver);
72
73 Ok(cfg)
74 }
75}
76
77mod resolve_server {
78 use crate::resolve::MaterialWatcher;
79 use rustls::server::ResolvesServerCert;
80 use rustls::sign::CertifiedKey;
81 use std::sync::Arc;
82
83 #[derive(Clone, Debug)]
84 pub(crate) struct SpiffeServerCertResolver {
85 pub watcher: MaterialWatcher,
86 }
87
88 impl ResolvesServerCert for SpiffeServerCertResolver {
89 fn resolve(
90 &self,
91 _client_hello: rustls::server::ClientHello<'_>,
92 ) -> Option<Arc<CertifiedKey>> {
93 Some(self.watcher.current().certified_key.clone())
94 }
95 }
96}