@@ -25,12 +25,13 @@ use snafu::{OptionExt, ResultExt, Snafu, ensure};
2525use stackable_operator:: { kube:: runtime:: reflector:: ObjectRef , shared:: time:: Duration } ;
2626use time:: OffsetDateTime ;
2727
28- use super :: {
29- ScopeAddressesError , SecretBackend , SecretBackendError , SecretContents ,
30- pod_info:: { Address , PodInfo } ,
31- scope:: SecretScope ,
32- } ;
3328use crate :: {
29+ backend:: {
30+ ProvisionParts , ScopeAddressesError , SecretBackend , SecretBackendError , SecretContents ,
31+ SecretVolumeSelector ,
32+ pod_info:: { Address , PodInfo } ,
33+ scope:: SecretScope ,
34+ } ,
3435 crd:: v1alpha2,
3536 format:: { SecretData , WellKnownSecretData , well_known} ,
3637 utils:: iterator_try_concat_bytes,
@@ -257,7 +258,7 @@ impl SecretBackend for TlsGenerate {
257258 /// Then add the ca certificate and return these files for provisioning to the volume.
258259 async fn get_secret_data (
259260 & self ,
260- selector : & super :: SecretVolumeSelector ,
261+ selector : & SecretVolumeSelector ,
261262 pod_info : PodInfo ,
262263 ) -> Result < SecretContents , Self :: Error > {
263264 let now = OffsetDateTime :: now_utc ( ) ;
@@ -295,6 +296,7 @@ impl SecretBackend for TlsGenerate {
295296 let jitter_amount = Duration :: from ( cert_lifetime. mul_f64 ( jitter_factor) ) ;
296297 let unjittered_cert_lifetime = cert_lifetime;
297298 let cert_lifetime = cert_lifetime - jitter_amount;
299+
298300 tracing:: info!(
299301 certificate. lifetime. requested = %unjittered_cert_lifetime,
300302 certificate. lifetime. jitter = %jitter_amount,
@@ -314,112 +316,133 @@ impl SecretBackend for TlsGenerate {
314316 . fail ( ) ?;
315317 }
316318
317- let conf =
318- Conf :: new ( ConfMethod :: default ( ) ) . expect ( "failed to initialize OpenSSL configuration" ) ;
319-
320- let pod_key_length = match self . key_generation {
321- v1alpha2:: CertificateKeyGeneration :: Rsa { length } => length,
322- } ;
323-
324- let pod_key = Rsa :: generate ( pod_key_length)
325- . and_then ( PKey :: try_from)
326- . context ( GenerateKeySnafu ) ?;
327- let mut addresses = Vec :: new ( ) ;
328- for scope in & selector. scope {
329- addresses. extend (
330- selector
331- . scope_addresses ( & pod_info, scope)
332- . context ( ScopeAddressesSnafu { scope } ) ?,
333- ) ;
334- }
335- for address in & mut addresses {
336- if let Address :: Dns ( dns) = address {
337- // Turn FQDNs into bare domain names by removing the trailing dot
338- if dns. ends_with ( '.' ) {
339- dns. pop ( ) ;
340- }
341- }
342- }
343319 let ca = self
344320 . ca_manager
345321 . find_certificate_authority_for_signing ( not_after)
346322 . context ( PickCaSnafu ) ?;
347- let pod_cert = X509Builder :: new ( )
348- . and_then ( |mut x509| {
349- let subject_name = X509NameBuilder :: new ( )
350- . and_then ( |mut name| {
351- name. append_entry_by_nid ( Nid :: COMMONNAME , "generated certificate for pod" ) ?;
352- Ok ( name)
353- } ) ?
354- . build ( ) ;
355- x509. set_subject_name ( & subject_name) ?;
356- x509. set_issuer_name ( ca. certificate . subject_name ( ) ) ?;
357- x509. set_not_before ( Asn1Time :: from_unix ( not_before. unix_timestamp ( ) ) ?. as_ref ( ) ) ?;
358- x509. set_not_after ( Asn1Time :: from_unix ( not_after. unix_timestamp ( ) ) ?. as_ref ( ) ) ?;
359- x509. set_pubkey ( & pod_key) ?;
360- x509. set_version (
361- 3 - 1 , // zero-indexed
362- ) ?;
363- let mut serial = BigNum :: new ( ) ?;
364- serial. rand ( 64 , MsbOption :: MAYBE_ZERO , false ) ?;
365- x509. set_serial_number ( Asn1Integer :: from_bn ( & serial) ?. as_ref ( ) ) ?;
366- let ctx = x509. x509v3_context ( Some ( & ca. certificate ) , Some ( & conf) ) ;
367- let mut exts = vec ! [
368- BasicConstraints :: new( ) . critical( ) . build( ) ?,
369- KeyUsage :: new( )
370- . key_encipherment( )
371- . digital_signature( )
372- . build( ) ?,
373- ExtendedKeyUsage :: new( )
374- . server_auth( )
375- . client_auth( )
376- . build( ) ?,
377- SubjectKeyIdentifier :: new( ) . build( & ctx) ?,
378- AuthorityKeyIdentifier :: new( )
379- . issuer( true )
380- . keyid( true )
381- . build( & ctx) ?,
382- ] ;
383- let mut san_ext = SubjectAlternativeName :: new ( ) ;
384- san_ext. critical ( ) ;
385- let mut has_san = false ;
386- for addr in addresses {
387- has_san = true ;
388- match addr {
389- Address :: Dns ( dns) => san_ext. dns ( & dns) ,
390- Address :: Ip ( ip) => san_ext. ip ( & ip. to_string ( ) ) ,
391- } ;
392- }
393- if has_san {
394- exts. push ( san_ext. build ( & ctx) ?) ;
323+
324+ // Only run leaf certificate generation if it was requested based on the
325+ // secret volume selector. Otherwise only a ca.crt file as a PEM envelope
326+ // will be available (to be mounted).
327+ let ( certificate_pem, key_pem) = match selector. provision_parts {
328+ ProvisionParts :: Public => ( None , None ) ,
329+ ProvisionParts :: PublicPrivate => {
330+ let conf = Conf :: new ( ConfMethod :: default ( ) )
331+ . expect ( "failed to initialize OpenSSL configuration" ) ;
332+
333+ let pod_key_length = match self . key_generation {
334+ v1alpha2:: CertificateKeyGeneration :: Rsa { length } => length,
335+ } ;
336+
337+ let pod_key = Rsa :: generate ( pod_key_length)
338+ . and_then ( PKey :: try_from)
339+ . context ( GenerateKeySnafu ) ?;
340+
341+ let mut addresses = Vec :: new ( ) ;
342+ for scope in & selector. scope {
343+ addresses. extend (
344+ selector
345+ . scope_addresses ( & pod_info, scope)
346+ . context ( ScopeAddressesSnafu { scope } ) ?,
347+ ) ;
395348 }
396- for ext in exts {
397- x509. append_extension ( ext) ?;
349+ for address in & mut addresses {
350+ if let Address :: Dns ( dns) = address {
351+ // Turn FQDNs into bare domain names by removing the trailing dot
352+ if dns. ends_with ( '.' ) {
353+ dns. pop ( ) ;
354+ }
355+ }
398356 }
399- x509. sign ( & ca. private_key , MessageDigest :: sha256 ( ) ) ?;
400- Ok ( x509)
401- } )
402- . context ( BuildCertificateSnafu ) ?
403- . build ( ) ;
357+
358+ let pod_cert = X509Builder :: new ( )
359+ . and_then ( |mut x509| {
360+ let subject_name = X509NameBuilder :: new ( )
361+ . and_then ( |mut name| {
362+ name. append_entry_by_nid (
363+ Nid :: COMMONNAME ,
364+ "generated certificate for pod" ,
365+ ) ?;
366+ Ok ( name)
367+ } ) ?
368+ . build ( ) ;
369+ x509. set_subject_name ( & subject_name) ?;
370+ x509. set_issuer_name ( ca. certificate . subject_name ( ) ) ?;
371+ x509. set_not_before (
372+ Asn1Time :: from_unix ( not_before. unix_timestamp ( ) ) ?. as_ref ( ) ,
373+ ) ?;
374+ x509. set_not_after (
375+ Asn1Time :: from_unix ( not_after. unix_timestamp ( ) ) ?. as_ref ( ) ,
376+ ) ?;
377+ x509. set_pubkey ( & pod_key) ?;
378+ x509. set_version (
379+ 3 - 1 , // zero-indexed
380+ ) ?;
381+ let mut serial = BigNum :: new ( ) ?;
382+ serial. rand ( 64 , MsbOption :: MAYBE_ZERO , false ) ?;
383+ x509. set_serial_number ( Asn1Integer :: from_bn ( & serial) ?. as_ref ( ) ) ?;
384+ let ctx = x509. x509v3_context ( Some ( & ca. certificate ) , Some ( & conf) ) ;
385+ let mut exts = vec ! [
386+ BasicConstraints :: new( ) . critical( ) . build( ) ?,
387+ KeyUsage :: new( )
388+ . key_encipherment( )
389+ . digital_signature( )
390+ . build( ) ?,
391+ ExtendedKeyUsage :: new( )
392+ . server_auth( )
393+ . client_auth( )
394+ . build( ) ?,
395+ SubjectKeyIdentifier :: new( ) . build( & ctx) ?,
396+ AuthorityKeyIdentifier :: new( )
397+ . issuer( true )
398+ . keyid( true )
399+ . build( & ctx) ?,
400+ ] ;
401+ let mut san_ext = SubjectAlternativeName :: new ( ) ;
402+ san_ext. critical ( ) ;
403+ let mut has_san = false ;
404+ for addr in addresses {
405+ has_san = true ;
406+ match addr {
407+ Address :: Dns ( dns) => san_ext. dns ( & dns) ,
408+ Address :: Ip ( ip) => san_ext. ip ( & ip. to_string ( ) ) ,
409+ } ;
410+ }
411+ if has_san {
412+ exts. push ( san_ext. build ( & ctx) ?) ;
413+ }
414+ for ext in exts {
415+ x509. append_extension ( ext) ?;
416+ }
417+ x509. sign ( & ca. private_key , MessageDigest :: sha256 ( ) ) ?;
418+ Ok ( x509)
419+ } )
420+ . context ( BuildCertificateSnafu ) ?
421+ . build ( ) ;
422+
423+ let certificate_pem = pod_cert
424+ . to_pem ( )
425+ . context ( SerializeCertificateSnafu { tpe : CertType :: Pod } ) ?;
426+ let key_pem = pod_key
427+ . private_key_to_pem_pkcs8 ( )
428+ . context ( SerializeCertificateSnafu { tpe : CertType :: Pod } ) ?;
429+
430+ ( Some ( certificate_pem) , Some ( key_pem) )
431+ }
432+ } ;
433+
434+ let ca_pem =
435+ iterator_try_concat_bytes ( self . ca_manager . trust_roots ( now) . into_iter ( ) . map ( |ca| {
436+ ca. to_pem ( )
437+ . context ( SerializeCertificateSnafu { tpe : CertType :: Ca } )
438+ } ) ) ?;
439+
404440 Ok (
405441 SecretContents :: new ( SecretData :: WellKnown ( WellKnownSecretData :: TlsPem (
406442 well_known:: TlsPem {
407- ca_pem : iterator_try_concat_bytes (
408- self . ca_manager . trust_roots ( now) . into_iter ( ) . map ( |ca| {
409- ca. to_pem ( )
410- . context ( SerializeCertificateSnafu { tpe : CertType :: Ca } )
411- } ) ,
412- ) ?,
413- certificate_pem : Some (
414- pod_cert
415- . to_pem ( )
416- . context ( SerializeCertificateSnafu { tpe : CertType :: Pod } ) ?,
417- ) ,
418- key_pem : Some (
419- pod_key
420- . private_key_to_pem_pkcs8 ( )
421- . context ( SerializeCertificateSnafu { tpe : CertType :: Pod } ) ?,
422- ) ,
443+ certificate_pem,
444+ key_pem,
445+ ca_pem,
423446 } ,
424447 ) ) )
425448 . expires_after (
0 commit comments