mirror of https://github.com/k3s-io/k3s
Fix issue that caused passwd file and psk to be regenerated when rotating CA certs
Signed-off-by: Brad Davidson <brad.davidson@rancher.com>
(cherry picked from commit c6392c9ffc
)
Signed-off-by: Brad Davidson <brad.davidson@rancher.com>
pull/11074/head
parent
11c49f0c0b
commit
36cc03671d
|
@ -75,6 +75,10 @@ func caCertReplace(server *config.Control, buf io.ReadCloser, force bool) error
|
||||||
return err
|
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 err := validateBootstrap(server, tmpServer); err != nil {
|
||||||
if !force {
|
if !force {
|
||||||
return errors.Wrap(err, "failed to validate new CA certificates and keys")
|
return errors.Wrap(err, "failed to validate new CA certificates and keys")
|
||||||
|
@ -85,6 +89,36 @@ func caCertReplace(server *config.Control, buf io.ReadCloser, force bool) error
|
||||||
return cluster.Save(context.TODO(), tmpServer, true)
|
return cluster.Save(context.TODO(), tmpServer, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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 {
|
||||||
|
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()
|
||||||
|
|
||||||
|
// use the existing file if the new file does not exist or is empty
|
||||||
|
for _, field := range reflect.VisibleFields(oldMeta.Type()) {
|
||||||
|
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))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if field.Tag.Get("rotate") != "true" || info == nil || info.Size() == 0 {
|
||||||
|
if newVal.CanSet() {
|
||||||
|
oldVal := oldMeta.FieldByName(field.Name)
|
||||||
|
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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return merr.NewErrors(errs...)
|
||||||
|
}
|
||||||
|
|
||||||
// validateBootstrap checks the new certs and keys to ensure that the cluster would function properly were they to be used.
|
// 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 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.
|
// - The new service account signing key bundle must include the currently active signing key.
|
||||||
|
@ -94,39 +128,12 @@ func validateBootstrap(oldServer, newServer *config.Control) error {
|
||||||
// Use reflection to iterate over all of the bootstrap fields, checking files at each of the new paths.
|
// 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()
|
oldMeta := reflect.ValueOf(&oldServer.Runtime.ControlRuntimeBootstrap).Elem()
|
||||||
newMeta := reflect.ValueOf(&newServer.Runtime.ControlRuntimeBootstrap).Elem()
|
newMeta := reflect.ValueOf(&newServer.Runtime.ControlRuntimeBootstrap).Elem()
|
||||||
fields := []reflect.StructField{}
|
|
||||||
|
|
||||||
for _, field := range reflect.VisibleFields(oldMeta.Type()) {
|
for _, field := range reflect.VisibleFields(oldMeta.Type()) {
|
||||||
// Only handle bootstrap fields tagged for rotation
|
// Only handle bootstrap fields tagged for rotation
|
||||||
if field.Tag.Get("rotate") != "true" {
|
if field.Tag.Get("rotate") != "true" {
|
||||||
continue
|
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))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if 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)
|
|
||||||
newVal.Set(oldVal)
|
|
||||||
} else {
|
|
||||||
errs = append(errs, fmt.Errorf("cannot use current data for %s; field is not settable", field.Name))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// second pass: validate file contents
|
|
||||||
for _, field := range fields {
|
|
||||||
oldVal := oldMeta.FieldByName(field.Name)
|
oldVal := oldMeta.FieldByName(field.Name)
|
||||||
newVal := newMeta.FieldByName(field.Name)
|
newVal := newMeta.FieldByName(field.Name)
|
||||||
|
|
||||||
|
@ -150,10 +157,7 @@ func validateBootstrap(oldServer, newServer *config.Control) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(errs) > 0 {
|
return merr.NewErrors(errs...)
|
||||||
return merr.NewErrors(errs...)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateCA(oldCAPath, newCAPath string) error {
|
func validateCA(oldCAPath, newCAPath string) error {
|
||||||
|
|
Loading…
Reference in New Issue