@@ -27,12 +27,13 @@ use stackable_operator::{
2727} ;
2828use time:: OffsetDateTime ;
2929
30- use super :: {
31- ScopeAddressesError , SecretBackend , SecretBackendError , SecretContents ,
32- pod_info:: { Address , PodInfo } ,
33- scope:: SecretScope ,
34- } ;
3530use crate :: {
31+ backend:: {
32+ ScopeAddressesError , SecretBackend , SecretBackendError , SecretContents ,
33+ SecretVolumeSelector ,
34+ pod_info:: { Address , PodInfo } ,
35+ scope:: SecretScope ,
36+ } ,
3637 crd:: v1alpha2,
3738 format:: { SecretData , WellKnownSecretData , well_known} ,
3839 utils:: iterator_try_concat_bytes,
@@ -262,7 +263,7 @@ impl SecretBackend for TlsGenerate {
262263 /// Then add the ca certificate and return these files for provisioning to the volume.
263264 async fn get_secret_data (
264265 & self ,
265- selector : & super :: SecretVolumeSelector ,
266+ selector : & SecretVolumeSelector ,
266267 pod_info : PodInfo ,
267268 ) -> Result < SecretContents , Self :: Error > {
268269 let now = OffsetDateTime :: now_utc ( ) ;
@@ -271,6 +272,7 @@ impl SecretBackend for TlsGenerate {
271272 // Extract and convert consumer input from the Volume annotations.
272273 let cert_lifetime = selector. autotls_cert_lifetime ;
273274 let cert_restart_buffer = selector. autotls_cert_restart_buffer ;
275+ let provision_cert = !selector. only_provision_identity ;
274276
275277 // We need to check that the cert lifetime it is not longer than allowed,
276278 // by capping it to the maximum configured at the SecretClass.
@@ -300,6 +302,7 @@ impl SecretBackend for TlsGenerate {
300302 let jitter_amount = Duration :: from ( cert_lifetime. mul_f64 ( jitter_factor) ) ;
301303 let unjittered_cert_lifetime = cert_lifetime;
302304 let cert_lifetime = cert_lifetime - jitter_amount;
305+
303306 tracing:: info!(
304307 certificate. lifetime. requested = %unjittered_cert_lifetime,
305308 certificate. lifetime. jitter = %jitter_amount,
@@ -319,113 +322,140 @@ impl SecretBackend for TlsGenerate {
319322 . fail ( ) ?;
320323 }
321324
322- let conf =
323- Conf :: new ( ConfMethod :: default ( ) ) . expect ( "failed to initialize OpenSSL configuration" ) ;
324-
325- let pod_key_length = match self . key_generation {
326- v1alpha2:: CertificateKeyGeneration :: Rsa { length } => length,
327- } ;
328-
329- let pod_key = Rsa :: generate ( pod_key_length)
330- . and_then ( PKey :: try_from)
331- . context ( GenerateKeySnafu ) ?;
332- let mut addresses = Vec :: new ( ) ;
333- for scope in & selector. scope {
334- addresses. extend (
335- selector
336- . scope_addresses ( & pod_info, scope)
337- . context ( ScopeAddressesSnafu { scope } ) ?,
338- ) ;
339- }
340- for address in & mut addresses {
341- if let Address :: Dns ( dns) = address {
342- // Turn FQDNs into bare domain names by removing the trailing dot
343- if dns. ends_with ( '.' ) {
344- dns. pop ( ) ;
345- }
346- }
347- }
348325 let ca = self
349326 . ca_manager
350327 . find_certificate_authority_for_signing ( not_after)
351328 . context ( PickCaSnafu ) ?;
352- let pod_cert = X509Builder :: new ( )
353- . and_then ( |mut x509| {
354- let subject_name = X509NameBuilder :: new ( )
355- . and_then ( |mut name| {
356- name. append_entry_by_nid ( Nid :: COMMONNAME , "generated certificate for pod" ) ?;
357- Ok ( name)
358- } ) ?
359- . build ( ) ;
360- x509. set_subject_name ( & subject_name) ?;
361- x509. set_issuer_name ( ca. certificate . subject_name ( ) ) ?;
362- x509. set_not_before ( Asn1Time :: from_unix ( not_before. unix_timestamp ( ) ) ?. as_ref ( ) ) ?;
363- x509. set_not_after ( Asn1Time :: from_unix ( not_after. unix_timestamp ( ) ) ?. as_ref ( ) ) ?;
364- x509. set_pubkey ( & pod_key) ?;
365- x509. set_version (
366- 3 - 1 , // zero-indexed
367- ) ?;
368- let mut serial = BigNum :: new ( ) ?;
369- serial. rand ( 64 , MsbOption :: MAYBE_ZERO , false ) ?;
370- x509. set_serial_number ( Asn1Integer :: from_bn ( & serial) ?. as_ref ( ) ) ?;
371- let ctx = x509. x509v3_context ( Some ( & ca. certificate ) , Some ( & conf) ) ;
372- let mut exts = vec ! [
373- BasicConstraints :: new( ) . critical( ) . build( ) ?,
374- KeyUsage :: new( )
375- . key_encipherment( )
376- . digital_signature( )
377- . build( ) ?,
378- ExtendedKeyUsage :: new( )
379- . server_auth( )
380- . client_auth( )
381- . build( ) ?,
382- SubjectKeyIdentifier :: new( ) . build( & ctx) ?,
383- AuthorityKeyIdentifier :: new( )
384- . issuer( true )
385- . keyid( true )
386- . build( & ctx) ?,
387- ] ;
388- let mut san_ext = SubjectAlternativeName :: new ( ) ;
389- san_ext. critical ( ) ;
390- let mut has_san = false ;
391- for addr in addresses {
392- has_san = true ;
393- match addr {
394- Address :: Dns ( dns) => san_ext. dns ( & dns) ,
395- Address :: Ip ( ip) => san_ext. ip ( & ip. to_string ( ) ) ,
396- } ;
397- }
398- if has_san {
399- exts. push ( san_ext. build ( & ctx) ?) ;
400- }
401- for ext in exts {
402- x509. append_extension ( ext) ?;
329+
330+ // Only run leaf certificate generation if it was requested based on the
331+ // secret volume selector. Otherwise only a ca.crt file as a PEM envelope
332+ // will be available (to be mounted).
333+ let tls_secret_data = if provision_cert {
334+ let conf = Conf :: new ( ConfMethod :: default ( ) )
335+ . expect ( "failed to initialize OpenSSL configuration" ) ;
336+
337+ let pod_key_length = match self . key_generation {
338+ v1alpha2:: CertificateKeyGeneration :: Rsa { length } => length,
339+ } ;
340+
341+ let pod_key = Rsa :: generate ( pod_key_length)
342+ . and_then ( PKey :: try_from)
343+ . context ( GenerateKeySnafu ) ?;
344+
345+ let mut addresses = Vec :: new ( ) ;
346+ for scope in & selector. scope {
347+ addresses. extend (
348+ selector
349+ . scope_addresses ( & pod_info, scope)
350+ . context ( ScopeAddressesSnafu { scope } ) ?,
351+ ) ;
352+ }
353+ for address in & mut addresses {
354+ if let Address :: Dns ( dns) = address {
355+ // Turn FQDNs into bare domain names by removing the trailing dot
356+ if dns. ends_with ( '.' ) {
357+ dns. pop ( ) ;
358+ }
403359 }
404- x509. sign ( & ca. private_key , MessageDigest :: sha256 ( ) ) ?;
405- Ok ( x509)
406- } )
407- . context ( BuildCertificateSnafu ) ?
408- . build ( ) ;
360+ }
361+
362+ let pod_cert = X509Builder :: new ( )
363+ . and_then ( |mut x509| {
364+ let subject_name = X509NameBuilder :: new ( )
365+ . and_then ( |mut name| {
366+ name. append_entry_by_nid (
367+ Nid :: COMMONNAME ,
368+ "generated certificate for pod" ,
369+ ) ?;
370+ Ok ( name)
371+ } ) ?
372+ . build ( ) ;
373+ x509. set_subject_name ( & subject_name) ?;
374+ x509. set_issuer_name ( ca. certificate . subject_name ( ) ) ?;
375+ x509. set_not_before (
376+ Asn1Time :: from_unix ( not_before. unix_timestamp ( ) ) ?. as_ref ( ) ,
377+ ) ?;
378+ x509. set_not_after ( Asn1Time :: from_unix ( not_after. unix_timestamp ( ) ) ?. as_ref ( ) ) ?;
379+ x509. set_pubkey ( & pod_key) ?;
380+ x509. set_version (
381+ 3 - 1 , // zero-indexed
382+ ) ?;
383+ let mut serial = BigNum :: new ( ) ?;
384+ serial. rand ( 64 , MsbOption :: MAYBE_ZERO , false ) ?;
385+ x509. set_serial_number ( Asn1Integer :: from_bn ( & serial) ?. as_ref ( ) ) ?;
386+ let ctx = x509. x509v3_context ( Some ( & ca. certificate ) , Some ( & conf) ) ;
387+ let mut exts = vec ! [
388+ BasicConstraints :: new( ) . critical( ) . build( ) ?,
389+ KeyUsage :: new( )
390+ . key_encipherment( )
391+ . digital_signature( )
392+ . build( ) ?,
393+ ExtendedKeyUsage :: new( )
394+ . server_auth( )
395+ . client_auth( )
396+ . build( ) ?,
397+ SubjectKeyIdentifier :: new( ) . build( & ctx) ?,
398+ AuthorityKeyIdentifier :: new( )
399+ . issuer( true )
400+ . keyid( true )
401+ . build( & ctx) ?,
402+ ] ;
403+ let mut san_ext = SubjectAlternativeName :: new ( ) ;
404+ san_ext. critical ( ) ;
405+ let mut has_san = false ;
406+ for addr in addresses {
407+ has_san = true ;
408+ match addr {
409+ Address :: Dns ( dns) => san_ext. dns ( & dns) ,
410+ Address :: Ip ( ip) => san_ext. ip ( & ip. to_string ( ) ) ,
411+ } ;
412+ }
413+ if has_san {
414+ exts. push ( san_ext. build ( & ctx) ?) ;
415+ }
416+ for ext in exts {
417+ x509. append_extension ( ext) ?;
418+ }
419+ x509. sign ( & ca. private_key , MessageDigest :: sha256 ( ) ) ?;
420+ Ok ( x509)
421+ } )
422+ . context ( BuildCertificateSnafu ) ?
423+ . build ( ) ;
424+
425+ well_known:: TlsPem {
426+ ca_pem : iterator_try_concat_bytes (
427+ self . ca_manager . trust_roots ( now) . into_iter ( ) . map ( |ca| {
428+ ca. to_pem ( )
429+ . context ( SerializeCertificateSnafu { tpe : CertType :: Ca } )
430+ } ) ,
431+ ) ?,
432+ certificate_pem : Some (
433+ pod_cert
434+ . to_pem ( )
435+ . context ( SerializeCertificateSnafu { tpe : CertType :: Pod } ) ?,
436+ ) ,
437+ key_pem : Some (
438+ pod_key
439+ . private_key_to_pem_pkcs8 ( )
440+ . context ( SerializeCertificateSnafu { tpe : CertType :: Pod } ) ?,
441+ ) ,
442+ }
443+ } else {
444+ well_known:: TlsPem {
445+ ca_pem : iterator_try_concat_bytes (
446+ self . ca_manager . trust_roots ( now) . into_iter ( ) . map ( |ca| {
447+ ca. to_pem ( )
448+ . context ( SerializeCertificateSnafu { tpe : CertType :: Ca } )
449+ } ) ,
450+ ) ?,
451+ certificate_pem : None ,
452+ key_pem : None ,
453+ }
454+ } ;
455+
409456 Ok (
410457 SecretContents :: new ( SecretData :: WellKnown ( WellKnownSecretData :: TlsPem (
411- well_known:: TlsPem {
412- ca_pem : iterator_try_concat_bytes (
413- self . ca_manager . trust_roots ( now) . into_iter ( ) . map ( |ca| {
414- ca. to_pem ( )
415- . context ( SerializeCertificateSnafu { tpe : CertType :: Ca } )
416- } ) ,
417- ) ?,
418- certificate_pem : Some (
419- pod_cert
420- . to_pem ( )
421- . context ( SerializeCertificateSnafu { tpe : CertType :: Pod } ) ?,
422- ) ,
423- key_pem : Some (
424- pod_key
425- . private_key_to_pem_pkcs8 ( )
426- . context ( SerializeCertificateSnafu { tpe : CertType :: Pod } ) ?,
427- ) ,
428- } ,
458+ tls_secret_data,
429459 ) ) )
430460 . expires_after (
431461 time_datetime_to_chrono ( expire_pod_after) . context ( InvalidCertLifetimeSnafu ) ?,
0 commit comments