2022-09-23 09:14:00 -04:00
|
|
|
// Copyright (c) HashiCorp, Inc.
|
2022-06-07 16:43:07 -04:00
|
|
|
// SPDX-License-Identifier: BUSL-1.1
|
2023-02-02 17:15:17 -08:00
|
|
|
|
2022-06-07 14:26:33 -04:00
|
|
|
package worker
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"context"
|
2023-05-17 18:12:19 -04:00
|
|
|
"crypto/x509"
|
2022-06-07 14:26:33 -04:00
|
|
|
"errors"
|
2023-05-17 18:12:19 -04:00
|
|
|
"fmt"
|
2023-05-20 21:04:03 -04:00
|
|
|
"math/rand"
|
2022-06-07 14:26:33 -04:00
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
berrors "github.com/hashicorp/boundary/internal/errors"
|
2023-09-12 08:15:34 -04:00
|
|
|
"github.com/hashicorp/boundary/internal/event"
|
2022-06-07 14:26:33 -04:00
|
|
|
"github.com/hashicorp/nodeenrollment"
|
|
|
|
|
"github.com/hashicorp/nodeenrollment/multihop"
|
|
|
|
|
"github.com/hashicorp/nodeenrollment/types"
|
|
|
|
|
)
|
|
|
|
|
|
2023-05-20 21:04:03 -04:00
|
|
|
// The default time to use when we encounter an error or some other reason
|
|
|
|
|
// we can't get a better reset time
|
|
|
|
|
const defaultAuthRotationResetDuration = 5 * time.Second
|
|
|
|
|
|
2022-06-07 14:26:33 -04:00
|
|
|
func (w *Worker) startAuthRotationTicking(cancelCtx context.Context) {
|
|
|
|
|
const op = "worker.(Worker).startAuthRotationTicking"
|
2023-03-30 16:20:28 -04:00
|
|
|
|
2023-05-24 23:33:51 -04:00
|
|
|
event.WriteSysEvent(cancelCtx, op, "starting auth rotation ticking")
|
|
|
|
|
|
|
|
|
|
// This will start at 0 which will cause us to run immediately
|
|
|
|
|
var authRotationResetDuration time.Duration
|
|
|
|
|
|
2023-05-20 21:04:03 -04:00
|
|
|
// Get a valid value in
|
|
|
|
|
startNow := time.Now()
|
2023-05-24 23:33:51 -04:00
|
|
|
w.AuthRotationNextRotation.Store(&startNow)
|
2023-05-20 21:04:03 -04:00
|
|
|
|
|
|
|
|
timer := time.NewTimer(defaultAuthRotationResetDuration)
|
2023-05-19 17:15:58 -04:00
|
|
|
lastRotation := time.Time{}.UTC()
|
2022-06-07 14:26:33 -04:00
|
|
|
for {
|
2023-05-20 21:04:03 -04:00
|
|
|
// Per the example in the docs, if you stop a timer you should drain the
|
|
|
|
|
// channel if it returns false. However, their example of blindly
|
|
|
|
|
// reading from the channel can deadlock. So we just do a select here to
|
|
|
|
|
// be safer.
|
2023-05-19 17:15:58 -04:00
|
|
|
timer.Stop()
|
2023-05-20 21:04:03 -04:00
|
|
|
select {
|
|
|
|
|
case <-timer.C:
|
|
|
|
|
default:
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-07 14:26:33 -04:00
|
|
|
if w.TestOverrideAuthRotationPeriod != 0 {
|
2023-05-24 23:33:51 -04:00
|
|
|
authRotationResetDuration = w.TestOverrideAuthRotationPeriod
|
2022-06-07 14:26:33 -04:00
|
|
|
}
|
2023-05-24 23:33:51 -04:00
|
|
|
timer.Reset(authRotationResetDuration)
|
2022-06-07 14:26:33 -04:00
|
|
|
|
|
|
|
|
select {
|
|
|
|
|
case <-cancelCtx.Done():
|
2022-06-15 22:39:52 -04:00
|
|
|
event.WriteSysEvent(cancelCtx, op, "pki auth rotation ticking shutting down")
|
2022-06-07 14:26:33 -04:00
|
|
|
return
|
|
|
|
|
|
|
|
|
|
case <-timer.C:
|
2023-05-20 21:04:03 -04:00
|
|
|
// Add some jitter in case there is some issue to prevent thundering
|
|
|
|
|
// herd
|
|
|
|
|
jitter := time.Duration(rand.Intn(6)) * time.Second
|
2023-05-24 23:33:51 -04:00
|
|
|
authRotationResetDuration = defaultAuthRotationResetDuration + jitter
|
2022-06-07 14:26:33 -04:00
|
|
|
|
|
|
|
|
// Check if it's time to rotate and if not don't do anything
|
2023-03-30 16:20:28 -04:00
|
|
|
currentNodeCreds, err := types.LoadNodeCredentials(
|
|
|
|
|
cancelCtx,
|
|
|
|
|
w.WorkerAuthStorage,
|
|
|
|
|
nodeenrollment.CurrentId,
|
|
|
|
|
nodeenrollment.WithStorageWrapper(w.conf.WorkerAuthStorageKms),
|
|
|
|
|
)
|
2022-06-07 14:26:33 -04:00
|
|
|
if err != nil {
|
|
|
|
|
if errors.Is(err, nodeenrollment.ErrNotFound) {
|
2023-05-20 21:04:03 -04:00
|
|
|
// Be silent as we likely haven't authorized yet
|
2022-06-07 14:26:33 -04:00
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
event.WriteError(cancelCtx, op, err)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if currentNodeCreds == nil {
|
2022-06-15 22:39:52 -04:00
|
|
|
event.WriteSysEvent(cancelCtx, op, "no error loading worker pki auth creds but nil creds, skipping rotation")
|
2022-06-07 14:26:33 -04:00
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check the certificates to see if it's time
|
|
|
|
|
if len(currentNodeCreds.CertificateBundles) != 2 {
|
2023-05-17 18:12:19 -04:00
|
|
|
// Likely this means we haven't been authorized yet, and unclear
|
|
|
|
|
// what to do in any other situation. However, we should try
|
|
|
|
|
// again fairly quickly because this may also be prior to the
|
|
|
|
|
// first rotation and we want to ensure the validity period is
|
|
|
|
|
// checked soon.
|
2022-06-07 14:26:33 -04:00
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-19 17:15:58 -04:00
|
|
|
var current, next *types.CertificateBundle
|
|
|
|
|
// Go through the bundles and intuit the rotation interval
|
|
|
|
|
for _, bundle := range currentNodeCreds.CertificateBundles {
|
|
|
|
|
if current == nil {
|
|
|
|
|
current = bundle
|
|
|
|
|
continue
|
2022-06-07 14:26:33 -04:00
|
|
|
}
|
2023-05-19 17:15:58 -04:00
|
|
|
if current.CertificateNotAfter.AsTime().Before(bundle.CertificateNotAfter.AsTime()) {
|
|
|
|
|
next = bundle
|
|
|
|
|
} else {
|
|
|
|
|
next = current
|
|
|
|
|
current = bundle
|
2022-06-07 14:26:33 -04:00
|
|
|
}
|
2023-05-19 17:15:58 -04:00
|
|
|
}
|
|
|
|
|
rotationInterval := next.CertificateNotAfter.AsTime().Sub(current.CertificateNotAfter.AsTime())
|
2023-05-17 18:12:19 -04:00
|
|
|
|
2023-05-19 17:15:58 -04:00
|
|
|
// This is useful output, but doesn't do anything other than output information
|
|
|
|
|
str := "current"
|
|
|
|
|
var args []any
|
|
|
|
|
for i, bundle := range []*types.CertificateBundle{current, next} {
|
|
|
|
|
if i == 1 {
|
|
|
|
|
str = "next"
|
|
|
|
|
}
|
2023-05-17 18:12:19 -04:00
|
|
|
cert, err := x509.ParseCertificate(bundle.CertificateDer)
|
|
|
|
|
if err != nil {
|
|
|
|
|
event.WriteError(cancelCtx, op, fmt.Errorf("error parsing leaf certificate in current worker auth bundle: %w", err))
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
certPkixBytes, err := x509.MarshalPKIXPublicKey(cert.PublicKey)
|
|
|
|
|
if err != nil {
|
|
|
|
|
event.WriteError(cancelCtx, op, fmt.Errorf("error marshaling leaf certificate public key in current worker auth bundle: %w", err))
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
certKeyId, err := nodeenrollment.KeyIdFromPkix(certPkixBytes)
|
|
|
|
|
if err != nil {
|
|
|
|
|
event.WriteError(cancelCtx, op, fmt.Errorf("error deriving pkix string from leaf certificate public key in current worker auth bundle: %w", err))
|
|
|
|
|
continue
|
|
|
|
|
}
|
2024-01-26 14:54:00 -05:00
|
|
|
|
|
|
|
|
certId, err := nodeenrollment.KeyIdFromPkix(bundle.CertificateDer)
|
|
|
|
|
if err != nil {
|
|
|
|
|
event.WriteError(cancelCtx, op, fmt.Errorf("error deriving cert id from certificate in current worker auth bundle: %w", err))
|
|
|
|
|
continue
|
|
|
|
|
}
|
2023-05-17 18:12:19 -04:00
|
|
|
args = append(args,
|
2024-01-26 14:54:00 -05:00
|
|
|
fmt.Sprintf("leaf_cert_%s_cert_id", str), certId,
|
|
|
|
|
fmt.Sprintf("leaf_cert_%s_key_id", str), certKeyId,
|
2023-05-19 17:15:58 -04:00
|
|
|
fmt.Sprintf("leaf_cert_%s_not_before", str), cert.NotBefore.Format(time.RFC3339),
|
|
|
|
|
fmt.Sprintf("leaf_cert_%s_not_after", str), cert.NotAfter.Format(time.RFC3339),
|
2023-05-17 18:12:19 -04:00
|
|
|
)
|
|
|
|
|
caCert, err := x509.ParseCertificate(bundle.CaCertificateDer)
|
|
|
|
|
if err != nil {
|
|
|
|
|
event.WriteError(cancelCtx, op, fmt.Errorf("error parsing CA certificate in current worker auth bundle: %w", err))
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
caCertPkixBytes, err := x509.MarshalPKIXPublicKey(caCert.PublicKey)
|
|
|
|
|
if err != nil {
|
|
|
|
|
event.WriteError(cancelCtx, op, fmt.Errorf("error marshaling CA certificate public key in current worker auth bundle: %w", err))
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
caCertKeyId, err := nodeenrollment.KeyIdFromPkix(caCertPkixBytes)
|
|
|
|
|
if err != nil {
|
|
|
|
|
event.WriteError(cancelCtx, op, fmt.Errorf("error deriving pkix string from CA certificate public key in current worker auth bundle: %w", err))
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
args = append(args,
|
2024-01-26 14:54:00 -05:00
|
|
|
fmt.Sprintf("ca_cert_%s_key_id", str), caCertKeyId,
|
2023-05-19 17:15:58 -04:00
|
|
|
fmt.Sprintf("ca_cert_%s_not_before", str), caCert.NotBefore.Format(time.RFC3339),
|
|
|
|
|
fmt.Sprintf("ca_cert_%s_not_after", str), caCert.NotAfter.Format(time.RFC3339),
|
2023-05-17 18:12:19 -04:00
|
|
|
)
|
2022-06-07 14:26:33 -04:00
|
|
|
}
|
2023-05-19 17:15:58 -04:00
|
|
|
|
|
|
|
|
// We'll rotate the first time we get this far, which is fine --
|
|
|
|
|
// better to rotate early than late -- and then we'll rotate at
|
|
|
|
|
// halfway through the current rotation interval
|
|
|
|
|
now := time.Now().UTC()
|
|
|
|
|
nextRotation := lastRotation.Add(rotationInterval / 2)
|
2023-05-20 08:24:56 -04:00
|
|
|
if lastRotation.IsZero() {
|
|
|
|
|
nextRotation = now
|
|
|
|
|
}
|
2023-05-17 18:12:19 -04:00
|
|
|
event.WriteSysEvent(cancelCtx, op, "checking if worker auth should rotate", append(
|
|
|
|
|
args,
|
|
|
|
|
"now", now.Format(time.RFC3339),
|
2023-05-19 17:15:58 -04:00
|
|
|
"last_rotation", lastRotation.Format(time.RFC3339),
|
|
|
|
|
"intuited_rotation_interval", rotationInterval.String(),
|
|
|
|
|
"next_rotation", nextRotation.Format(time.RFC3339),
|
2023-05-17 18:12:19 -04:00
|
|
|
)...,
|
|
|
|
|
)
|
2022-06-07 14:26:33 -04:00
|
|
|
|
2023-05-20 21:04:03 -04:00
|
|
|
// See if we don't need to do anything, and if so calculate reset
|
|
|
|
|
// duration and loop back
|
2023-05-19 17:15:58 -04:00
|
|
|
if !lastRotation.IsZero() && now.Before(nextRotation) {
|
2023-05-24 23:33:51 -04:00
|
|
|
authRotationResetDuration = lastRotation.Add(rotationInterval / 2).Sub(now)
|
2022-06-07 14:26:33 -04:00
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-19 17:15:58 -04:00
|
|
|
newRotationInterval, err := rotateWorkerAuth(cancelCtx, w, currentNodeCreds)
|
|
|
|
|
if err != nil {
|
2022-06-07 14:26:33 -04:00
|
|
|
event.WriteError(cancelCtx, op, err)
|
|
|
|
|
continue
|
|
|
|
|
}
|
2023-05-20 08:24:56 -04:00
|
|
|
lastRotation = now
|
2023-05-19 17:15:58 -04:00
|
|
|
nextRotation = lastRotation.Add(newRotationInterval / 2)
|
2023-05-24 23:33:51 -04:00
|
|
|
w.AuthRotationNextRotation.Store(&nextRotation)
|
|
|
|
|
authRotationResetDuration = nextRotation.Sub(now)
|
2023-05-19 17:15:58 -04:00
|
|
|
event.WriteSysEvent(cancelCtx, op, "worker credentials rotated", "next_rotation", nextRotation)
|
2022-06-07 14:26:33 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// rotateWorkerAuth is a one-stop shop to perform a rotation, given a valid set
|
|
|
|
|
// of current node credentials. Note that it doesn't really sanity check inputs;
|
|
|
|
|
// it is meant to be called from other functions that have validated these
|
|
|
|
|
// inputs and is separated out purely for (a) cleanliness/readability of the
|
|
|
|
|
// ticking function and (b) possible future re-use.
|
2023-05-19 17:15:58 -04:00
|
|
|
func rotateWorkerAuth(ctx context.Context, w *Worker, currentNodeCreds *types.NodeCredentials) (time.Duration, error) {
|
2022-06-07 14:26:33 -04:00
|
|
|
const op = "worker.rotateWorkerAuth"
|
|
|
|
|
|
|
|
|
|
randReaderOpt := nodeenrollment.WithRandomReader(w.conf.SecureRandomReader)
|
|
|
|
|
|
|
|
|
|
// Ensure we can get some needed values prior to actually doing generation
|
|
|
|
|
client := w.controllerMultihopConn.Load()
|
|
|
|
|
if client == nil {
|
2023-05-19 17:15:58 -04:00
|
|
|
return 0, berrors.New(ctx, berrors.Internal, op, "nil multihop client")
|
2022-06-07 14:26:33 -04:00
|
|
|
}
|
|
|
|
|
multihopClient, ok := client.(multihop.MultihopServiceClient)
|
|
|
|
|
if !ok {
|
2023-05-19 17:15:58 -04:00
|
|
|
return 0, berrors.New(ctx, berrors.Internal, op, "multihop client is not the right type")
|
2022-06-07 14:26:33 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Generate a new set of credentials but don't persist them yet
|
|
|
|
|
newNodeCreds, err := types.NewNodeCredentials(
|
|
|
|
|
ctx,
|
|
|
|
|
w.WorkerAuthStorage,
|
|
|
|
|
randReaderOpt,
|
2023-03-30 16:20:28 -04:00
|
|
|
nodeenrollment.WithStorageWrapper(w.conf.WorkerAuthStorageKms),
|
2022-06-07 14:26:33 -04:00
|
|
|
nodeenrollment.WithSkipStorage(true),
|
|
|
|
|
)
|
|
|
|
|
if err != nil {
|
2023-05-19 17:15:58 -04:00
|
|
|
return 0, berrors.Wrap(ctx, err, op)
|
2022-06-07 14:26:33 -04:00
|
|
|
}
|
|
|
|
|
|
2024-06-14 13:20:50 -04:00
|
|
|
newNodeCreds.PreviousCertificatePublicKeyPkix = currentNodeCreds.CertificatePublicKeyPkix
|
2022-09-26 11:22:20 -04:00
|
|
|
|
2022-06-07 14:26:33 -04:00
|
|
|
// Get a signed request from the new credentials
|
|
|
|
|
fetchReq, err := newNodeCreds.CreateFetchNodeCredentialsRequest(ctx, randReaderOpt)
|
|
|
|
|
if err != nil {
|
2023-05-19 17:15:58 -04:00
|
|
|
return 0, berrors.Wrap(ctx, err, op)
|
2022-06-07 14:26:33 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Encrypt the values to the server
|
2022-09-23 09:14:00 -04:00
|
|
|
encFetchReq, err := nodeenrollment.EncryptMessage(ctx, fetchReq, currentNodeCreds, randReaderOpt)
|
2022-06-07 14:26:33 -04:00
|
|
|
if err != nil {
|
2023-05-19 17:15:58 -04:00
|
|
|
return 0, berrors.Wrap(ctx, err, op)
|
2022-06-07 14:26:33 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
resp, err := multihopClient.RotateNodeCredentials(ctx, &types.RotateNodeCredentialsRequest{
|
|
|
|
|
CertificatePublicKeyPkix: currentNodeCreds.CertificatePublicKeyPkix,
|
|
|
|
|
EncryptedFetchNodeCredentialsRequest: encFetchReq,
|
|
|
|
|
})
|
|
|
|
|
if err != nil {
|
2023-05-19 17:15:58 -04:00
|
|
|
return 0, berrors.Wrap(ctx, err, op)
|
2022-06-07 14:26:33 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Decrypt the response using current credentials
|
|
|
|
|
fetchResp := new(types.FetchNodeCredentialsResponse)
|
|
|
|
|
if err := nodeenrollment.DecryptMessage(
|
|
|
|
|
ctx,
|
|
|
|
|
resp.EncryptedFetchNodeCredentialsResponse,
|
|
|
|
|
currentNodeCreds,
|
|
|
|
|
fetchResp,
|
|
|
|
|
); err != nil {
|
2023-05-19 17:15:58 -04:00
|
|
|
return 0, berrors.Wrap(ctx, err, op)
|
2022-06-07 14:26:33 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Call handle on the inner response, which will be encrypted to the
|
|
|
|
|
// new node credentials. This will also store the result,
|
|
|
|
|
// overwriting the current credentials.
|
2022-06-07 16:43:07 -04:00
|
|
|
newNodeCreds, err = newNodeCreds.HandleFetchNodeCredentialsResponse(
|
2022-06-07 14:26:33 -04:00
|
|
|
ctx,
|
|
|
|
|
w.WorkerAuthStorage,
|
|
|
|
|
fetchResp,
|
2023-03-30 16:20:28 -04:00
|
|
|
nodeenrollment.WithStorageWrapper(w.conf.WorkerAuthStorageKms),
|
2022-06-07 14:26:33 -04:00
|
|
|
)
|
|
|
|
|
if err != nil {
|
2023-05-19 17:15:58 -04:00
|
|
|
return 0, berrors.Wrap(ctx, err, op)
|
2022-06-07 14:26:33 -04:00
|
|
|
}
|
|
|
|
|
|
2022-06-07 16:43:07 -04:00
|
|
|
newKeyId, err := nodeenrollment.KeyIdFromPkix(newNodeCreds.CertificatePublicKeyPkix)
|
|
|
|
|
if err != nil {
|
2023-05-19 17:15:58 -04:00
|
|
|
return 0, berrors.Wrap(ctx, err, op)
|
2022-06-07 16:43:07 -04:00
|
|
|
}
|
|
|
|
|
w.WorkerAuthCurrentKeyId.Store(newKeyId)
|
|
|
|
|
|
2023-05-19 17:15:58 -04:00
|
|
|
var current, next *types.CertificateBundle
|
|
|
|
|
// Go through the bundles and intuit the rotation interval
|
|
|
|
|
for _, bundle := range newNodeCreds.CertificateBundles {
|
|
|
|
|
if current == nil {
|
|
|
|
|
current = bundle
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
if current.CertificateNotAfter.AsTime().Before(bundle.CertificateNotAfter.AsTime()) {
|
|
|
|
|
next = bundle
|
|
|
|
|
} else {
|
|
|
|
|
next = current
|
|
|
|
|
current = bundle
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
rotationInterval := next.CertificateNotAfter.AsTime().Sub(current.CertificateNotAfter.AsTime())
|
|
|
|
|
|
|
|
|
|
// This is useful output, but doesn't do anything other than output information
|
|
|
|
|
str := "current"
|
2023-05-17 18:12:19 -04:00
|
|
|
var args []any
|
2023-05-19 17:15:58 -04:00
|
|
|
for i, bundle := range []*types.CertificateBundle{current, next} {
|
|
|
|
|
if i == 1 {
|
|
|
|
|
str = "next"
|
|
|
|
|
}
|
2023-05-17 18:12:19 -04:00
|
|
|
cert, err := x509.ParseCertificate(bundle.CertificateDer)
|
|
|
|
|
if err != nil {
|
2023-05-19 17:15:58 -04:00
|
|
|
event.WriteError(ctx, op, fmt.Errorf("error parsing leaf certificate in current worker auth bundle: %w", err))
|
2023-05-17 18:12:19 -04:00
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
certPkixBytes, err := x509.MarshalPKIXPublicKey(cert.PublicKey)
|
|
|
|
|
if err != nil {
|
2023-05-19 17:15:58 -04:00
|
|
|
event.WriteError(ctx, op, fmt.Errorf("error marshaling leaf certificate public key in current worker auth bundle: %w", err))
|
2023-05-17 18:12:19 -04:00
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
certKeyId, err := nodeenrollment.KeyIdFromPkix(certPkixBytes)
|
|
|
|
|
if err != nil {
|
2023-05-19 17:15:58 -04:00
|
|
|
event.WriteError(ctx, op, fmt.Errorf("error deriving pkix string from leaf certificate public key in current worker auth bundle: %w", err))
|
2023-05-17 18:12:19 -04:00
|
|
|
continue
|
|
|
|
|
}
|
2024-01-26 14:54:00 -05:00
|
|
|
certId, err := nodeenrollment.KeyIdFromPkix(bundle.CertificateDer)
|
|
|
|
|
if err != nil {
|
|
|
|
|
event.WriteError(ctx, op, fmt.Errorf("error deriving cert id from certificate in current worker auth bundle: %w", err))
|
|
|
|
|
continue
|
|
|
|
|
}
|
2023-05-17 18:12:19 -04:00
|
|
|
args = append(args,
|
2024-01-26 14:54:00 -05:00
|
|
|
fmt.Sprintf("leaf_cert_%s_cert_id", str), certId,
|
|
|
|
|
fmt.Sprintf("leaf_cert_%s_key_id", str), certKeyId,
|
2023-05-19 17:15:58 -04:00
|
|
|
fmt.Sprintf("leaf_cert_%s_not_before", str), cert.NotBefore.Format(time.RFC3339),
|
|
|
|
|
fmt.Sprintf("leaf_cert_%s_not_after", str), cert.NotAfter.Format(time.RFC3339),
|
2023-05-17 18:12:19 -04:00
|
|
|
)
|
|
|
|
|
caCert, err := x509.ParseCertificate(bundle.CaCertificateDer)
|
|
|
|
|
if err != nil {
|
2023-05-19 17:15:58 -04:00
|
|
|
event.WriteError(ctx, op, fmt.Errorf("error parsing CA certificate in current worker auth bundle: %w", err))
|
2023-05-17 18:12:19 -04:00
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
caCertPkixBytes, err := x509.MarshalPKIXPublicKey(caCert.PublicKey)
|
|
|
|
|
if err != nil {
|
2023-05-19 17:15:58 -04:00
|
|
|
event.WriteError(ctx, op, fmt.Errorf("error marshaling CA certificate public key in current worker auth bundle: %w", err))
|
2023-05-17 18:12:19 -04:00
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
caCertKeyId, err := nodeenrollment.KeyIdFromPkix(caCertPkixBytes)
|
|
|
|
|
if err != nil {
|
2023-05-19 17:15:58 -04:00
|
|
|
event.WriteError(ctx, op, fmt.Errorf("error deriving pkix string from CA certificate public key in current worker auth bundle: %w", err))
|
2023-05-17 18:12:19 -04:00
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
args = append(args,
|
2024-01-26 14:54:00 -05:00
|
|
|
fmt.Sprintf("ca_cert_%s_key_id", str), caCertKeyId,
|
2023-05-19 17:15:58 -04:00
|
|
|
fmt.Sprintf("ca_cert_%s_not_before", str), caCert.NotBefore.Format(time.RFC3339),
|
|
|
|
|
fmt.Sprintf("ca_cert_%s_not_after", str), caCert.NotAfter.Format(time.RFC3339),
|
2023-05-17 18:12:19 -04:00
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
event.WriteSysEvent(ctx, op, "rotate worker auth job finished successfully", args...)
|
|
|
|
|
|
2023-05-19 17:15:58 -04:00
|
|
|
return rotationInterval, nil
|
2022-06-07 14:26:33 -04:00
|
|
|
}
|