Skip to content

Commit 4a29c04

Browse files
authored
fix(stackable-webhook): Move certificate generation to the blocking thread (#815)
* fix(stackable-webhook): move certificate generation to the blocking thread * chore(stackable-webhook): update changelog * chore(stackable-webhook): add explanation for the use of spawn_blocking
1 parent 7bc8489 commit 4a29c04

File tree

2 files changed

+47
-30
lines changed

2 files changed

+47
-30
lines changed

crates/stackable-webhook/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@ All notable changes to this project will be documented in this file.
1414
the `Host` info (data about the server) in the `AxumTraceLayer`. This was
1515
previously not extracted correctly and thus not included in the OpenTelemetry
1616
compatible traces ([#806]).
17+
- Spawn blocking code on a blocking thread ([#815]).
1718

1819
[#806]: https://github.com/stackabletech/operator-rs/pull/806
1920
[#811]: https://github.com/stackabletech/operator-rs/pull/811
21+
[#815]: https://github.com/stackabletech/operator-rs/pull/815
2022

2123
## [0.3.0] - 2024-05-08
2224

crates/stackable-webhook/src/tls.rs

Lines changed: 45 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ pub enum Error {
5656

5757
#[snafu(display("failed to set safe TLS protocol versions"))]
5858
SetSafeTlsProtocolVersions { source: tokio_rustls::rustls::Error },
59+
60+
#[snafu(display("failed to run task in blocking thread"))]
61+
TokioSpawnBlocking { source: tokio::task::JoinError },
5962
}
6063

6164
/// Custom implementation of [`std::cmp::PartialEq`] because some inner types
@@ -94,37 +97,49 @@ pub struct TlsServer {
9497
impl TlsServer {
9598
#[instrument(name = "create_tls_server", skip(router))]
9699
pub async fn new(socket_addr: SocketAddr, router: Router) -> Result<Self> {
97-
let mut certificate_authority =
98-
CertificateAuthority::new_rsa().context(CreateCertificateAuthoritySnafu)?;
99-
100-
let leaf_certificate = certificate_authority
101-
.generate_rsa_leaf_certificate("Leaf", "webhook", Duration::from_secs(3600))
102-
.context(GenerateLeafCertificateSnafu)?;
103-
104-
let certificate_der = leaf_certificate
105-
.certificate_der()
106-
.context(EncodeCertificateDerSnafu)?;
107-
108-
let private_key_der = leaf_certificate
109-
.private_key_der()
110-
.context(EncodePrivateKeyDerSnafu)?;
111-
112-
let tls_provider = default_provider();
113-
let mut config = ServerConfig::builder_with_provider(tls_provider.into())
114-
.with_protocol_versions(&[&TLS12, &TLS13])
115-
.context(SetSafeTlsProtocolVersionsSnafu)?
116-
.with_no_client_auth()
117-
.with_single_cert(vec![certificate_der], private_key_der)
118-
.context(InvalidTlsPrivateKeySnafu)?;
119-
120-
config.alpn_protocols = vec![b"h2".to_vec(), b"http/1.1".to_vec()];
121-
let config = Arc::new(config);
122-
123-
Ok(Self {
124-
socket_addr,
125-
config,
126-
router,
100+
// NOTE(@NickLarsenNZ): This code is not async, and does take some
101+
// non-negligable amount of time to complete (moreso in debug ).
102+
// We run this in a thread reserved for blocking code so that the Tokio
103+
// executor is able to make progress on other futures instead of being
104+
// blocked.
105+
// See https://docs.rs/tokio/latest/tokio/task/fn.spawn_blocking.html
106+
let task = tokio::task::spawn_blocking(move || {
107+
let mut certificate_authority =
108+
CertificateAuthority::new_rsa().context(CreateCertificateAuthoritySnafu)?;
109+
110+
let leaf_certificate = certificate_authority
111+
.generate_rsa_leaf_certificate("Leaf", "webhook", Duration::from_secs(3600))
112+
.context(GenerateLeafCertificateSnafu)?;
113+
114+
let certificate_der = leaf_certificate
115+
.certificate_der()
116+
.context(EncodeCertificateDerSnafu)?;
117+
118+
let private_key_der = leaf_certificate
119+
.private_key_der()
120+
.context(EncodePrivateKeyDerSnafu)?;
121+
122+
let tls_provider = default_provider();
123+
let mut config = ServerConfig::builder_with_provider(tls_provider.into())
124+
.with_protocol_versions(&[&TLS12, &TLS13])
125+
.context(SetSafeTlsProtocolVersionsSnafu)?
126+
.with_no_client_auth()
127+
.with_single_cert(vec![certificate_der], private_key_der)
128+
.context(InvalidTlsPrivateKeySnafu)?;
129+
130+
config.alpn_protocols = vec![b"h2".to_vec(), b"http/1.1".to_vec()];
131+
let config = Arc::new(config);
132+
133+
Ok(Self {
134+
socket_addr,
135+
config,
136+
router,
137+
})
127138
})
139+
.await
140+
.context(TokioSpawnBlockingSnafu)??;
141+
142+
Ok(task)
128143
}
129144

130145
/// Runs the TLS server by listening for incoming TCP connections on the

0 commit comments

Comments
 (0)