Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crates/stackable-certs/src/ca/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ where
//
// The root profile doesn't add the AuthorityKeyIdentifier extension.
// We manually add it below by using the 160-bit SHA-1 hash of the
// subject pulic key. This conforms to one of the outlined methods for
// subject public key. This conforms to one of the outlined methods for
// generating key identifiers outlined in RFC 5280, section 4.2.1.2.
//
// Prepare extensions so we can avoid clones.
Expand Down
5 changes: 5 additions & 0 deletions crates/stackable-webhook/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@ All notable changes to this project will be documented in this file.
Both `WebhookServer::run` and `TlsServer::run` now require passing a shutdown signal, which is any
`Future<Output = ()>` ([#1144]).

### Changed

- Improve certificate rotation instrumentation ([#1145]).

[#1144]: https://github.com/stackabletech/operator-rs/pull/1144
[#1145]: https://github.com/stackabletech/operator-rs/pull/1145

## [0.8.1] - 2026-01-07

Expand Down
16 changes: 14 additions & 2 deletions crates/stackable-webhook/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,9 +187,21 @@ impl WebhookServer {
// run associated function consumes self. This in turn means that when the receiver is
// polled, it will return `Ok(Ready(None))`, which will cause this while loop to break
// and the future to complete.
while let Some(cert) = cert_rx.recv().await {
while let Some(certificate) = cert_rx.recv().await {
// NOTE (@Techassi): There are currently NO semantic conventions for X509 certificates
// and as such, these are pretty much made up and potentially not ideal.
#[rustfmt::skip]
tracing::info!(
x509.not_before = certificate.tbs_certificate.validity.not_before.to_string(),
x509.not_after = certificate.tbs_certificate.validity.not_after.to_string(),
x509.serial_number = certificate.tbs_certificate.serial_number.to_string(),
x509.subject = certificate.tbs_certificate.subject.to_string(),
x509.issuer = certificate.tbs_certificate.issuer.to_string(),
"rotate certificate for registered webhooks"
);

// The caBundle needs to be provided as a base64-encoded PEM envelope.
let ca_bundle = cert
let ca_bundle = certificate
.to_pem(LineEnding::LF)
.context(EncodeCertificateAuthorityAsPemSnafu)?;
let ca_bundle = ByteString(ca_bundle.as_bytes().to_vec());
Expand Down
15 changes: 7 additions & 8 deletions crates/stackable-webhook/src/webhooks/conversion_webhook.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ use snafu::{ResultExt, Snafu};
use tokio::sync::oneshot;
use tracing::instrument;

use super::{Webhook, WebhookError};
use crate::WebhookServerOptions;
use crate::{Webhook, WebhookError, WebhookServerOptions};

#[derive(Debug, Snafu)]
pub enum ConversionWebhookError {
Expand Down Expand Up @@ -138,7 +137,7 @@ impl<H> ConversionWebhook<H> {
}

#[instrument(
skip(self, crd, crd_api, new_ca_bundle),
skip(self, crd, crd_api, ca_bundle),
fields(
name = crd.name_any(),
kind = &crd.spec.names.kind
Expand All @@ -148,7 +147,7 @@ impl<H> ConversionWebhook<H> {
&self,
mut crd: CustomResourceDefinition,
crd_api: &Api<CustomResourceDefinition>,
new_ca_bundle: &ByteString,
ca_bundle: ByteString,
options: &WebhookServerOptions,
) -> Result<(), WebhookError> {
let crd_kind = &crd.spec.names.kind;
Expand Down Expand Up @@ -178,7 +177,7 @@ impl<H> ConversionWebhook<H> {
port: Some(options.socket_addr.port().into()),
}),
// Here, ByteString takes care of encoding the provided content as base64.
ca_bundle: Some(new_ca_bundle.to_owned()),
ca_bundle: Some(ca_bundle),
url: None,
}),
}),
Expand Down Expand Up @@ -247,15 +246,15 @@ where
self.options.disable_crd_maintenance
}

#[instrument(skip(self, new_ca_bundle))]
#[instrument(skip(self, ca_bundle))]
async fn handle_certificate_rotation(
&mut self,
new_ca_bundle: &ByteString,
ca_bundle: &ByteString,
options: &WebhookServerOptions,
) -> Result<(), WebhookError> {
let crd_api: Api<CustomResourceDefinition> = Api::all(self.client.clone());
for (crd, _) in &self.crds_and_handlers {
self.reconcile_crd(crd.clone(), &crd_api, new_ca_bundle, options)
self.reconcile_crd(crd.clone(), &crd_api, ca_bundle.to_owned(), options)
.await?;
}

Expand Down
2 changes: 1 addition & 1 deletion crates/stackable-webhook/src/webhooks/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ pub trait Webhook {
/// Webhooks are informed about new certificates by this function and can react accordingly.
async fn handle_certificate_rotation(
&mut self,
new_ca_bundle: &ByteString,
ca_bundle: &ByteString,
options: &WebhookServerOptions,
) -> Result<(), WebhookError>;
}
Expand Down
10 changes: 5 additions & 5 deletions crates/stackable-webhook/src/webhooks/mutating_webhook.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ use serde::{Serialize, de::DeserializeOwned};
use snafu::{ResultExt, Snafu};
use tracing::instrument;

use super::{Webhook, WebhookError};
use crate::{WebhookServerOptions, webhooks::create_webhook_client_config};
use crate::{Webhook, WebhookError, WebhookServerOptions, webhooks::create_webhook_client_config};

#[derive(Debug, Snafu)]
pub enum MutatingWebhookError {
Expand Down Expand Up @@ -209,14 +208,15 @@ where
self.options.disable_mwc_maintenance
}

#[instrument(skip(self, new_ca_bundle))]
#[instrument(skip(self, ca_bundle))]
async fn handle_certificate_rotation(
&mut self,
new_ca_bundle: &ByteString,
ca_bundle: &ByteString,
options: &WebhookServerOptions,
) -> Result<(), WebhookError> {
let mut mutating_webhook_configuration = self.mutating_webhook_configuration.clone();
let mwc_name = mutating_webhook_configuration.name_any();

tracing::info!(
k8s.mutatingwebhookconfiguration.name = mwc_name,
"reconciling mutating webhook configurations"
Expand All @@ -225,7 +225,7 @@ where
for webhook in mutating_webhook_configuration.webhooks.iter_mut().flatten() {
// We know how we can be called (and with what certificate), so we can always set that
webhook.client_config =
create_webhook_client_config(options, new_ca_bundle.to_owned(), self.http_path());
create_webhook_client_config(options, ca_bundle.to_owned(), self.http_path());
}

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