-
-
Notifications
You must be signed in to change notification settings - Fork 16
feat!: Add working conversion webhook with cert rotation #1066
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
pub const WEBHOOK_CA_LIFETIME: Duration = Duration::from_minutes_unchecked(3); | ||
pub const WEBHOOK_CERTIFICATE_LIFETIME: Duration = Duration::from_minutes_unchecked(2); | ||
pub const WEBHOOK_CERTIFICATE_ROTATION_INTERVAL: Duration = Duration::from_minutes_unchecked(1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
reminder to bump these before merging. Currently they are so low for easy testing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Partial review, I didn't look at the CertificateResolver
yet.
Co-authored-by: Techassi <[email protected]>
Co-authored-by: Techassi <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left a bunch of comments.
I encountered the ConversionWebhookServer which is missing the changes we talked about a few weeks back. As such, it doesn't make a whole lot of sense to continue the review before these changes are implemented. I've sent you an appropriate patch as a private message which should be a good starting point for the changes we discussed.
"--operator-namespace", | ||
"stackable-operators", | ||
"--operator-service-name", | ||
"foo-operator", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note: I still feel like all these CLI unit tests are pretty much useless and should be removed to speed up the testing runs.
use kube::{ | ||
Api, Client, ResourceExt, | ||
api::{Patch, PatchParams}, | ||
}; | ||
use snafu::{OptionExt, ResultExt, Snafu}; | ||
use stackable_operator::cli::OperatorEnvironmentOptions; | ||
use tokio::{sync::mpsc, try_join}; | ||
use tracing::instrument; | ||
use x509_cert::{ | ||
Certificate, | ||
der::{EncodePem, pem::LineEnding}, | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note: Please combine these imports with the others above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm, what imports exactly can be combined? rustfmt groups them like this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah this is sub-optimal formatting sadly. You need to manually move them to the top imports above line 11.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are mostly there, just some small things left.
@@ -4,6 +4,17 @@ All notable changes to this project will be documented in this file. | |||
|
|||
## [Unreleased] | |||
|
|||
### Added | |||
|
|||
- BREAKING: Add two new required CLI arguments: `--operator-namespace` and `-operator-service-name`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- BREAKING: Add two new required CLI arguments: `--operator-namespace` and `-operator-service-name`. | |
- BREAKING: Add two new required CLI arguments: `--operator-namespace` and `--operator-service-name`. |
RunWebhookServer { source: WebhookError }, | ||
|
||
#[snafu(display("failed to receive certificate from channel"))] | ||
ReceiverCertificateFromChannel, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ReceiverCertificateFromChannel, | |
ReceiveCertificateFromChannel, |
/// The environment the operator is running in, notably the namespace and service name it is | ||
/// reachable at. | ||
pub operator_environment: OperatorEnvironmentOptions, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note: Let's avoid pulling in a type from stackable_operator
here. Instead, split it into two separate fields.
/// The environment the operator is running in, notably the namespace and service name it is | |
/// reachable at. | |
pub operator_environment: OperatorEnvironmentOptions, | |
pub namespace: String, | |
pub service_name: String, |
@@ -2,4 +2,5 @@ | |||
//! purposes. | |||
mod conversion; | |||
|
|||
pub use conversion::*; | |||
pub use conversion::{ConversionWebhookError, ConversionWebhookOptions, ConversionWebhookServer}; | |||
pub use kube::core::conversion::ConversionReview; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note: This is already re-exported via stackable_webhook::servers::conversion::ConversionReview
. As such, please remove it from here again.
let certificate = ca | ||
.generate_ecdsa_leaf_certificate( | ||
"Leaf", | ||
"webhook", | ||
subject_alterative_dns_names.iter().map(|san| san.as_str()), | ||
WEBHOOK_CERTIFICATE_LIFETIME, | ||
) | ||
.context(GenerateLeafCertificateSnafu)?; | ||
|
||
let certificate_der = certificate | ||
.certificate_der() | ||
.context(EncodeCertificateDerSnafu)?; | ||
let private_key_der = certificate | ||
.private_key_der() | ||
.context(EncodePrivateKeyDerSnafu)?; | ||
let certificate_key = | ||
CertifiedKey::from_der(vec![certificate_der], private_key_der, &tls_provider) | ||
.context(DecodeCertifiedKeyFromDerSnafu)?; | ||
|
||
Ok((certificate.certificate().clone(), Arc::new(certificate_key))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: Rename this to certificate_pair
to better indicate what this is.
let certificate = ca | |
.generate_ecdsa_leaf_certificate( | |
"Leaf", | |
"webhook", | |
subject_alterative_dns_names.iter().map(|san| san.as_str()), | |
WEBHOOK_CERTIFICATE_LIFETIME, | |
) | |
.context(GenerateLeafCertificateSnafu)?; | |
let certificate_der = certificate | |
.certificate_der() | |
.context(EncodeCertificateDerSnafu)?; | |
let private_key_der = certificate | |
.private_key_der() | |
.context(EncodePrivateKeyDerSnafu)?; | |
let certificate_key = | |
CertifiedKey::from_der(vec![certificate_der], private_key_der, &tls_provider) | |
.context(DecodeCertifiedKeyFromDerSnafu)?; | |
Ok((certificate.certificate().clone(), Arc::new(certificate_key))) | |
let certificate_pair = ca | |
.generate_ecdsa_leaf_certificate( | |
"Leaf", | |
"webhook", | |
subject_alterative_dns_names.iter().map(|san| san.as_str()), | |
WEBHOOK_CERTIFICATE_LIFETIME, | |
) | |
.context(GenerateLeafCertificateSnafu)?; | |
let certificate_der = certificate_pair | |
.certificate_der() | |
.context(EncodeCertificateDerSnafu)?; | |
let private_key_der = certificate_pair | |
.private_key_der() | |
.context(EncodePrivateKeyDerSnafu)?; | |
let certificate_key = | |
CertifiedKey::from_der(vec![certificate_der], private_key_der, &tls_provider) | |
.context(DecodeCertifiedKeyFromDerSnafu)?; | |
Ok((certificate_pair.certificate().clone(), Arc::new(certificate_key))) |
let (cert, certified_key) = Self::generate_new_cert(subject_alterative_dns_names.clone()) | ||
.await | ||
.context(GenerateNewCertificateSnafu)?; | ||
|
||
cert_tx | ||
.send(cert) | ||
.await | ||
.map_err(|_err| CertificateResolverError::SendCertificateToChannel)?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note: I feel like this can be moved into its own function, because we repeat the exact same code below.
/// | ||
/// Usually, this struct is not constructed manually, but instead by calling | ||
/// [`Options::builder()`] or [`OptionsBuilder::default()`]. | ||
/// [`WebhookOptions::builder()`] or [`OptionsBuilder::default()`]. | ||
#[derive(Debug, Default)] | ||
pub struct OptionsBuilder { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note: We renamed Options
to WebhookOptions
. As such, I think we should also rename the builder accordingly.
pub struct OptionsBuilder { | |
pub struct WebhookOptionsBuilder { |
### Added | ||
|
||
- BREAKING: Re-write the `ConversionWebhookServer`. | ||
It can now do CRD conversions, handle multiple CRDs and takes care of reconciling the CRDs ([#1066]). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note: I still feel like the webhhok should not take care of reconciling the CRDs, but the operator should do it instead. Let's tackle this in a follow-up PR and leave it as is to get something out of the door.
@@ -4,6 +4,23 @@ All notable changes to this project will be documented in this file. | |||
|
|||
## [Unreleased] | |||
|
|||
### Added |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note: I feel like this should go under the "Changed" section instead. We additionally need to mention the Options
renames.
Also, `TlsServer::new` now returns an additional `mpsc::Receiver<Certificate>`, so that the caller | ||
can get notified about certificate rotations happening ([#1066]). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note: (Addition to the comment above) This would be the perfect trigger for the operator (the caller if this function) to reconcile the CRDs.
Description
Part of stackabletech/issues#642
An working example usage can be found in stackabletech/zookeeper-operator#958 (mainly look at
rust/operator-binary/src/main.rs
)Definition of Done Checklist
Author
Reviewer
Acceptance