Loop over the CA type list in collections (#21292)

* Loop over the CA type list in collections

Also adds a NewlyAdded method to CertAuthType to indicate the CA types
that have been added in the current major version, so that we can
ignore any related BadParameter error when handling those kinds of CAs
with potentially older versions of Teleport.

* Mention NewlyAdded in the CertAuthType description
This commit is contained in:
Edoardo Spadolini 2023-02-06 18:50:43 +01:00 committed by GitHub
parent 757a80e75f
commit 86df3aa981
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 25 additions and 75 deletions

View file

@ -23,7 +23,8 @@ import (
"github.com/gravitational/trace"
)
// CertAuthType specifies certificate authority type
// CertAuthType specifies certificate authority type. New variants should be
// added to CertAuthTypes and, for one major version, to NewlyAdded().
type CertAuthType string
const (
@ -52,6 +53,16 @@ const (
// CertAuthTypes lists all certificate authority types.
var CertAuthTypes = []CertAuthType{HostCA, UserCA, DatabaseCA, OpenSSHCA, JWTSigner, SAMLIDPCA}
// NewlyAdded should return true for CA types that were added in the current
// major version, so that we can avoid erroring out when a potentially older
// remote server doesn't know about them.
func (c CertAuthType) NewlyAdded() bool {
switch c {
default:
return false
}
}
// Check checks if certificate authority type value is correct
func (c CertAuthType) Check() error {
for _, caType := range CertAuthTypes {

View file

@ -822,91 +822,30 @@ type certAuthority struct {
}
func (c *certAuthority) fetch(ctx context.Context) (apply func(ctx context.Context) error, err error) {
applyHostCAs, err := c.fetchCertAuthorities(ctx, types.HostCA)
if err != nil {
return nil, trace.Wrap(err)
}
applyUserCAs, err := c.fetchCertAuthorities(ctx, types.UserCA)
if err != nil {
return nil, trace.Wrap(err)
}
// DELETE IN 11.0.
// missingDatabaseCA is needed only when leaf cluster v9 is connected
// to root cluster v10. Database CA has been added in v10, so older
// clusters don't have it and fetchCertAuthorities() returns an error.
missingDatabaseCA := false
applyDatabaseCAs, err := c.fetchCertAuthorities(ctx, types.DatabaseCA)
if trace.IsBadParameter(err) {
missingDatabaseCA = true
} else if err != nil {
return nil, trace.Wrap(err)
}
// DELETE IN 13.0.
// missingOpenSSHCA is needed only when leaf cluster v11 is connected
// to root cluster v12. OpenSSH CA has been added in v12, so older
// clusters don't have it and fetchCertAuthorities() returns an error.
var missingOpenSSHCA bool
applyOpenSSHCAs, err := c.fetchCertAuthorities(ctx, types.OpenSSHCA)
if trace.IsBadParameter(err) {
missingOpenSSHCA = true
} else if err != nil {
return nil, trace.Wrap(err)
}
applyJWTSigners, err := c.fetchCertAuthorities(ctx, types.JWTSigner)
if err != nil {
return nil, trace.Wrap(err)
}
applySAMLIDPCAs, err := c.fetchCertAuthorities(ctx, types.SAMLIDPCA)
if err != nil {
return nil, trace.Wrap(err)
fs := make([]func(context.Context) error, 0, len(types.CertAuthTypes))
for _, caType := range types.CertAuthTypes {
f, err := c.fetchCertAuthorities(ctx, caType)
if err != nil {
return nil, trace.Wrap(err)
}
fs = append(fs, f)
}
return func(ctx context.Context) error {
if err := applyHostCAs(ctx); err != nil {
return trace.Wrap(err)
}
if err := applyUserCAs(ctx); err != nil {
return trace.Wrap(err)
}
if !missingDatabaseCA {
if err := applyDatabaseCAs(ctx); err != nil {
for _, f := range fs {
if err := f(ctx); err != nil {
return trace.Wrap(err)
}
} else {
if err := c.trustCache.DeleteAllCertAuthorities(types.DatabaseCA); err != nil {
if !trace.IsNotFound(err) {
return trace.Wrap(err)
}
}
}
if !missingOpenSSHCA {
if err := applyOpenSSHCAs(ctx); err != nil {
return trace.Wrap(err)
}
} else {
if err := c.trustCache.DeleteAllCertAuthorities(types.OpenSSHCA); err != nil {
if !trace.IsNotFound(err) {
return trace.Wrap(err)
}
}
}
if err := applyJWTSigners(ctx); err != nil {
return trace.Wrap(err)
}
return trace.Wrap(applySAMLIDPCAs(ctx))
return nil
}, nil
}
func (c *certAuthority) fetchCertAuthorities(ctx context.Context, caType types.CertAuthType) (apply func(ctx context.Context) error, err error) {
authorities, err := c.Trust.GetCertAuthorities(ctx, caType, c.watch.LoadSecrets)
if err != nil {
// if caType was added in this major version we might get a BadParameter
// error if we're connecting to an older upstream that doesn't know about it
if err != nil && !(caType.NewlyAdded() && trace.IsBadParameter(err)) {
return nil, trace.Wrap(err)
}