Skip to content

Commit 263e59c

Browse files
committed
feat: Conditionally generate Kerberos keytab
1 parent fe1d9ca commit 263e59c

2 files changed

Lines changed: 103 additions & 90 deletions

File tree

rust/krb5-provision-keytab/src/lib.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,10 @@ pub enum Error {
6868
/// Provisions a Kerberos Keytab based on the [`Request`].
6969
///
7070
/// This function assumes that the binary produced by this crate is on the `$PATH`, and will fail otherwise.
71-
pub async fn provision_keytab(krb5_config_path: &Path, req: &Request) -> Result<Response, Error> {
71+
pub async fn provision_keytab_file(
72+
krb5_config_path: &Path,
73+
req: &Request,
74+
) -> Result<Response, Error> {
7275
let req_str = serde_json::to_vec(&req).context(SerializeRequestSnafu)?;
7376

7477
let mut child = Command::new("stackable-krb5-provision-keytab")

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

Lines changed: 99 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use snafu::{OptionExt, ResultExt, Snafu};
33
use stackable_krb5_provision_keytab::{
44
// Some qualified paths get long enough to break rustfmt, alias the crate name to work around that
55
self as provision,
6-
provision_keytab,
6+
provision_keytab_file,
77
};
88
use stackable_operator::{
99
commons::networking::{HostName, KerberosRealmName},
@@ -167,6 +167,8 @@ impl SecretBackend for KerberosKeytab {
167167
admin_principal,
168168
} = self;
169169

170+
let provision_keytab = !selector.only_provision_identity;
171+
170172
let admin_server_clause = match admin {
171173
v1alpha2::KerberosKeytabBackendAdmin::Mit(v1alpha2::KerberosKeytabBackendMit {
172174
kadmin_server,
@@ -207,102 +209,110 @@ cluster.local = {realm_name}
207209
.await
208210
.context(WriteConfigSnafu)?;
209211
}
210-
let admin_keytab_file_path = tmp.path().join("admin-keytab");
211-
{
212-
let mut admin_keytab_file = File::create(&admin_keytab_file_path)
213-
.await
214-
.context(WriteAdminKeytabSnafu)?;
215-
admin_keytab_file
216-
.write_all(admin_keytab)
217-
.await
218-
.context(WriteAdminKeytabSnafu)?;
219-
}
220212

221-
let keytab_file_path = tmp.path().join("pod-keytab");
222-
let mut pod_principals: Vec<KerberosPrincipal> = Vec::new();
223-
for service_name in &selector.kerberos_service_names {
224-
for scope in &selector.scope {
225-
for addr in
226-
selector
227-
.scope_addresses(&pod_info, scope)
228-
.context(ScopeAddressesSnafu {
229-
scope: scope.clone(),
230-
})?
213+
let keytab_data =
214+
if provision_keytab {
215+
let admin_keytab_file_path = tmp.path().join("admin-keytab");
231216
{
232-
pod_principals.push(
233-
match addr {
234-
Address::Dns(hostname) => {
235-
format!("{service_name}/{hostname}")
236-
}
237-
Address::Ip(ip) => {
238-
format!("{service_name}/{ip}")
239-
}
240-
}
241-
.try_into()
242-
.context(PodPrincipalSnafu)?,
243-
);
217+
let mut admin_keytab_file = File::create(&admin_keytab_file_path)
218+
.await
219+
.context(WriteAdminKeytabSnafu)?;
220+
admin_keytab_file
221+
.write_all(admin_keytab)
222+
.await
223+
.context(WriteAdminKeytabSnafu)?;
244224
}
245-
}
246-
}
247-
provision_keytab(
248-
&profile_file_path,
249-
&stackable_krb5_provision_keytab::Request {
250-
admin_keytab_path: admin_keytab_file_path,
251-
admin_principal_name: admin_principal.to_string(),
252-
pod_keytab_path: keytab_file_path.clone(),
253-
principals: pod_principals
254-
.into_iter()
255-
.map(|princ| stackable_krb5_provision_keytab::PrincipalRequest {
256-
name: princ.to_string(),
257-
})
258-
.collect(),
259-
admin_backend: match admin {
260-
v1alpha2::KerberosKeytabBackendAdmin::Mit { .. } => {
261-
stackable_krb5_provision_keytab::AdminBackend::Mit
262-
}
263-
v1alpha2::KerberosKeytabBackendAdmin::ActiveDirectory(
264-
v1alpha2::KerberosKeytabBackendActiveDirectory {
265-
ldap_server,
266-
ldap_tls_ca_secret,
267-
password_cache_secret,
268-
user_distinguished_name,
269-
schema_distinguished_name,
270-
generate_sam_account_name,
271-
},
272-
) => stackable_krb5_provision_keytab::AdminBackend::ActiveDirectory {
273-
ldap_server: ldap_server.to_string(),
274-
ldap_tls_ca_secret: ldap_tls_ca_secret.clone(),
275-
password_cache_secret: password_cache_secret.clone(),
276-
user_distinguished_name: user_distinguished_name.clone(),
277-
schema_distinguished_name: schema_distinguished_name.clone(),
278-
generate_sam_account_name: generate_sam_account_name.clone().map(
279-
|v1alpha2::ActiveDirectorySamAccountNameRules {
280-
prefix,
281-
total_length,
282-
}| {
283-
provision::ActiveDirectorySamAccountNameRules {
284-
prefix,
285-
total_length,
225+
226+
let keytab_file_path = tmp.path().join("pod-keytab");
227+
let mut pod_principals: Vec<KerberosPrincipal> = Vec::new();
228+
for service_name in &selector.kerberos_service_names {
229+
for scope in &selector.scope {
230+
for addr in selector.scope_addresses(&pod_info, scope).context(
231+
ScopeAddressesSnafu {
232+
scope: scope.clone(),
233+
},
234+
)? {
235+
pod_principals.push(
236+
match addr {
237+
Address::Dns(hostname) => {
238+
format!("{service_name}/{hostname}")
239+
}
240+
Address::Ip(ip) => {
241+
format!("{service_name}/{ip}")
242+
}
286243
}
244+
.try_into()
245+
.context(PodPrincipalSnafu)?,
246+
);
247+
}
248+
}
249+
}
250+
provision_keytab_file(
251+
&profile_file_path,
252+
&stackable_krb5_provision_keytab::Request {
253+
admin_keytab_path: admin_keytab_file_path,
254+
admin_principal_name: admin_principal.to_string(),
255+
pod_keytab_path: keytab_file_path.clone(),
256+
principals: pod_principals
257+
.into_iter()
258+
.map(|princ| stackable_krb5_provision_keytab::PrincipalRequest {
259+
name: princ.to_string(),
260+
})
261+
.collect(),
262+
admin_backend: match admin {
263+
v1alpha2::KerberosKeytabBackendAdmin::Mit { .. } => {
264+
stackable_krb5_provision_keytab::AdminBackend::Mit
265+
}
266+
v1alpha2::KerberosKeytabBackendAdmin::ActiveDirectory(
267+
v1alpha2::KerberosKeytabBackendActiveDirectory {
268+
ldap_server,
269+
ldap_tls_ca_secret,
270+
password_cache_secret,
271+
user_distinguished_name,
272+
schema_distinguished_name,
273+
generate_sam_account_name,
274+
},
275+
) => stackable_krb5_provision_keytab::AdminBackend::ActiveDirectory {
276+
ldap_server: ldap_server.to_string(),
277+
ldap_tls_ca_secret: ldap_tls_ca_secret.clone(),
278+
password_cache_secret: password_cache_secret.clone(),
279+
user_distinguished_name: user_distinguished_name.clone(),
280+
schema_distinguished_name: schema_distinguished_name.clone(),
281+
generate_sam_account_name: generate_sam_account_name.clone().map(
282+
|v1alpha2::ActiveDirectorySamAccountNameRules {
283+
prefix,
284+
total_length,
285+
}| {
286+
provision::ActiveDirectorySamAccountNameRules {
287+
prefix,
288+
total_length,
289+
}
290+
},
291+
),
287292
},
288-
),
293+
},
289294
},
290-
},
291-
},
292-
)
293-
.await
294-
.context(ProvisionKeytabSnafu)?;
295-
let mut keytab_data = Vec::new();
296-
let mut keytab_file = File::open(keytab_file_path)
297-
.await
298-
.context(ReadProvisionedKeytabSnafu)?;
299-
keytab_file
300-
.read_to_end(&mut keytab_data)
301-
.await
302-
.context(ReadProvisionedKeytabSnafu)?;
295+
)
296+
.await
297+
.context(ProvisionKeytabSnafu)?;
298+
let mut keytab_data = Vec::new();
299+
let mut keytab_file = File::open(keytab_file_path)
300+
.await
301+
.context(ReadProvisionedKeytabSnafu)?;
302+
keytab_file
303+
.read_to_end(&mut keytab_data)
304+
.await
305+
.context(ReadProvisionedKeytabSnafu)?;
306+
307+
Some(keytab_data)
308+
} else {
309+
// NOTE (@Techassi): I kinda hate this, but I guess there is no way around it
310+
None
311+
};
312+
303313
Ok(SecretContents::new(SecretData::WellKnown(
304314
WellKnownSecretData::Kerberos(well_known::Kerberos {
305-
keytab: Some(keytab_data),
315+
keytab: keytab_data,
306316
krb5_conf: profile.into_bytes(),
307317
}),
308318
)))

0 commit comments

Comments
 (0)