Skip to content

Commit 9acae12

Browse files
authored
Merge branch 'main' into spike/secret-op-volume-request-parts
2 parents 28b83db + fbebe74 commit 9acae12

16 files changed

Lines changed: 940 additions & 51 deletions

File tree

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: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@ All notable changes to this project will be documented in this file.
66

77
### Added
88

9+
- Git sync: add support for CAs ([#1154]).
910
- Add support for specifying a `clientAuthenticationMethod` for OIDC ([#1178]).
1011
This was originally done in [#1158] and had been reverted in [#1170].
12+
- Implement `Deref` for `kvp::Key` to be more ergonomic to use ([#1182]).
1113

1214
### Changed
1315

@@ -19,8 +21,15 @@ All notable changes to this project will be documented in this file.
1921
Additionally, `SecretClassVolume::to_volume` and `SecretClassVolume::to_ephemeral_volume_source`
2022
also take the same new argument.
2123

24+
### Removed
25+
26+
- BREAKING: Remove unused `add_prefix`, `try_add_prefix`, `set_name`, and `try_set_name` associated
27+
functions from `kvp::Key` to disallow mutable access to inner values ([#1182]).
28+
29+
[#1154]: https://github.com/stackabletech/operator-rs/pull/1154
2230
[#1165]: https://github.com/stackabletech/operator-rs/pull/1165
2331
[#1178]: https://github.com/stackabletech/operator-rs/pull/1178
32+
[#1182]: https://github.com/stackabletech/operator-rs/pull/1182
2433

2534
## [0.108.0] - 2026-03-10
2635

crates/stackable-operator/crds/DummyCluster.yaml

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,56 @@ spec:
152152
description: 'The git repository URL that will be cloned, for example: `https://github.com/stackabletech/airflow-operator` or `ssh://git@github.com:stackable-airflow/dags.git`.'
153153
format: uri
154154
type: string
155+
tls:
156+
default:
157+
verification:
158+
server:
159+
caCert:
160+
webPki: {}
161+
description: Configure a TLS connection. If not specified it will default to webPki validation.
162+
nullable: true
163+
properties:
164+
verification:
165+
description: The verification method used to verify the certificates of the server and/or the client.
166+
oneOf:
167+
- required:
168+
- none
169+
- required:
170+
- server
171+
properties:
172+
none:
173+
description: Use TLS but don't verify certificates.
174+
type: object
175+
server:
176+
description: Use TLS and a CA certificate to verify the server.
177+
properties:
178+
caCert:
179+
description: CA cert to verify the server.
180+
oneOf:
181+
- required:
182+
- webPki
183+
- required:
184+
- secretClass
185+
properties:
186+
secretClass:
187+
description: |-
188+
Name of the [SecretClass](https://docs.stackable.tech/home/nightly/secret-operator/secretclass) which will provide the CA certificate.
189+
Note that a SecretClass does not need to have a key but can also work with just a CA certificate,
190+
so if you got provided with a CA cert but don't have access to the key you can still use this method.
191+
type: string
192+
webPki:
193+
description: |-
194+
Use TLS and the CA certificates trusted by the common web browsers to verify the server.
195+
This can be useful when you e.g. use public AWS S3 or other public available services.
196+
type: object
197+
type: object
198+
required:
199+
- caCert
200+
type: object
201+
type: object
202+
required:
203+
- verification
204+
type: object
155205
wait:
156206
default: 20s
157207
description: |-

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

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ pub enum TlsClientDetailsError {
2828
},
2929
}
3030

31+
#[repr(transparent)]
3132
#[derive(
3233
Clone, Debug, Deserialize, Eq, Hash, JsonSchema, Ord, PartialEq, PartialOrd, Serialize,
3334
)]
@@ -37,6 +38,40 @@ pub struct TlsClientDetails {
3738
pub tls: Option<Tls>,
3839
}
3940

41+
#[repr(transparent)]
42+
#[derive(
43+
Clone, Debug, Deserialize, Eq, Hash, JsonSchema, Ord, PartialEq, PartialOrd, Serialize,
44+
)]
45+
#[serde(rename_all = "camelCase")]
46+
pub struct TlsClientDetailsWithSecureDefaults {
47+
/// Configure a TLS connection. If not specified it will default to webPki validation.
48+
#[serde(default = "default_web_pki_tls")]
49+
pub tls: Option<Tls>,
50+
}
51+
52+
impl std::ops::Deref for TlsClientDetailsWithSecureDefaults {
53+
type Target = TlsClientDetails;
54+
55+
fn deref(&self) -> &TlsClientDetails {
56+
// SAFETY: both types are `#[repr(transparent)]` over `Option<Tls>`, so they share
57+
// the same memory layout and this cast is sound.
58+
//
59+
// This cannot silently break due to struct changes: `#[repr(transparent)]` requires
60+
// exactly one non-zero-sized field, so adding a second real field to either struct
61+
// is a compile error. The only scenario that would NOT be caught at compile time is
62+
// deliberately removing `#[repr(transparent)]` from one of the two structs.
63+
unsafe { &*(self as *const Self as *const TlsClientDetails) }
64+
}
65+
}
66+
67+
fn default_web_pki_tls() -> Option<Tls> {
68+
Some(Tls {
69+
verification: TlsVerification::Server(TlsServerVerification {
70+
ca_cert: CaCert::WebPki {},
71+
}),
72+
})
73+
}
74+
4075
impl TlsClientDetails {
4176
/// This functions adds
4277
///
@@ -168,3 +203,51 @@ pub enum CaCert {
168203
/// so if you got provided with a CA cert but don't have access to the key you can still use this method.
169204
SecretClass(String),
170205
}
206+
207+
#[cfg(test)]
208+
mod tests {
209+
use super::*;
210+
use crate::utils::yaml_from_str_singleton_map;
211+
212+
#[test]
213+
fn tls_client_details_with_secure_defaults_deserialization() {
214+
// No tls key at all → WebPki default kicks in
215+
let parsed: TlsClientDetailsWithSecureDefaults =
216+
yaml_from_str_singleton_map("{}").expect("failed to deserialize empty input");
217+
assert_eq!(parsed.tls, default_web_pki_tls());
218+
219+
// Explicit null → opt out of TLS entirely
220+
let parsed: TlsClientDetailsWithSecureDefaults =
221+
yaml_from_str_singleton_map("tls: null").expect("failed to deserialize tls: null");
222+
assert_eq!(parsed.tls, None);
223+
224+
// Explicit SecretClass value is preserved as-is
225+
let parsed: TlsClientDetailsWithSecureDefaults = yaml_from_str_singleton_map(
226+
"tls:
227+
verification:
228+
server:
229+
caCert:
230+
secretClass: my-ca",
231+
)
232+
.expect("failed to deserialize secretClass");
233+
assert_eq!(
234+
parsed.tls,
235+
Some(Tls {
236+
verification: TlsVerification::Server(TlsServerVerification {
237+
ca_cert: CaCert::SecretClass("my-ca".to_owned()),
238+
}),
239+
})
240+
);
241+
}
242+
243+
#[test]
244+
#[allow(clippy::explicit_auto_deref)]
245+
fn tls_client_details_with_secure_defaults_deref() {
246+
let secure: TlsClientDetailsWithSecureDefaults =
247+
yaml_from_str_singleton_map("{}").expect("failed to deserialize");
248+
249+
// Deref must not panic and must expose the same tls value
250+
let tls_client_details: &TlsClientDetails = &*secure;
251+
assert_eq!(tls_client_details.tls, secure.tls);
252+
}
253+
}

crates/stackable-operator/src/crd/git_sync/mod.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,17 @@ use serde::{Deserialize, Serialize};
77
use stackable_shared::time::Duration;
88
use url::Url;
99

10-
use crate::{crd::git_sync::v1alpha2::Credentials, versioned::versioned};
10+
use crate::{
11+
commons::tls_verification::TlsClientDetailsWithSecureDefaults,
12+
crd::git_sync::v1alpha2::Credentials, versioned::versioned,
13+
};
1114

1215
mod v1alpha1_impl;
1316
mod v1alpha2_impl;
1417

1518
#[versioned(version(name = "v1alpha1"), version(name = "v1alpha2"))]
1619
pub mod versioned {
20+
1721
pub mod v1alpha1 {
1822
pub use v1alpha1_impl::{Error, GitSyncResources};
1923
}
@@ -68,6 +72,12 @@ pub mod versioned {
6872
downgrade_with = credentials_to_secret
6973
))]
7074
pub credentials: Option<Credentials>,
75+
76+
/// An optional field used for referencing CA certificates that will be used to verify the git server's TLS certificate by passing it to the git config option `http.sslCAInfo` passed with the gitsync command. The secret must have a key named `ca.crt` whose value is the PEM-encoded certificate bundle.
77+
/// If `http.sslCAInfo` is also set via `gitSyncConf` (the `--git-config` option) then a warning will be logged.
78+
/// If not specified no TLS will be used, defaulting to github/lab using commonly-recognised certificates.
79+
#[serde(flatten)]
80+
pub tls: TlsClientDetailsWithSecureDefaults,
7181
}
7282

7383
#[derive(strum::Display, Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]

0 commit comments

Comments
 (0)