11use std:: collections:: BTreeMap ;
22
33use rand:: { RngExt , distr:: Alphanumeric } ;
4- use snafu:: { OptionExt , ResultExt , Snafu } ;
4+ use snafu:: { ResultExt , Snafu } ;
55use stackable_operator:: {
6- builder:: meta:: ObjectMetaBuilder ,
7- client:: Client ,
86 commons:: tls_verification:: { CaCert , TlsServerVerification , TlsVerification } ,
97 crd:: authentication:: oidc,
10- k8s_openapi:: api:: core:: v1:: Secret ,
11- kube:: { ResourceExt , runtime:: reflector:: ObjectRef } ,
12- kvp:: ObjectLabels ,
8+ k8s_openapi:: { ByteString , api:: core:: v1:: Secret } ,
9+ kube:: ResourceExt ,
1310} ;
1411
1512use crate :: { crd:: v1alpha1, security:: authentication:: STACKABLE_ADMIN_USERNAME } ;
@@ -18,93 +15,60 @@ type Result<T, E = Error> = std::result::Result<T, E>;
1815
1916#[ derive( Snafu , Debug ) ]
2017pub enum Error {
21- #[ snafu( display( "the NiFi object defines no namespace" ) ) ]
22- ObjectHasNoNamespace ,
23-
24- #[ snafu( display( "failed to fetch or create OIDC admin password secret" ) ) ]
25- OidcAdminPasswordSecret {
26- source : stackable_operator:: client:: Error ,
27- } ,
28-
29- #[ snafu( display(
30- "found existing admin password secret {secret:?}, but the key {STACKABLE_ADMIN_USERNAME} is missing" ,
31- ) ) ]
32- MissingAdminPasswordKey { secret : ObjectRef < Secret > } ,
33-
3418 #[ snafu( display( "invalid well-known OIDC configuration URL" ) ) ]
3519 InvalidWellKnownConfigUrl {
3620 source : stackable_operator:: crd:: authentication:: oidc:: v1alpha1:: Error ,
3721 } ,
3822
3923 #[ snafu( display( "Nifi doesn't support skipping the OIDC TLS verification" ) ) ]
4024 SkippingTlsVerificationNotSupported { } ,
41-
42- #[ snafu( display( "failed to build OIDC admin password secret metadata" ) ) ]
43- BuildOidcAdminPasswordSecretMetadata {
44- source : stackable_operator:: builder:: meta:: Error ,
45- } ,
4625}
4726
48- /// Build a Secret containing the OIDC admin password.
49- ///
50- /// If the secret already exists, the existing password is preserved.
27+ /// Returns a password to be used by the OIDC admin user.
28+ /// If the Secret containing the password already exists and contains the expected key, the existing password is returned.
5129/// Otherwise a new random password is generated.
52- pub ( crate ) async fn build_oidc_admin_password_secret (
53- client : & Client ,
54- nifi : & v1alpha1:: NifiCluster ,
55- labels : ObjectLabels < ' _ , v1alpha1:: NifiCluster > ,
56- ) -> Result < Secret , Error > {
57- let namespace: & str = & nifi. namespace ( ) . context ( ObjectHasNoNamespaceSnafu ) ?;
58- tracing:: debug!( "Checking for OIDC admin password configuration" ) ;
59-
60- let password = match client
61- . get_opt :: < Secret > ( & build_oidc_admin_password_secret_name ( nifi) , namespace)
62- . await
63- . context ( OidcAdminPasswordSecretSnafu ) ?
64- {
30+ pub ( crate ) fn build_oidc_admin_password_secret ( oidc_admin_secret : Option < Secret > ) -> String {
31+ match oidc_admin_secret {
6532 Some ( secret) => {
6633 let existing_password = secret
6734 . data
6835 . as_ref ( )
6936 . and_then ( |data| data. get ( STACKABLE_ADMIN_USERNAME ) )
70- . map ( |bytes| String :: from_utf8_lossy ( & bytes . 0 ) . into_owned ( ) ) ;
37+ . map ( decode_admin_password ) ;
7138
7239 match existing_password {
7340 Some ( password) => password,
74- None => MissingAdminPasswordKeySnafu {
75- secret : ObjectRef :: from_obj ( & secret) ,
41+ None => {
42+ tracing:: info!(
43+ expected_key = STACKABLE_ADMIN_USERNAME ,
44+ "Found existing OIDC admin password secret, but it doesn't contain the expected key, generating new password"
45+ ) ;
46+ encode_admin_password ( 15 )
7647 }
77- . fail ( ) ?,
7848 }
7949 }
8050 None => {
8151 tracing:: info!( "No existing OIDC admin password secret found, generating new one" ) ;
82- rand:: rng ( )
83- . sample_iter ( & Alphanumeric )
84- . take ( 15 )
85- . map ( char:: from)
86- . collect ( )
52+ encode_admin_password ( 15 )
8753 }
88- } ;
89-
90- Ok ( Secret {
91- metadata : ObjectMetaBuilder :: new ( )
92- . name_and_namespace ( nifi)
93- . name ( build_oidc_admin_password_secret_name ( nifi) )
94- . ownerreference_from_resource ( nifi, None , Some ( true ) )
95- . context ( BuildOidcAdminPasswordSecretMetadataSnafu ) ?
96- . with_recommended_labels ( labels)
97- . context ( BuildOidcAdminPasswordSecretMetadataSnafu ) ?
98- . build ( ) ,
99- string_data : Some ( BTreeMap :: from ( [ (
100- STACKABLE_ADMIN_USERNAME . to_string ( ) ,
101- password,
102- ) ] ) ) ,
103- ..Secret :: default ( )
104- } )
54+ }
55+ }
56+
57+ // TODO: maybe switch to get_random_base64() (not public atm) from op-rs which is ASCII clean and thus more suitable for passwords:
58+ // https://github.com/stackabletech/operator-rs/blob/main/crates/stackable-operator/src/commons/random_secret_creation.rs#L127-L127
59+ fn encode_admin_password ( size_bytes : usize ) -> String {
60+ rand:: rng ( )
61+ . sample_iter ( & Alphanumeric )
62+ . take ( size_bytes)
63+ . map ( char:: from)
64+ . collect ( )
65+ }
66+
67+ fn decode_admin_password ( encoded : & ByteString ) -> String {
68+ String :: from_utf8_lossy ( & encoded. 0 ) . into_owned ( )
10569}
10670
107- pub fn build_oidc_admin_password_secret_name ( nifi : & v1alpha1:: NifiCluster ) -> String {
71+ pub ( crate ) fn build_oidc_admin_password_secret_name ( nifi : & v1alpha1:: NifiCluster ) -> String {
10872 format ! ( "{}-oidc-admin-password" , nifi. name_any( ) )
10973}
11074
0 commit comments