Skip to content

Commit e9cfcee

Browse files
Log when secrets are issued (#413)
* Log when secrets are issued Fixes #348 * Changelog --------- Co-authored-by: Nick <NickLarsenNZ@users.noreply.github.com>
1 parent c35b243 commit e9cfcee

File tree

10 files changed

+80
-16
lines changed

10 files changed

+80
-16
lines changed

CHANGELOG.md

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

55
## [Unreleased]
66

7+
### Added
8+
9+
- The associated configuration is now logged for each issued secret ([#413]).
10+
711
### Changed
812

913
- [BREAKING] The TLS CA Secret is now installed into the Namespace of the operator (typically `stackable-operators`), rather than `default` ([#397]).
@@ -19,6 +23,7 @@ All notable changes to this project will be documented in this file.
1923

2024
[#397]: https://github.com/stackabletech/secret-operator/pull/397
2125
[#403]: https://github.com/stackabletech/secret-operator/pull/403
26+
[#413]: https://github.com/stackabletech/secret-operator/pull/413
2227
[#440]: https://github.com/stackabletech/secret-operator/pull/440
2328

2429
## [24.3.0] - 2024-03-20

rust/operator-binary/src/backend/dynamic.rs

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,36 @@
11
//! Support code for runtime-configurable dynamic [`SecretBackend`]s
22
3-
use std::{collections::HashSet, fmt::Display};
3+
use std::{
4+
collections::HashSet,
5+
fmt::{Debug, Display},
6+
};
47

58
use async_trait::async_trait;
69
use snafu::{ResultExt, Snafu};
710
use stackable_operator::kube::runtime::reflector::ObjectRef;
811

9-
use crate::crd::{self, SecretClass};
12+
use crate::{
13+
crd::{self, SecretClass},
14+
utils::Unloggable,
15+
};
1016

1117
use super::{
1218
kerberos_keytab::{self, KerberosProfile},
1319
pod_info::{PodInfo, SchedulingPodInfo},
1420
tls, SecretBackend, SecretBackendError, SecretVolumeSelector,
1521
};
1622

17-
#[derive(Debug)]
1823
pub struct DynError(Box<dyn SecretBackendError>);
1924

25+
impl Debug for DynError {
26+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
27+
Debug::fmt(&self.0, f)
28+
}
29+
}
30+
2031
impl Display for DynError {
2132
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
22-
self.0.fmt(f)
33+
Display::fmt(&self.0, f)
2334
}
2435
}
2536
impl std::error::Error for DynError {
@@ -35,6 +46,12 @@ impl SecretBackendError for DynError {
3546

3647
pub struct DynamicAdapter<B>(B);
3748

49+
impl<B: Debug> Debug for DynamicAdapter<B> {
50+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
51+
self.0.fmt(f)
52+
}
53+
}
54+
3855
#[async_trait]
3956
impl<B: SecretBackend + Send + Sync> SecretBackend for DynamicAdapter<B> {
4057
type Error = DynError;
@@ -96,7 +113,7 @@ pub async fn from_class(
96113
Ok(match class.spec.backend {
97114
crd::SecretClassBackend::K8sSearch(crd::K8sSearchBackend { search_namespace }) => {
98115
from(super::K8sSearch {
99-
client: client.clone(),
116+
client: Unloggable(client.clone()),
100117
search_namespace,
101118
})
102119
}

rust/operator-binary/src/backend/k8s_search.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use stackable_operator::{
1212
kvp::{LabelError, LabelSelectorExt, Labels},
1313
};
1414

15-
use crate::{crd::SearchNamespace, format::SecretData};
15+
use crate::{crd::SearchNamespace, format::SecretData, utils::Unloggable};
1616

1717
use super::{
1818
pod_info::{PodInfo, SchedulingPodInfo},
@@ -60,8 +60,10 @@ impl SecretBackendError for Error {
6060
}
6161
}
6262

63+
#[derive(Debug)]
6364
pub struct K8sSearch {
64-
pub client: stackable_operator::client::Client,
65+
// Not secret per se, but isn't Debug: https://github.com/stackabletech/secret-operator/issues/411
66+
pub client: Unloggable<stackable_operator::client::Client>,
6567
pub search_namespace: SearchNamespace,
6668
}
6769

rust/operator-binary/src/backend/kerberos_keytab.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use tokio::{
1212
use crate::{
1313
crd::{Hostname, InvalidKerberosPrincipal, KerberosKeytabBackendAdmin, KerberosPrincipal},
1414
format::{well_known, SecretData, WellKnownSecretData},
15+
utils::Unloggable,
1516
};
1617

1718
use super::{
@@ -72,15 +73,17 @@ impl SecretBackendError for Error {
7273
}
7374
}
7475

76+
#[derive(Debug)]
7577
pub struct KerberosProfile {
7678
pub realm_name: Hostname,
7779
pub kdc: Hostname,
7880
pub admin: KerberosKeytabBackendAdmin,
7981
}
8082

83+
#[derive(Debug)]
8184
pub struct KerberosKeytab {
8285
profile: KerberosProfile,
83-
admin_keytab: Vec<u8>,
86+
admin_keytab: Unloggable<Vec<u8>>,
8487
admin_principal: KerberosPrincipal,
8588
}
8689

@@ -110,7 +113,7 @@ impl KerberosKeytab {
110113
.0;
111114
Ok(Self {
112115
profile,
113-
admin_keytab,
116+
admin_keytab: Unloggable(admin_keytab),
114117
admin_principal,
115118
})
116119
}

rust/operator-binary/src/backend/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use stackable_operator::{
1414
k8s_openapi::chrono::{DateTime, FixedOffset},
1515
time::Duration,
1616
};
17-
use std::{collections::HashSet, convert::Infallible};
17+
use std::{collections::HashSet, convert::Infallible, fmt::Debug};
1818

1919
pub use k8s_search::K8sSearch;
2020
pub use kerberos_keytab::KerberosKeytab;
@@ -228,7 +228,7 @@ impl SecretContents {
228228
/// It gets the pod information as well as volume definition and has to
229229
/// return any number of files.
230230
#[async_trait]
231-
pub trait SecretBackend: Send + Sync {
231+
pub trait SecretBackend: Debug + Send + Sync {
232232
type Error: SecretBackendError;
233233

234234
/// Provision or load secret data from the source.

rust/operator-binary/src/backend/pod_info.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ pub enum FromPodError {
101101
}
102102

103103
/// Validated metadata about a scheduled [`Pod`]
104+
#[derive(Debug)]
104105
pub struct PodInfo {
105106
pub pod_ips: Vec<IpAddr>,
106107
pub service_name: Option<String>,
@@ -187,6 +188,7 @@ impl TryFrom<(AddressType, &str)> for Address {
187188
}
188189

189190
/// Validated metadata about a pod that may or may not be scheduled yet.
191+
#[derive(Debug)]
190192
pub struct SchedulingPodInfo {
191193
pub namespace: String,
192194
pub pod_name: String,

rust/operator-binary/src/backend/tls/ca.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ use tracing::{info, info_span, warn};
3434

3535
use crate::{
3636
backend::SecretBackendError,
37-
utils::{asn1time_to_offsetdatetime, Asn1TimeParseError},
37+
utils::{asn1time_to_offsetdatetime, Asn1TimeParseError, Unloggable},
3838
};
3939

4040
/// v1 format: support a single cert/pkey pair
@@ -156,9 +156,10 @@ pub struct Config {
156156
}
157157

158158
/// A single certificate authority certificate.
159+
#[derive(Debug)]
159160
pub struct CertificateAuthority {
160161
pub certificate: X509,
161-
pub private_key: PKey<Private>,
162+
pub private_key: Unloggable<PKey<Private>>,
162163
not_after: OffsetDateTime,
163164
}
164165

@@ -227,7 +228,7 @@ impl CertificateAuthority {
227228
.context(BuildCertificateSnafu)?
228229
.build();
229230
Ok(Self {
230-
private_key,
231+
private_key: Unloggable(private_key),
231232
certificate,
232233
not_after,
233234
})
@@ -274,12 +275,13 @@ impl CertificateAuthority {
274275
}
275276
})?,
276277
certificate,
277-
private_key,
278+
private_key: Unloggable(private_key),
278279
})
279280
}
280281
}
281282

282283
/// Manages multiple [`CertificateAuthorities`](`CertificateAuthority`), rotating them as needed.
284+
#[derive(Debug)]
283285
pub struct Manager {
284286
certificate_authorities: Vec<CertificateAuthority>,
285287
}

rust/operator-binary/src/backend/tls/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ impl SecretBackendError for Error {
128128
}
129129
}
130130

131+
#[derive(Debug)]
131132
pub struct TlsGenerate {
132133
ca_manager: ca::Manager,
133134
max_cert_lifetime: Duration,

rust/operator-binary/src/csi_server/node.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use snafu::{ResultExt, Snafu};
1010
use stackable_operator::{
1111
builder::meta::ObjectMetaBuilder,
1212
k8s_openapi::api::core::v1::Pod,
13+
kube::runtime::reflector::ObjectRef,
1314
kvp::{AnnotationError, Annotations},
1415
};
1516
use sys_mount::{unmount, Mount, MountFlags, UnmountFlags};
@@ -371,6 +372,8 @@ impl Node for SecretProvisionerNode {
371372
let backend = backend::dynamic::from_selector(&self.client, &selector)
372373
.await
373374
.context(publish_error::InitBackendSnafu)?;
375+
let pod_ref = ObjectRef::<Pod>::new(&selector.pod).within(&selector.namespace);
376+
tracing::info!(pod = %pod_ref, ?selector, ?pod_info, ?backend, "issuing secret for Pod");
374377
let data = backend
375378
.get_secret_data(&selector, pod_info)
376379
.await

rust/operator-binary/src/utils.rs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
use std::{fmt::LowerHex, os::unix::prelude::AsRawFd, path::Path};
1+
use std::{
2+
fmt::{Debug, LowerHex},
3+
ops::{Deref, DerefMut},
4+
os::unix::prelude::AsRawFd,
5+
path::Path,
6+
};
27

38
use futures::{pin_mut, Stream, StreamExt};
49
use openssl::asn1::{Asn1Time, Asn1TimeRef, TimeDiff};
@@ -173,6 +178,30 @@ pub fn asn1time_to_offsetdatetime(asn: &Asn1TimeRef) -> Result<OffsetDateTime, A
173178
.context(ParseSnafu)
174179
}
175180

181+
/// Wrapper for (mostly) secret values that should not be logged.
182+
// When/if migrating to Valuable, provide a dummy implementation of Value too
183+
pub struct Unloggable<T>(pub T);
184+
185+
impl<T> Debug for Unloggable<T> {
186+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
187+
f.write_str("<redacted>")
188+
}
189+
}
190+
191+
impl<T> Deref for Unloggable<T> {
192+
type Target = T;
193+
194+
fn deref(&self) -> &Self::Target {
195+
&self.0
196+
}
197+
}
198+
199+
impl<T> DerefMut for Unloggable<T> {
200+
fn deref_mut(&mut self) -> &mut Self::Target {
201+
&mut self.0
202+
}
203+
}
204+
176205
#[cfg(test)]
177206
mod tests {
178207
use futures::StreamExt;

0 commit comments

Comments
 (0)