aws_smithy_http_client/client/
tls.rs1use std::fmt;
6
7use crate::cfg::{cfg_rustls, cfg_s2n_tls};
8use crate::HttpClientError;
9
10#[derive(Debug, PartialEq, Clone)]
12#[non_exhaustive]
13pub enum Provider {
14 #[cfg(feature = "__rustls")]
15 Rustls(rustls_provider::CryptoMode),
17 #[cfg(feature = "s2n-tls")]
19 S2nTls,
20}
21
22#[cfg(not(all(aws_sdk_unstable, feature = "__rustls")))]
23impl Eq for Provider {}
24
25#[derive(Debug, Clone)]
27pub struct TlsContext {
28 #[allow(unused)]
29 trust_store: TrustStore,
30 #[allow(unused)]
31 additional_server_names: Vec<ServerName>,
32}
33
34impl TlsContext {
35 pub fn builder() -> TlsContextBuilder {
37 TlsContextBuilder::new()
38 }
39}
40
41impl Default for TlsContext {
42 fn default() -> Self {
43 TlsContext::builder().build().expect("valid default config")
44 }
45}
46
47#[derive(Debug)]
49pub struct TlsContextBuilder {
50 trust_store: TrustStore,
51 additional_server_names: Vec<ServerName>,
52}
53
54impl TlsContextBuilder {
55 fn new() -> Self {
56 TlsContextBuilder {
57 trust_store: TrustStore::default(),
58 additional_server_names: Vec::default(),
59 }
60 }
61
62 pub fn with_trust_store(mut self, trust_store: TrustStore) -> Self {
64 self.trust_store = trust_store;
65 self
66 }
67
68 pub fn with_additional_server_names(
70 mut self,
71 additional_server_names: Vec<ServerName>,
72 ) -> Self {
73 self.additional_server_names = additional_server_names;
74 self
75 }
76
77 pub fn build(self) -> Result<TlsContext, HttpClientError> {
79 Ok(TlsContext {
80 trust_store: self.trust_store,
81 additional_server_names: self.additional_server_names,
82 })
83 }
84}
85
86#[allow(unused)]
88#[derive(Debug, Clone)]
89struct CertificatePEM(Vec<u8>);
90
91impl From<&[u8]> for CertificatePEM {
92 fn from(value: &[u8]) -> Self {
93 CertificatePEM(value.to_vec())
94 }
95}
96
97#[derive(Debug, Clone)]
102pub struct TrustStore {
103 enable_native_roots: bool,
104 custom_certs: Vec<CertificatePEM>,
105}
106
107impl TrustStore {
108 pub fn empty() -> Self {
110 Self {
111 enable_native_roots: false,
112 custom_certs: Vec::new(),
113 }
114 }
115
116 pub fn with_native_roots(mut self, enable_native_roots: bool) -> Self {
120 self.enable_native_roots = enable_native_roots;
121 self
122 }
123
124 pub fn with_pem_certificate(mut self, pem_bytes: impl Into<Vec<u8>>) -> Self {
130 self.custom_certs.push(CertificatePEM(pem_bytes.into()));
133 self
134 }
135
136 pub fn add_pem_certificate(&mut self, pem_bytes: impl Into<Vec<u8>>) -> &mut Self {
142 self.custom_certs.push(CertificatePEM(pem_bytes.into()));
143 self
144 }
145}
146
147impl Default for TrustStore {
148 fn default() -> Self {
149 Self {
150 enable_native_roots: true,
151 custom_certs: Vec::new(),
152 }
153 }
154}
155
156#[derive(Debug, Clone, PartialEq, Eq, Hash)]
170pub struct ServerName(rustls_pki_types::ServerName<'static>);
171
172#[derive(Debug, Clone, PartialEq, Eq)]
174pub struct InvalidServerName {
175 name: String,
176}
177
178impl fmt::Display for InvalidServerName {
179 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
180 write!(f, "invalid server name: {:?}", self.name)
181 }
182}
183
184impl std::error::Error for InvalidServerName {}
185
186impl TryFrom<String> for ServerName {
187 type Error = InvalidServerName;
188
189 fn try_from(name: String) -> Result<Self, Self::Error> {
190 match rustls_pki_types::ServerName::try_from(name.as_str()) {
191 Ok(sn) => Ok(ServerName(sn.to_owned())),
192 Err(_) => Err(InvalidServerName { name }),
193 }
194 }
195}
196
197impl TryFrom<&str> for ServerName {
198 type Error = InvalidServerName;
199
200 fn try_from(name: &str) -> Result<Self, Self::Error> {
201 match rustls_pki_types::ServerName::try_from(name) {
202 Ok(sn) => Ok(ServerName(sn.to_owned())),
203 Err(_) => Err(InvalidServerName {
204 name: name.to_owned(),
205 }),
206 }
207 }
208}
209
210cfg_rustls! {
211 pub mod rustls_provider;
213}
214
215cfg_s2n_tls! {
216 pub(crate) mod s2n_tls_provider;
218}