@@ -254,9 +254,7 @@ func (r *BMCReconciler) reconcile(ctx context.Context, bmcObj *metalv1alpha1.BMC
254254 log .Error (condErr , "Failed to update certificate condition" )
255255 }
256256 }
257- if err := r .checkCertificateExpiration (ctx , bmcObj ); err != nil {
258- log .Error (err , "Failed to check certificate expiration" )
259- }
257+ r .checkCertificateExpiration (ctx , bmcObj )
260258
261259 log .V (1 ).Info ("Reconciled BMC" )
262260 return ctrl.Result {}, nil
@@ -760,9 +758,21 @@ func (r *BMCReconciler) initiateCertificateRequest(ctx context.Context, bmcObj *
760758 signerName = DefaultCertificateSignerName
761759 }
762760
761+ // Generate safe CSR name (max 253 chars for Kubernetes metadata.name)
762+ // Format: bmc-<bmcName>-<shortUID>
763+ // Ensure bmcName is truncated if needed to stay under limit
764+ uidStr := string (bmcObj .UID )
765+ shortUID := uidStr [:8 ] // First 8 chars of UUID
766+ maxBMCNameLen := 253 - 4 - 1 - 8 - 1 // 253 - "bmc-" - "-" - shortUID - null = 239
767+ bmcName := bmcObj .Name
768+ if len (bmcName ) > maxBMCNameLen {
769+ bmcName = bmcName [:maxBMCNameLen ]
770+ }
771+ csrName := fmt .Sprintf ("bmc-%s-%s" , bmcName , shortUID )
772+
763773 k8sCSR := & certificatesv1.CertificateSigningRequest {
764774 ObjectMeta : metav1.ObjectMeta {
765- Name : fmt . Sprintf ( "bmc-%s-%s" , bmcObj . Name , string ( bmcObj . UID [: 8 ])) ,
775+ Name : csrName ,
766776 Labels : map [string ]string {
767777 "metal.ironcore.dev/bmc" : bmcObj .Name ,
768778 },
@@ -987,13 +997,7 @@ func (r *BMCReconciler) installCertificate(ctx context.Context, bmcObj *metalv1a
987997 return fmt .Errorf ("certificate missing ServerAuth extended key usage" )
988998 }
989999
990- if err := bmcClient .InstallCertificate (ctx , string (k8sCSR .Status .Certificate ), bmc .CertificateTypeHTTPS ); err != nil {
991- _ = r .updateConditions (ctx , bmcObj , true , bmcCertificateInstalledConditionType ,
992- corev1 .ConditionFalse , bmcCertificateInstallFailedReason ,
993- fmt .Sprintf ("Failed to install certificate: %v" , err ))
994- return err
995- }
996-
1000+ // Create/update secret first
9971001 secret := & corev1.Secret {
9981002 ObjectMeta : metav1.ObjectMeta {
9991003 Name : fmt .Sprintf ("bmc-%s-cert" , bmcObj .Name ),
@@ -1017,18 +1021,28 @@ func (r *BMCReconciler) installCertificate(ctx context.Context, bmcObj *metalv1a
10171021 }
10181022 log .Info ("Certificate secret created or updated" , "operation" , opResult )
10191023
1024+ // Persist secret reference to status before calling BMC
10201025 bmcBase := bmcObj .DeepCopy ()
10211026 bmcObj .Status .CertificateSecretRef = & corev1.LocalObjectReference {Name : secret .Name }
10221027 bmcObj .Status .CertificateSigningRequestRef = nil
10231028
1024- if err := r .updateCertificateInfo ( ctx , bmcObj , bmcClient ); err != nil {
1025- log . Error ( err , "Failed to update certificate info" )
1029+ if err := r .Status (). Patch ( ctx , bmcObj , client . MergeFrom ( bmcBase ) ); err != nil {
1030+ return fmt . Errorf ( "failed to persist certificate secret reference: %w" , err )
10261031 }
10271032
1028- if err := r .Status ().Patch (ctx , bmcObj , client .MergeFrom (bmcBase )); err != nil {
1033+ // Now install certificate on BMC
1034+ // If this fails, on retry we'll have secretRef set and can skip secret creation
1035+ if err := bmcClient .InstallCertificate (ctx , string (k8sCSR .Status .Certificate ), bmc .CertificateTypeHTTPS ); err != nil {
1036+ _ = r .updateConditions (ctx , bmcObj , true , bmcCertificateInstalledConditionType ,
1037+ corev1 .ConditionFalse , bmcCertificateInstallFailedReason ,
1038+ fmt .Sprintf ("Failed to install certificate: %v" , err ))
10291039 return err
10301040 }
10311041
1042+ if err := r .updateCertificateInfo (ctx , bmcObj , bmcClient ); err != nil {
1043+ log .Error (err , "Failed to update certificate info" )
1044+ }
1045+
10321046 log .Info ("Certificate installed successfully" )
10331047 _ = r .updateConditions (ctx , bmcObj , true , bmcCertificateInstalledConditionType ,
10341048 corev1 .ConditionTrue , bmcCertificateInstalledReason ,
@@ -1037,11 +1051,11 @@ func (r *BMCReconciler) installCertificate(ctx context.Context, bmcObj *metalv1a
10371051 return nil
10381052}
10391053
1040- func (r * BMCReconciler ) checkCertificateExpiration (ctx context.Context , bmcObj * metalv1alpha1.BMC ) error {
1054+ func (r * BMCReconciler ) checkCertificateExpiration (ctx context.Context , bmcObj * metalv1alpha1.BMC ) {
10411055 log := ctrl .LoggerFrom (ctx )
10421056
10431057 if bmcObj .Status .CertificateInfo == nil {
1044- return nil
1058+ return
10451059 }
10461060
10471061 renewalThreshold := r .DefaultCertificateRenewalThreshold
@@ -1058,29 +1072,21 @@ func (r *BMCReconciler) checkCertificateExpiration(ctx context.Context, bmcObj *
10581072 _ = r .updateConditions (ctx , bmcObj , true , bmcCertificateExpiringConditionType ,
10591073 corev1 .ConditionTrue , bmcCertificateExpiringSoonReason ,
10601074 fmt .Sprintf ("Certificate expires in %s" , timeUntilExpiry ))
1061-
1062- if bmcObj .Spec .CertificateManagementPolicy != nil &&
1063- * bmcObj .Spec .CertificateManagementPolicy == metalv1alpha1 .CertificateManagementPolicyAutomatic {
1064- bmcBase := bmcObj .DeepCopy ()
1065- bmcObj .Status .CertificateSecretRef = nil
1066- if err := r .Status ().Patch (ctx , bmcObj , client .MergeFrom (bmcBase )); err != nil {
1067- return err
1068- }
1069- }
10701075 } else {
10711076 _ = r .updateConditions (ctx , bmcObj , true , bmcCertificateExpiringConditionType ,
10721077 corev1 .ConditionFalse , bmcCertificateValidReason ,
10731078 fmt .Sprintf ("Certificate valid until %s" , expiryTime ))
10741079 }
10751080 }
1076-
1077- return nil
10781081}
10791082
10801083func (r * BMCReconciler ) approveCSR (ctx context.Context , csr * certificatesv1.CertificateSigningRequest ) error {
10811084 allowedSigners := []string {
10821085 DefaultCertificateSignerName ,
10831086 }
1087+ if r .DefaultCertificateSignerName != "" && r .DefaultCertificateSignerName != DefaultCertificateSignerName {
1088+ allowedSigners = append (allowedSigners , r .DefaultCertificateSignerName )
1089+ }
10841090
10851091 if ! slices .Contains (allowedSigners , csr .Spec .SignerName ) {
10861092 return fmt .Errorf ("controller not authorized to approve signer: %s (only allowed: %v)" ,
@@ -1096,7 +1102,7 @@ func (r *BMCReconciler) approveCSR(ctx context.Context, csr *certificatesv1.Cert
10961102 LastTransitionTime : metav1 .Now (),
10971103 })
10981104
1099- if err := r .Status ( ).Update (ctx , csr ); err != nil {
1105+ if err := r .SubResource ( "approval" ).Update (ctx , csr ); err != nil {
11001106 return err
11011107 }
11021108
@@ -1178,9 +1184,9 @@ func (r *BMCReconciler) updateCertificateInfo(ctx context.Context, bmcObj *metal
11781184 return err
11791185 }
11801186
1181- // Find HTTPS certificate
1187+ // Find HTTPS certificate (determined by URI path, not CertificateType field)
11821188 for _ , cert := range certs {
1183- if cert .Type == bmc . CertificateTypeHTTPS {
1189+ if strings . Contains ( cert .URI , "/HTTPS/Certificates" ) {
11841190 notBefore , _ := time .Parse (time .RFC3339 , cert .ValidNotBefore )
11851191 notAfter , _ := time .Parse (time .RFC3339 , cert .ValidNotAfter )
11861192
0 commit comments