2323package reconcile
2424
2525import (
26- "crypto/x509"
27- "encoding/pem"
28- "time"
29-
3026 "github.com/rs/zerolog"
3127 "github.com/rs/zerolog/log"
3228 "k8s.io/api/core/v1"
@@ -58,7 +54,7 @@ func (d *Reconciler) CreatePlan() error {
5854 apiObject := d .context .GetAPIObject ()
5955 spec := d .context .GetSpec ()
6056 status , lastVersion := d .context .GetStatus ()
61- newPlan , changed := createPlan (d .log , apiObject , status .Plan , spec , status , pods , d .context .GetTLSKeyfile )
57+ newPlan , changed := createPlan (d .log , apiObject , status .Plan , spec , status , pods , d .context .GetTLSKeyfile , d . context . GetTLSCA )
6258
6359 // If not change, we're done
6460 if ! changed {
@@ -83,7 +79,8 @@ func (d *Reconciler) CreatePlan() error {
8379func createPlan (log zerolog.Logger , apiObject metav1.Object ,
8480 currentPlan api.Plan , spec api.DeploymentSpec ,
8581 status api.DeploymentStatus , pods []v1.Pod ,
86- getTLSKeyfile func (group api.ServerGroup , member api.MemberStatus ) (string , error )) (api.Plan , bool ) {
82+ getTLSKeyfile func (group api.ServerGroup , member api.MemberStatus ) (string , error ),
83+ getTLSCA func (string ) (string , string , bool , error )) (api.Plan , bool ) {
8784 if len (currentPlan ) > 0 {
8885 // Plan already exists, complete that first
8986 return currentPlan , false
@@ -178,41 +175,14 @@ func createPlan(log zerolog.Logger, apiObject metav1.Object,
178175 })
179176 }
180177
178+ // Check for the need to rotate TLS CA certificate and all members
179+ if len (plan ) == 0 {
180+ plan = createRotateTLSCAPlan (log , spec , status , getTLSCA )
181+ }
182+
181183 // Check for the need to rotate TLS certificate of a members
182- if len (plan ) == 0 && spec .TLS .IsSecure () {
183- status .Members .ForeachServerGroup (func (group api.ServerGroup , members api.MemberStatusList ) error {
184- for _ , m := range members {
185- if len (plan ) > 0 {
186- // Only 1 change at a time
187- continue
188- }
189- if m .Phase != api .MemberPhaseCreated {
190- // Only make changes when phase is created
191- continue
192- }
193- if group == api .ServerGroupSyncWorkers {
194- // SyncWorkers have no externally created TLS keyfile
195- continue
196- }
197- // Load keyfile
198- keyfile , err := getTLSKeyfile (group , m )
199- if err != nil {
200- log .Warn ().Err (err ).
201- Str ("role" , group .AsRole ()).
202- Str ("id" , m .ID ).
203- Msg ("Failed to get TLS secret" )
204- continue
205- }
206- renewalNeeded := tlsKeyfileNeedsRenewal (log , keyfile )
207- if renewalNeeded {
208- plan = append (append (plan ,
209- api .NewAction (api .ActionTypeRenewTLSCertificate , group , m .ID )),
210- createRotateMemberPlan (log , m , group , "TLS certificate renewal" )... ,
211- )
212- }
213- }
214- return nil
215- })
184+ if len (plan ) == 0 {
185+ plan = createRotateTLSServerCertificatePlan (log , spec , status , getTLSKeyfile )
216186 }
217187
218188 // Return plan
@@ -304,44 +274,6 @@ func normalizeServiceAccountName(name string) string {
304274 return ""
305275}
306276
307- // tlsKeyfileNeedsRenewal decides if the certificate in the given keyfile
308- // should be renewed.
309- func tlsKeyfileNeedsRenewal (log zerolog.Logger , keyfile string ) bool {
310- raw := []byte (keyfile )
311- for {
312- var derBlock * pem.Block
313- derBlock , raw = pem .Decode (raw )
314- if derBlock == nil {
315- break
316- }
317- if derBlock .Type == "CERTIFICATE" {
318- cert , err := x509 .ParseCertificate (derBlock .Bytes )
319- if err != nil {
320- // We do not understand the certificate, let's renew it
321- log .Warn ().Err (err ).Msg ("Failed to parse x509 certificate. Renewing it" )
322- return true
323- }
324- if cert .IsCA {
325- // Only look at the server certificate, not CA or intermediate
326- continue
327- }
328- // Check expiration date. Renewal at 2/3 of lifetime.
329- ttl := cert .NotAfter .Sub (cert .NotBefore )
330- expirationDate := cert .NotBefore .Add ((ttl / 3 ) * 2 )
331- if expirationDate .Before (time .Now ()) {
332- // We should renew now
333- log .Debug ().
334- Str ("not-before" , cert .NotBefore .String ()).
335- Str ("not-after" , cert .NotAfter .String ()).
336- Str ("expiration-date" , expirationDate .String ()).
337- Msg ("TLS certificate renewal needed" )
338- return true
339- }
340- }
341- }
342- return false
343- }
344-
345277// createScalePlan creates a scaling plan for a single server group
346278func createScalePlan (log zerolog.Logger , members api.MemberStatusList , group api.ServerGroup , count int ) api.Plan {
347279 var plan api.Plan
0 commit comments