Skip to content

Commit

Permalink
Fix issue that caused passwd file and psk to be regenerated when rota…
Browse files Browse the repository at this point in the history
…ting CA certs

Signed-off-by: Brad Davidson <brad.davidson@rancher.com>
  • Loading branch information
brandond committed Oct 8, 2024
1 parent 87d72d5 commit 4657b89
Showing 1 changed file with 28 additions and 20 deletions.
48 changes: 28 additions & 20 deletions pkg/server/cert.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ func caCertReplace(server *config.Control, buf io.ReadCloser, force bool) error
return err
}

if err := defaultBootstrap(server, tmpServer); err != nil {
return errors.Wrap(err, "failed to set default bootstrap values")
}

if err := validateBootstrap(server, tmpServer); err != nil {
if !force {
return errors.Wrap(err, "failed to validate new CA certificates and keys")
Expand All @@ -85,48 +89,52 @@ func caCertReplace(server *config.Control, buf io.ReadCloser, force bool) error
return cluster.Save(context.TODO(), tmpServer, true)
}

// validateBootstrap checks the new certs and keys to ensure that the cluster would function properly were they to be used.
// - The new leaf CA certificates must be verifiable using the same root and intermediate certs as the current leaf CA certificates.
// - The new service account signing key bundle must include the currently active signing key.
func validateBootstrap(oldServer, newServer *config.Control) error {
errs := []error{}

// defaultBootstrap provides default values from the existing bootstrap fields
// if the value is not tagged for rotation, or the current value is empty.
func defaultBootstrap(oldServer, newServer *config.Control) error {
// Use reflection to iterate over all of the bootstrap fields, checking files at each of the new paths.
oldMeta := reflect.ValueOf(&oldServer.Runtime.ControlRuntimeBootstrap).Elem()
newMeta := reflect.ValueOf(&newServer.Runtime.ControlRuntimeBootstrap).Elem()
fields := []reflect.StructField{}

Check failure on line 98 in pkg/server/cert.go

View workflow job for this annotation

GitHub Actions / Unit Tests

fields declared and not used

// use the existing file if the new file does not exist or is empty
for _, field := range reflect.VisibleFields(oldMeta.Type()) {
// Only handle bootstrap fields tagged for rotation
if field.Tag.Get("rotate") != "true" {
continue
}
fields = append(fields, field)
}

// first pass: use the existing file if the new file does not exist or is empty
for _, field := range fields {
newVal := newMeta.FieldByName(field.Name)
info, err := os.Stat(newVal.String())
if err != nil && !errors.Is(err, fs.ErrNotExist) {
errs = append(errs, errors.Wrap(err, field.Name))

Check failure on line 105 in pkg/server/cert.go

View workflow job for this annotation

GitHub Actions / Unit Tests

undefined: errs
continue
}

if info == nil || info.Size() == 0 {
if field.Tag.Get("rotate") != "true" || info == nil || info.Size() == 0 {
if newVal.CanSet() {
oldVal := oldMeta.FieldByName(field.Name)
logrus.Infof("certificate: %s not provided; using current value %s", field.Name, oldVal)
logrus.Infof("Using current data for %s: %s", field.Name, oldVal)
newVal.Set(oldVal)
} else {
errs = append(errs, fmt.Errorf("cannot use current data for %s; field is not settable", field.Name))

Check failure on line 115 in pkg/server/cert.go

View workflow job for this annotation

GitHub Actions / Unit Tests

undefined: errs
}
}

}
return errs

Check failure on line 119 in pkg/server/cert.go

View workflow job for this annotation

GitHub Actions / Unit Tests

undefined: errs
}

// second pass: validate file contents
for _, field := range fields {
// validateBootstrap checks the new certs and keys to ensure that the cluster would function properly were they to be used.
// - The new leaf CA certificates must be verifiable using the same root and intermediate certs as the current leaf CA certificates.
// - The new service account signing key bundle must include the currently active signing key.
func validateBootstrap(oldServer, newServer *config.Control) error {
errs := []error{}

// Use reflection to iterate over all of the bootstrap fields, checking files at each of the new paths.
oldMeta := reflect.ValueOf(&oldServer.Runtime.ControlRuntimeBootstrap).Elem()
newMeta := reflect.ValueOf(&newServer.Runtime.ControlRuntimeBootstrap).Elem()
fields := []reflect.StructField{}

Check failure on line 131 in pkg/server/cert.go

View workflow job for this annotation

GitHub Actions / Unit Tests

fields declared and not used

for _, field := range reflect.VisibleFields(oldMeta.Type()) {
// Only handle bootstrap fields tagged for rotation
if field.Tag.Get("rotate") != "true" {
continue
}
oldVal := oldMeta.FieldByName(field.Name)
newVal := newMeta.FieldByName(field.Name)

Expand Down

0 comments on commit 4657b89

Please sign in to comment.