Skip to content

Commit caaeb08

Browse files
authored
feat(webhook): Improve instrumentation for certificate rotation (#1145)
* feat(webhook): Improve instrumentation for certificate rotation * chore(webhook): Adjust CA bundle handling * chore(certs): Fix typo in dev comment * chore: Add changelog entry
1 parent f2a0840 commit caaeb08

File tree

6 files changed

+33
-17
lines changed

6 files changed

+33
-17
lines changed

crates/stackable-certs/src/ca/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ where
247247
//
248248
// The root profile doesn't add the AuthorityKeyIdentifier extension.
249249
// We manually add it below by using the 160-bit SHA-1 hash of the
250-
// subject pulic key. This conforms to one of the outlined methods for
250+
// subject public key. This conforms to one of the outlined methods for
251251
// generating key identifiers outlined in RFC 5280, section 4.2.1.2.
252252
//
253253
// Prepare extensions so we can avoid clones.

crates/stackable-webhook/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,12 @@ All notable changes to this project will be documented in this file.
1010
Both `WebhookServer::run` and `TlsServer::run` now require passing a shutdown signal, which is any
1111
`Future<Output = ()>` ([#1144]).
1212

13+
### Changed
14+
15+
- Improve certificate rotation instrumentation ([#1145]).
16+
1317
[#1144]: https://github.com/stackabletech/operator-rs/pull/1144
18+
[#1145]: https://github.com/stackabletech/operator-rs/pull/1145
1419

1520
## [0.8.1] - 2026-01-07
1621

crates/stackable-webhook/src/lib.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,9 +187,21 @@ impl WebhookServer {
187187
// run associated function consumes self. This in turn means that when the receiver is
188188
// polled, it will return `Ok(Ready(None))`, which will cause this while loop to break
189189
// and the future to complete.
190-
while let Some(cert) = cert_rx.recv().await {
190+
while let Some(certificate) = cert_rx.recv().await {
191+
// NOTE (@Techassi): There are currently NO semantic conventions for X509 certificates
192+
// and as such, these are pretty much made up and potentially not ideal.
193+
#[rustfmt::skip]
194+
tracing::info!(
195+
x509.not_before = certificate.tbs_certificate.validity.not_before.to_string(),
196+
x509.not_after = certificate.tbs_certificate.validity.not_after.to_string(),
197+
x509.serial_number = certificate.tbs_certificate.serial_number.to_string(),
198+
x509.subject = certificate.tbs_certificate.subject.to_string(),
199+
x509.issuer = certificate.tbs_certificate.issuer.to_string(),
200+
"rotate certificate for registered webhooks"
201+
);
202+
191203
// The caBundle needs to be provided as a base64-encoded PEM envelope.
192-
let ca_bundle = cert
204+
let ca_bundle = certificate
193205
.to_pem(LineEnding::LF)
194206
.context(EncodeCertificateAuthorityAsPemSnafu)?;
195207
let ca_bundle = ByteString(ca_bundle.as_bytes().to_vec());

crates/stackable-webhook/src/webhooks/conversion_webhook.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@ use snafu::{ResultExt, Snafu};
2222
use tokio::sync::oneshot;
2323
use tracing::instrument;
2424

25-
use super::{Webhook, WebhookError};
26-
use crate::WebhookServerOptions;
25+
use crate::{Webhook, WebhookError, WebhookServerOptions};
2726

2827
#[derive(Debug, Snafu)]
2928
pub enum ConversionWebhookError {
@@ -138,7 +137,7 @@ impl<H> ConversionWebhook<H> {
138137
}
139138

140139
#[instrument(
141-
skip(self, crd, crd_api, new_ca_bundle),
140+
skip(self, crd, crd_api, ca_bundle),
142141
fields(
143142
name = crd.name_any(),
144143
kind = &crd.spec.names.kind
@@ -148,7 +147,7 @@ impl<H> ConversionWebhook<H> {
148147
&self,
149148
mut crd: CustomResourceDefinition,
150149
crd_api: &Api<CustomResourceDefinition>,
151-
new_ca_bundle: &ByteString,
150+
ca_bundle: ByteString,
152151
options: &WebhookServerOptions,
153152
) -> Result<(), WebhookError> {
154153
let crd_kind = &crd.spec.names.kind;
@@ -178,7 +177,7 @@ impl<H> ConversionWebhook<H> {
178177
port: Some(options.socket_addr.port().into()),
179178
}),
180179
// Here, ByteString takes care of encoding the provided content as base64.
181-
ca_bundle: Some(new_ca_bundle.to_owned()),
180+
ca_bundle: Some(ca_bundle),
182181
url: None,
183182
}),
184183
}),
@@ -247,15 +246,15 @@ where
247246
self.options.disable_crd_maintenance
248247
}
249248

250-
#[instrument(skip(self, new_ca_bundle))]
249+
#[instrument(skip(self, ca_bundle))]
251250
async fn handle_certificate_rotation(
252251
&mut self,
253-
new_ca_bundle: &ByteString,
252+
ca_bundle: &ByteString,
254253
options: &WebhookServerOptions,
255254
) -> Result<(), WebhookError> {
256255
let crd_api: Api<CustomResourceDefinition> = Api::all(self.client.clone());
257256
for (crd, _) in &self.crds_and_handlers {
258-
self.reconcile_crd(crd.clone(), &crd_api, new_ca_bundle, options)
257+
self.reconcile_crd(crd.clone(), &crd_api, ca_bundle.to_owned(), options)
259258
.await?;
260259
}
261260

crates/stackable-webhook/src/webhooks/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ pub trait Webhook {
4848
/// Webhooks are informed about new certificates by this function and can react accordingly.
4949
async fn handle_certificate_rotation(
5050
&mut self,
51-
new_ca_bundle: &ByteString,
51+
ca_bundle: &ByteString,
5252
options: &WebhookServerOptions,
5353
) -> Result<(), WebhookError>;
5454
}

crates/stackable-webhook/src/webhooks/mutating_webhook.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@ use serde::{Serialize, de::DeserializeOwned};
1212
use snafu::{ResultExt, Snafu};
1313
use tracing::instrument;
1414

15-
use super::{Webhook, WebhookError};
16-
use crate::{WebhookServerOptions, webhooks::create_webhook_client_config};
15+
use crate::{Webhook, WebhookError, WebhookServerOptions, webhooks::create_webhook_client_config};
1716

1817
#[derive(Debug, Snafu)]
1918
pub enum MutatingWebhookError {
@@ -209,14 +208,15 @@ where
209208
self.options.disable_mwc_maintenance
210209
}
211210

212-
#[instrument(skip(self, new_ca_bundle))]
211+
#[instrument(skip(self, ca_bundle))]
213212
async fn handle_certificate_rotation(
214213
&mut self,
215-
new_ca_bundle: &ByteString,
214+
ca_bundle: &ByteString,
216215
options: &WebhookServerOptions,
217216
) -> Result<(), WebhookError> {
218217
let mut mutating_webhook_configuration = self.mutating_webhook_configuration.clone();
219218
let mwc_name = mutating_webhook_configuration.name_any();
219+
220220
tracing::info!(
221221
k8s.mutatingwebhookconfiguration.name = mwc_name,
222222
"reconciling mutating webhook configurations"
@@ -225,7 +225,7 @@ where
225225
for webhook in mutating_webhook_configuration.webhooks.iter_mut().flatten() {
226226
// We know how we can be called (and with what certificate), so we can always set that
227227
webhook.client_config =
228-
create_webhook_client_config(options, new_ca_bundle.to_owned(), self.http_path());
228+
create_webhook_client_config(options, ca_bundle.to_owned(), self.http_path());
229229
}
230230

231231
let mwc_api: Api<MutatingWebhookConfiguration> = Api::all(self.client.clone());

0 commit comments

Comments
 (0)