Skip to content

Commit a7e70f1

Browse files
sbernauerNickLarsenNZTechassi
authored
fix!: Make fields on S3 structs mandatory, add S3 helpers (#863)
* refactor!: Add Host type. Fix S3 structs to have mandatory fields * TLS verification struct now reside top-level in the `commons` module * WIP * fix: Use String for Host JsonSchema * changelog * changelog * Add unique identifier to avoid clashing volumes and mounts * move identifier to front * clippy * Apply suggestions from code review Co-authored-by: Nick <[email protected]> * Remove RetrieveS3Bucket error * Add some error details * typo * Add docs for unique_identifier * Apply suggestions from code review Co-authored-by: Techassi <[email protected]> * Rename NotAHost -> NotAHost * Add invalid host to error message * Move to HostParseError * Rename Host -> HostName * Update crates/stackable-operator/src/commons/networking.rs Co-authored-by: Techassi <[email protected]> * Update crates/stackable-operator/CHANGELOG.md Co-authored-by: Techassi <[email protected]> * Update crates/stackable-operator/CHANGELOG.md Co-authored-by: Techassi <[email protected]> * changelog * Bump to 0.76.0 * Update crates/stackable-operator/src/commons/networking.rs Co-authored-by: Techassi <[email protected]> * fix domain names --------- Co-authored-by: Nick <[email protected]> Co-authored-by: Techassi <[email protected]>
1 parent 85af082 commit a7e70f1

File tree

14 files changed

+777
-471
lines changed

14 files changed

+777
-471
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/stackable-operator/CHANGELOG.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,23 @@ All notable changes to this project will be documented in this file.
44

55
## [Unreleased]
66

7+
## [0.76.0] - 2024-09-19
8+
9+
### Added
10+
11+
- BREAKING: Add `HostName` type and use it within LDAP and OIDC AuthenticationClass as well as S3Connection ([#863]).
12+
13+
### Changed
14+
15+
- BREAKING: The TLS verification struct now resides in the `commons::tls_verification` module, instead of being placed below `commons::authentication::tls` ([#863]).
16+
- BREAKING: Rename the `Hostname` type to `DomainName` to be consistent with RFC 1123 ([#863]).
17+
18+
### Fixed
19+
20+
- BREAKING: The fields `bucketName`, `connection` and `host` on `S3BucketSpec`, `InlinedS3BucketSpec` and `S3ConnectionSpec` are now mandatory. Previously operators errored out in case these fields where missing ([#863]).
21+
22+
[#863]: https://github.com/stackabletech/operator-rs/pull/863
23+
724
## [0.75.0] - 2024-09-19
825

926
### Added

crates/stackable-operator/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "stackable-operator"
33
description = "Stackable Operator Framework"
4-
version = "0.75.0"
4+
version = "0.76.0"
55
authors.workspace = true
66
license.workspace = true
77
edition.workspace = true

crates/stackable-operator/src/commons/authentication/ldap.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,10 @@ use url::{ParseError, Url};
77
use crate::{
88
builder::pod::{container::ContainerBuilder, volume::VolumeMountBuilder, PodBuilder},
99
commons::{
10-
authentication::{
11-
tls::{TlsClientDetails, TlsClientDetailsError},
12-
SECRET_BASE_PATH,
13-
},
10+
authentication::SECRET_BASE_PATH,
11+
networking::HostName,
1412
secret_class::{SecretClassVolume, SecretClassVolumeError},
13+
tls_verification::{TlsClientDetails, TlsClientDetailsError},
1514
},
1615
};
1716

@@ -36,8 +35,8 @@ pub enum Error {
3635
)]
3736
#[serde(rename_all = "camelCase")]
3837
pub struct AuthenticationProvider {
39-
/// Hostname of the LDAP server, for example: `my.ldap.server`.
40-
pub hostname: String,
38+
/// Host of the LDAP server, for example: `my.ldap.server` or `127.0.0.1`.
39+
pub hostname: HostName,
4140

4241
/// Port of the LDAP server. If TLS is used defaults to 636 otherwise to 389.
4342
port: Option<u16>,

crates/stackable-operator/src/commons/authentication/oidc.rs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ use url::{ParseError, Url};
1111

1212
#[cfg(doc)]
1313
use crate::commons::authentication::AuthenticationClass;
14-
use crate::commons::authentication::{tls::TlsClientDetails, SECRET_BASE_PATH};
14+
use crate::commons::{
15+
authentication::SECRET_BASE_PATH, networking::HostName, tls_verification::TlsClientDetails,
16+
};
1517

1618
pub type Result<T, E = Error> = std::result::Result<T, E>;
1719

@@ -40,8 +42,8 @@ pub enum Error {
4042
)]
4143
#[serde(rename_all = "camelCase")]
4244
pub struct AuthenticationProvider {
43-
/// Hostname of the identity provider, e.g. `my.keycloak.corp`.
44-
hostname: String,
45+
/// Host of the identity provider, e.g. `my.keycloak.corp` or `127.0.0.1`.
46+
hostname: HostName,
4547

4648
/// Port of the identity provider. If TLS is used defaults to 443,
4749
/// otherwise to 80.
@@ -90,7 +92,7 @@ fn default_root_path() -> String {
9092

9193
impl AuthenticationProvider {
9294
pub fn new(
93-
hostname: String,
95+
hostname: HostName,
9496
port: Option<u16>,
9597
root_path: String,
9698
tls: TlsClientDetails,
@@ -113,8 +115,12 @@ impl AuthenticationProvider {
113115
/// configuration path, use `url.join()`. This module provides the default
114116
/// path at [`DEFAULT_OIDC_WELLKNOWN_PATH`].
115117
pub fn endpoint_url(&self) -> Result<Url> {
116-
let mut url = Url::parse(&format!("http://{}:{}", self.hostname, self.port()))
117-
.context(ParseOidcEndpointUrlSnafu)?;
118+
let mut url = Url::parse(&format!(
119+
"http://{host}:{port}",
120+
host = self.hostname.as_url_host(),
121+
port = self.port()
122+
))
123+
.context(ParseOidcEndpointUrlSnafu)?;
118124

119125
if self.tls.uses_tls() {
120126
url.set_scheme("https").map_err(|_| {
@@ -317,7 +323,7 @@ mod test {
317323
fn test_oidc_ipv6_endpoint_url() {
318324
let oidc = serde_yaml::from_str::<AuthenticationProvider>(
319325
"
320-
hostname: '[2606:2800:220:1:248:1893:25c8:1946]'
326+
hostname: 2606:2800:220:1:248:1893:25c8:1946
321327
rootPath: my-root-path
322328
port: 12345
323329
scopes: [openid]
Lines changed: 0 additions & 155 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,5 @@
1-
use k8s_openapi::api::core::v1::{Volume, VolumeMount};
21
use schemars::JsonSchema;
32
use serde::{Deserialize, Serialize};
4-
use snafu::{ResultExt, Snafu};
5-
6-
use crate::{
7-
builder::pod::{container::ContainerBuilder, volume::VolumeMountBuilder, PodBuilder},
8-
commons::{
9-
authentication::SECRET_BASE_PATH,
10-
secret_class::{SecretClassVolume, SecretClassVolumeError},
11-
},
12-
};
133

144
#[derive(
155
Clone, Debug, Deserialize, Eq, Hash, JsonSchema, Ord, PartialEq, PartialOrd, Serialize,
@@ -22,148 +12,3 @@ pub struct AuthenticationProvider {
2212
/// will be used to provision client certificates.
2313
pub client_cert_secret_class: Option<String>,
2414
}
25-
26-
#[derive(Debug, PartialEq, Snafu)]
27-
pub enum TlsClientDetailsError {
28-
#[snafu(display("failed to convert secret class volume into named Kubernetes volume"))]
29-
SecretClassVolume { source: SecretClassVolumeError },
30-
}
31-
32-
#[derive(
33-
Clone, Debug, Deserialize, Eq, Hash, JsonSchema, Ord, PartialEq, PartialOrd, Serialize,
34-
)]
35-
#[serde(rename_all = "camelCase")]
36-
pub struct TlsClientDetails {
37-
/// Use a TLS connection. If not specified no TLS will be used.
38-
pub tls: Option<Tls>,
39-
}
40-
41-
impl TlsClientDetails {
42-
/// This functions adds
43-
///
44-
/// * The needed volumes to the PodBuilder
45-
/// * The needed volume_mounts to all the ContainerBuilder in the list (e.g. init + main container)
46-
///
47-
/// This function will handle
48-
///
49-
/// * Tls secret class used to verify the cert of the LDAP server
50-
pub fn add_volumes_and_mounts(
51-
&self,
52-
pod_builder: &mut PodBuilder,
53-
container_builders: Vec<&mut ContainerBuilder>,
54-
) -> Result<(), TlsClientDetailsError> {
55-
let (volumes, mounts) = self.volumes_and_mounts()?;
56-
pod_builder.add_volumes(volumes);
57-
58-
for cb in container_builders {
59-
cb.add_volume_mounts(mounts.clone());
60-
}
61-
62-
Ok(())
63-
}
64-
65-
/// It is recommended to use [`Self::add_volumes_and_mounts`], this function returns you the
66-
/// volumes and mounts in case you need to add them by yourself.
67-
pub fn volumes_and_mounts(
68-
&self,
69-
) -> Result<(Vec<Volume>, Vec<VolumeMount>), TlsClientDetailsError> {
70-
let mut volumes = Vec::new();
71-
let mut mounts = Vec::new();
72-
73-
if let Some(secret_class) = self.tls_ca_cert_secret_class() {
74-
let volume_name = format!("{secret_class}-ca-cert");
75-
let secret_class_volume = SecretClassVolume::new(secret_class.clone(), None);
76-
let volume = secret_class_volume
77-
.to_volume(&volume_name)
78-
.context(SecretClassVolumeSnafu)?;
79-
80-
volumes.push(volume);
81-
mounts.push(
82-
VolumeMountBuilder::new(volume_name, format!("{SECRET_BASE_PATH}/{secret_class}"))
83-
.build(),
84-
);
85-
}
86-
87-
Ok((volumes, mounts))
88-
}
89-
90-
/// Whether TLS is configured
91-
pub const fn uses_tls(&self) -> bool {
92-
self.tls.is_some()
93-
}
94-
95-
/// Whether TLS verification is configured. Returns `false` if TLS itself isn't configured
96-
pub fn uses_tls_verification(&self) -> bool {
97-
self.tls
98-
.as_ref()
99-
.map(|tls| tls.verification != TlsVerification::None {})
100-
.unwrap_or_default()
101-
}
102-
103-
/// Returns the path of the ca.crt that should be used to verify the LDAP server certificate
104-
/// if TLS verification with a CA cert from a SecretClass is configured.
105-
pub fn tls_ca_cert_mount_path(&self) -> Option<String> {
106-
self.tls_ca_cert_secret_class()
107-
.map(|secret_class| format!("{SECRET_BASE_PATH}/{secret_class}/ca.crt"))
108-
}
109-
110-
/// Extracts the SecretClass that provides the CA cert used to verify the server certificate.
111-
pub(crate) fn tls_ca_cert_secret_class(&self) -> Option<String> {
112-
if let Some(Tls {
113-
verification:
114-
TlsVerification::Server(TlsServerVerification {
115-
ca_cert: CaCert::SecretClass(secret_class),
116-
}),
117-
}) = &self.tls
118-
{
119-
Some(secret_class.to_owned())
120-
} else {
121-
None
122-
}
123-
}
124-
}
125-
126-
#[derive(
127-
Clone, Debug, Deserialize, Eq, Hash, JsonSchema, Ord, PartialEq, PartialOrd, Serialize,
128-
)]
129-
#[serde(rename_all = "camelCase")]
130-
pub struct Tls {
131-
/// The verification method used to verify the certificates of the server and/or the client.
132-
pub verification: TlsVerification,
133-
}
134-
135-
#[derive(
136-
Clone, Debug, Deserialize, Eq, Hash, JsonSchema, Ord, PartialEq, PartialOrd, Serialize,
137-
)]
138-
#[serde(rename_all = "camelCase")]
139-
pub enum TlsVerification {
140-
/// Use TLS but don't verify certificates.
141-
None {},
142-
143-
/// Use TLS and a CA certificate to verify the server.
144-
Server(TlsServerVerification),
145-
}
146-
147-
#[derive(
148-
Clone, Debug, Deserialize, Eq, Hash, JsonSchema, Ord, PartialEq, PartialOrd, Serialize,
149-
)]
150-
#[serde(rename_all = "camelCase")]
151-
pub struct TlsServerVerification {
152-
/// CA cert to verify the server.
153-
pub ca_cert: CaCert,
154-
}
155-
156-
#[derive(
157-
Clone, Debug, Deserialize, Eq, Hash, JsonSchema, Ord, PartialEq, PartialOrd, Serialize,
158-
)]
159-
#[serde(rename_all = "camelCase")]
160-
pub enum CaCert {
161-
/// Use TLS and the CA certificates trusted by the common web browsers to verify the server.
162-
/// This can be useful when you e.g. use public AWS S3 or other public available services.
163-
WebPki {},
164-
165-
/// Name of the [SecretClass](DOCS_BASE_URL_PLACEHOLDER/secret-operator/secretclass) which will provide the CA certificate.
166-
/// Note that a SecretClass does not need to have a key but can also work with just a CA certificate,
167-
/// so if you got provided with a CA cert but don't have access to the key you can still use this method.
168-
SecretClass(String),
169-
}

crates/stackable-operator/src/commons/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ pub mod resources;
1313
pub mod s3;
1414
pub mod secret;
1515
pub mod secret_class;
16+
pub mod tls_verification;

0 commit comments

Comments
 (0)