diff --git a/api/types/authority_test.go b/api/types/authority_test.go index 962ba8c44175b..624f10c16ff9c 100644 --- a/api/types/authority_test.go +++ b/api/types/authority_test.go @@ -52,3 +52,17 @@ func TestRotationZero(t *testing.T) { require.Equal(t, tt.z, tt.r.IsZero(), tt.d) } } + +// Test that the spec cluster name name will be set to match the resource name +func TestCheckAndSetDefaults(t *testing.T) { + ca := CertAuthorityV2{ + Metadata: Metadata{Name: "caName"}, + Spec: CertAuthoritySpecV2{ + ClusterName: "clusterName", + Type: HostCA, + }, + } + err := ca.CheckAndSetDefaults() + require.NoError(t, err) + require.Equal(t, ca.Metadata.Name, ca.Spec.ClusterName) +} diff --git a/integration/assist/command_test.go b/integration/assist/command_test.go index 9afd3afcfb724..7c529a79a8708 100644 --- a/integration/assist/command_test.go +++ b/integration/assist/command_test.go @@ -288,7 +288,8 @@ func newTestCredentials(t *testing.T, rc *helpers.TeleInstance, user types.User) } pool := x509.NewCertPool() - pool.AppendCertsFromPEM(rc.Secrets.TLSCACert) + pool.AppendCertsFromPEM(rc.Secrets.TLSHostCACert) + pool.AppendCertsFromPEM(rc.Secrets.TLSUserCACert) tlsConf := &tls.Config{ Certificates: []tls.Certificate{cert}, diff --git a/integration/helpers/instance.go b/integration/helpers/instance.go index 455557516ef8a..fb8fdf788b1c3 100644 --- a/integration/helpers/instance.go +++ b/integration/helpers/instance.go @@ -17,7 +17,6 @@ package helpers import ( "bytes" "context" - "crypto/rsa" "crypto/tls" "crypto/x509/pkix" "encoding/json" @@ -44,6 +43,7 @@ import ( "github.com/gravitational/teleport/api/breaker" clientproto "github.com/gravitational/teleport/api/client/proto" "github.com/gravitational/teleport/api/types" + "github.com/gravitational/teleport/api/utils/keys" "github.com/gravitational/teleport/lib/auth/authclient" "github.com/gravitational/teleport/lib/auth/keygen" "github.com/gravitational/teleport/lib/auth/state" @@ -97,11 +97,15 @@ type InstanceSecrets struct { // PrivKey is instance private key PrivKey []byte `json:"priv"` // Cert is SSH host certificate - Cert []byte `json:"cert"` - // TLSCACert is the certificate of the trusted certificate authority - TLSCACert []byte `json:"tls_ca_cert"` - // TLSCert is client TLS X509 certificate - TLSCert []byte `json:"tls_cert"` + SSHHostCert []byte `json:"cert"` + // TLSHostCACert is the certificate of the trusted host certificate authority + TLSHostCACert []byte `json:"tls_host_ca_cert"` + // TLSCert is client TLS host X509 certificate + TLSHostCert []byte `json:"tls_host_cert"` + // TLSUserCACert is the certificate of the trusted user certificate authority + TLSUserCACert []byte `json:"tls_user_ca_cert"` + // TLSUserCert is client TLS user X509 certificate + TLSUserCert []byte `json:"tls_user_cert"` // TunnelAddr is a reverse tunnel listening port, allowing // other sites to connect to i instance. Set to empty // string if i instance is not allowing incoming tunnels @@ -132,9 +136,7 @@ func (s *InstanceSecrets) GetRoles(t *testing.T) []types.Role { return roles } -// GetCAs return an array of CAs stored by the secrets object. In i -// case we always return hard-coded userCA + hostCA (and they share keys -// for simplicity) +// GetCAs return an array of CAs stored by the secrets object func (s *InstanceSecrets) GetCAs() ([]types.CertAuthority, error) { hostCA, err := types.NewCertAuthority(types.CertAuthoritySpecV2{ Type: types.HostCA, @@ -148,7 +150,7 @@ func (s *InstanceSecrets) GetCAs() ([]types.CertAuthority, error) { TLS: []*types.TLSKeyPair{{ Key: s.PrivKey, KeyType: types.PrivateKeyType_RAW, - Cert: s.TLSCACert, + Cert: s.TLSHostCACert, }}, }, }) @@ -168,7 +170,7 @@ func (s *InstanceSecrets) GetCAs() ([]types.CertAuthority, error) { TLS: []*types.TLSKeyPair{{ Key: s.PrivKey, KeyType: types.PrivateKeyType_RAW, - Cert: s.TLSCACert, + Cert: s.TLSUserCACert, }}, }, Roles: []string{services.RoleNameForCertAuthority(s.SiteName)}, @@ -184,7 +186,7 @@ func (s *InstanceSecrets) GetCAs() ([]types.CertAuthority, error) { TLS: []*types.TLSKeyPair{{ Key: s.PrivKey, KeyType: types.PrivateKeyType_RAW, - Cert: s.TLSCACert, + Cert: s.TLSHostCACert, }}, }, }) @@ -199,7 +201,7 @@ func (s *InstanceSecrets) GetCAs() ([]types.CertAuthority, error) { TLS: []*types.TLSKeyPair{{ Key: s.PrivKey, KeyType: types.PrivateKeyType_RAW, - Cert: s.TLSCACert, + Cert: s.TLSHostCACert, }}, }, }) @@ -256,9 +258,9 @@ func (s *InstanceSecrets) AsSlice() []*InstanceSecrets { func (s *InstanceSecrets) GetIdentity() *state.Identity { i, err := state.ReadIdentityFromKeyPair(s.PrivKey, &clientproto.Certs{ - SSH: s.Cert, - TLS: s.TLSCert, - TLSCACerts: [][]byte{s.TLSCACert}, + SSH: s.SSHHostCert, + TLS: s.TLSHostCert, + TLSCACerts: [][]byte{s.TLSHostCACert}, }) fatalIf(err) return i @@ -338,20 +340,14 @@ func NewInstance(t *testing.T, cfg InstanceConfig) *TeleInstance { if cfg.Priv == nil || cfg.Pub == nil { cfg.Priv, cfg.Pub, _ = keygen.GenerateKeyPair() } - rsaKey, err := ssh.ParseRawPrivateKey(cfg.Priv) + key, err := keys.ParsePrivateKey(cfg.Priv) fatalIf(err) - tlsCACert, err := tlsca.GenerateSelfSignedCAWithSigner(rsaKey.(*rsa.PrivateKey), pkix.Name{ - CommonName: cfg.ClusterName, - Organization: []string{cfg.ClusterName}, - }, nil, defaults.CATTL) - fatalIf(err) - - signer, err := ssh.ParsePrivateKey(cfg.Priv) + sshSigner, err := ssh.NewSignerFromSigner(key) fatalIf(err) - cert, err := keygen.GenerateHostCert(services.HostCertParams{ - CASigner: signer, + hostCert, err := keygen.GenerateHostCert(services.HostCertParams{ + CASigner: sshSigner, PublicHostKey: cfg.Pub, HostID: cfg.HostID, NodeName: cfg.NodeName, @@ -360,23 +356,48 @@ func NewInstance(t *testing.T, cfg InstanceConfig) *TeleInstance { TTL: 24 * time.Hour, }) fatalIf(err) - tlsCA, err := tlsca.FromKeys(tlsCACert, cfg.Priv) - fatalIf(err) - cryptoPubKey, err := sshutils.CryptoPublicKey(cfg.Pub) - fatalIf(err) - identity := tlsca.Identity{ - Username: fmt.Sprintf("%v.%v", cfg.HostID, cfg.ClusterName), - Groups: []string{string(types.RoleAdmin)}, - } + clock := cfg.Clock if clock == nil { clock = clockwork.NewRealClock() } + + identity := tlsca.Identity{ + Username: fmt.Sprintf("%v.%v", cfg.HostID, cfg.ClusterName), + Groups: []string{string(types.RoleAdmin)}, + } subject, err := identity.Subject() fatalIf(err) - tlsCert, err := tlsCA.GenerateCertificate(tlsca.CertificateRequest{ + + tlsCAHostCert, err := tlsca.GenerateSelfSignedCAWithSigner(key, pkix.Name{ + CommonName: cfg.ClusterName, + Organization: []string{cfg.ClusterName}, + }, nil, defaults.CATTL) + fatalIf(err) + tlsHostCA, err := tlsca.FromKeys(tlsCAHostCert, cfg.Priv) + fatalIf(err) + hostCryptoPubKey, err := sshutils.CryptoPublicKey(cfg.Pub) + fatalIf(err) + tlsHostCert, err := tlsHostCA.GenerateCertificate(tlsca.CertificateRequest{ + Clock: clock, + PublicKey: hostCryptoPubKey, + Subject: subject, + NotAfter: clock.Now().UTC().Add(time.Hour * 24), + }) + fatalIf(err) + + tlsCAUserCert, err := tlsca.GenerateSelfSignedCAWithSigner(key, pkix.Name{ + CommonName: cfg.ClusterName, + Organization: []string{cfg.ClusterName}, + }, nil, defaults.CATTL) + fatalIf(err) + tlsUserCA, err := tlsca.FromKeys(tlsCAHostCert, cfg.Priv) + fatalIf(err) + userCryptoPubKey, err := sshutils.CryptoPublicKey(cfg.Pub) + fatalIf(err) + tlsUserCert, err := tlsUserCA.GenerateCertificate(tlsca.CertificateRequest{ Clock: clock, - PublicKey: cryptoPubKey, + PublicKey: userCryptoPubKey, Subject: subject, NotAfter: clock.Now().UTC().Add(time.Hour * 24), }) @@ -391,14 +412,16 @@ func NewInstance(t *testing.T, cfg InstanceConfig) *TeleInstance { } secrets := InstanceSecrets{ - SiteName: cfg.ClusterName, - PrivKey: cfg.Priv, - PubKey: cfg.Pub, - Cert: cert, - TLSCACert: tlsCACert, - TLSCert: tlsCert, - TunnelAddr: i.ReverseTunnel, - Users: make(map[string]*User), + SiteName: cfg.ClusterName, + PrivKey: cfg.Priv, + PubKey: cfg.Pub, + SSHHostCert: hostCert, + TLSHostCACert: tlsCAHostCert, + TLSHostCert: tlsHostCert, + TLSUserCACert: tlsCAUserCert, + TLSUserCert: tlsUserCert, + TunnelAddr: i.ReverseTunnel, + Users: make(map[string]*User), } i.Secrets = secrets diff --git a/lib/auth/authclient/tls.go b/lib/auth/authclient/tls.go index 7c607badb2f85..e2acf48484ee7 100644 --- a/lib/auth/authclient/tls.go +++ b/lib/auth/authclient/tls.go @@ -39,59 +39,113 @@ type CAGetter interface { GetCertAuthorities(ctx context.Context, caType types.CertAuthType, loadKeys bool) ([]types.CertAuthority, error) } -// ClientCertPool returns trusted x509 certificate authority pool with CAs provided as caTypes. +// HostAndUserCAInfo is a map of CA raw subjects and type info for Host +// and User CAs. The key is the RawSubject of the X.509 certificate authority +// (so it's ASN.1 data, not printable). +type HostAndUserCAInfo = map[string]CATypeInfo + +// CATypeInfo indicates whether the CA is a host or user CA, or both. +type CATypeInfo struct { + IsHostCA bool + IsUserCA bool +} + +// ClientCertPool returns trusted x509 certificate authority pool with CAs provided as caType. // In addition, it returns the total length of all subjects added to the cert pool, allowing // the caller to validate that the pool doesn't exceed the maximum 2-byte length prefix before // using it. -func ClientCertPool(ctx context.Context, client CAGetter, clusterName string, caTypes ...types.CertAuthType) (*x509.CertPool, int64, error) { - if len(caTypes) == 0 { - return nil, 0, trace.BadParameter("at least one CA type is required") +func ClientCertPool(ctx context.Context, client CAGetter, clusterName string, caType types.CertAuthType) (*x509.CertPool, int64, error) { + authorities, err := getCACerts(ctx, client, clusterName, caType) + if err != nil { + return nil, 0, trace.Wrap(err) } pool := x509.NewCertPool() - var authorities []types.CertAuthority - if clusterName == "" { - for _, caType := range caTypes { - cas, err := client.GetCertAuthorities(ctx, caType, false) - if err != nil { - return nil, 0, trace.Wrap(err) - } - authorities = append(authorities, cas...) - } - } else { - for _, caType := range caTypes { - ca, err := client.GetCertAuthority( - ctx, - types.CertAuthID{Type: caType, DomainName: clusterName}, - false) + var totalSubjectsLen int64 + for _, auth := range authorities { + for _, keyPair := range auth.GetTrustedTLSKeyPairs() { + cert, err := tlsca.ParseCertificatePEM(keyPair.Cert) if err != nil { return nil, 0, trace.Wrap(err) } + pool.AddCert(cert) - authorities = append(authorities, ca) + // Each subject in the list gets a separate 2-byte length prefix. + totalSubjectsLen += 2 + totalSubjectsLen += int64(len(cert.RawSubject)) } } + return pool, totalSubjectsLen, nil +} + +// DefaultClientCertPool returns default trusted x509 certificate authority pool. +func DefaultClientCertPool(ctx context.Context, client CAGetter, clusterName string) (*x509.CertPool, HostAndUserCAInfo, int64, error) { + authorities, err := getCACerts(ctx, client, clusterName, types.HostCA, types.UserCA) + if err != nil { + return nil, nil, 0, trace.Wrap(err) + } + pool := x509.NewCertPool() + caInfos := make(HostAndUserCAInfo, len(authorities)) var totalSubjectsLen int64 for _, auth := range authorities { for _, keyPair := range auth.GetTrustedTLSKeyPairs() { cert, err := tlsca.ParseCertificatePEM(keyPair.Cert) if err != nil { - return nil, 0, trace.Wrap(err) + return nil, nil, 0, trace.Wrap(err) } pool.AddCert(cert) + caType := auth.GetType() + caInfo := caInfos[string(cert.RawSubject)] + switch caType { + case types.HostCA: + caInfo.IsHostCA = true + case types.UserCA: + caInfo.IsUserCA = true + default: + return nil, nil, 0, trace.BadParameter("unexpected CA type %q", caType) + } + caInfos[string(cert.RawSubject)] = caInfo + // Each subject in the list gets a separate 2-byte length prefix. totalSubjectsLen += 2 totalSubjectsLen += int64(len(cert.RawSubject)) } } - return pool, totalSubjectsLen, nil + + return pool, caInfos, totalSubjectsLen, nil } -// DefaultClientCertPool returns default trusted x509 certificate authority pool. -func DefaultClientCertPool(ctx context.Context, client CAGetter, clusterName string) (*x509.CertPool, int64, error) { - return ClientCertPool(ctx, client, clusterName, types.HostCA, types.UserCA) +func getCACerts(ctx context.Context, client CAGetter, clusterName string, caTypes ...types.CertAuthType) ([]types.CertAuthority, error) { + if len(caTypes) == 0 { + return nil, trace.BadParameter("at least one CA type is required") + } + + var authorities []types.CertAuthority + if clusterName == "" { + for _, caType := range caTypes { + cas, err := client.GetCertAuthorities(ctx, caType, false) + if err != nil { + return nil, trace.Wrap(err) + } + authorities = append(authorities, cas...) + } + } else { + for _, caType := range caTypes { + ca, err := client.GetCertAuthority( + ctx, + types.CertAuthID{Type: caType, DomainName: clusterName}, + false) + if err != nil { + return nil, trace.Wrap(err) + } + + authorities = append(authorities, ca) + } + } + + return authorities, nil } // WithClusterCAs returns a TLS hello callback that returns a copy of the provided @@ -110,7 +164,7 @@ func WithClusterCAs(tlsConfig *tls.Config, ap CAGetter, currentClusterName strin } } } - pool, totalSubjectsLen, err := DefaultClientCertPool(info.Context(), ap, clusterName) + pool, _, totalSubjectsLen, err := DefaultClientCertPool(info.Context(), ap, clusterName) if err != nil { log.WithError(err).Errorf("Failed to retrieve client pool for %q.", clusterName) // this falls back to the default config @@ -132,7 +186,7 @@ func WithClusterCAs(tlsConfig *tls.Config, ap CAGetter, currentClusterName strin if totalSubjectsLen >= int64(math.MaxUint16) { log.Debugf("Number of CAs in client cert pool is too large and cannot be encoded in a TLS handshake; this is due to a large number of trusted clusters; will use only the CA of the current cluster to validate.") - pool, _, err = DefaultClientCertPool(info.Context(), ap, currentClusterName) + pool, _, _, err = DefaultClientCertPool(info.Context(), ap, currentClusterName) if err != nil { log.WithError(err).Errorf("Failed to retrieve client pool for %q.", currentClusterName) // this falls back to the default config diff --git a/lib/auth/client_tls_config_generator.go b/lib/auth/client_tls_config_generator.go index 61cd6c4707eac..fd47480296ea0 100644 --- a/lib/auth/client_tls_config_generator.go +++ b/lib/auth/client_tls_config_generator.go @@ -21,16 +21,19 @@ package auth import ( "context" "crypto/tls" + "crypto/x509" "errors" "log/slog" "math" "time" "github.com/gravitational/trace" + "github.com/sirupsen/logrus" "github.com/gravitational/teleport/api/types" apiutils "github.com/gravitational/teleport/api/utils" "github.com/gravitational/teleport/lib/auth/authclient" + "github.com/gravitational/teleport/lib/tlsca" "github.com/gravitational/teleport/lib/utils" "github.com/gravitational/teleport/lib/utils/genmap" ) @@ -75,13 +78,70 @@ func (cfg *ClientTLSConfigGeneratorConfig) CheckAndSetDefaults() error { type ClientTLSConfigGenerator struct { // cfg holds the config parameters for this generator. cfg ClientTLSConfigGeneratorConfig - // clientTLSConfigs is a specialized cache that stores tls configs - // by cluster name. - clientTLSConfigs *genmap.GenMap[string, *tls.Config] + // clientTLSPools is a specialized cache that stores client CA + // certificate pools by cluster name. + clientTLSPools *genmap.GenMap[string, *HostAndUserCAPoolInfo] // cancel terminates the above close context. cancel context.CancelFunc } +// HostAndUserCAPoolInfo bundles a CA pool with a map of CA raw subjects +// to the registered types of that CA. [x509.CertPool] doesn't make it +// easy to view info on its certs so this info is stored alongside it. +type HostAndUserCAPoolInfo struct { + Pool *x509.CertPool + CATypes authclient.HostAndUserCAInfo +} + +// verifyPeerCert returns a function that checks that the client peer +// certificate's cluster name matches the cluster name of the CA +// that issued it. +func (p *HostAndUserCAPoolInfo) verifyPeerCert() func([][]byte, [][]*x509.Certificate) error { + return func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error { + if len(verifiedChains) == 0 || len(verifiedChains[0]) == 0 { + return nil + } + + peerCert := verifiedChains[0][0] + identity, err := tlsca.FromSubject(peerCert.Subject, peerCert.NotAfter) + if err != nil { + log.WithError(err).Warn("Failed to parse identity from client certificate subject") + return trace.Wrap(err) + } + certClusterName := identity.TeleportCluster + issuerClusterName, err := tlsca.ClusterName(peerCert.Issuer) + if err != nil { + log.WithError(err).Warn("Failed to parse client certificate") + return trace.AccessDenied(invalidCertErrMsg) + } + if certClusterName != issuerClusterName { + log.WithFields(logrus.Fields{ + "peer_cert_cluster_name": certClusterName, + "issuer_cluster_name": issuerClusterName, + }).Warn("Client peer certificate was issued by a CA from a different cluster than what the certificate claims to be from") + return trace.AccessDenied(invalidCertErrMsg) + } + + ca, ok := p.CATypes[string(peerCert.RawIssuer)] + if !ok { + log.Warn("Could not find issuer CA of client certificate") + return trace.AccessDenied(invalidCertErrMsg) + } + + // Ensure the CA that issued this client cert is of the appropriate type + systemRole := findPrimarySystemRole(identity.Groups) + if systemRole != nil && !ca.IsHostCA { + log.WithField("role", systemRole.String()).Warn("Client peer certificate has a builtin role but was not issued by a host CA") + return trace.AccessDenied(invalidCertErrMsg) + } else if systemRole == nil && !ca.IsUserCA { + log.Warn("Client peer certificate has a local role but was not issued by a user CA") + return trace.AccessDenied(invalidCertErrMsg) + } + + return nil + } +} + // NewClientTLSConfigGenerator sets up a new generator based on the supplied parameters. func NewClientTLSConfigGenerator(cfg ClientTLSConfigGeneratorConfig) (*ClientTLSConfigGenerator, error) { if err := cfg.CheckAndSetDefaults(); err != nil { @@ -96,7 +156,7 @@ func NewClientTLSConfigGenerator(cfg ClientTLSConfigGeneratorConfig) (*ClientTLS } var err error - c.clientTLSConfigs, err = genmap.New(genmap.Config[string, *tls.Config]{ + c.clientTLSPools, err = genmap.New(genmap.Config[string, *HostAndUserCAPoolInfo]{ Generator: c.generator, }) @@ -110,6 +170,8 @@ func NewClientTLSConfigGenerator(cfg ClientTLSConfigGeneratorConfig) (*ClientTLS return c, nil } +const invalidCertErrMsg = "access denied: invalid client certificate" + // GetConfigForClient is intended to be slotted into the GetConfigForClient field of tls.Config. func (c *ClientTLSConfigGenerator) GetConfigForClient(info *tls.ClientHelloInfo) (*tls.Config, error) { var clusterName string @@ -127,7 +189,15 @@ func (c *ClientTLSConfigGenerator) GetConfigForClient(info *tls.ClientHelloInfo) } } - cfg, err := c.clientTLSConfigs.Get(context.Background(), clusterName) + poolInfo, err := c.clientTLSPools.Get(context.Background(), clusterName) + cfg := c.cfg.TLS.Clone() + if poolInfo != nil { + cfg.ClientCAs = poolInfo.Pool + // Verify that the peer cert matches the cluster name of the + // issuer CA and that the CA type matches the cert Teleport role + cfg.VerifyPeerCertificate = poolInfo.verifyPeerCert() + } + return cfg, trace.Wrap(err) } @@ -135,19 +205,19 @@ var errNonLocalCluster = errors.New("non-local cluster specified in client hello // generator is the underlying lookup function used to resolve the tls config that should be used for a // given cluster. this method is used by the underlying genmap to load/refresh values as-needed. -func (c *ClientTLSConfigGenerator) generator(ctx context.Context, clusterName string) (*tls.Config, error) { +func (c *ClientTLSConfigGenerator) generator(ctx context.Context, clusterName string) (*HostAndUserCAPoolInfo, error) { if !c.cfg.PermitRemoteClusters && clusterName != c.cfg.ClusterName { if clusterName != "" { slog.WarnContext(ctx, "refusing to set up client cert pool for non-local cluster", "cluster_name", clusterName) return nil, trace.Wrap(errNonLocalCluster) } - // unsepcified cluster name should be treated as a request for local cluster CAs + // unspecified cluster name should be treated as a request for local cluster CAs clusterName = c.cfg.ClusterName } // update client certificate pool based on currently trusted TLS // certificate authorities. - pool, totalSubjectsLen, err := authclient.DefaultClientCertPool(ctx, c.cfg.AccessPoint, clusterName) + pool, caMap, totalSubjectsLen, err := authclient.DefaultClientCertPool(ctx, c.cfg.AccessPoint, clusterName) if err != nil { slog.ErrorContext(ctx, "failed to retrieve client cert pool for target cluster", "cluster_name", clusterName, "error", err) // this falls back to the default config @@ -168,7 +238,7 @@ func (c *ClientTLSConfigGenerator) generator(ctx context.Context, clusterName st // client will be rejected. if totalSubjectsLen >= int64(math.MaxUint16) { slog.WarnContext(ctx, "cluster subject name set too large for TLS handshake, falling back to using local cluster CAs only") - pool, _, err = authclient.DefaultClientCertPool(ctx, c.cfg.AccessPoint, c.cfg.ClusterName) + pool, caMap, _, err = authclient.DefaultClientCertPool(ctx, c.cfg.AccessPoint, c.cfg.ClusterName) if err != nil { slog.ErrorContext(ctx, "failed to retrieve client cert pool for current cluster", "cluster_name", c.cfg.ClusterName, "error", err) // this falls back to the default config @@ -176,9 +246,10 @@ func (c *ClientTLSConfigGenerator) generator(ctx context.Context, clusterName st } } - tlsCopy := c.cfg.TLS.Clone() - tlsCopy.ClientCAs = pool - return tlsCopy, nil + return &HostAndUserCAPoolInfo{ + Pool: pool, + CATypes: caMap, + }, nil } // refreshClientTLSConfigs is the top-level loop for client TLS config regen. note that it @@ -233,7 +304,7 @@ func (c *ClientTLSConfigGenerator) watchForCAChanges(ctx context.Context) error return nil } - c.clientTLSConfigs.RegenAll() + c.clientTLSPools.RegenAll() for { select { @@ -241,14 +312,14 @@ func (c *ClientTLSConfigGenerator) watchForCAChanges(ctx context.Context) error return trace.Errorf("ca watcher exited with: %v", watcher.Error()) case event := <-watcher.Events(): if event.Type == types.OpDelete { - c.clientTLSConfigs.Terminate(event.Resource.GetName()) + c.clientTLSPools.Terminate(event.Resource.GetName()) } else { if !c.cfg.PermitRemoteClusters && event.Resource.GetName() != c.cfg.ClusterName { // ignore non-local cluster CA events when we aren't configured to support them continue } // trigger regen of client tls configs for the associated cluster. - c.clientTLSConfigs.Generate(event.Resource.GetName()) + c.clientTLSPools.Generate(event.Resource.GetName()) } case <-ctx.Done(): return nil @@ -258,7 +329,7 @@ func (c *ClientTLSConfigGenerator) watchForCAChanges(ctx context.Context) error // Close terminates background ca load/refresh operations. func (c *ClientTLSConfigGenerator) Close() error { - c.clientTLSConfigs.Close() + c.clientTLSPools.Close() c.cancel() return nil } diff --git a/lib/auth/init.go b/lib/auth/init.go index 737f1566ac416..73687b872b489 100644 --- a/lib/auth/init.go +++ b/lib/auth/init.go @@ -621,6 +621,12 @@ func initCluster(ctx context.Context, cfg InitConfig, asrv *Server) error { } span.AddEvent("completed migration legacy resources") + span.AddEvent("checking certificate authority cluster names") + if err := checkAuthorityClusterNames(ctx, asrv); err != nil { + return trace.Wrap(err) + } + span.AddEvent("completed checking certificate authority cluster names") + // Create presets - convenience and example resources. if !services.IsDashboard(*modules.GetModules().Features().ToProto()) { span.AddEvent("creating preset roles") @@ -668,6 +674,35 @@ func generateAuthority(ctx context.Context, asrv *Server, caID types.CertAuthID) return ca, nil } +func checkAuthorityClusterNames(ctx context.Context, asrv *Server) error { + for _, caType := range types.CertAuthTypes { + authorities, err := asrv.Services.GetCertAuthorities(ctx, caType, false) + if err != nil { + return trace.Wrap(err) + } + for _, ca := range authorities { + caClusterName := ca.GetClusterName() + // sanity check that the cluster name in the CA certificates + // matches the authority resource's cluster name + for _, keyPair := range ca.GetTrustedTLSKeyPairs() { + cert, err := tlsca.ParseCertificatePEM(keyPair.Cert) + if err != nil { + return trace.Wrap(err) + } + clusterName, err := tlsca.ClusterName(cert.Subject) + if err != nil { + return trace.Wrap(err) + } + if clusterName != caClusterName { + return trace.BadParameter("CA certificate of type %s has cluster name %q that does not match the cluster name %q found in the subject", ca.GetType(), caClusterName, clusterName) + } + } + } + } + + return nil +} + func initSetAuthPreference(ctx context.Context, asrv *Server, newAuthPref types.AuthPreference) error { storedAuthPref, err := asrv.Services.GetAuthPreference(ctx) if err != nil && !trace.IsNotFound(err) { @@ -925,7 +960,8 @@ func checkResourceConsistency(ctx context.Context, keyStore *keystore.Manager, c case types.CertAuthority: // check that signing CAs have expected cluster name and that // all CAs for this cluster do having signing keys. - seemsLocal := r.GetClusterName() == clusterName + caClusterName := r.GetClusterName() + seemsLocal := caClusterName == clusterName var hasKeys bool var signerErr error @@ -954,6 +990,9 @@ func checkResourceConsistency(ctx context.Context, keyStore *keystore.Manager, c if !seemsLocal && hasKeys { return trace.BadParameter("unexpected cluster name %q for signing ca (expected %q)", r.GetClusterName(), clusterName) } + if !seemsLocal { + continue + } case types.TrustedCluster: if r.GetName() == clusterName { return trace.BadParameter("trusted cluster has same name as local cluster (%q)", clusterName) diff --git a/lib/auth/init_test.go b/lib/auth/init_test.go index fb4cc9000325a..bcc2a1c3c8f78 100644 --- a/lib/auth/init_test.go +++ b/lib/auth/init_test.go @@ -1023,64 +1023,50 @@ func newWebauthnAuthPreferenceConfigFromFile(t *testing.T) types.AuthPreference const ( hostCAYAML = `kind: cert_authority metadata: - id: 1630515580178991000 + id: 1736815462679560000 name: me.localhost + revision: 1a206afd-01ab-4fb6-9bd4-8615e17d60e0 spec: active_keys: ssh: - - private_key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcFFJQkFBS0NBUUVBMGpYWHA5SmM3amFVVThydC9NUXZyZjY3TXZoZnk3ZG5ldHoyenBKWFFNNmJQUG5PCjdQVGdIV1o1TFFndVVJTldXLzN6ci9xa2V6UHhmU0lXaUVlcDlRTy9HSytBWHVNWTdmUThNTEc2cS93ckM3UU8KeWxaY3htWGZuS2ZXSkV5RUdralA5VlZmakd3UEdxRUNGWmZtT1pJdXFMVWVadEJKVzduZTZWbkYvWnYzbUhBZwpkc1FFRHphTjdlQnN2NHJyOVhQeHI4anh4Tzg5TjZZN0lsRStoUXNiT3FNSVVsSUVvSk0xYjBOcVFldlhHLzhVClBWWXJLK21hR2dNclNqZHppTjl6VHUzRzNCKzJ3SkJNZzd3VitMQjlJRUU0Y2NHYVVDbUM0QzBuZlByM283emgKTE1UNTZpdGZLdGw0TlkrN1NjRHVSSkN2TkFra3IrNkZtVUc5NXdJREFRQUJBb0lCQVFEUUVJTVlsVnR1WFkrTApNTDFIQjFpNk8veEdneGt1cHFaQ01od0ljMGp4Mkk1SFdHdThsdFNOeFRRRG9xbFUvK3FtdTBKTTJTV2MzTmtXCkpudHZBSi8wNkhScGxxelZQcXNhUERpbmFnTiszK1lyZTFsNFpPc0haU1prQkt3czJaK1g5S0lDRHpLMzV1MDgKU2ttcDNlUCs3L1pHL3A3TTNUVC9HWWJPS2hHUzV0VXdTY291NXV3aFMxQjFJOFNQQW05UGdsMmkyTjVib2s2YgpQTHBqT0xwOUZPVmpVMlNXYUhVa0ZiUUc2TENzOGlJdVdlVzdvMEtkY3B1QndXeGQxd0p3bm5nbjlJVzJ0aUdyCnZLTGlsYzJLR2xITnJxZldiRWw4Z2N5eXBKeUNqZEIvVXkvOFFBOG9uOHBnK1hldThrcnFyRjNTZm5iZHNOaDQKVmNKV09zTUJBb0dCQVBvY1E1ZWd0enZSL1djR0ZtbUxNbTUxTEVDMytPOWxVSUMwMGZ0Q1lkYW5vK0NGUTdEbgpQd0IyLzUyZWZMeUhLUlpjc0lrd2IreXZjYXp3eG9BWlNzMnRlV1FqRUJoOXdRbGlzWlNacVJIVEVMbnY0WjdvCkFMM3JmUjNtM3FHR0tmMm9UQnQ3dEVCcEMwZEVITDlxOVRpbkJJVDVKWGVSSVNzZUcyOGFKUG9IQW9HQkFOY3AKREtjc2hVKzJnaSs2V3p4eThOU3gyMkV5Y29FdUFKbWlSdm1jcExNNE9OTW03dUlQQ2RDYWYyY0UxYzJjVUg5OAppRGw2ZzBYN1ViUjQ4NzdJeVluMi9TU2hiOG56R3ZBNmVBbGJYZk9PYlYvTkIrczUxQzduTGFVSUE1ZEkyTE1WClRJL2xRTnV4cDhieXZDNjU3UVFQZk9jVXlGMVZIVVo5VzNPbU1hVWhBb0dCQU5RREZZRDQ2Wm81M1RaeHdKbmoKTnZMUFBKMzMxWHNKUlA1MVNQSldTUjF1cWNudTdYeU42YWY1TjZGaThaWFdkUXZSc292NGxVZnJTTTh5b3ZGLwpmeHR1aTlKSXJxSTBKMmhQVXYwR2JIMEJqOUl0OS9GOTlQTUpKZHd0RWxlVnBRNnlsU0ZPOFhNUUdGRm0rWCtCCnFURkcwdHZ0WHNkR0xQbWg0ZHVDTEFvTkFvR0FLSS9aamM2TDEwbzk0c2VNR2FwRmtxTnhDekxhZVZYMTBRRFIKeG83c1Vja2dsVlg2cE8xVzJWZTIrdkhqYUo2MllrSlU0QmtqbEZiYndWMG4vbWlWN2dkOUU2SEhsRmZiVlR5QQprcXNCM0QrV2lQLzdKVEpDdVJEbC92Mnl4NXQ1RnRIR0hENkk2cUhrVWxKQ2ZjQ1pXVEdlUjJZWW05Zkc3Qm9ICjJwYVROMkVDZ1lFQXRUQ2o1M253M213RDE1ZjAyZ2pKcWNjeHBkRk1lYlJpNUltMXJ5RUFaSzhwTmNlL2xNclgKVXM1KzM2eFpHWG1CR1ByMVl0UmxIVThQL1owWFdJM3ZDOFpLRHB6SnB4dnB6QmRFV0pUZGlPZEhpV2J4TzZOOQpiYjh3ZUM4STl4ZDlwd0cyMHdYNUVnR0krekdjMlNGa1VDTWROd1JkV3NSTWNCMklMeVV0MmZzPQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo= - public_key: c3NoLXJzYSBBQUFBQjNOemFDMXljMkVBQUFBREFRQUJBQUFCQVFEU05kZW4wbHp1TnBSVHl1Mzh4Qyt0L3JzeStGL0x0MmQ2M1BiT2tsZEF6cHM4K2M3czlPQWRabmt0Q0M1UWcxWmIvZk92K3FSN00vRjlJaGFJUjZuMUE3OFlyNEJlNHhqdDlEd3dzYnFyL0NzTHRBN0tWbHpHWmQrY3A5WWtUSVFhU00vMVZWK01iQThhb1FJVmwrWTVraTZvdFI1bTBFbGJ1ZDdwV2NYOW0vZVljQ0IyeEFRUE5vM3Q0R3kvaXV2MWMvR3Z5UEhFN3owM3Bqc2lVVDZGQ3hzNm93aFNVZ1Nna3pWdlEycEI2OWNiL3hROVZpc3I2Wm9hQXl0S04zT0kzM05PN2NiY0g3YkFrRXlEdkJYNHNIMGdRVGh4d1pwUUtZTGdMU2Q4K3ZlanZPRXN4UG5xSzE4cTJYZzFqN3RKd081RWtLODBDU1N2N29XWlFiM24K + - private_key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcFFJQkFBS0NBUUVBdlpkajF2dXdoUktJL3BFVjkxdllEVHJUOHBpVzVrQjBKVXU3UGxUa0tiVG9TbVRsClozQ1lSNk5xMkVNYUE2QTIrZDJUT0Vyb2R1Mlp2K2tjWlYxK055T2czKzhQcUtiWG1JampBV3YyYlVFZEtmZUMKTW9Rb3Q5Rk8yelI1SkNEVVBWOWduSS9PbHU4WUdYdWJqYnZQU3k2NFM5RmQ4ZjM5YzhMdGpYbkUzZXRLTUtRcgpUVkpFb0dxa05YVmJUd2x2RkFUbUdUcmZHSDJNdG5FdTZMMEozLzNmT1pmOG1SRXBWMXg4YkZjNUEydWxmUDZRCjFqOUJaOFBTRmFlV0pEWFV4dzJwSzl4c0pPaW9LNEREcHU1K0ZZcTRqQnpmS1ZyamF0ejJhVjBKWVRvWFpiY2oKK2wwVXpKemxQRUdjSjBzRmpkU3grV0RZdS9sbTljT29hdzEzSXdJREFRQUJBb0lCQVFDODB5TGs0eGdUOFRudwpFS0JJRkhsQjgrMVVHUlZ4alpBZjlTVXdGMnlHL1Y2OWVXL2hiZ3E4anMzRFJsR0tldTlHUEtCNzJGOWUwNVhsCnhVNDZ4cnNHUDczaVNqN1dRaFZJSGsyNUJNWVNXbCtwaEpGdnJxQy9Ndi9PNHB3a2wyM0xFa3N1b3l1bXQ4clEKMW9NK3ptYlBBbUViWWhLbkNjaDhtdy90Yi9IYTh0ckpyWWVDaGlMV0cvN0NSZU9uQlZubXlnN21tTnNYNHFTQgpFcFlYSUdIOXhRN0VoUXJ6UGxvTWRJQWtLTGdiZE5MM2tkdzFMRFBhaGhwanhEK09VTEJVYkx0a1JrTEM5ajYvCml2dnUxVXUyZjhhYklseTNaNWxQTUlINk12Unh4bS83d21FRVowY2JjM0dSb29ZSTJPOFdjamRYTjJpRFBWQmYKNDFmOGNvMUJBb0dCQU1RZTJQSTF5NE0rZnVpUll1N1dvbWNETVdGUm1CTGFKOWo1V3NYWXJLamtSS1owMk8wRAo5dHlZanpHT2VYZ2pSOHFGNHRJL0RaTHdZSWVPREtpWFN6RlplanpGdG9HK3pXNWFDM2MxOGswem5VeDhpQnpBClhic0wzRmN6ckw1OUVtbDVwVVNmRUhqWmJPUTU5bG9DaEhqSDl4cHVoVUo3YnBidFpPd1d0REFsQW9HQkFQZDYKTnBhZjdjWkN0TFlJQk5pSzhTV1RIZXZSUFBHRUI5Y055b3VxQ0svdS9Rb3JITkRNRWE2UTMyRHI4MnJ6V3Iwago5U3NIL1plNU5UWVlxZUdtRkZmS2RpWms4d2JpUWtCYWFNd1N5ZEprc01ocjZ3T0NXd0J2QjFUMmFodmU3Mm9qCitTa1lqMzFvOXVrY2trT3pBa0pwelZrQTdwb2g1V0hSZ25GSEtTT25Bb0dBSndhQVl3b2pXaFZvaVh6TXMvd1AKeXZIT3RLL1kwLytIS0Z6T0hFcDJhUkVyTy9oS1pqZUF1dnE4bTc3Zkd2SGlTa0dFRmhRbjdsSlkwd0NJTWxBUQp6VndodjlBVDloTnlxMy9OZ2taQTFlM3NZaGp4dU03cWw5clBXS2JXdS8wRldlbXo0a2pJclZPT29JZU1Kdk1UClN6bDNTVkl1d0VEeGk2VG5qVGNqV2VVQ2dZRUE3RWYzVHFDcmVKdS94ZnlxQThYRXI4ZGl6Z0FjVzh0ZllPaDkKOWhNRjhGUVJyRisxUjNWUGZJZzlmbUJKTEZma3pxbENMeStWNUFLazExMTg5VUNJTTduT1RLSWRsdmozb0ZHeAp0UVpMUTJGM21DUFJZcXhYRG5ielhSOVg5L3hHUWVUT3czbjdwaFZOaVF3S2FqRERlMzFnM2hXUnVmK2E3bVlHClVQbE1RZ2tDZ1lFQWx2ZVR5THVGK3JlQ0xZUjgyRllBYzZHV3o0bFNzMWE1RzB3NFBnQXI0ZFVuU1ZSRVpaeHAKTlZabVZvdW5weFJWdHNCVjV4dVp5YXpzQ2hCNVBsZE56d3ZRS0JXaTlvQWNyOEpKVkhvKzJHM3IwYURUK0xlSQpFUFVqRkJvMFZrZ0VvU05tazBBOXY2N0lBUzZvTk00UkY4cHJvRm1CWEliQTdXZ2V3c25kWHM0PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo= + public_key: c3NoLXJzYSBBQUFBQjNOemFDMXljMkVBQUFBREFRQUJBQUFCQVFDOWwyUFcrN0NGRW9qK2tSWDNXOWdOT3RQeW1KYm1RSFFsUzdzK1ZPUXB0T2hLWk9WbmNKaEhvMnJZUXhvRG9EYjUzWk00U3VoMjdabS82UnhsWFg0M0k2RGY3dytvcHRlWWlPTUJhL1p0UVIwcDk0SXloQ2kzMFU3Yk5Ia2tJTlE5WDJDY2o4Nlc3eGdaZTV1TnU4OUxMcmhMMFYzeC9mMXp3dTJOZWNUZDYwb3dwQ3ROVWtTZ2FxUTFkVnRQQ1c4VUJPWVpPdDhZZll5MmNTN292UW5mL2Q4NWwveVpFU2xYWEh4c1Z6a0RhNlY4L3BEV1AwRm53OUlWcDVZa05kVEhEYWtyM0d3azZLZ3JnTU9tN240VmlyaU1ITjhwV3VOcTNQWnBYUWxoT2hkbHR5UDZYUlRNbk9VOFFad25Td1dOMUxINVlOaTcrV2IxdzZockRYY2oK tls: - - cert: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURlVENDQW1HZ0F3SUJBZ0lSQUlvWW1QRUhNV0wwZmp6VkZVZ2l2Ykl3RFFZSktvWklodmNOQVFFTEJRQXcKVmpFUU1BNEdBMVVFQ2hNSGVtRnljWFZ2YmpFUU1BNEdBMVVFQXhNSGVtRnljWFZ2YmpFd01DNEdBMVVFQlJNbgpNVGd6TlRZeE1UZ3dOVFkxTXprMk1qUTNNRFV4TXpRM05qa3pOREV5TmpNME56Y3dPRFkyTUI0WERUSXhNRGt3Ck1URTJOVGswTUZvWERUTXhNRGd6TURFMk5UazBNRm93VmpFUU1BNEdBMVVFQ2hNSGVtRnljWFZ2YmpFUU1BNEcKQTFVRUF4TUhlbUZ5Y1hWdmJqRXdNQzRHQTFVRUJSTW5NVGd6TlRZeE1UZ3dOVFkxTXprMk1qUTNNRFV4TXpRMwpOamt6TkRFeU5qTTBOemN3T0RZMk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBCjlzNGgrUTlpKzBlQ0c0VWNtSThFbEg1MHBlWmFkV2JzdzZDUStCZmF0em1NQWJEa016WGpSTHlNZy8xNFdSRGsKWTU4OUpCWVgrTzRBYXBRNno5MFRhTzhHamN1RmxvcWlFcTZOci9VTjJMYnc2am9KdTYvQ0dmcWIzNXZKT1NDdApKMWp5am5Cc2ZVNTRzRGFGcWpPRG1BL2l3YjNsSlZSV1pmYUdQSGZtRTRUcHJCSzdXV2FHbmlDZktUdGQza3lHCnkzWXpGZEJzSDU0OU9Lc1BFUlJOdTVCdlpzcmZWazRDdnlKNWVxREE1NlBaU1pmSVptZEk4VUdsRmk0V3lhMHEKUHRtWmg4bURGSnpVNnNXZWY5bTRqM3grMmF1UFEra2M3cjJneFdLZ2lTR1FBT2hLU0VhaEZDUW9UU3NzemVReApoZG9xamZUK1NsUWlQQlhJbDhTbzlRSURBUUFCbzBJd1FEQU9CZ05WSFE4QkFmOEVCQU1DQXFRd0R3WURWUjBUCkFRSC9CQVV3QXdFQi96QWRCZ05WSFE0RUZnUVVlSDJQTUhjRmwwTnkvQmozcE4xTExlSStPZTB3RFFZSktvWkkKaHZjTkFRRUxCUUFEZ2dFQkFMeU5aRXByOWtWbk5ORERiWWxWd0M1bnRlUEU2Z0ZQdGRjU3JjYmcyU01temtMMgppSjhCQnJ1ZVBmTllrMVE0c2xlN0FDeTRQL1dzU2xYZThqQkY0bm5KaUkxM2kvaUtQOEJzNVVIQWwwUTJ6RnlMCmp0Sk9JRlFuT1hiUmxQU1RQY21jcWdVUUcrL3lGOGhQVndHNnRwOVZoeXlCVkdlMDRlWU44eVNnbkZKTUloNGcKeDEzcytTWjE1RFkzSERnTGNCSjA5dXA4Q3NJdGV1RG05aG1jbGJ1bUc4OVEyQ3I4T25TcmYzTDNFSVhyelZBbwp3eEUwN21IWnkxSjBvNnljdWJXOWVuS2J3bTRKRHRhaHc4QzlERitvQXJlUEdaSXJXdVZpWFZYeTV6S2NOQW9LCjVXY0Q5RHdjcTFFUnVreGNFWWlrV05BV1FFNnVaMGVYZ0pKWlJ2OD0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= - key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb3dJQkFBS0NBUUVBOXM0aCtROWkrMGVDRzRVY21JOEVsSDUwcGVaYWRXYnN3NkNRK0JmYXR6bU1BYkRrCk16WGpSTHlNZy8xNFdSRGtZNTg5SkJZWCtPNEFhcFE2ejkwVGFPOEdqY3VGbG9xaUVxNk5yL1VOMkxidzZqb0oKdTYvQ0dmcWIzNXZKT1NDdEoxanlqbkJzZlU1NHNEYUZxak9EbUEvaXdiM2xKVlJXWmZhR1BIZm1FNFRwckJLNwpXV2FHbmlDZktUdGQza3lHeTNZekZkQnNINTQ5T0tzUEVSUk51NUJ2WnNyZlZrNEN2eUo1ZXFEQTU2UFpTWmZJClptZEk4VUdsRmk0V3lhMHFQdG1aaDhtREZKelU2c1dlZjltNGozeCsyYXVQUStrYzdyMmd4V0tnaVNHUUFPaEsKU0VhaEZDUW9UU3NzemVReGhkb3FqZlQrU2xRaVBCWElsOFNvOVFJREFRQUJBb0lCQUhkODZ1TzYrRS94bWVNYQorZkkrWTVoRTlOS1JDTUNJT1I2cE1TWjczZzhSRkdDSk5LSTZkN0tDbW9FWWlWaU5uaFZCTmdldmpxR2RFS1NJCjZVUlRveDhOZ2gzS0ovM3ZWbkkzQWkvck0yMzFmQVBhWDNYM3JNQ0pIVWdRRTBiT05DYTFvSkVuaXM3TDNCQnMKQlNDVzJpSVhwcy9uMFBYV3RCR2ZYZlFPbEZ4ajdKbXdwdDlqYTYyankxa3hlTVdMemlqQUZ1QzRwRTl3WUVaVApGa0ovb2FVdzR4WXM5N0pnelRNUHFJSlUzMStNYTNoNGFPQ2lPK2RzSExhK2tRUkZIN0tHOUtRaWlRYzdrTmdGCnljN2s3L2s3UVJSbG1mZmZLN3E3YUtVNkNueHVxOG05UThob2Q5QVdjQ3ZyTm9jSmVjSzcvSzFzNlhMYXhSTFgKRGFLc0xRMENnWUVBK0lBOGNRVmcveU5xbGQ5c2lHZ0NETy9DVUNwM21uZjdxZTNQeEZIWHVSdFNzaHJheE9qVQpRVXFtbHV5VWRCZTZLQnA4ZWxoVmFlYlZsdFNNd2xyWXNpUlIxaTV0SDNnRGUybXRheE5VZ0xtTGoyZUhVWGN3Cmk1UW1yQ1AyTzY4V0xQZjg4SkkwQWtOWWx3em5aWUg2VEZKbFp0MkxoU3ZRTG1qeFArWDZTT01DZ1lFQS9rREwKNndJMjVoYU1DbTBSWitrQWM1T2FJcUx0OUNWeWNTaGdzblBjK2xBQll0ZVRkclhjVW1FaklQYW1uZ1pKZUpvSgpoUDNxaHBja1JVcWwrSldhN3lXRnJocTdyTHlpTVNBb0VwaXdQMkRUMkxROWFXR0lONjdwSU9ObWtpamU2NmNNCjBsd05hQTBtL3Q5ZWZUZ2RLOUpHYnNoaTVnRFFiTFVtMW5Gd1prY0NnWUFMenJ3UWVycnpKSkdwOFdYTXpYUmIKZlFEMG9pL3dyUWJPT2ppSEVZUjRqUzNPdkt2c2MwdXlsb04zNUdIaGFrYzBKSjRKaWl6MHpUMFUzNkNZazR4OApXbkZ4QmQrMWdSUlpSdG93bmtpRG5VMWVVUU1EQWZEU2tRV05aR0FNMGZMeHpBNit0NU8xRDlJanl6OHJlWk9WCkVNMDBxQTQ3RTZ2ZXFLbmQ2V1dORlFLQmdBa3Z6aTV2cGd3cVJHVWNDOFQxWms3R3hvcjUyQjg2T3loYmpTTGwKak5aK2pZNUV1ODlPUXVlM0dzM1dHNjhhQ3cyUWcwZUs1UzUzeDVlNVdzWGdvZmlDSXBKbjVPQVk4TU5WcGgwRgo1MWhpNTBTdFBvclFPMXZIdGlTNkVycTFQMWpFY0hJcFlWS2hKd2VPaXB0N3E1SXB4dUc1MjlqenJwUSs5MmhJCk1RZUJBb0dCQUkrNnE2OGFvdW41bE5sU3NoTVg0citoZlNtbFhXYmcvdU1OQXROdWhtZndmSE0zWmR3SU9ZWlYKRTloalFNQXh6RFduZkx1ajljRkJQM2NER0s0NytoU0U2N082eHBrYk9BYzk4dUlXZVEzb3lyWEd5akQ3TGdrYwpxajFRa2ZiZE4wMU1BdEN0MDhaSlRwZzR1OUdXUUVVQWY2ckJaKzJPN2ZVdEJuUG40TXpsCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg== + - cert: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURpakNDQW5LZ0F3SUJBZ0lRSXoxQlR1aHZqUFBvWVk3M29UNUZTREFOQmdrcWhraUc5dzBCQVFzRkFEQmYKTVJVd0V3WURWUVFLRXd4dFpTNXNiMk5oYkdodmMzUXhGVEFUQmdOVkJBTVRERzFsTG14dlkyRnNhRzl6ZERFdgpNQzBHQTFVRUJSTW1ORFk0TkRFd016UTFOamt4T1RnNU56SXhPRE16TVRBd01EazNPREUzTURJeU5EYzNOVEl3CkhoY05NalV3TVRFME1EQTBOREl5V2hjTk16VXdNVEV5TURBME5ESXlXakJmTVJVd0V3WURWUVFLRXd4dFpTNXMKYjJOaGJHaHZjM1F4RlRBVEJnTlZCQU1UREcxbExteHZZMkZzYUc5emRERXZNQzBHQTFVRUJSTW1ORFk0TkRFdwpNelExTmpreE9UZzVOekl4T0RNek1UQXdNRGszT0RFM01ESXlORGMzTlRJd2dnRWlNQTBHQ1NxR1NJYjNEUUVCCkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDanVtZ3c3bDlkNUNMMGpxdHlPbCs5Y1hrMXZkSDhYL1R5RmhjQ0lWZnkKaDBJOFdlS2lWMGFzQnFIYnVJOWpDcnF5ck9wS0NieFlxV1k1QmpMb0YzNUVjblc2U3dLUEhGU0hwRWoyMEZLNwordGdyckxOdHVSM2Y2WUp6ZytML3M4SkF5Y0U3TTRIZDNQbnhYM3hiOE1mUlBRNHh3L2E1SE9tZ0dFcGhKZG82CnhqQm9KQ2dkNUVsL0MxSnBPVE5Fd1MraFpJSUxpcVZKUHV4T20xWkUzYnJUY3VYL0tHR0NndlVGSlpxV0g4ekwKQ011QVVkWG5WUTBxVUZXOUxGUnM1Z0Nkb1BjVzl2TGxLS1hyUW0yZXpHbms1NEJQbHR5L1V5RTNXNEo5WCtOTApQaXlEeEtZOTQ4eTlVazVIV2FlYWZsRWRQbkR6b3VKWmg0Nk9EelpmOWthdEFnTUJBQUdqUWpCQU1BNEdBMVVkCkR3RUIvd1FFQXdJQnBqQVBCZ05WSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCUm94bWZGSWNPSCsvckUKUzlQM1NncCsxenAvdnpBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQUNTUEVRMU5UazZPWGp5ZHhYbEpqUThrYQpqbUlFcG44WUQzU1NHV3duSkRqbUVDbXU1NXFZYmFhY3pBM3NackZ6Q2lLMWpyY2lBNUEwVGhkNFkxa1N5eXJTCjlteGswZTNHQ3IzUVRVeWF4T2FjZVVWb1hhK2FGMmJrZi96SnN1ckdOL3ZHY1duUkpBWmZxUUdmVWphN2MyLzkKbEtGbE5PazkrbTZUd2VCbGZvUWYvR01OaTBDSTNpTDQ0RFBsMzVaN0hFSlFqYkdGNWMyYkhNM3I4TkhMTm5QYwp1YUJKNFZSRG02N3N6aHI0UERvMm9YSkFGVDFSSGxnd0UvbWZQQTlscklaRFBXRGlBckhoMFpqSTR3T2xDTDBpClFlRDBraDlkeXB6b3FwdS9LQXlTMm1wZ1lVU3huazRJTEhPNDdnZGc0MUVPTGk1ZE1PcDRNOTRFMTVLdTZnPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= + key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBbzdwb01PNWZYZVFpOUk2cmNqcGZ2WEY1TmIzUi9GLzA4aFlYQWlGWDhvZENQRm5pCm9sZEdyQWFoMjdpUFl3cTZzcXpxU2dtOFdLbG1PUVl5NkJkK1JISjF1a3NDanh4VWg2Ukk5dEJTdS9yWUs2eXoKYmJrZDMrbUNjNFBpLzdQQ1FNbkJPek9CM2R6NThWOThXL0RIMFQwT01jUDJ1Unpwb0JoS1lTWGFPc1l3YUNRbwpIZVJKZnd0U2FUa3pSTUV2b1dTQ0M0cWxTVDdzVHB0V1JOMjYwM0xsL3loaGdvTDFCU1dhbGgvTXl3akxnRkhWCjUxVU5LbEJWdlN4VWJPWUFuYUQzRnZieTVTaWw2MEp0bnN4cDVPZUFUNWJjdjFNaE4xdUNmVi9qU3o0c2c4U20KUGVQTXZWSk9SMW1ubW41UkhUNXc4NkxpV1llT2pnODJYL1pHclFJREFRQUJBb0lCQUZEaUxjYStlKzV1WGJaagpKTjl4WndxM25DR29mS3dvMjJFYytKRGMyQTNBTkVDTVJ5SGI2OVhnRU9YeTd5TUdrZVRpOTN0TUEvZm85ODhECitQSWZhUWwzWWlGK0hPMkdHVnhKRktLWmw4VzF6a1VGTkQ3b1RKSHBVY0N2VHR6emVPdDR3RFQyNVJrdHFXeE0KdDZyVDhHSzF2dVZtNGVQaEhLa3lWc3hYWHMvWmZvTHhxa1BxWXFHRkd4NU1VelVJY0hnQmpyRVVIWXJVNHN1VAoycklzOFl4Vm5nYWdGdXdmSk1WdkN1aDVvNndyWHJvbHJKdDlFY1BtMzFVWFpGTXlhaTRVa3JVbk5qbkNMU3JsCmYxalEyQWRkYWp2UE5mYTk0ZFBsRVdOeHlRM29YNEVwOFRqUFhTc3NUdURXVFdZVUFURXFIb25MNEZUYytNVzkKTXh1SjJ5RUNnWUVBeHVjRDRwaW1TaDBkTGZPZTBVM0VmQ04zNll3UDVXdDVIMHJJTzBQQ2l5ZVNoSEZvaUVJMQp0eTZnWTk2UFFEYU1ycW5OZDN1Y3Q5WjYwVHlwUloxbUtNa01hV2hOVG41L1NqbWNxTTV4ZVZYSWVvV1QrRWkzCnQ4bmd3U1ZlZUQ1OExnQ3dFaFF6ZUJLM2l6UVVQN3ZPclRXcWlRNmxUZGNXa1JPRWhQL0lDdE1DZ1lFQTBycC8Kbnh4enh2MXEyUmY4ekZvVTRvMG5Mb1dvRFYwM1BTcGIwU0xUSzYwVndFZGNESVRqSnlmbTBQRFcyNXJobmVhOQpQeGw1R1NtakExMFpKNlprZVVIMkJwMlJjNDhraHd4Rit2bVkzSUZKeFlLMXBGWlEwOS9yYjkxendESWhtSGQrCk10b3JvbE5jb0srcC8zWXN4SkZFOXJxVzVjbmhLYnlwUFRzQ2VIOENnWUVBa2tuTWNMZEc3cEdWS1h2Wm5pVXQKVXdRZktKVk1CN2RRNFRQMktxaCtpQ3cxdGRWWFJZZzB5Nkt1Y21WNVJJZ2FWa2dyQnlyU0s5L0NldXU3cjZqQgpQMVFISGV1Sm1DYXZaaDhUV3BCam94TDFuUzlya2h1aGk3b2Q1TkNnTjUzMVpUdzZRMEc2VFNDdS8rSHcxcU5CCnNlRWJxU3d0WmgvQXlEanJxWW9hVGVNQ2dZQUZRZGZiUFZkNkdHcG8vaHMxY2UzaGRRb01OQk5zT2U0ZDNZZXEKNFFhSnFXaklnajgrcExZU0RRSEtKcWdGbElpYWF0NC95Ny9rcTlCQVRqdEpiUEpHd0NtR0lybzFPdFg3ZElmdQphZm14VHB4cmpBWkNFbEV6NS9zMHNENnFCZFltdXB4d1lsY0NWcmdSM2pBTWlvTTFhRFpqUFdaMFZ5UUI2WTREClZBeU11d0tCZ1FDdlA0RUVHOUcxSFYzQUpXVkVhSmpLai9paEhJTFdYTk1ZWVR4OVVHdjd1My93d1hiQ0tTRDgKTG4wdkp0UVFQNnpISGtSV05GM003U2RlU0VGSHQ4SWlXTThueXFTOUxOVkJtSW8vNVNUUWwyTlZYdmdYVlZNUwpLUU1lVlZHTkR0Ykd0REFhclo1VFZhTHFqMmNGaWF1U3h4SGdneVU0NUlrVzlHQkJqM3g3WGc9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo= additional_trusted_keys: {} - checking_keys: - - c3NoLXJzYSBBQUFBQjNOemFDMXljMkVBQUFBREFRQUJBQUFCQVFEU05kZW4wbHp1TnBSVHl1Mzh4Qyt0L3JzeStGL0x0MmQ2M1BiT2tsZEF6cHM4K2M3czlPQWRabmt0Q0M1UWcxWmIvZk92K3FSN00vRjlJaGFJUjZuMUE3OFlyNEJlNHhqdDlEd3dzYnFyL0NzTHRBN0tWbHpHWmQrY3A5WWtUSVFhU00vMVZWK01iQThhb1FJVmwrWTVraTZvdFI1bTBFbGJ1ZDdwV2NYOW0vZVljQ0IyeEFRUE5vM3Q0R3kvaXV2MWMvR3Z5UEhFN3owM3Bqc2lVVDZGQ3hzNm93aFNVZ1Nna3pWdlEycEI2OWNiL3hROVZpc3I2Wm9hQXl0S04zT0kzM05PN2NiY0g3YkFrRXlEdkJYNHNIMGdRVGh4d1pwUUtZTGdMU2Q4K3ZlanZPRXN4UG5xSzE4cTJYZzFqN3RKd081RWtLODBDU1N2N29XWlFiM24K cluster_name: me.localhost - signing_alg: 3 - signing_keys: - - LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcFFJQkFBS0NBUUVBMGpYWHA5SmM3amFVVThydC9NUXZyZjY3TXZoZnk3ZG5ldHoyenBKWFFNNmJQUG5PCjdQVGdIV1o1TFFndVVJTldXLzN6ci9xa2V6UHhmU0lXaUVlcDlRTy9HSytBWHVNWTdmUThNTEc2cS93ckM3UU8KeWxaY3htWGZuS2ZXSkV5RUdralA5VlZmakd3UEdxRUNGWmZtT1pJdXFMVWVadEJKVzduZTZWbkYvWnYzbUhBZwpkc1FFRHphTjdlQnN2NHJyOVhQeHI4anh4Tzg5TjZZN0lsRStoUXNiT3FNSVVsSUVvSk0xYjBOcVFldlhHLzhVClBWWXJLK21hR2dNclNqZHppTjl6VHUzRzNCKzJ3SkJNZzd3VitMQjlJRUU0Y2NHYVVDbUM0QzBuZlByM283emgKTE1UNTZpdGZLdGw0TlkrN1NjRHVSSkN2TkFra3IrNkZtVUc5NXdJREFRQUJBb0lCQVFEUUVJTVlsVnR1WFkrTApNTDFIQjFpNk8veEdneGt1cHFaQ01od0ljMGp4Mkk1SFdHdThsdFNOeFRRRG9xbFUvK3FtdTBKTTJTV2MzTmtXCkpudHZBSi8wNkhScGxxelZQcXNhUERpbmFnTiszK1lyZTFsNFpPc0haU1prQkt3czJaK1g5S0lDRHpLMzV1MDgKU2ttcDNlUCs3L1pHL3A3TTNUVC9HWWJPS2hHUzV0VXdTY291NXV3aFMxQjFJOFNQQW05UGdsMmkyTjVib2s2YgpQTHBqT0xwOUZPVmpVMlNXYUhVa0ZiUUc2TENzOGlJdVdlVzdvMEtkY3B1QndXeGQxd0p3bm5nbjlJVzJ0aUdyCnZLTGlsYzJLR2xITnJxZldiRWw4Z2N5eXBKeUNqZEIvVXkvOFFBOG9uOHBnK1hldThrcnFyRjNTZm5iZHNOaDQKVmNKV09zTUJBb0dCQVBvY1E1ZWd0enZSL1djR0ZtbUxNbTUxTEVDMytPOWxVSUMwMGZ0Q1lkYW5vK0NGUTdEbgpQd0IyLzUyZWZMeUhLUlpjc0lrd2IreXZjYXp3eG9BWlNzMnRlV1FqRUJoOXdRbGlzWlNacVJIVEVMbnY0WjdvCkFMM3JmUjNtM3FHR0tmMm9UQnQ3dEVCcEMwZEVITDlxOVRpbkJJVDVKWGVSSVNzZUcyOGFKUG9IQW9HQkFOY3AKREtjc2hVKzJnaSs2V3p4eThOU3gyMkV5Y29FdUFKbWlSdm1jcExNNE9OTW03dUlQQ2RDYWYyY0UxYzJjVUg5OAppRGw2ZzBYN1ViUjQ4NzdJeVluMi9TU2hiOG56R3ZBNmVBbGJYZk9PYlYvTkIrczUxQzduTGFVSUE1ZEkyTE1WClRJL2xRTnV4cDhieXZDNjU3UVFQZk9jVXlGMVZIVVo5VzNPbU1hVWhBb0dCQU5RREZZRDQ2Wm81M1RaeHdKbmoKTnZMUFBKMzMxWHNKUlA1MVNQSldTUjF1cWNudTdYeU42YWY1TjZGaThaWFdkUXZSc292NGxVZnJTTTh5b3ZGLwpmeHR1aTlKSXJxSTBKMmhQVXYwR2JIMEJqOUl0OS9GOTlQTUpKZHd0RWxlVnBRNnlsU0ZPOFhNUUdGRm0rWCtCCnFURkcwdHZ0WHNkR0xQbWg0ZHVDTEFvTkFvR0FLSS9aamM2TDEwbzk0c2VNR2FwRmtxTnhDekxhZVZYMTBRRFIKeG83c1Vja2dsVlg2cE8xVzJWZTIrdkhqYUo2MllrSlU0QmtqbEZiYndWMG4vbWlWN2dkOUU2SEhsRmZiVlR5QQprcXNCM0QrV2lQLzdKVEpDdVJEbC92Mnl4NXQ1RnRIR0hENkk2cUhrVWxKQ2ZjQ1pXVEdlUjJZWW05Zkc3Qm9ICjJwYVROMkVDZ1lFQXRUQ2o1M253M213RDE1ZjAyZ2pKcWNjeHBkRk1lYlJpNUltMXJ5RUFaSzhwTmNlL2xNclgKVXM1KzM2eFpHWG1CR1ByMVl0UmxIVThQL1owWFdJM3ZDOFpLRHB6SnB4dnB6QmRFV0pUZGlPZEhpV2J4TzZOOQpiYjh3ZUM4STl4ZDlwd0cyMHdYNUVnR0krekdjMlNGa1VDTWROd1JkV3NSTWNCMklMeVV0MmZzPQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo= - tls_key_pairs: - - cert: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURlVENDQW1HZ0F3SUJBZ0lSQUlvWW1QRUhNV0wwZmp6VkZVZ2l2Ykl3RFFZSktvWklodmNOQVFFTEJRQXcKVmpFUU1BNEdBMVVFQ2hNSGVtRnljWFZ2YmpFUU1BNEdBMVVFQXhNSGVtRnljWFZ2YmpFd01DNEdBMVVFQlJNbgpNVGd6TlRZeE1UZ3dOVFkxTXprMk1qUTNNRFV4TXpRM05qa3pOREV5TmpNME56Y3dPRFkyTUI0WERUSXhNRGt3Ck1URTJOVGswTUZvWERUTXhNRGd6TURFMk5UazBNRm93VmpFUU1BNEdBMVVFQ2hNSGVtRnljWFZ2YmpFUU1BNEcKQTFVRUF4TUhlbUZ5Y1hWdmJqRXdNQzRHQTFVRUJSTW5NVGd6TlRZeE1UZ3dOVFkxTXprMk1qUTNNRFV4TXpRMwpOamt6TkRFeU5qTTBOemN3T0RZMk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBCjlzNGgrUTlpKzBlQ0c0VWNtSThFbEg1MHBlWmFkV2JzdzZDUStCZmF0em1NQWJEa016WGpSTHlNZy8xNFdSRGsKWTU4OUpCWVgrTzRBYXBRNno5MFRhTzhHamN1RmxvcWlFcTZOci9VTjJMYnc2am9KdTYvQ0dmcWIzNXZKT1NDdApKMWp5am5Cc2ZVNTRzRGFGcWpPRG1BL2l3YjNsSlZSV1pmYUdQSGZtRTRUcHJCSzdXV2FHbmlDZktUdGQza3lHCnkzWXpGZEJzSDU0OU9Lc1BFUlJOdTVCdlpzcmZWazRDdnlKNWVxREE1NlBaU1pmSVptZEk4VUdsRmk0V3lhMHEKUHRtWmg4bURGSnpVNnNXZWY5bTRqM3grMmF1UFEra2M3cjJneFdLZ2lTR1FBT2hLU0VhaEZDUW9UU3NzemVReApoZG9xamZUK1NsUWlQQlhJbDhTbzlRSURBUUFCbzBJd1FEQU9CZ05WSFE4QkFmOEVCQU1DQXFRd0R3WURWUjBUCkFRSC9CQVV3QXdFQi96QWRCZ05WSFE0RUZnUVVlSDJQTUhjRmwwTnkvQmozcE4xTExlSStPZTB3RFFZSktvWkkKaHZjTkFRRUxCUUFEZ2dFQkFMeU5aRXByOWtWbk5ORERiWWxWd0M1bnRlUEU2Z0ZQdGRjU3JjYmcyU01temtMMgppSjhCQnJ1ZVBmTllrMVE0c2xlN0FDeTRQL1dzU2xYZThqQkY0bm5KaUkxM2kvaUtQOEJzNVVIQWwwUTJ6RnlMCmp0Sk9JRlFuT1hiUmxQU1RQY21jcWdVUUcrL3lGOGhQVndHNnRwOVZoeXlCVkdlMDRlWU44eVNnbkZKTUloNGcKeDEzcytTWjE1RFkzSERnTGNCSjA5dXA4Q3NJdGV1RG05aG1jbGJ1bUc4OVEyQ3I4T25TcmYzTDNFSVhyelZBbwp3eEUwN21IWnkxSjBvNnljdWJXOWVuS2J3bTRKRHRhaHc4QzlERitvQXJlUEdaSXJXdVZpWFZYeTV6S2NOQW9LCjVXY0Q5RHdjcTFFUnVreGNFWWlrV05BV1FFNnVaMGVYZ0pKWlJ2OD0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= - key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb3dJQkFBS0NBUUVBOXM0aCtROWkrMGVDRzRVY21JOEVsSDUwcGVaYWRXYnN3NkNRK0JmYXR6bU1BYkRrCk16WGpSTHlNZy8xNFdSRGtZNTg5SkJZWCtPNEFhcFE2ejkwVGFPOEdqY3VGbG9xaUVxNk5yL1VOMkxidzZqb0oKdTYvQ0dmcWIzNXZKT1NDdEoxanlqbkJzZlU1NHNEYUZxak9EbUEvaXdiM2xKVlJXWmZhR1BIZm1FNFRwckJLNwpXV2FHbmlDZktUdGQza3lHeTNZekZkQnNINTQ5T0tzUEVSUk51NUJ2WnNyZlZrNEN2eUo1ZXFEQTU2UFpTWmZJClptZEk4VUdsRmk0V3lhMHFQdG1aaDhtREZKelU2c1dlZjltNGozeCsyYXVQUStrYzdyMmd4V0tnaVNHUUFPaEsKU0VhaEZDUW9UU3NzemVReGhkb3FqZlQrU2xRaVBCWElsOFNvOVFJREFRQUJBb0lCQUhkODZ1TzYrRS94bWVNYQorZkkrWTVoRTlOS1JDTUNJT1I2cE1TWjczZzhSRkdDSk5LSTZkN0tDbW9FWWlWaU5uaFZCTmdldmpxR2RFS1NJCjZVUlRveDhOZ2gzS0ovM3ZWbkkzQWkvck0yMzFmQVBhWDNYM3JNQ0pIVWdRRTBiT05DYTFvSkVuaXM3TDNCQnMKQlNDVzJpSVhwcy9uMFBYV3RCR2ZYZlFPbEZ4ajdKbXdwdDlqYTYyankxa3hlTVdMemlqQUZ1QzRwRTl3WUVaVApGa0ovb2FVdzR4WXM5N0pnelRNUHFJSlUzMStNYTNoNGFPQ2lPK2RzSExhK2tRUkZIN0tHOUtRaWlRYzdrTmdGCnljN2s3L2s3UVJSbG1mZmZLN3E3YUtVNkNueHVxOG05UThob2Q5QVdjQ3ZyTm9jSmVjSzcvSzFzNlhMYXhSTFgKRGFLc0xRMENnWUVBK0lBOGNRVmcveU5xbGQ5c2lHZ0NETy9DVUNwM21uZjdxZTNQeEZIWHVSdFNzaHJheE9qVQpRVXFtbHV5VWRCZTZLQnA4ZWxoVmFlYlZsdFNNd2xyWXNpUlIxaTV0SDNnRGUybXRheE5VZ0xtTGoyZUhVWGN3Cmk1UW1yQ1AyTzY4V0xQZjg4SkkwQWtOWWx3em5aWUg2VEZKbFp0MkxoU3ZRTG1qeFArWDZTT01DZ1lFQS9rREwKNndJMjVoYU1DbTBSWitrQWM1T2FJcUx0OUNWeWNTaGdzblBjK2xBQll0ZVRkclhjVW1FaklQYW1uZ1pKZUpvSgpoUDNxaHBja1JVcWwrSldhN3lXRnJocTdyTHlpTVNBb0VwaXdQMkRUMkxROWFXR0lONjdwSU9ObWtpamU2NmNNCjBsd05hQTBtL3Q5ZWZUZ2RLOUpHYnNoaTVnRFFiTFVtMW5Gd1prY0NnWUFMenJ3UWVycnpKSkdwOFdYTXpYUmIKZlFEMG9pL3dyUWJPT2ppSEVZUjRqUzNPdkt2c2MwdXlsb04zNUdIaGFrYzBKSjRKaWl6MHpUMFUzNkNZazR4OApXbkZ4QmQrMWdSUlpSdG93bmtpRG5VMWVVUU1EQWZEU2tRV05aR0FNMGZMeHpBNit0NU8xRDlJanl6OHJlWk9WCkVNMDBxQTQ3RTZ2ZXFLbmQ2V1dORlFLQmdBa3Z6aTV2cGd3cVJHVWNDOFQxWms3R3hvcjUyQjg2T3loYmpTTGwKak5aK2pZNUV1ODlPUXVlM0dzM1dHNjhhQ3cyUWcwZUs1UzUzeDVlNVdzWGdvZmlDSXBKbjVPQVk4TU5WcGgwRgo1MWhpNTBTdFBvclFPMXZIdGlTNkVycTFQMWpFY0hJcFlWS2hKd2VPaXB0N3E1SXB4dUc1MjlqenJwUSs5MmhJCk1RZUJBb0dCQUkrNnE2OGFvdW41bE5sU3NoTVg0citoZlNtbFhXYmcvdU1OQXROdWhtZndmSE0zWmR3SU9ZWlYKRTloalFNQXh6RFduZkx1ajljRkJQM2NER0s0NytoU0U2N082eHBrYk9BYzk4dUlXZVEzb3lyWEd5akQ3TGdrYwpxajFRa2ZiZE4wMU1BdEN0MDhaSlRwZzR1OUdXUUVVQWY2ckJaKzJPN2ZVdEJuUG40TXpsCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg== type: host sub_kind: host version: v2` userCAYAML = `kind: cert_authority metadata: - id: 1630515579836524000 + id: 1736815462679182000 name: me.localhost + revision: ea729b7f-99e0-4330-a46d-71c8dda9d3f7 spec: active_keys: ssh: - - private_key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb3dJQkFBS0NBUUVBMnZ1ekRQRHZWTElYZTdicDZIc1ZiM3NHak0xZ3lFa2hkWVBUMVVzZ01Kd1JuL1VSCk5EQTZST2pya2NUSEhyRXhnL002dVlQaGN2K2UweUFOZk9JMXROWVgvQ3hGcWdCcGFpRE5YRGpRajdyV2E4RDQKWmNyNkdIVXoza3VDN0k0QTJaUlJXK2M3ajhlZDFEbTlzZ0lpOW1BU3NXL0M2RTZTblEvVGlXVk9hTEdqdEVTdwo5L0lpenc1S2pPYnJLMGRXUXZiMXY1SW8rTUpVbko1NE5jWUlMRm9pYk9WeDdQU1FzWCtDK1JwQ3BIbFIrWnNWClVmSzFrd0l4eXg1Q25BTEMzcnlkOUFaSnY2aVdoci9uczZyWmU5b21xMHd6VUpnT045VE5aQjdZTjRhUmlYSmMKNkpsZmpjdUpnZ2ZDbVZaSWNyRm9wd3kzdnp4LzBxNVVCOVRNRFFJREFRQUJBb0lCQUhVNHkyNGdBMTJwUDl6ZgoyM0t4Z0pYK20xRUFGOURmSk9RTlAzWXNFdjB5YmxUY0VPdUk3WWc1enZCbkQ5Z2tMa2RlQ28rSVEwVVdCT1VyCmdVemFvcms4NmZYNWxRa2QwMUFXWXhmODZkZ213ZVZJbFMrWWFpeHhnT1I4TTRlQnRIN0VZSkQ3eE95QWhNSTQKYm8wOWk0MnJmQll6cDNoSHAwQWdXckp2NG5zenJtVGl2d2s4b0JRS2pGbDZ5VjU2L0g4K3VxaWlSS28vRDlPTApXSU51M1JXRTd4RVpJdlNBZlFMYUFyVG1XaXVVMkhrTklTSmJqRGxrd1phMmtjQ1VQUnVkbFJsOWw2WVM0ZUpSClhNU3RaVmQrcVRpVHhFc29TcTBjRmI3dTlYcEs0a3U3TXR5dDFHY0V0MnIvQzRrcXJFNFAyK3c3RmkvalN2VjYKdUZoWW41a0NnWUVBM3VuK0JMN21hSUhsOGxNclVrcG5SUFJNenllOGFyREplbnM4RXYzTUNyVkxLR0p5NUV6cwppc2ZmVythYTJSejhGOFk0U09aZjZaTk9CS3RzOHFYbkVxL0RhVEgyY3NxMFZXUWxNOFZQNkl3SHpTemNXaThwCnVVRUFOTFg3aG9maTFmZERGNnE2cTFrcmJtdjREa085RGdnRVpxVUR6KzB1dWZhTFNWWG05TzhDZ1lFQSszeFoKTGRJdjVjbXNHWTZhL0xXVjgwRjZHMVMxYUVJVDlBdXNpTThFcnhybEZpbjRSL2dDcEMzSjJod0ZKYldzUjN0OApMVUgxdWxqdE82Mmk2enkzUUlJa1RFNDRveUo0V1RVSEpWQ0VEYXFvcldySklWWTZxMFBlWGs5VDVwa1dzRFpOCldGeDRKQzZhdDZDcEtSTEJPSHdoSm1mYU53K1daamVob251L1pzTUNnWUJpMGI2UFlnV0luTlZRYUxoU3diTW8KS1ZrSG1LajVieWZTU1dGblZlV25kWms4N08vYjc1SUpML1AvcktwR3g0ZW1EblNUTkxXZU9YUWpzODhYZnA2QwpkVEtlcHN5SE5QOWV2NGVTZk0wZzNUcjBKUWdHWHRRVFVSS0RTNDJXcFJUVkg4azVhN0ZYRnErZlF2UHpkdW9QCmwxUkVJTEVnOHhkOHp5UU9QYXVtTndLQmdRREprZXlrMW5DL3ZMcXRyV2k2bncwMmNjZmVlaklCQTkyY1lYTUUKSVBJL0s4NXN5bTBQdWxEYnFUdStEM0ZzdlVYOThaTWhiMW4yNStvV1NHRnFMVHN3Z0Y5NXJjU2x0UzVEU2thVQorUWt2THhlT0VDWndDdjV4WWErdFplWDQwY0dtc1krakFGTG5wVmNyVWFIa292eXVPb2dUa1hBTmEvZi9yQjFvCjc4a0ZJd0tCZ0Q1cHVRd3NodXRYdmNOOCs1bUZDc2d6YW5hckYxSllPdTE2MkhVU2ZPQ2k4aS9VRDNWSUpYQmwKbWpNQVN4elhRamFSa2dQZXNqTmtsTEoyekJsK3ZLaG1jb3NJelNOdzM5b1ZMcC9ObTBiRzlpZmdUdmlha1N6MwpHNFhLYUdNczdRQ3h4bjZsc2ptYTRxYlFlU3JwWmVSMXVtOXJ4TVhLaVdGSUtERXN5TUpNCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg== - public_key: c3NoLXJzYSBBQUFBQjNOemFDMXljMkVBQUFBREFRQUJBQUFCQVFEYSs3TU04TzlVc2hkN3R1bm9leFZ2ZXdhTXpXRElTU0YxZzlQVlN5QXduQkdmOVJFME1EcEU2T3VSeE1jZXNUR0Q4enE1ZytGeS81N1RJQTE4NGpXMDFoZjhMRVdxQUdscUlNMWNPTkNQdXRacndQaGx5dm9ZZFRQZVM0THNqZ0RabEZGYjV6dVB4NTNVT2IyeUFpTDJZQkt4YjhMb1RwS2REOU9KWlU1b3NhTzBSTEQzOGlMUERrcU01dXNyUjFaQzl2Vy9raWo0d2xTY25uZzF4Z2dzV2lKczVYSHM5SkN4ZjRMNUdrS2tlVkg1bXhWUjhyV1RBakhMSGtLY0FzTGV2SjMwQmttL3FKYUd2K2V6cXRsNzJpYXJURE5RbUE0MzFNMWtIdGczaHBHSmNsem9tVitOeTRtQ0I4S1pWa2h5c1dpbkRMZS9QSC9TcmxRSDFNd04K + - private_key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcFFJQkFBS0NBUUVBbnBZd1JWUXhZS0VTWVJJZVdIQXhGRGtFNmRwM2R1MEFyUlNrSnlhRmlzVG9wRzlGCkV6SDRuRkpPU3prbW5rWVE2R2hJZ0ZxdFRURDhtVGt3bVJGZy9LQXViVTBrSmxNbldkQW54dHAreVkvRGNPUTIKV2dGN0o2MlVzSG85U2VDWnVCZG9WM3ZpaUw3cm9XVE1hTUYrZmhTMlN1bVZaUEl4U1l1aEtNcjlZK2dVVzhULwp2NUI4azA1MTVyTGxrVVU1aC81dm5YVEVWMVRmSTdFTmc0V3FZWVdOc2JDWkpjUEZ5RFMwU0pVdUtwbEt6RW9SCk80aDVTZzRkTnZDMFFoc1VvL0pUVmE1ZXQyUi9WQ0NXN1FjNHdhbklaQ2tGNXoxbHczcU9CQ0VSdlJRUW5zVk0KZm90eVh4VGY1M1hGdEk4ZE5yekJPeWVXeVlHNGFhR2doYytweVFJREFRQUJBb0lCQVFDQUVXK24vVWJtN3d6RgpvWGtxR0dnNkdaWHpPSDh6WmxBZWRrWGViQWg2T1d4YXBwVVUzRTBXQ0kyN3g4cDlGTDVBd1Q2VGtTYlU2Sk9GCk5aOGViZDl5QS9XYVJTckZYRyt4NHh6TVJOVVE5MjF3dEl1RUFpQXZ1Y2tTLzVTUkhiVmw2bGxVRlBLclZlczUKNmduOUt3MTR5a2N3bGhRVWNsWUZPNktKSyt5WGlhV3lpSXZLOU1RWlBEUUtEWG5sUitPeGw4VWsyTVk4NmdPYQo1a2l1M3lZbFZla0NiMjVETG5renhsRFVuQ0QvT2pSaW1uVDB2MjJnRzZ4Y3ZRdG8rSlBtYmxwaEZ0bk1hQTI2CkFSOW05YmVvWDVFRlArdDRNNzhEVEFRUFkvcW0rN29lTlMrRkRmL1N5YlJsWlBFaE43dTdTN3dZWmVUdGs4cGkKb2ZSWDRrd0JBb0dCQU1YcXZHbmQzZ3Y1WGljRjh3SU5ISnBzd04rS01YVWN1NHZZN0NlOWVycllvb3djNnI5TApadnVRbWN0amdmdG5HWDhrSVRmNXdsenRjQ1gvNVJmam5OeE50bGJubE5qM0pQNDYxZWVHMmRKYTJzWWd0VE5DCnBpNE1QZTJ4M1QyZFV1N21UMEcyUnJJMW9Kc294b2JCMEQyYkJnVlIvV0thR240OWJpLzd3eXVCQW9HQkFNMGcKbmQ2SURMR2NiYVlhV0xJYUwyWDRFckJJTmFGRU9URVBrSHNMTUYxVUJJZXRNcDl4WGNLaTZZWHJlRUZva2xqeApWY0RDM2hzQ2VQK3hQY29icDZ5UG9Sd29yREpGcnVWTU04Wm1HWEI5ditWakpSeHpYUGdUSURUN0U4WEEzb3pSClQvT28vV0s0blFGUTdqMnFaMUdOMm51TzZtQ3JTUzRGSGJZMmNVSkpBb0dCQUt5QVVPSXhCOVVGN3lNeUUwRUoKYnBIR0VrR0Q4R0Z6dnA5QVhXeXh3S1BVSjdEWmoxMVYraGR2VEN5eXVWc0czSGt0WTJxblhObWo5YWlaSmZNeApac201VGlEbXpaeGhwTE9WVWxUdSt6RldFUEs1RlZYdFZHdzBMVkhjUWNudk1wYVkxQ0doSG5NN1BKV2Y3NUVLCm9sYmZwRnJFd0lYTmJTUDBwUEpiakJ1QkFvR0FReXN2QnJOZUZMcTRYTys3bzNaWGx2aElobGplMXRQVU5uQjIKU3hRNjNoU285eFNMd3hJSU5iZks2QU5XK1hRWWwrOU91VFFXTHBuOHJSMklzaW1rR2lsZUJDNTlWR2psQUVpWAptNXZMTUw2OG00eC9sblZnT0F0clBHNEs1M0prYlpBTXNpamY3L2VyMGNhQ2ZNYlQxaXl4SWt5R0N1bUxxUG9iCjVKS25PNkVDZ1lFQW9JTi9vd3ZqbVNIczRRV1hGMEpacHhsYmp4QW1FdXdkNXBBOEpiUitlc2VwZE9MYVNRK2YKM2lyL2lIZXgxem5mcHhyMUdqRS9rQmNCM0lrRTA0emhwRk5xTFUvYTI2bTBZMWI1RkxmVEtMNHpvTklXU3BuUApFKzVmQnkrSkhVczc2dkJWM2ZaY09WRjZqc0RpMjUyV0NoK2VrbFNVVWpLQmdpa1dNVVpDMnA0PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo= + public_key: c3NoLXJzYSBBQUFBQjNOemFDMXljMkVBQUFBREFRQUJBQUFCQVFDZWxqQkZWREZnb1JKaEVoNVljREVVT1FUcDJuZDI3UUN0RktRbkpvV0t4T2lrYjBVVE1maWNVazVMT1NhZVJoRG9hRWlBV3ExTk1QeVpPVENaRVdEOG9DNXRUU1FtVXlkWjBDZkcybjdKajhOdzVEWmFBWHNuclpTd2VqMUo0Sm00RjJoWGUrS0l2dXVoWk14b3dYNStGTFpLNlpWazhqRkppNkVveXYxajZCUmJ4UCsva0h5VFRuWG1zdVdSUlRtSC9tK2RkTVJYVk44anNRMkRoYXBoaFkyeHNKa2x3OFhJTkxSSWxTNHFtVXJNU2hFN2lIbEtEaDAyOExSQ0d4U2o4bE5Wcmw2M1pIOVVJSmJ0QnpqQnFjaGtLUVhuUFdYRGVvNEVJUkc5RkJDZXhVeCtpM0pmRk4vbmRjVzBqeDAydk1FN0o1YkpnYmhwb2FDRno2bkoK tls: - - cert: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURlRENDQW1DZ0F3SUJBZ0lRVENnQUVvV3BBa2U4YWdHandmVmtkVEFOQmdrcWhraUc5dzBCQVFzRkFEQlcKTVJBd0RnWURWUVFLRXdkNllYSnhkVzl1TVJBd0RnWURWUVFERXdkNllYSnhkVzl1TVRBd0xnWURWUVFGRXljeApNREV5TWprd01qRXdNakUwTmpjM05UQXlOREF6TnpBNE5qQXpPVEV6TmpNd056Y3lNemN3SGhjTk1qRXdPVEF4Ck1UWTFPVE01V2hjTk16RXdPRE13TVRZMU9UTTVXakJXTVJBd0RnWURWUVFLRXdkNllYSnhkVzl1TVJBd0RnWUQKVlFRREV3ZDZZWEp4ZFc5dU1UQXdMZ1lEVlFRRkV5Y3hNREV5TWprd01qRXdNakUwTmpjM05UQXlOREF6TnpBNApOakF6T1RFek5qTXdOemN5TXpjd2dnRWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUJEd0F3Z2dFS0FvSUJBUUM5Cjg5dFE1YTB0bzQ5dkN3dmxFTUpYTnBiYkpzUVIram96QzJScFFTLzZBSHlHbytueXRKUTZSclp6UWlZeTVkb2UKUTArUmhPTGM0R1Q4R0JQdTBrRmUwejk4Zlp4TC8wb2kvZ0trVTgrM0VOaDFuN1krbjV0RVBvbHZsZTBZUm5lWAp3NWpna1lDZG1TTjFMZXVqYW96OUpyYXVUMzRPSGwzdFNoZ3pBUkV1ZlBVVDJQNXlaQXNCdW9nYzBHd055MUo4Cml1UXpDb0tNektOM2ZidFhYU2llU3pubWxQeWMyeXpIcW1UZGdQNnVDNWFrVXpnT3E5ZGFjUkpxVWJRVXlXOUUKVk80MWRQK2wrMXdzNmdSaFNuK29Sc0JLOG1TVW1JNjc4VjE2b3RxT1I2ZDl5VnZKVTZSbjEvMWIzYk5ES3I2awpYSWwwR1FYczNtajd0QUEzVHNCRkFnTUJBQUdqUWpCQU1BNEdBMVVkRHdFQi93UUVBd0lDcERBUEJnTlZIUk1CCkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCVFovZGxCRDdncWpKTU9rR2laSitGL0NXbkh5akFOQmdrcWhraUcKOXcwQkFRc0ZBQU9DQVFFQXU4cVZUZTYzZnd4UkM3cFU2bzRscldSby9ldnB3VkhkV04yT1NES0t4UU5ISURhbQovRDlnamhtdnphQWFKY3E2UmdkaTNCWlRuZDhsSDYzUlZuVHk4RzljUTNTYmFBMHlSQzMyQnQ3bjh6aUYxTTNqCkFxck5zV0hIWkZydkJKWkx2UDBqbms5RmRtSmFYc3o0cGgyRndYQjFTUkdFT3lVcFAvSS9OeVUyNFovRGFvOG4KWlRSazAvbHBVUis2SGp0UGliUTdJejkxcWtxNmsxcEY0SXdlbG5xU1Vqc2FjLzBGa1lib1I0UHkvT1BUbmtIRgpVR2doRUFHRzNnZXFsaGI4Q3FUYmRwKzhLb0R6RzNBOUtRUURBWUlMNkh5Mm9nVEJmU241Uk5WY2pLdHI0QS9UClhnSnlUdjdHZ0FabkZHT1dMc3B2TDhJQVdGYmN4T2hwV2hEaDNRPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= - key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBdmZQYlVPV3RMYU9QYndzTDVSRENWemFXMnliRUVmbzZNd3RrYVVFditnQjhocVBwCjhyU1VPa2EyYzBJbU11WGFIa05Qa1lUaTNPQmsvQmdUN3RKQlh0TS9mSDJjUy85S0l2NENwRlBQdHhEWWRaKzIKUHArYlJENkpiNVh0R0VaM2w4T1k0SkdBblpramRTM3JvMnFNL1NhMnJrOStEaDVkN1VvWU13RVJMbnoxRTlqKwpjbVFMQWJxSUhOQnNEY3RTZklya013cUNqTXlqZDMyN1YxMG9ua3M1NXBUOG5Oc3N4NnBrM1lEK3JndVdwRk00CkRxdlhXbkVTYWxHMEZNbHZSRlR1TlhUL3BmdGNMT29FWVVwL3FFYkFTdkprbEppT3UvRmRlcUxhamtlbmZjbGIKeVZPa1o5ZjlXOTJ6UXlxK3BGeUpkQmtGN041bys3UUFOMDdBUlFJREFRQUJBb0lCQVFDWkFiTHBxUGdrU1JtaQpncTFrS0duQ3dwQWxtMFpZak0wUWpONm5BZ0ZaU2NjRTFVZi9Yb0gvcHpJVUNYYW5qUXB6VWhqbnlMak0zbHU1CnpOTlJqajlsMkpmTStZbEtsaXJyb053VDdnYmxHVWFqQ0xGT0pGWjNWRUIwaDduaDBmRkhhQ0RlMDVWY1hSeDQKcVRLa0FaSHI0S0ZLSzNJSWdXRjdZREc1OCtRWkl0N01BdDQyc1NrUlhaenNyaUVzVWxZNU9xT1dlVHlkYy93dQpDK292V1FlOUU2bnRSc0EvY25nS0M1bnp6T0pCano3SlVTMGQ2UnBGK1Zodk9SRlZ6YTZKMnpRRXJsWWtFdVVUCkJYdThsVmhhcDVOU09nd3ByZXVmb2tNZVY4eGRNdUxuVEthdHVjajIwT3JFRUlHZVFrb08yTzhTeDJtNitOS0kKbzBTT2kzU0pBb0dCQU5LVkk4R0JHQUpSUlV2NVBnVkNDQ1VHSkFBRmtxY0FMTFlaZ0NMZCtLYStBVW41L2VONwpWemR4b2VqNG1UcnFOb0RLTnk5b0N2Z1RBWTlWZ3RZZllpdlNQbW5ZZk9FbTJUR2pLRTJSYzhBd0R5UWdHWFJVCm5WOUVueHRUUHF5dU9tQTFqa0ladXBLeUU0b0drdTE4MDRVaTB2d2pJUWI3cDdML0ZGYksvaGlmQW9HQkFPYnIKclBrOHdicnBlVk9QWmVudzVzbjVhTUpjdDM3emt4dHZzejVSVWlsZnZtVkdja1lyMU41SGpmZjVVVGcwNmNWdgp1N0dGY0NLQmhncFdqSXM3dHZ4cDhUVFM1VEZaWHZqY2VhRC91ZkFiN3ZUVnR0L1hRMFUwQ28rcDdzMENKWlZKCjY2MUtUU1RCYlFtR0xYYmNqNmFYdVM3bzFJM1FRU1l4NW5LV1F5aWJBb0dCQUtBTWZocUtGVWRkb1g5MnRhNmwKV3k5WWxXLzJ6RmxsQnBaNGx5em83QjArK0JmVGl5V2tEc3V5NzgzemMvS1ZKRXVLWlpzQVJxWDVQQXhHZjZSaQpRZWp3YUVObUtMT3ZKUkJXNDBEaE5jcHlQRy9HZmRJdXBWVk5BR2h5UW9aWC9VSTJNaU1IRHdpRGs5b3AyTzNyCkc1QnF3VlNsRm1zS1JaRUQwZCtOZE1ZZEFvR0FkVDNQRXJQd1FHL3RzNmtvdTBBZVRRbWVVS0EyWWZSVkNpY0sKUUdlVmFZQTg4THAxcG43Mmt1eU5mZ3ROVzFZeUlwWDZHOFYrQzJicm9UQVVKMVRvTVB1eEJYclY5dHBEUitMWQp0ZzlnWGpJd2ZvcExVUmJBQnRESFUrMlpXdWp1SC8vcDhvKzQzeUo5czhvMkp4VVFzaXB5VVFqUmNqYjcvT0owCitGU21RR1VDZ1lBdU5XcFhrbVkzbGtRSEFpU3RlblhTT2Zqc0xsbm5XWFJoTDVBYTZqRVZRT3FnUldVQnZ2YWkKK1RQRTNUTHQ5MGwveTZOdjU0dDdrT1QvSlEvREU4WmFiMERlTjdBRzRwRjMwNkxpYlpZNmswc3M1UDNXME8vbAozekJzQ0lEY3BHOWw4bDZSNkUwdHN0Z0I1c25hOE4rRzA2V3Q1R0M0UitRSVd1YTVpUmtVTXc9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo= + - cert: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURqVENDQW5XZ0F3SUJBZ0lSQU1GY3prVVhnOFV4WnRBMkI1dStUUFV3RFFZSktvWklodmNOQVFFTEJRQXcKWURFVk1CTUdBMVVFQ2hNTWJXVXViRzlqWVd4b2IzTjBNUlV3RXdZRFZRUURFd3h0WlM1c2IyTmhiR2h2YzNReApNREF1QmdOVkJBVVRKekkxTnpBeU1qZzNPREUwTnpnM01qazRPVEEyTmpNMk1qY3hOREV4TWpRMU16a3lNakF6Ck56QWVGdzB5TlRBeE1UUXdNRFEwTWpKYUZ3MHpOVEF4TVRJd01EUTBNakphTUdBeEZUQVRCZ05WQkFvVERHMWwKTG14dlkyRnNhRzl6ZERFVk1CTUdBMVVFQXhNTWJXVXViRzlqWVd4b2IzTjBNVEF3TGdZRFZRUUZFeWN5TlRjdwpNakk0TnpneE5EYzROekk1T0Rrd05qWXpOakkzTVRReE1USTBOVE01TWpJd016Y3dnZ0VpTUEwR0NTcUdTSWIzCkRRRUJBUVVBQTRJQkR3QXdnZ0VLQW9JQkFRREdCK0c3UE1OR1FCYXUrQUJvL0xPNDdIMjQ5ZUpqeEhDRnlrWkEKeDMxYWphNWs3M1RLaWlFVmNBOXJxZ1FBWVJkcGZRdUU4cUR6SExPTGZFRTB5Nm9ERVhhNHJtV1hGam1wRjVlNApmTmYvdUZqMkJPMFI4N2JoQ2hOSHY3cUh5YU5vVjYxNXdKNStRMkVNblc4R2FoTEx5YnliZzRtZ2QwZEZkaHBrCnE2SXk5OFJTQlQ4WXk1aG5WT09YOTFJemFOWlpKQ2tHUWlkZ3d1R1lCRkdUcGNMQjhQVUVYOVZPNDVMYTFZYUkKTS96NDZ4TEdmcWVlWWdHZURObC96S3JDdVpZc0s2eHkrdERVek5ILzBWT3Jpb3c0aEhWbi9SdHV5eEJyZTRuNApwVHovVXRDWjVZQWVmTVBIWWo4UlBFWFlqTmg0MlY4bVpobkc4TWNVRFU2cWxUa3JBZ01CQUFHalFqQkFNQTRHCkExVWREd0VCL3dRRUF3SUJwakFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlQ3RTZrUEh2dFQKanMrUlRWSVVLclhBaDlKTmNEQU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFRb01lRE1xVUt2VFE0OHEyemRpbApQc3p2dzFNdlhveUxHZWw3L01wclVEK0l6THl2cU1DUzZmbnhvV0NSRy9SbjAwaHorS1BIc3gva0RubHVjNVhKCnNqYjEzMjRhdDVhQlB0NmRibUpUR0lqK1NnenlUWmQxVVpSdTgxS0xCRWlxa0FMUE15aG1LYUEzSXhsYnk5S2kKNGpQNWwwK2JwanNTR3ZNTzNaK0thY1JGQlN0c21kbkJXZEdSMW5Hck9mVlBPRWUzSDg5NTFkbWpFNVdrTnNEUgpUNXNjVXRDYzlCdDduNVU0S0k3TE53SFA3cWppc0dpbXZuTWlOcVFOdjIxS2VEZ3E0eko3SkxrcENNRzlxRDB2CnFTQWlnYXhWL2o5bTVWcWF3d3k2VDlsUDh2WHhoZGV3dkhSY0hrSTdNc2VFYnYwdGlyelRLdDlzTVM1UGd3czgKQ0E9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== + key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb3dJQkFBS0NBUUVBeGdmaHV6ekRSa0FXcnZnQWFQeXp1T3g5dVBYaVk4UndoY3BHUU1kOVdvMnVaTzkwCnlvb2hGWEFQYTZvRUFHRVhhWDBMaFBLZzh4eXppM3hCTk11cUF4RjJ1SzVsbHhZNXFSZVh1SHpYLzdoWTlnVHQKRWZPMjRRb1RSNys2aDhtamFGZXRlY0NlZmtOaERKMXZCbW9TeThtOG00T0pvSGRIUlhZYVpLdWlNdmZFVWdVLwpHTXVZWjFUamwvZFNNMmpXV1NRcEJrSW5ZTUxobUFSUms2WEN3ZkQxQkYvVlR1T1MydFdHaURQOCtPc1N4bjZuCm5tSUJuZ3paZjh5cXdybVdMQ3VzY3ZyUTFNelIvOUZUcTRxTU9JUjFaLzBiYnNzUWEzdUorS1U4LzFMUW1lV0EKSG56RHgySS9FVHhGMkl6WWVObGZKbVlaeHZESEZBMU9xcFU1S3dJREFRQUJBb0lCQVFDVUdFTGMxcFVtalRrcApnbmcwQzMrUU5QUFVoYlhYYkluRjFENXpwWHgrWXVSZndaL3k5QmZIdzNVVXpDR1A4d3dpTEl5WDBTZENpRjFSClhBd2Jvbyt6R2JWU2FjRzVtcnBtVlNsMm80NlpROURyczBWam5vSk9pMDFkNCtsb01RaE9PUHVYeU0vK2x2OFcKQXdxTG5ub09Bd0ZVdjZzRjRRM2d5WEQxaGxHWGtOZnlTWEI5QlkyQmZ0dGswREszMEVqeEd6NjJpVWRITEJObwpTUllEalpBRHZpeTZzamcxWVBFczc1UHc2Y0JSdzRteTF6MWRyRnlESHlMbVd1NWZlMzhMd3pWeXQ5SVc2N2tBCjgrRUVlZTU1c0RNdml5OUd1Zm1mMlNyV0J3L3BDSitNbkVTYkhNWDQ5U3U0Z01rTndPc3VlZjNrK1hHTmFrdU0KZFpsZko2MHhBb0dCQU8yMG9vcUxHS2hhUk15c2FEaWNESXNaWU5FTzRRc1FaME9iOVI5RTVqQmY4TmtnTkZIcApiWHF1aFJmSmNHN2pTZmN3NGRLOGx0aUVnek9sTVMzeUlJV2FSeEc3OXIxNTllaXB5ZDBtbTdTYXdtSkN6VmsvCmt1S1p3SE5wWnI3ckYvVWcrSkNQODMzSXBZS1YxWGNrZER5Q0RIY1J2aFVKT0VmZnlwWjR0bzNKQW9HQkFOVkYKandhOEdrcy8rUDRiRytXZExJOHZ6TFJxT3N4dEZ1bHNUNlBtcGxzYnF0OVZNK3hkd0RzMk5WeGNtK0g1TnhrZAo5bUVJMVljaDh2WFVyMTBiYllhTzNMU2lKYm1uK25vNDNOM3h2dEcvU2N4Umc5RjlQbm41NU54UzRrMGdKdWEwCjNUSmdidWt3UmtIbkpwZ2pUbERURjhrK0RmZytFRWtPSjk5ZTk3bFRBb0dBYkdpaWJLOE5XdEo0YUNRRkVEUlQKSUNrOTEzcUN0aW9QL215bE9WS1I3T1FFa3ZHMkN0bDd2YVRVUEVuNWhna1ExYlNzZVJEYmR2blFZSUJwVW53SAp5d2JXZk1jTnU5SmdqWERLQ0pzd0RnazZ0OWVoa1orRjNPU2tPYjZMUm0wdnF2TVRpZEt0Q09PMllEejNjdlBrCk15aFlpUUZGZ0pDSTQzYTBEVFlXZzhrQ2dZQlJvM25YaXlQSmtHaUE1T0d0NkplSkREUWhEOVVJTWU0bVZtYTYKQiszQVRId0JWNzB6aXNPdUp0Y1FUd2NBM29RLzRoOVJENitsTmRLcVZjcjNLaXVuNllJRXgxa0hrNHluUXFNUgpkcHVqOE1TUUtOZjcxaVNYVHBoVDJvcDBHWTJxbkt0YndGeFVlVDA3dHY4b0Y4Ty8zcjVwTTQ3bmF1S1RCSTh3CnkwcXFyd0tCZ0NHT251RjFGUU5LdW85b0g0YmhOVW1xbVhmYng5czMwQm1ZTmVHUWczZ1F5amVzYmh5MDdVV0YKWnkzQXZNYmdlL3pralpaSnZPcFN5QzlLWER2aVBGK2UwRG9WY0Z5VFI3TVlyLy9IcVBlVHcwVVVXZnlQb2FxWgp5QXI1cUU0MVR6NGsyR2FOYnN4R3hpU2J2cFdWa2gxMFdjdmpwdHRka1I3UW9RSlg2UU9xCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg== additional_trusted_keys: {} - checking_keys: - - c3NoLXJzYSBBQUFBQjNOemFDMXljMkVBQUFBREFRQUJBQUFCQVFEYSs3TU04TzlVc2hkN3R1bm9leFZ2ZXdhTXpXRElTU0YxZzlQVlN5QXduQkdmOVJFME1EcEU2T3VSeE1jZXNUR0Q4enE1ZytGeS81N1RJQTE4NGpXMDFoZjhMRVdxQUdscUlNMWNPTkNQdXRacndQaGx5dm9ZZFRQZVM0THNqZ0RabEZGYjV6dVB4NTNVT2IyeUFpTDJZQkt4YjhMb1RwS2REOU9KWlU1b3NhTzBSTEQzOGlMUERrcU01dXNyUjFaQzl2Vy9raWo0d2xTY25uZzF4Z2dzV2lKczVYSHM5SkN4ZjRMNUdrS2tlVkg1bXhWUjhyV1RBakhMSGtLY0FzTGV2SjMwQmttL3FKYUd2K2V6cXRsNzJpYXJURE5RbUE0MzFNMWtIdGczaHBHSmNsem9tVitOeTRtQ0I4S1pWa2h5c1dpbkRMZS9QSC9TcmxRSDFNd04K cluster_name: me.localhost - signing_alg: 3 - signing_keys: - - LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb3dJQkFBS0NBUUVBMnZ1ekRQRHZWTElYZTdicDZIc1ZiM3NHak0xZ3lFa2hkWVBUMVVzZ01Kd1JuL1VSCk5EQTZST2pya2NUSEhyRXhnL002dVlQaGN2K2UweUFOZk9JMXROWVgvQ3hGcWdCcGFpRE5YRGpRajdyV2E4RDQKWmNyNkdIVXoza3VDN0k0QTJaUlJXK2M3ajhlZDFEbTlzZ0lpOW1BU3NXL0M2RTZTblEvVGlXVk9hTEdqdEVTdwo5L0lpenc1S2pPYnJLMGRXUXZiMXY1SW8rTUpVbko1NE5jWUlMRm9pYk9WeDdQU1FzWCtDK1JwQ3BIbFIrWnNWClVmSzFrd0l4eXg1Q25BTEMzcnlkOUFaSnY2aVdoci9uczZyWmU5b21xMHd6VUpnT045VE5aQjdZTjRhUmlYSmMKNkpsZmpjdUpnZ2ZDbVZaSWNyRm9wd3kzdnp4LzBxNVVCOVRNRFFJREFRQUJBb0lCQUhVNHkyNGdBMTJwUDl6ZgoyM0t4Z0pYK20xRUFGOURmSk9RTlAzWXNFdjB5YmxUY0VPdUk3WWc1enZCbkQ5Z2tMa2RlQ28rSVEwVVdCT1VyCmdVemFvcms4NmZYNWxRa2QwMUFXWXhmODZkZ213ZVZJbFMrWWFpeHhnT1I4TTRlQnRIN0VZSkQ3eE95QWhNSTQKYm8wOWk0MnJmQll6cDNoSHAwQWdXckp2NG5zenJtVGl2d2s4b0JRS2pGbDZ5VjU2L0g4K3VxaWlSS28vRDlPTApXSU51M1JXRTd4RVpJdlNBZlFMYUFyVG1XaXVVMkhrTklTSmJqRGxrd1phMmtjQ1VQUnVkbFJsOWw2WVM0ZUpSClhNU3RaVmQrcVRpVHhFc29TcTBjRmI3dTlYcEs0a3U3TXR5dDFHY0V0MnIvQzRrcXJFNFAyK3c3RmkvalN2VjYKdUZoWW41a0NnWUVBM3VuK0JMN21hSUhsOGxNclVrcG5SUFJNenllOGFyREplbnM4RXYzTUNyVkxLR0p5NUV6cwppc2ZmVythYTJSejhGOFk0U09aZjZaTk9CS3RzOHFYbkVxL0RhVEgyY3NxMFZXUWxNOFZQNkl3SHpTemNXaThwCnVVRUFOTFg3aG9maTFmZERGNnE2cTFrcmJtdjREa085RGdnRVpxVUR6KzB1dWZhTFNWWG05TzhDZ1lFQSszeFoKTGRJdjVjbXNHWTZhL0xXVjgwRjZHMVMxYUVJVDlBdXNpTThFcnhybEZpbjRSL2dDcEMzSjJod0ZKYldzUjN0OApMVUgxdWxqdE82Mmk2enkzUUlJa1RFNDRveUo0V1RVSEpWQ0VEYXFvcldySklWWTZxMFBlWGs5VDVwa1dzRFpOCldGeDRKQzZhdDZDcEtSTEJPSHdoSm1mYU53K1daamVob251L1pzTUNnWUJpMGI2UFlnV0luTlZRYUxoU3diTW8KS1ZrSG1LajVieWZTU1dGblZlV25kWms4N08vYjc1SUpML1AvcktwR3g0ZW1EblNUTkxXZU9YUWpzODhYZnA2QwpkVEtlcHN5SE5QOWV2NGVTZk0wZzNUcjBKUWdHWHRRVFVSS0RTNDJXcFJUVkg4azVhN0ZYRnErZlF2UHpkdW9QCmwxUkVJTEVnOHhkOHp5UU9QYXVtTndLQmdRREprZXlrMW5DL3ZMcXRyV2k2bncwMmNjZmVlaklCQTkyY1lYTUUKSVBJL0s4NXN5bTBQdWxEYnFUdStEM0ZzdlVYOThaTWhiMW4yNStvV1NHRnFMVHN3Z0Y5NXJjU2x0UzVEU2thVQorUWt2THhlT0VDWndDdjV4WWErdFplWDQwY0dtc1krakFGTG5wVmNyVWFIa292eXVPb2dUa1hBTmEvZi9yQjFvCjc4a0ZJd0tCZ0Q1cHVRd3NodXRYdmNOOCs1bUZDc2d6YW5hckYxSllPdTE2MkhVU2ZPQ2k4aS9VRDNWSUpYQmwKbWpNQVN4elhRamFSa2dQZXNqTmtsTEoyekJsK3ZLaG1jb3NJelNOdzM5b1ZMcC9ObTBiRzlpZmdUdmlha1N6MwpHNFhLYUdNczdRQ3h4bjZsc2ptYTRxYlFlU3JwWmVSMXVtOXJ4TVhLaVdGSUtERXN5TUpNCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg== - tls_key_pairs: - - cert: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURlRENDQW1DZ0F3SUJBZ0lRVENnQUVvV3BBa2U4YWdHandmVmtkVEFOQmdrcWhraUc5dzBCQVFzRkFEQlcKTVJBd0RnWURWUVFLRXdkNllYSnhkVzl1TVJBd0RnWURWUVFERXdkNllYSnhkVzl1TVRBd0xnWURWUVFGRXljeApNREV5TWprd01qRXdNakUwTmpjM05UQXlOREF6TnpBNE5qQXpPVEV6TmpNd056Y3lNemN3SGhjTk1qRXdPVEF4Ck1UWTFPVE01V2hjTk16RXdPRE13TVRZMU9UTTVXakJXTVJBd0RnWURWUVFLRXdkNllYSnhkVzl1TVJBd0RnWUQKVlFRREV3ZDZZWEp4ZFc5dU1UQXdMZ1lEVlFRRkV5Y3hNREV5TWprd01qRXdNakUwTmpjM05UQXlOREF6TnpBNApOakF6T1RFek5qTXdOemN5TXpjd2dnRWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUJEd0F3Z2dFS0FvSUJBUUM5Cjg5dFE1YTB0bzQ5dkN3dmxFTUpYTnBiYkpzUVIram96QzJScFFTLzZBSHlHbytueXRKUTZSclp6UWlZeTVkb2UKUTArUmhPTGM0R1Q4R0JQdTBrRmUwejk4Zlp4TC8wb2kvZ0trVTgrM0VOaDFuN1krbjV0RVBvbHZsZTBZUm5lWAp3NWpna1lDZG1TTjFMZXVqYW96OUpyYXVUMzRPSGwzdFNoZ3pBUkV1ZlBVVDJQNXlaQXNCdW9nYzBHd055MUo4Cml1UXpDb0tNektOM2ZidFhYU2llU3pubWxQeWMyeXpIcW1UZGdQNnVDNWFrVXpnT3E5ZGFjUkpxVWJRVXlXOUUKVk80MWRQK2wrMXdzNmdSaFNuK29Sc0JLOG1TVW1JNjc4VjE2b3RxT1I2ZDl5VnZKVTZSbjEvMWIzYk5ES3I2awpYSWwwR1FYczNtajd0QUEzVHNCRkFnTUJBQUdqUWpCQU1BNEdBMVVkRHdFQi93UUVBd0lDcERBUEJnTlZIUk1CCkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCVFovZGxCRDdncWpKTU9rR2laSitGL0NXbkh5akFOQmdrcWhraUcKOXcwQkFRc0ZBQU9DQVFFQXU4cVZUZTYzZnd4UkM3cFU2bzRscldSby9ldnB3VkhkV04yT1NES0t4UU5ISURhbQovRDlnamhtdnphQWFKY3E2UmdkaTNCWlRuZDhsSDYzUlZuVHk4RzljUTNTYmFBMHlSQzMyQnQ3bjh6aUYxTTNqCkFxck5zV0hIWkZydkJKWkx2UDBqbms5RmRtSmFYc3o0cGgyRndYQjFTUkdFT3lVcFAvSS9OeVUyNFovRGFvOG4KWlRSazAvbHBVUis2SGp0UGliUTdJejkxcWtxNmsxcEY0SXdlbG5xU1Vqc2FjLzBGa1lib1I0UHkvT1BUbmtIRgpVR2doRUFHRzNnZXFsaGI4Q3FUYmRwKzhLb0R6RzNBOUtRUURBWUlMNkh5Mm9nVEJmU241Uk5WY2pLdHI0QS9UClhnSnlUdjdHZ0FabkZHT1dMc3B2TDhJQVdGYmN4T2hwV2hEaDNRPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= - key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBdmZQYlVPV3RMYU9QYndzTDVSRENWemFXMnliRUVmbzZNd3RrYVVFditnQjhocVBwCjhyU1VPa2EyYzBJbU11WGFIa05Qa1lUaTNPQmsvQmdUN3RKQlh0TS9mSDJjUy85S0l2NENwRlBQdHhEWWRaKzIKUHArYlJENkpiNVh0R0VaM2w4T1k0SkdBblpramRTM3JvMnFNL1NhMnJrOStEaDVkN1VvWU13RVJMbnoxRTlqKwpjbVFMQWJxSUhOQnNEY3RTZklya013cUNqTXlqZDMyN1YxMG9ua3M1NXBUOG5Oc3N4NnBrM1lEK3JndVdwRk00CkRxdlhXbkVTYWxHMEZNbHZSRlR1TlhUL3BmdGNMT29FWVVwL3FFYkFTdkprbEppT3UvRmRlcUxhamtlbmZjbGIKeVZPa1o5ZjlXOTJ6UXlxK3BGeUpkQmtGN041bys3UUFOMDdBUlFJREFRQUJBb0lCQVFDWkFiTHBxUGdrU1JtaQpncTFrS0duQ3dwQWxtMFpZak0wUWpONm5BZ0ZaU2NjRTFVZi9Yb0gvcHpJVUNYYW5qUXB6VWhqbnlMak0zbHU1CnpOTlJqajlsMkpmTStZbEtsaXJyb053VDdnYmxHVWFqQ0xGT0pGWjNWRUIwaDduaDBmRkhhQ0RlMDVWY1hSeDQKcVRLa0FaSHI0S0ZLSzNJSWdXRjdZREc1OCtRWkl0N01BdDQyc1NrUlhaenNyaUVzVWxZNU9xT1dlVHlkYy93dQpDK292V1FlOUU2bnRSc0EvY25nS0M1bnp6T0pCano3SlVTMGQ2UnBGK1Zodk9SRlZ6YTZKMnpRRXJsWWtFdVVUCkJYdThsVmhhcDVOU09nd3ByZXVmb2tNZVY4eGRNdUxuVEthdHVjajIwT3JFRUlHZVFrb08yTzhTeDJtNitOS0kKbzBTT2kzU0pBb0dCQU5LVkk4R0JHQUpSUlV2NVBnVkNDQ1VHSkFBRmtxY0FMTFlaZ0NMZCtLYStBVW41L2VONwpWemR4b2VqNG1UcnFOb0RLTnk5b0N2Z1RBWTlWZ3RZZllpdlNQbW5ZZk9FbTJUR2pLRTJSYzhBd0R5UWdHWFJVCm5WOUVueHRUUHF5dU9tQTFqa0ladXBLeUU0b0drdTE4MDRVaTB2d2pJUWI3cDdML0ZGYksvaGlmQW9HQkFPYnIKclBrOHdicnBlVk9QWmVudzVzbjVhTUpjdDM3emt4dHZzejVSVWlsZnZtVkdja1lyMU41SGpmZjVVVGcwNmNWdgp1N0dGY0NLQmhncFdqSXM3dHZ4cDhUVFM1VEZaWHZqY2VhRC91ZkFiN3ZUVnR0L1hRMFUwQ28rcDdzMENKWlZKCjY2MUtUU1RCYlFtR0xYYmNqNmFYdVM3bzFJM1FRU1l4NW5LV1F5aWJBb0dCQUtBTWZocUtGVWRkb1g5MnRhNmwKV3k5WWxXLzJ6RmxsQnBaNGx5em83QjArK0JmVGl5V2tEc3V5NzgzemMvS1ZKRXVLWlpzQVJxWDVQQXhHZjZSaQpRZWp3YUVObUtMT3ZKUkJXNDBEaE5jcHlQRy9HZmRJdXBWVk5BR2h5UW9aWC9VSTJNaU1IRHdpRGs5b3AyTzNyCkc1QnF3VlNsRm1zS1JaRUQwZCtOZE1ZZEFvR0FkVDNQRXJQd1FHL3RzNmtvdTBBZVRRbWVVS0EyWWZSVkNpY0sKUUdlVmFZQTg4THAxcG43Mmt1eU5mZ3ROVzFZeUlwWDZHOFYrQzJicm9UQVVKMVRvTVB1eEJYclY5dHBEUitMWQp0ZzlnWGpJd2ZvcExVUmJBQnRESFUrMlpXdWp1SC8vcDhvKzQzeUo5czhvMkp4VVFzaXB5VVFqUmNqYjcvT0owCitGU21RR1VDZ1lBdU5XcFhrbVkzbGtRSEFpU3RlblhTT2Zqc0xsbm5XWFJoTDVBYTZqRVZRT3FnUldVQnZ2YWkKK1RQRTNUTHQ5MGwveTZOdjU0dDdrT1QvSlEvREU4WmFiMERlTjdBRzRwRjMwNkxpYlpZNmswc3M1UDNXME8vbAozekJzQ0lEY3BHOWw4bDZSNkUwdHN0Z0I1c25hOE4rRzA2V3Q1R0M0UitRSVd1YTVpUmtVTXc9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo= type: user sub_kind: user version: v2` - databaseClientCAYAML = ` -kind: cert_authority + databaseClientCAYAML = `kind: cert_authority metadata: - id: 1696989861240620000 + id: 1736815462678741000 name: me.localhost + revision: 2ab94406-c75b-4894-bc63-04191d54c15a spec: active_keys: tls: - - cert: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURqVENDQW5XZ0F3SUJBZ0lSQU5XcUtsOWR3WGYrVTBWUmhxNGEyaTB3RFFZSktvWklodmNOQVFFTEJRQXcKWURFVk1CTUdBMVVFQ2hNTWJXVXViRzlqWVd4b2IzTjBNUlV3RXdZRFZRUURFd3h0WlM1c2IyTmhiR2h2YzNReApNREF1QmdOVkJBVVRKekk0TkRBd09URXhNams0TlRBek1qYzRPVEV3TURJNE5qUXlPREV6TmpRMk9UQTVNamt3Ck9UQWVGdzB5TXpFd01URXdNakEwTWpGYUZ3MHpNekV3TURnd01qQTBNakZhTUdBeEZUQVRCZ05WQkFvVERHMWwKTG14dlkyRnNhRzl6ZERFVk1CTUdBMVVFQXhNTWJXVXViRzlqWVd4b2IzTjBNVEF3TGdZRFZRUUZFeWN5T0RRdwpNRGt4TVRJNU9EVXdNekkzT0RreE1EQXlPRFkwTWpneE16WTBOamt3T1RJNU1Ea3dnZ0VpTUEwR0NTcUdTSWIzCkRRRUJBUVVBQTRJQkR3QXdnZ0VLQW9JQkFRRGlDNU5GVDhmUy9hSzdSSVVRVnFjVmFxaFBzMFNuU0prTmd3azEKUHZkeFV1OWZZMlNwek5NaUUzSGZlb0Y4S1h2YUU0aHJzMEFGOVRmYlpJTnM1RjNHNTNzOUg3Q2JXWHpOWVRtZApCN0gyWEVxVGp3N0xGL2pzYzkwcTN4ZnZqMkk0Z29tOUdYK3dGMXdaRldjZXVJRkJTdXdCRkV6a1Yzc1o5NEVqClBsWUIxK2lnNlJoWGhvUjdhRlJUNDFvZmtMUUovMDdBVmR4blUranp5VkVFSVk3SjUwUWU3bFc2Nk9wL3BncmwKR1FBSnkwbnowUVpVYVJjVmZrODVHK3NwMnhjcUJ6clJHbXNybmw1TmhMdGJqcUJIUkZ2cU5XS1pLa1V2M0NjUApiTytWT1krV1FmV0UzRThhekxUQ2ppcnJXYWVXeTNLR0RTZGF5YktOK0FKbVpqU3hBZ01CQUFHalFqQkFNQTRHCkExVWREd0VCL3dRRUF3SUJwakFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlFhVmMzdXlYWnoKdDBWLzFnNzE3MzMrRjFhaHNqQU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUF6NTVkVnVFdmVLdnJtYThzL0dWSQo2Q0t5akNNYXNjWmhwV1JIT3QxRjQ1T0pjcXg1RDBQeVhSenZXS2NTYzlZTkN0M1BzSi8yNGp3VDlLaElqK2NiClQ5Z0h5WXNkb3pWY2NzMXNZTkFjK3VFSmRSOEsydHJqa1JJN0Q5VmZvTEJJVFlHUkJGTWpSOEE1bENlUzVnTkgKRG42V09rSlpRUi9UQS9IbFFlUmttMW5teUp3VVVQOVA0aUVWVlVSS0lMRVVNTS9EdERXdTZuNnM2K0pVVXNDNwp5QmI2T3JQeVRGbkV4TFljN2RhYUM1bm5UVDZHY2xUSm4wYkJ2UmtXdUFVa1FtWXJyYkpBMnhEVjFBL0JOcmp3Ci9aU2ErU1ZlVWJxSW05ZEVESE4zQUhXcmJzbWwyVjI3YUtrMHVUK0JmeUJBZ3NSdGpMN0U2YUdJanlNcStlOW4KYmc9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== - key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb3dJQkFBS0NBUUVBNGd1VFJVL0gwdjJpdTBTRkVGYW5GV3FvVDdORXAwaVpEWU1KTlQ3M2NWTHZYMk5rCnFjelRJaE54MzNxQmZDbDcyaE9JYTdOQUJmVTMyMlNEYk9SZHh1ZDdQUit3bTFsOHpXRTVuUWV4OWx4S2s0OE8KeXhmNDdIUGRLdDhYNzQ5aU9JS0p2Umwvc0JkY0dSVm5IcmlCUVVyc0FSUk01RmQ3R2ZlQkl6NVdBZGZvb09rWQpWNGFFZTJoVVUrTmFINUMwQ2Y5T3dGWGNaMVBvODhsUkJDR095ZWRFSHU1VnV1anFmNllLNVJrQUNjdEo4OUVHClZHa1hGWDVQT1J2cktkc1hLZ2M2MFJwcks1NWVUWVM3VzQ2Z1IwUmI2alZpbVNwRkw5d25EMnp2bFRtUGxrSDEKaE54UEdzeTB3bzRxNjFtbmxzdHloZzBuV3NteWpmZ0NabVkwc1FJREFRQUJBb0lCQUQ5R01EWkJxOVRDek0rUQowWktPUHZ6K3V4aDhQT1o2cXVVZVhmQjZyTGNiR1FoaGdTY0t2N3NWS0ZYL0s4bStydjJQWkN1SnBJMUdaQmxVCm5IbFp2MnBURjZzM2VLOHpzSHlwRDRDR1MrbURVaGpWL2JVYUE4TGtkKzl0UFgwQWJPVVduVW5Dbm55RFBYT0UKQ3phTlBSa3l5TGRRb0dsMmwyM2dXMVNyT1ZZUVBEUjZncWVJZVFYa3pHYUFUQ2twZWYrOVk4US9pTkZUR05oZAppamtXSUZOdEYzQjdIODUwdnR0VFFRckE3QXQ3ZnN2bmo2YVVDUkQ3MmFYZGJmeHIwK0VQbUR6WGNhejM3U20yClg3ZkJrakRFa0pCa0gwVnBnZHdvMDh3cmtzbnBieUNpbE95alp4Z3lhUWw2NGFKcGVUN1FHbEMxcm1kUEFmTU4KSEdweFBwVUNnWUVBK21vbllBVW1oSVpTR0R6VjI0NFc0QVRnVFdGb2gxb24wKzlZZ2xxR1RUZFFBM2dXYy9ReQowSmJ6QXpOVFZnODNibWhvU3NtbUMwZ1BoSytBb3BCZXc5ZlVxMmhIOVptUzVjZE1CaTJ6cFdvZHQrWXMvNys1Ckk3d3d2bGgvY3llelQvU0ZyazVCVVB0azZFR1pLZk1KdGZlNDcvb05uUzRmc3lmYlAyWDVUWHNDZ1lFQTV4WkcKSmhiYkwwWFljL0plc0JucXBuRFZHNXhkbkh6aGx0aVB3QzdGbHRDRUpuNFdhTUNpSUtsL0o3VGUzbndqMHk0YQpSVzFTWGN6anc5dHZxY0V3aE9CQUZBUHlsd0FWWjUyOTRzdWZzMnk4SHBFcFhhMjlIRXNReW50TE9JRFZyYkVsClJCV1pEb0xhbllVRTNtWml5WnZ0ZU9TT0hTajVhUnIzRTg1UmtNTUNnWUFweUVLUG8reGNXbWtpUUN4U3VPK2EKSzFZZHN5NFV2M2M3eG9qWEh6R2ZlcVl3SGY1cEZJclNBUTNGTC9Bc3dOYzM1ZFhZL0xKbTJYdzFZRzh2TUxXUApLZGtEVEtBTkc3WEYveTN4TGZqMmxiRWx1Uk16RFJOZ0lndGtCeklremEvK25FY2Q0VkxHcDF1YjRTNGtNTGdqCkU1VlkvVGorUys3Z0hydFhaYlZtTndLQmdET3A2eTBBMXlnT2VZSVNvZERGT296VGxSR0ROL3FRZ083MG84N1gKcGgwOXFRM2lDcWlJeUxaOHJvejJCdzIrdTFPdmJ2Z3VwTWVMMHpBcWt5QmtyTEJJWW9zWEJ0bHpqMVdIRXJqdAp4VnFiNk1MOHVUN1VaUDg2V1JxcnpmbG45RjNNeVFRYndBaGFnUDNPaTNRZGQrQ1RGOWg3WUxwc09yYWc3TFJrCjRCOTVBb0dCQU9maHNVSzVSZm1RU1ZzN08wMmMrdWFVelB2dnEwaXNqNW45dWlOaFQxdjFDUGY4YStZdkkyTisKcWV5bHkwRjN3L2sxbElaUzFjWlMwRDVWMUd6bmVHTUgreWYwVFAvNmlUcElHTC94N1pTNGJEZjE3dEc5dklDdgoya1JBTno5WHpzVzFETm9CRkJmZXg5NDFmT0RzdHlvdThvYmF3dDdJWThTdU1GMHV3aDlBCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg== + - cert: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURpakNDQW5LZ0F3SUJBZ0lRTjlDcHA4VkYzQUpuWGFnbk5kVHVkekFOQmdrcWhraUc5dzBCQVFzRkFEQmYKTVJVd0V3WURWUVFLRXd4dFpTNXNiMk5oYkdodmMzUXhGVEFUQmdOVkJBTVRERzFsTG14dlkyRnNhRzl6ZERFdgpNQzBHQTFVRUJSTW1OelF4T1RBNU56ZzFNelF4TWpRM056VTVOVEl5TVRZeE5UZzBNalUxTURjME9URTBORGN3CkhoY05NalV3TVRFME1EQTBOREl5V2hjTk16VXdNVEV5TURBME5ESXlXakJmTVJVd0V3WURWUVFLRXd4dFpTNXMKYjJOaGJHaHZjM1F4RlRBVEJnTlZCQU1UREcxbExteHZZMkZzYUc5emRERXZNQzBHQTFVRUJSTW1OelF4T1RBNQpOemcxTXpReE1qUTNOelU1TlRJeU1UWXhOVGcwTWpVMU1EYzBPVEUwTkRjd2dnRWlNQTBHQ1NxR1NJYjNEUUVCCkFRVUFBNElCRHdBd2dnRUtBb0lCQVFEQzMyUDdINUs2T2tYZE1Hb3NsWjhMMDR2eWRMSGxYRGhEcHEvMnVTYW8KcVA2MjMyaTd3MXE1VThPblVPWFA0Nm5OcWFpclFMUkpHczZuaGsxdGNwMEZkQVlvRGhGdkVuVnc1WmVxVzFZSQo3YlpGKzQvM00xTnk2VmU1cy84aTJXRkdkd04xaHhKTE9VcENIRm5jTmlkYkFzL3hFSzdVaWdWVnprMmx6bm5QCkIzeVU4Y1hneCtuZ3lIbncwcFRwcjdIdFJjdW9TbkROSkthN1I3YkwwenN3aVB6V1RXbGhYaE44LzJCMUJ4MnEKSkZVRVltS1Znc2lXK2ErUTBJbW1PVm9JNXF2QjRRdE11NHVzWWc0enovS3NhMExWQnVwUWVwL2lleXlka211cgp6K0p6ckIxU3BtTDRGY21YTnIvUHFBbWtENmNkQ2lWVHNkNDNBdGxSak9NUEFnTUJBQUdqUWpCQU1BNEdBMVVkCkR3RUIvd1FFQXdJQnBqQVBCZ05WSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCUVp6cGh0aHVQdjlLdUMKd0d6c1ZrKzU0NkRMN2pBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQWlOM2lMeWdyZHVVU3MzYS90cS9NKzJmbwo4K0EyaWZYM2dOc0Yxa2l6NUhnczhvbnNOWmhSSDgrNU1ZSXVoSjNDYllGSHdCM29QNmdPSUdVWVlwbnExTTViCnR6WThycXZMaWpEZEpHUHR5YTRsVFhmY25saGljRE0yeE85WUpVT2xEVjZZdWNRV0VpdVpHajRnNUd5SVYwVkMKalhQV2puKzl0eG9yRG4yZWpqNkdwWnFGRlBkRjNwN3lGUCtaRFcrSDN6Y0lMNUxENDBoeHNGSlhRenYxR2N3UQpHd1hjMjBwekMvUGMrVzU1eEpTemp1ZXVnUUJVWVg4UDJVOUw0a3VZeU5qeXJMOXhGSGtFUVNQNEhhTDlpamdlCndVdkd6QnpnU2c5UFZVRldtMVVVTHdoN3BRQ1JlSFhBQnpLd3ArbTJpemxSRHRzUXdxeXhKbXJZeXNaUW9nPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= + key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcGdJQkFBS0NBUUVBd3Q5ait4K1N1anBGM1RCcUxKV2ZDOU9MOG5TeDVWdzRRNmF2OXJrbXFLait0dDlvCnU4TmF1VlBEcDFEbHorT3B6YW1vcTBDMFNSck9wNFpOYlhLZEJYUUdLQTRSYnhKMWNPV1hxbHRXQ08yMlJmdVAKOXpOVGN1bFh1YlAvSXRsaFJuY0RkWWNTU3psS1FoeFozRFluV3dMUDhSQ3UxSW9GVmM1TnBjNTV6d2Q4bFBIRgo0TWZwNE1oNThOS1U2YSt4N1VYTHFFcHd6U1NtdTBlMnk5TTdNSWo4MWsxcFlWNFRmUDlnZFFjZHFpUlZCR0ppCmxZTElsdm12a05DSnBqbGFDT2Fyd2VFTFRMdUxyR0lPTTgveXJHdEMxUWJxVUhxZjRuc3NuWkpycTgvaWM2d2QKVXFaaStCWEpsemEvejZnSnBBK25IUW9sVTdIZU53TFpVWXpqRHdJREFRQUJBb0lCQVFDUHdqTEV3RDhEQ1JnZgpHNmRINnJ6aEFaZTlMbDlLUDZUMksxS21aV0ppakFFVU1XM1hEait3ZGwzZzRhb1htZkRiV3F5bVlWNWVpOXNsCjlNckwwZ0NLVkZSeVdpWjhWUmEwU1h1QVhrN3kyVUpkRUQ3ZGMweTllZXlRZjN2Wlhwb0hYS2I5bmI1ZUpnNWwKQlBzNW0rMmVrMDJKbmZBTHRTSkljYUFRa0dpRjA4bFNNU2NhaVNDMHJ2cmRkYzhvTlhJYUN2dVFTbFNSV2wxWAo2TzVjQ3R0YzVlc2xmUkJ0S3dhbHNaalVTeUd5c3BQMGpLd2JpY2tvQnhya2ZvRXcrVGgzYTM5ejI2dGFLeXhyClJCbTJNZVJUMVpCTEpkOUpmamx1NjAzY3dmSjk1TlZZTjZYZHRZV2pPc0szdWtYNTBaUnhBWVAyYkNzbTFSdUoKU1hKYmE5MkpBb0dCQU1iOWRuYkpFN0dWVktkcGRlMUlyMG03WGxuQVJvTDJXRnlUdWlQenAwSWM0dHRmWDFqSgpQOTdiYXNmTkRzSkFIM2FJQWdsRThQQ2VMckFuV3d2UERDZzByMkdDTG9ZWk9VM0RGM1NjZ0ZtVVRzQllWZGRqCkN6eFJTSDJEcm0wSmR2NnVSR1JSNHpHcDFMK1dzNWJqRWpkaHpkRUU2QzJDL08zbE5BeG5sbzE3QW9HQkFQcXoKOEtsa0MvNm5YWnRSOStSV0xJb21SKzc2dG5hUjB6SXVyY0FQSExNcTNjUC8yUzBneHBGd1oydmpGRHhQMkJjMApydXlNUXV3bS9GSlJtT3JKL3JaYkFjK0hYQ2JOUk9FdjhNa042cjJINldhelBZOWRWK2ZmdXZiR1VJRkEzOGVzCjM0dEVpQ1ZHMFZSZnJpOEtHaXQ2TmRKdUwrMlVkVkp2VVRiWG1RcDlBb0dCQUxvSE1yeVI5c3RKNDc0dXBZU1QKTXV3bk1tbU5pMTNibDNmVTAydlEyVWpCWUlQZGdYR3JrdjV3K2o2WHdYaHdJZm5aNUsxdHVpSDRmNFZIQmFMZwppV2o4K0FpY2Y0bjJBdEJqMW9XNTJYUGxaa29EU3h6MUJ3ZjRwV0JSdnJ0STRlbnVXUm5BUkRtbG43TU0zQS92CmNKUTk1di9GS3BtQm41dDNiMVU1Y2xJSkFvR0JBSUl1VStheDArU3RKZGRVYmdPOGw2NDVDSnRZeHN5MUZsVDEKbGpXbjQwQktIeFA2MDl3eUs4b3o4eEE3dnpNK1JyaHVHL01yTmtrSVNYZTVkVTFlREl6R254OFRhOCtlUVlrcAphc0FNSVB2QUNudlEwVU9UdGVUcThWdlpTTTZGVUc2UUh4aGpRc3NRaGZ4cEhyckFaU3gwYm1SUjRVTmVGcm55Cm9kcDNnN25GQW9HQkFJNnJxTHZtazI2dC9YSVdQWDJQdDVHanFqTm5zQlllb3QrNXU5a0c5S2RmZEtRWExFd1YKUlA1OFM1Y3N2RkhhZ0IvMnV3WUFaSU9GSXdhdTlmVnl4TU1ieFpvSWg0eThhOEpqbmp5QzhWQzhlelZvalJXRQpvamhnWlNHeGRjdWVVNDFBNWhXNXQ3OXVVT0x2d3hTajArY2Q1ZndqZGFRZ0VoM3cxMm8zYUQ0MAotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo= additional_trusted_keys: {} cluster_name: me.localhost type: db_client @@ -1088,67 +1074,61 @@ sub_kind: db_client version: v2` databaseCAYAML = `kind: cert_authority metadata: - id: 1640648663670001000 + id: 1736815462678282000 name: me.localhost + revision: fc0e88e6-8dac-458c-9dec-f8cac14a660d spec: active_keys: - tls: - - cert: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURpakNDQW5LZ0F3SUJBZ0lRRU9IcEhIZkZwZ28wUndQSVJhdkdpakFOQmdrcWhraUc5dzBCQVFzRkFEQmYKTVJVd0V3WURWUVFLRXd4dFpTNXNiMk5oYkdodmMzUXhGVEFUQmdOVkJBTVRERzFsTG14dlkyRnNhRzl6ZERFdgpNQzBHQTFVRUJSTW1NakkwTkRBMk5ESTNPREkyTWpJNE5UQXdOemMzTmpVeU16STVOak15TWpNeU56VXhORFl3CkhoY05NakV4TWpJM01qTTBOREl6V2hjTk16RXhNakkxTWpNME5ESXpXakJmTVJVd0V3WURWUVFLRXd4dFpTNXMKYjJOaGJHaHZjM1F4RlRBVEJnTlZCQU1UREcxbExteHZZMkZzYUc5emRERXZNQzBHQTFVRUJSTW1NakkwTkRBMgpOREkzT0RJMk1qSTROVEF3TnpjM05qVXlNekk1TmpNeU1qTXlOelV4TkRZd2dnRWlNQTBHQ1NxR1NJYjNEUUVCCkFRVUFBNElCRHdBd2dnRUtBb0lCQVFETFRrVFkzQ0NMVStNUllkbEMwM2NUTTR6MUpiRGoxYjFQRWdING9iSmwKRjl4NWtQbzhncWNEbmp5L0x5NHdKeUR2Q2xPMkw1T0k3UnYwa1hFUXoybUVEeExnbjJYRG9ZNUh5VFNOVkZHNgpvZ3BlYmhlUFN1aWl0RUNZYUZDZVZFTGNDa1Q0ZGpqRDlwOExNTnJ4MHRPOXdQU1o1OXBLZUxCOG90RFloOHRCCkcyb2EzSGIzTWt0RGxOY0svVE94RFNzRzUrQ2ljdktTa3QrV04xaXJJQ2pvZ2hWTzJGcForRkdxWUM0Y1EwbWMKM0NRaGJwY1o2VTRkWnpGdFJZVzZPYzNucHBOSkZKWXZSSTRIS1FWY0RCM2N4VkhNTUd5Rzc3aFRzdEwvd0RuaQo4U2s5eml4VzN4S2FvUnlrV2FuWno4eC9WdHNydXJqanNzNDV4NlRoem1VWkFnTUJBQUdqUWpCQU1BNEdBMVVkCkR3RUIvd1FFQXdJQnBqQVBCZ05WSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCUmNKK2NRamFQWjZGbEIKcVhoYzYyWXZldGRpQWpBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQVdYNmxZdUhtMmQyMU41RDN1eUJJelFOdApKVFR3b0xnU3FQd09Tbk1EU0luSDkvMjBqZDNGUk9qakh1M3BQRkNLRmE4OVp0ekZxTHZsTjVOdlh2WHFuOXNKCkdudTYzSVo0TWtEZk9sSVZpWFhQWFF4YllHSkMxRVlVU28rTDdtUTY0VnN5UkFpTXdnbmVwMUxwSGhROGYzU2MKeEZoVkNybFJDMmUrNENBai8vOVZWaDdvTEdSMkNhM0xEcFc5VHFxYnB3MEh0QitNcFVqVWxCWnFVbzNVMm5HTQpia1VhSVZKcnNuYk1rYnNsUGQ2dWtVRDlVTHFuUmxJb3A4cjQ1VTdvYVBhR3g3QVFiWndzbGlsNVVJZlppRmlRCm5USk9kYnJHampVdXlRYkM4UUpZY3RhdENjbVBjZUlXMVVWWFVnZ2JsdXl4VjF1NWsyYzlSb1k2RzhiN0FRPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= - key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBeTA1RTJOd2dpMVBqRVdIWlF0TjNFek9NOVNXdzQ5VzlUeElCK0tHeVpSZmNlWkQ2ClBJS25BNTQ4dnk4dU1DY2c3d3BUdGkrVGlPMGI5SkZ4RU05cGhBOFM0SjlsdzZHT1I4azBqVlJSdXFJS1htNFgKajByb29yUkFtR2hRbmxSQzNBcEUrSFk0dy9hZkN6RGE4ZExUdmNEMG1lZmFTbml3ZktMUTJJZkxRUnRxR3R4Mgo5ekpMUTVUWEN2MHpzUTByQnVmZ29uTHlrcExmbGpkWXF5QW82SUlWVHRoYVdmaFJxbUF1SEVOSm5Od2tJVzZYCkdlbE9IV2N4YlVXRnVqbk41NmFUU1JTV0wwU09CeWtGWEF3ZDNNVlJ6REJzaHUrNFU3TFMvOEE1NHZFcFBjNHMKVnQ4U21xRWNwRm1wMmMvTWYxYmJLN3E0NDdMT09jZWs0YzVsR1FJREFRQUJBb0lCQVFDeXNLNXVkTHZkK2ZOQQpHZUtkaThQRENySS8zY3JsMWIwNFBEbWpVR3U5MHdVampEdUU1OGpuc3pMdFR3aW5waHlhUFZkcWI5S2FyTnkvClR2NHpxam14cXBZSys4Nno3ZEZpWXdSZm05YmgxUDZNRlBOOExIamdXTkhWb3dvSXYwS3NxQklLMTgzNDMxRFcKd3pBTkVDS3ZTMk14eXNqZ1g4ZXZKR092alZzbWN1SU1IWFljbVlORlo0dWpuTnc0dnVSWHhlYUtPY2ZWTGZ2ZwoxSWZMK05IYUh6UXI1YVoydkxST1NpdHVId2cvOFpZZ2hQcVFYLy92ak92M0FENzhXVGxINUZXWjExR0hoeCt1Ck9ZUXcwQ1lvTnNiV1UxeklwVTV0cHdCcDRGV0VlVy9jbTY5NXRBVVRlMzR1N3R1MlJJOVBZMEZDWVJ2ZkM2SUQKK2tDNjRFTEpBb0dCQVBSTEt5a0pjdHNGNngzN1liWXdmQm9ZK3V6YU4wV1o1d1RuRmVFaVp1ZzVVYWJUOTdqRApZTnpaYzQ0aitRbkxFUGVDak5tU1FhVHFxK2QvbUVjTnlXS244cVNFcXlOR0R6YlRXQ2tkMGtyWTVwcm9FVVJnClFqbWFwRHFNNEtOSm9jQ1RCS3lueHo2QzZ6ME9uSnhZM3lMdTdyYVBqeE9HTW5rcm9VMDhMVW56QW9HQkFOVU0KU2NsNGh1R0gxK3ZNL0RtenJoQ1NKbUZIcjE2QjhvWExaMHIyNmFKTnJVQ3AwYUFzV2FHd3JLZXZFcDkzRmg5Ygp3QlZYMHE0bXJ3cmZpTGpCYnRzdnlQM3l1ZWs5cWl6M2ZoMWIvZ0k2eWRKVFEzMEplQzB4UzUyRksvR2gwanEvCm43c2Y1bm5DbTlCRW01ZmdSeDFVUmVhOC9vL2M4cTNhbW94c0grdkRBb0dBZUVZUjU5QlpGZkJpQTQ3aVdwcWcKWHhEeGFXOCtTeXdzaTBOaWlFY3h0eCtSVGJ1S2VSTG9PNU5yeXcxMjdSVm5NeFM1Vjkwa0tKZkpMdDZwRUVKLwpaZTBlRDFXcUZHSEgxOHhSMlZ4dlRwNWZXdURxcjJsYzhaTnJTOUJVUU5CZHJMdzFUdlFEcW9rMlhBYzNuOW81CmNhK0ZJNmltWG94eGlTcXI3YVMwLzNVQ2dZQTJBWEJ1N3V1YUhocGcvc3h0UUJ2K3ZWMlhTVm11SmxpNUM4KzYKVkE3emdxZEpmZ0xTakl1SURrWW1GNTRyNkQ4bVlkYTJVbFhvcVl1endPaGlsVDRwdDlwR2JaSXRDdUdwbG05VQp0KzRTMko0eWY4TGEzbHlsY0JxUDZxTXlGR2c3VmpvQ2NGcTNRTnJJbDZ1dGV6L3JzbUlwMUh6Zk1RNGZmZ3V4ClR2Tmtpd0tCZ1FDbVhaSStvTUdQK3U4KzRVaGxjR01NYUNHZi92UVZLdVJYOHlOYVh1bUx6dk1Xajl0cVhpUzcKK1dQUlhuV01RSnd1QldYMzBTcWdFVVdDbjlzOGxWbzh2TVF4MmFtbXhhWkVEMGRoOHNMSkJDNXJoRmVqV29MbQp3cHg5MXR0S3JJODBKMDYyeW90SFpJYkRyQW1LSGZFeE85U1d4T1hUeFVMUGdvTlJVUW5qSnc9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo= + tls: + - cert: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURpakNDQW5LZ0F3SUJBZ0lRS09YVVNuWDVDVTI1TStsY25wKy9QekFOQmdrcWhraUc5dzBCQVFzRkFEQmYKTVJVd0V3WURWUVFLRXd4dFpTNXNiMk5oYkdodmMzUXhGVEFUQmdOVkJBTVRERzFsTG14dlkyRnNhRzl6ZERFdgpNQzBHQTFVRUJSTW1OVFF6TmpJME5qRTFPREl5TXpFNU1qTXlOall3TURBNU5EWTNNakkzTVRBeU1EZ3pNVGt3CkhoY05NalV3TVRFME1EQTBOREl5V2hjTk16VXdNVEV5TURBME5ESXlXakJmTVJVd0V3WURWUVFLRXd4dFpTNXMKYjJOaGJHaHZjM1F4RlRBVEJnTlZCQU1UREcxbExteHZZMkZzYUc5emRERXZNQzBHQTFVRUJSTW1OVFF6TmpJMApOakUxT0RJeU16RTVNak15TmpZd01EQTVORFkzTWpJM01UQXlNRGd6TVRrd2dnRWlNQTBHQ1NxR1NJYjNEUUVCCkFRVUFBNElCRHdBd2dnRUtBb0lCQVFEY1VCcEQxSkY1TC8xbmZ6YkF0Q2kvLzVvUDREQ2tNaFlhTlVSbXlWYnYKOEc3Z2Q5YitVVm5xaHVDcmdhRGM5a3pYbE5aZnBEczR6WWpTSlM2bk5BK1RaTXplcmdNbjlhMnFmZEVwZnNXcApPRkxBVzFqODFGZVh3dCswTy9aM0Q0cXVGdHIyRHp0R1plektkVWhsaXNQUGRXejJqUW1kMGJXNUZUTG5JSE1yCnhHRVcrN0E2YUdVbnh3b2M3aEdtKy9VOS9wMDNXN1FMQ3JEbWdjYVkxeEozaGpMWnN3WUhwd0UxbFlqWm9sc0IKNlRyVkxCZkJ3UXd3TXlxeWdDVXZvQldyMWRia01BV0h1dFpXWmdhL0ppdDAzT1J2Mit4Mm1GRUo0R3NIZWJrSgpHZUlXclRjbmxxRThwU2tjUWxmNWh1a25Ob0thamE5MkcrL1AzaitTanpuVEFnTUJBQUdqUWpCQU1BNEdBMVVkCkR3RUIvd1FFQXdJQnBqQVBCZ05WSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCUTNVakNxb1crYUhFYS8KNjNQdXBUeGJONHBFSVRBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQXFvWmo4QXphOFRsUEo4dTJZY2RSYnVscwpZSHFxaEd6bEpwMFNtUTlMR3diVjZVeGI0UHNBSEw4WmRWOUxyN2RNems4bWFwSC9FRURhRmpzQnB3N254TGNwCjhwVHkwbXJ6Wll0elRQYUw2dnQ3M2JHdnZ1bUsyVkxmTmh2OHBLNXBVS09UdXRHNVNPN1pzUVdJakVuQkpvMnkKcVN1MFNCTzM4SlkzNkNtRjVpckhFdG5HVHBMZVd1dWdyT25kRmVUdURYakMveUd1MkNsSzBnRWpIdVlVOUIwNgpMSUxzaU1iSHJqY0ZiQ1hiVjRCVXNPaXlMSFluV2Zna1NKRzk1VnNZRkRUNUxKdm82cUY5TE1kdzlEVW9SL3o0CkVzYktMT0I4b2dOVm92NWEvSFlhVkNIYjJSeTU3TDhWNEJLRXJoNzdJT1pZQ2RCZ25yRStmS1hZQ05JT0NRPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= + key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBM0ZBYVE5U1JlUy85WjM4MndMUW92LythRCtBd3BESVdHalZFWnNsVzcvQnU0SGZXCi9sRlo2b2JncTRHZzNQWk0xNVRXWDZRN09NMkkwaVV1cHpRUGsyVE0zcTRESi9XdHFuM1JLWDdGcVRoU3dGdFkKL05SWGw4TGZ0RHYyZHcrS3JoYmE5Zzg3Um1Yc3luVklaWXJEejNWczlvMEpuZEcxdVJVeTV5QnpLOFJoRnZ1dwpPbWhsSjhjS0hPNFJwdnYxUGY2ZE4xdTBDd3F3NW9IR21OY1NkNFl5MmJNR0I2Y0JOWldJMmFKYkFlazYxU3dYCndjRU1NRE1xc29BbEw2QVZxOVhXNURBRmg3cldWbVlHdnlZcmROemtiOXZzZHBoUkNlQnJCM201Q1JuaUZxMDMKSjVhaFBLVXBIRUpYK1licEp6YUNtbzJ2ZGh2dno5NC9rbzg1MHdJREFRQUJBb0lCQURaeTRacmovVFFMUlVCLwo4ME03QTFzNFM1WWkzVUtuVWtrVjR4cllKZEZWQmNJYVBCdE1kY0Y5cGljYytXbkN3WWtDTXQwZVZMaWNLM1ZzClZSUmp6SG1zRHVuMTdiZkJnek5BdHlIZlAvQ3JoK0FjYzJqQS9najIwNXpTdVA0QjdFOU1QTDlWVWx2NnNzUHkKcW5yV0NjRExENnY3ZldYd3YwM0h6SFhNMGtuOVlGUEpwU2JlMDR3aExMV3QrdFYyaGxzZytoSjA5RkFDdjVibAp0TWxwcG4zVjBSNS9CeC9ic2V1MXh2NGZ6Rm1aRGlkbnFjUUNyakFRQUV4aHYxNTVzZGhKbDFldnVYUGYzZWg2CnVSdVhGMGxnMnRyVnBOQ1h3TFVSRDNXWGpxdm5XUzdqTEd3SEFKTEpnVGFnMGk4SEM0YWRkcVdLK3R0U3dwU1IKdjd4aUhPRUNnWUVBK0dOeTIzdHZSRzFlRVRNeCs1MnZNRHFZRDduM2NpaXRzQWpJTlYxa0Uva2ZhRSthYk5VcApKZUZXNzN2Qkc0RU5SbitLRWphdGdDMzJyd05jK0xwd2RkNUM5bVpLVFdqcjJQa1dCNEFmeTVQVVFIVm1DTjRRClQvRUVsM2k1cWdmbGhvWm1nQlVjMFl6dWpGcW9PVXpMZ21lampNR2YzZlhOc3JGSmtZeUxrTU1DZ1lFQTR4Qm8KVGZNTllqNENtbkpNV1lDb0ZJa2ovalVBbzd4cDRCTlZCTFJlanlzdVpmTHVVekpxV3p4Wi9wb1I4K3Bxd3BadwpHd01jZlZocmk4Q040VHlCd29NUGFkb2k5b0sxbkJPcVNMUm9qMEdXTUtLdmJSMWw5R2lCZVhUZ1pHenpHSWQzCmpJVlh2YndhZ0o3Y2VVNG1JRjlOdG5lM1JJTWtEa0JSOGMrTkliRUNnWUJWSDkveEVEQmx4d1dCNTRXdHNiQ2sKV3JCYVUyVldIbExJRFhwdnIzM295bXZWRjlMWWtZVDBrbkYweVhpNHNGV1lYNFUyRUw4Tk9yTmI3MDhoZnVPagp3WFE1ZFh6cFlwZlJXQ3dRamZ4WGpHWWxZUmFDMjNmRHJkbmcvMkxCdnNzT2Uya05aQzdvTWVCZkFZSzlnSEFPClZPNWNBcytEQmdaa3d4VnZhRGM4ZVFLQmdRRFVUOEFudXE3MkFHTnd4SlR0VDJaYUpVMVpZWGZpb2NjaHRSSFcKMzB4WGRCbmpTNzVhWHBhaURwRmJoZlpwYXZRK1ZHb29aOFZZMHJka3Fqdy9zZExtN0tNWjU5U3ZTTkxGU0lIOQpqMnNCSUdOdHdJQmxkNHFnZUtNdnpRQVFCdXRiTVRld1ZmSVB2L1hMOUQ3VTBpVEdPamF3K2NtTUwwOGtZREgrCjk0SFFVUUtCZ1FDb1dQb281TkhXU2IxbEpRcjBWR1VUemtKQmp4RnpxTDNxbWxyMEVUanpzdEVDSy9EejFvU2oKYW1leG8rd0RTb2ZHTEUxZHBMYkVPS3BnaE84QllvZUxFdW1LNGh6dm5CaEJOQUpYTzNqZkFTK0NISW1BZmN4bgpMQnpEZzJlR0JrNUpUcHM5bjNkcjVvSzZPNU8rc3VlSDN0TTN3RW5Vckx2VGEwcDBzQStmcVE9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo= additional_trusted_keys: {} cluster_name: me.localhost - signing_alg: 3 type: db sub_kind: db version: v2` jwtCAYAML = `kind: cert_authority metadata: - id: 1630515580249460000 + id: 1736815462676799000 name: me.localhost + revision: 01d66f36-8bc8-4991-8731-35c961f6bccd spec: active_keys: jwt: - - private_key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBNWNQaFordnk2N05NbDhwbDJ4SllvSDVFOTl0a1UzVlByTGhnVkhOMmpuZmoyRlhNCm9RdVRKbUJOdWVEd3FiVFpKREJmQ0d1bTU2RVczK1YrQUtsY3pFNVdFS2NBR0wxL3ZvOGU0NDNBRmwzQXRHVVEKSWRHVzRoL0o0Q3BTNG9idVVlMGt3K0JiZnlocUJ2a2lTNmxtUUpjV0hLbzd2aWZhRTJKc1hmZStESklSMS80eApvYjlrbkw1QWVoRS9XV25CY0RiWXROcHlFOHBoQzdGaDgzYmFUdldqbXNWTEZaaWEzKzJqL255aWRzUmUxNGMyCnR4czRWRXp6UVpaYTMwMlpESFRpRmM4MzJtY3lCTEFzRnMycHNsSkxiUnZLdllBS1dLTnRRcnRlSHIwUFBmamEKQjM3cmNWMXlLYTJONjNRTnZrd2FRMWlnbllqSmE3blRQYWpVSndJREFRQUJBb0lCQUY0b1ZMSUt2bVVhK0RObwpMUytHcUMwMU1ieEUreXM4Y3VjOE03WElEM2k0NXZWYnk5emZhbkVhbkIrbGI5cU1FMFJDVWwrWUJqRDhFZXkxCkZscmREUHRveXRwT0picjl4V0RwTStaYXk3SWV2Mzd0djV1c1VXSGZWeEozSmJwUlEwN3RtTmh3ays1Yk9JQWQKRHBIbEhOTXhWMDF0OGNldWV5N2djYnBjY1ZTaXJNYy9ERTlGcFNONFRRWFloMlRDSnVZcTdncFo1SGJ2MlpleApDOHFTTnZqVVlVTithTGlDZ2pBRFhZdGdmV2RUVWN0YkhldVUrL2Ftb3cyUitOVjFWMGpML3lOQm0rdmZUVXNuCmprNFMxQWx1U3FrT0FFaHJhZjM2UzRNcWZQWm8zbXhFOC96TVZTdEY5MTdvQVRKMlZrNzVZaGxINnMzM1BKN1kKMXdDeVdZa0NnWUVBOFRoT1E4M01xTjFTL1VVcUJWeGRaaS9HZFBldmQrbFUvY2FIQVhTNmJyd2RYNEpITTkrbApaczZVWFdocWJHUXFSVlRvZ1dna2VBSHp4R3I1S2QvSTlRRnhEZHE2am1vRUhmU3VNNnNiNU4yVjgyQTVSaUhHCmduS3IzMUpWQS9FdEt3Vk5sZUY3L1VUM0tzWTJzajRZNFkxRnI3amRkOS9tdTVaNWVwODFidFVDZ1lFQTg5Zm0KSE9tc0JYZUQ0M0FHVmltSFhEWWVGckI3UWRhY3hOQ3R4NjZuTk5jMFpxM0pDZGtDMjVaTG1nQytON2JEbkRjMApNZ2NPUGdyUWxVdWpRbWl1d1daeFlXcDAvWDh3STFHZ2p4RkEvRkJvNjFnd3lwR2tqbjJlS3lVM1ovWlJBRTBjCmlxaW5UTVc5TFBlV1k0MEhOUzFic3E2YmFoeXg1bTFVV0gxclRRc0NnWUF3bE1WMmRHbEdqU1NjcTZSVjVnOU4KZUV2QTNPMXkrZ1JMQkFQR3NFcW42SzBGd2tneTAxVU5pb2RvOUpHU2VPM21mcjVBNmNlR2YrWW5aZC8rcGZwawpGY0UrS0JJd2dudUh5UEtZcDFwNzBvRFR2a3Bxckh5OVl2am9oajFuQ05pdTlHZDJ5eTNjaVZvNlBDZGg2STI4ClIyYUVpSGZhSDdicGl0bTJiNEFrYlFLQmdRQ2tmUUpraEppZkEzVTdpa2tyL0Uyc1BYRmttdDQ2bG53Z0pDam0KSjRIeG1pNW1DVnN4UW11MEZ4bWVwRnVzbDZReWorYXN6S2VsNElPK0FrejZNa1dZZnZPQzVGNVExbWh4bXRHMQpVTTFHcHpOdmRvbExUSjMxNVBVNlk1dVJqTTR0WnRjWERoZjFLUHFwQjhjeUZtTkRVdnFsZVRXcmlmblQxL0pxCjB3Zjc2d0tCZ1FDN3hIK3NXbTR6cjVRb1VvMWlrYlRMSHRBaVFETWE2TlpWTTk0MHcxZHExUWk4YXpMTE1lMUcKUVduU1ZqTDVLaVlSY0toSjVYOGpoQjF5a2U1OTR1ZU1CSFJRdjFRU3RCalRkSzIxN2tnTTFTRmZEbzFFQWpRdgpMWk5pWHROYXVDeG9BMi96SHJrZ0d0NGQzQldKZk5ENkJPQ1RKK2lSRnNWc1VvcjhITzJQR2c9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo= - public_key: LS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1JSUJDZ0tDQVFFQTVjUGhaK3Z5NjdOTWw4cGwyeEpZb0g1RTk5dGtVM1ZQckxoZ1ZITjJqbmZqMkZYTW9RdVQKSm1CTnVlRHdxYlRaSkRCZkNHdW01NkVXMytWK0FLbGN6RTVXRUtjQUdMMS92bzhlNDQzQUZsM0F0R1VRSWRHVwo0aC9KNENwUzRvYnVVZTBrdytCYmZ5aHFCdmtpUzZsbVFKY1dIS283dmlmYUUySnNYZmUrREpJUjEvNHhvYjlrCm5MNUFlaEUvV1duQmNEYll0TnB5RThwaEM3Rmg4M2JhVHZXam1zVkxGWmlhMysyai9ueWlkc1JlMTRjMnR4czQKVkV6elFaWmEzMDJaREhUaUZjODMybWN5QkxBc0ZzMnBzbEpMYlJ2S3ZZQUtXS050UXJ0ZUhyMFBQZmphQjM3cgpjVjF5S2EyTjYzUU52a3dhUTFpZ25ZakphN25UUGFqVUp3SURBUUFCCi0tLS0tRU5EIFJTQSBQVUJMSUMgS0VZLS0tLS0K + - private_key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb2dJQkFBS0NBUUVBdjc4Y3pqZjgyVEtFczN4VGJOU1djWU53S0p3ZUVZakF1M2RVNldGSC9yQ0ZoOW9ECmRRSVhKdTU2UmE4Uk5xenNpcTl5WGtDKzR3K2pyS2dXRFVtWWgxejJaS2lnVDZEVnFBVzNYVzdlL2pUZmdRbkIKYzl1dENINlVJYUxUYnQ2RmlUM2dCZ2NnK282aG82bjNVT0dXTDBIMXQwWm9sTE9OWDBrWHMwSTZvQmw4UEl3eQpzVzdzeGpKQXplc3ZDeFJCV2VoK1doOTRIa3ZTWGZuL2pVRUJSNFFCY2VSQmxxOE1nWjNkRTNWOWVHRzBEdDFhCkpQSUx3RHpyTlJLZ1d6RnhHeUJMQllDcUh2Vjl0aUtOeTIzcW5weS9SQ1FoVkpJM0pHRGdteEhZTmtuZ0NJL1EKL2VKMEFWc0tkdm45NTY5YVllUndCSFVmdXg2WW9EZGg2aDc3RlFJREFRQUJBb0lCQURIR3RmNmVzQ2ZlSW03Sgpwb3FKQVdrRVd2aGYxcnBzaXNQZnJZNU1MN2xoTDdqZGtxb3NXY0JFaGo5U3ZDQTZjY2xxMUVDOWhCQkR2aFNUCktlNVhIWjUrTm9SWTlnelZ6c0VvZ3JwaGpzZmxCK1JpbVBLdm8xS2lNV2d0OGI5RlN0c2UwZW9lcmFQOXBONXMKd0FRaUc2KzI2c2VpSW9IL3ZvSnU0aFVwNnpnbUVoR0l4RW1iNHpaN2NzM2RVZDN2dTJ1UlNmRnljUDFGRmphNApXZVlZK3RGUHBmVzRqSjdFSkRucWlIRmFXQlRRTEdIQ2hYZFdpQVBWM1kvZGl3RVAydm5lYjhLVHBzbGU5SlA2CktoWjAzYVljdHdsWVEzbXV2NU1FMkNVTW5nUXRHam5iYVFWTE1POUV1UzdJekxUQ2V5d1piL09sYW1HaVhjbEgKSkFtWlNnRUNnWUVBeXpvWUJ1TzhUZjBCdFJ1L3RvOXVCQ0QrdncwUmExVjhXQWxJMGpiL2FPRkUzM3o3K2RrKwpHaWZ1MDU2aWMvd1JaVjgySXpiMEdZemh1MC93YmpKQmdRVFJpMHJub0wvQ1JBd0p6c09tZ3lMK2JReXdOUXdUCmZqenVnV25HalRWQ0RwTW8rcXlxQ2RETXNEVDlMTmJBZjRFL2oyWWNGb2NhMmV0UmN3a1dMb0VDZ1lFQThZblcKUkdwT3ZTVlVWc1VWR1d6ZEtBK3dGQWxTTlN6K2piclBTdUlUNWR2TjVjTUlhb29wM1A5UUxGcFFiMUxQTXMzeAo1Qmltc2tvRTdnMVN5U0sxdEVOZVBQdUpLOWhPQm5sM3RYZExsK1B6ZU1CNzlnRXEyRHh4V0o1VW53KzY0QTRiCmUyZmt1N1dJeXhjSEdnV3N3TTZNU2hHaWd2Y2ZOd3VkOFNlMDZwVUNnWUJKb1FLVGZHNzgwbTJMOEVIRklySDUKVFByK3ZQMVNwZVltL3pZaTgwb1Y5WWUrY01uWis1dEVYck5vZUZEak5MQVl5aVlUSEJYVUsvYWNwcG0xVXYvbwpmcFpzb1BiS2hxOGJlRUVWYUUwcnRjSDRRR0NXMTRrNGMxcjJDQnluakdRaVk2NjFJMWwzdE81ejZMN1JQL3orCk5SV1NIcXlPZk9SOWo0UXk2VmZnQVFLQmdDTUt3RTlFclErNzdyUjMrMHVwQTV6Z1NjZGVZdExjS0VJZnJCdE4KR1YzcnViOXZ3RFRVdnFZVlZHaGE0ZmlFcHhMVDFoZ2xpMm1xVzNTOThoakVOR0JtdGJGYlBOZGpsazVTS1EvbQpzc3ppZ1Z3dmNNeUw5czlRVlpGcHh4VWNqeHdhYjlwRGhHZkhPb1ZjWGVka2sxK1ZsN3pYT2lDT0FiVld0aDlhCmgyRFJBb0dBRzFCUFdZeGE5ZFFIUnhhVEhFSHFyaUpvN1hTNUxRbUdQN3p3NUE4ck1seldKTFJQbXhZZjAyZmUKNGhoNG0xSEQxVzUzSmRpYWlHZlFxUUZJSGplelVNSFJEN2lMcURJemNYUnppWmZiaXF3dzYxUGt3bi9JRE1vWgpOTjJnekFhb2ZnM0F6UGFXZHZNV3Zka0RnZThuVy9VWUtGanJZZjMrR01wSG4zWjZUdlk9Ci0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg== + public_key: LS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1JSUJDZ0tDQVFFQXY3OGN6amY4MlRLRXMzeFRiTlNXY1lOd0tKd2VFWWpBdTNkVTZXRkgvckNGaDlvRGRRSVgKSnU1NlJhOFJOcXpzaXE5eVhrQys0dytqcktnV0RVbVloMXoyWktpZ1Q2RFZxQVczWFc3ZS9qVGZnUW5CYzl1dApDSDZVSWFMVGJ0NkZpVDNnQmdjZytvNmhvNm4zVU9HV0wwSDF0MFpvbExPTlgwa1hzMEk2b0JsOFBJd3lzVzdzCnhqSkF6ZXN2Q3hSQldlaCtXaDk0SGt2U1hmbi9qVUVCUjRRQmNlUkJscThNZ1ozZEUzVjllR0cwRHQxYUpQSUwKd0R6ck5SS2dXekZ4R3lCTEJZQ3FIdlY5dGlLTnkyM3FucHkvUkNRaFZKSTNKR0RnbXhIWU5rbmdDSS9RL2VKMApBVnNLZHZuOTU2OWFZZVJ3QkhVZnV4NllvRGRoNmg3N0ZRSURBUUFCCi0tLS0tRU5EIFJTQSBQVUJMSUMgS0VZLS0tLS0K additional_trusted_keys: {} cluster_name: me.localhost - jwt_key_pairs: - - private_key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBNWNQaFordnk2N05NbDhwbDJ4SllvSDVFOTl0a1UzVlByTGhnVkhOMmpuZmoyRlhNCm9RdVRKbUJOdWVEd3FiVFpKREJmQ0d1bTU2RVczK1YrQUtsY3pFNVdFS2NBR0wxL3ZvOGU0NDNBRmwzQXRHVVEKSWRHVzRoL0o0Q3BTNG9idVVlMGt3K0JiZnlocUJ2a2lTNmxtUUpjV0hLbzd2aWZhRTJKc1hmZStESklSMS80eApvYjlrbkw1QWVoRS9XV25CY0RiWXROcHlFOHBoQzdGaDgzYmFUdldqbXNWTEZaaWEzKzJqL255aWRzUmUxNGMyCnR4czRWRXp6UVpaYTMwMlpESFRpRmM4MzJtY3lCTEFzRnMycHNsSkxiUnZLdllBS1dLTnRRcnRlSHIwUFBmamEKQjM3cmNWMXlLYTJONjNRTnZrd2FRMWlnbllqSmE3blRQYWpVSndJREFRQUJBb0lCQUY0b1ZMSUt2bVVhK0RObwpMUytHcUMwMU1ieEUreXM4Y3VjOE03WElEM2k0NXZWYnk5emZhbkVhbkIrbGI5cU1FMFJDVWwrWUJqRDhFZXkxCkZscmREUHRveXRwT0picjl4V0RwTStaYXk3SWV2Mzd0djV1c1VXSGZWeEozSmJwUlEwN3RtTmh3ays1Yk9JQWQKRHBIbEhOTXhWMDF0OGNldWV5N2djYnBjY1ZTaXJNYy9ERTlGcFNONFRRWFloMlRDSnVZcTdncFo1SGJ2MlpleApDOHFTTnZqVVlVTithTGlDZ2pBRFhZdGdmV2RUVWN0YkhldVUrL2Ftb3cyUitOVjFWMGpML3lOQm0rdmZUVXNuCmprNFMxQWx1U3FrT0FFaHJhZjM2UzRNcWZQWm8zbXhFOC96TVZTdEY5MTdvQVRKMlZrNzVZaGxINnMzM1BKN1kKMXdDeVdZa0NnWUVBOFRoT1E4M01xTjFTL1VVcUJWeGRaaS9HZFBldmQrbFUvY2FIQVhTNmJyd2RYNEpITTkrbApaczZVWFdocWJHUXFSVlRvZ1dna2VBSHp4R3I1S2QvSTlRRnhEZHE2am1vRUhmU3VNNnNiNU4yVjgyQTVSaUhHCmduS3IzMUpWQS9FdEt3Vk5sZUY3L1VUM0tzWTJzajRZNFkxRnI3amRkOS9tdTVaNWVwODFidFVDZ1lFQTg5Zm0KSE9tc0JYZUQ0M0FHVmltSFhEWWVGckI3UWRhY3hOQ3R4NjZuTk5jMFpxM0pDZGtDMjVaTG1nQytON2JEbkRjMApNZ2NPUGdyUWxVdWpRbWl1d1daeFlXcDAvWDh3STFHZ2p4RkEvRkJvNjFnd3lwR2tqbjJlS3lVM1ovWlJBRTBjCmlxaW5UTVc5TFBlV1k0MEhOUzFic3E2YmFoeXg1bTFVV0gxclRRc0NnWUF3bE1WMmRHbEdqU1NjcTZSVjVnOU4KZUV2QTNPMXkrZ1JMQkFQR3NFcW42SzBGd2tneTAxVU5pb2RvOUpHU2VPM21mcjVBNmNlR2YrWW5aZC8rcGZwawpGY0UrS0JJd2dudUh5UEtZcDFwNzBvRFR2a3Bxckh5OVl2am9oajFuQ05pdTlHZDJ5eTNjaVZvNlBDZGg2STI4ClIyYUVpSGZhSDdicGl0bTJiNEFrYlFLQmdRQ2tmUUpraEppZkEzVTdpa2tyL0Uyc1BYRmttdDQ2bG53Z0pDam0KSjRIeG1pNW1DVnN4UW11MEZ4bWVwRnVzbDZReWorYXN6S2VsNElPK0FrejZNa1dZZnZPQzVGNVExbWh4bXRHMQpVTTFHcHpOdmRvbExUSjMxNVBVNlk1dVJqTTR0WnRjWERoZjFLUHFwQjhjeUZtTkRVdnFsZVRXcmlmblQxL0pxCjB3Zjc2d0tCZ1FDN3hIK3NXbTR6cjVRb1VvMWlrYlRMSHRBaVFETWE2TlpWTTk0MHcxZHExUWk4YXpMTE1lMUcKUVduU1ZqTDVLaVlSY0toSjVYOGpoQjF5a2U1OTR1ZU1CSFJRdjFRU3RCalRkSzIxN2tnTTFTRmZEbzFFQWpRdgpMWk5pWHROYXVDeG9BMi96SHJrZ0d0NGQzQldKZk5ENkJPQ1RKK2lSRnNWc1VvcjhITzJQR2c9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo= - public_key: LS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1JSUJDZ0tDQVFFQTVjUGhaK3Z5NjdOTWw4cGwyeEpZb0g1RTk5dGtVM1ZQckxoZ1ZITjJqbmZqMkZYTW9RdVQKSm1CTnVlRHdxYlRaSkRCZkNHdW01NkVXMytWK0FLbGN6RTVXRUtjQUdMMS92bzhlNDQzQUZsM0F0R1VRSWRHVwo0aC9KNENwUzRvYnVVZTBrdytCYmZ5aHFCdmtpUzZsbVFKY1dIS283dmlmYUUySnNYZmUrREpJUjEvNHhvYjlrCm5MNUFlaEUvV1duQmNEYll0TnB5RThwaEM3Rmg4M2JhVHZXam1zVkxGWmlhMysyai9ueWlkc1JlMTRjMnR4czQKVkV6elFaWmEzMDJaREhUaUZjODMybWN5QkxBc0ZzMnBzbEpMYlJ2S3ZZQUtXS050UXJ0ZUhyMFBQZmphQjM3cgpjVjF5S2EyTjYzUU52a3dhUTFpZ25ZakphN25UUGFqVUp3SURBUUFCCi0tLS0tRU5EIFJTQSBQVUJMSUMgS0VZLS0tLS0K type: jwt sub_kind: jwt version: v2` openSSHCAYAML = `kind: cert_authority metadata: - id: 1630513579536527000 + id: 1736815462675350000 name: me.localhost + revision: 64116dbb-d9b4-4765-961f-e126750732f6 spec: active_keys: ssh: - - private_key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb3dJQkFBS0NBUUVBeHpRdWtjUlhCR09nRDUrS3B1MGRrdVpXVjVsc294Wlp1cFRhRHdFcmYvQ1prOWFqCjRaZzJoeTBoUHl5SXRBRytIN08xRVYwZ0taWVRDWWs4REtiaFQ4ZWl3QldDNUhKaGtpYW9ZRStSUXpQTHd3STcKcElmb0t4ejR2WG5MRnNvWHVVY2hLTmhYdk1RZU9pVVJ3OVQ3L0RSREE0dDdsazlPY01jWE9ySHV3L2JxTTA0VApmTmhVeXhHVmhyTC90aFpQNDE4b04xZjZKQzZMU3grZThIM01iSEQralVGMjBVbU8wVUFLUHUwRXVQS3hkS2loCm1tbVZDZ3FaRWhBWjhrcklVYlV5R0tUemZjQyt4VFNrUEN3UE1qejg1aTJQVVBYS3hmVE00cW54QVh5VzRCSzYKeXo1Znk5UTgyalVESi9VS0JvSU92N1hUU2JhNUpDUHdiUUx4cHdJREFRQUJBb0lCQUJydU53MkYyYTNDT2pWaQpnRUFvOWtLUjJVSm1mNFZjMUN5aFN3bVVRdWs5QWNZMjBsa0JWdjNYWUJOR1ZnVGY1M0FwdjJUbGpoK1JKbW0zCm4rS2wvUGZvS1Z5R2kvZU9ieHB2RjN4TnhYbXNXdk8yTFpJRXZhSjJmRHBCYU85Znl1MUZiSG8xSlVkanpDSlkKT0pxZEJLUUgvTGRSK0JkT0NYQzl1YW81dStuS0RxZTZvaE1FZm5VUUpmeGd4QzNwMHhzRGkvNGovYWhCV3cvaApoZk02TUloaUlmZEhWNlN1MWlPQWlNbXNtcDBWSkd4OVR5SG9UZFdKWHkxYjRTNDh5L21rNjdNeThzUDJ0SXRHCksvdGxaaDFteDYwbCtscnZkTDZFVW9CVDVScXdCZDBCN0g3c1V0UkZjVVVkMVZBNXpMYVowYnhkbHVpL1dEMlcKaHVtOHJpRUNnWUVBN0hPZlN3OVRKQzIxSHFwb2kvUHRKOGZ5QjVMRXJaQTBmY21vd2VtMG55dTRyMVkxN2FSTwp6bU5qYmZtYWRrOU95RnJNaS9Ydm5pbW1wcnNmK3Z1dEVkeEJEK3JYMGJPZk52ZEl5NHNMNEFaN2JZSkdUVEk0ClVFREdPRVF2UkpUQmxhQ3hvMGVEcGVSbTZqamhjYjdmcHV6K3ZCaVB2ZFBHbExxU0JuaTczSDBDZ1lFQTE2dzYKazhzUDlCK251MFFkSVdRano0MU9wTzJlb2FKenhndFVRTnkyV0VuRi9ydk51K21ra1BtL0lWbWZvdzFOYXAwNApGL29FeHpUSWw2WkFCcUdjWUtHVDRNSjRlVS9QT2RsbWZtSE5DcThHTGs4TlRBaC9UdVFuZ0VKTDB2UE9Ta0wzCjMrWHg2N010MDhVUXNmRjlDQU8yS3BuQzhOOEw5NmhjOXp6ZTgvTUNnWUEwakptNVQ4V1ZnOGI5OHJkYmF6R28KcHFvbWZyclJLL3hPZkZQU0RNT0VvRzNpSWRISVo3elA1NHpBY3ptZDA1Qlp2THc2MnNTUExRaUpnNHJlOTdJRwpCeUk2akdHOGpDUDFUazNTVnF1ajlTelhNSjI1S0ZFVm5OK3d2NDZWdWsydm1GQUNUckYyVytWM1puN01EYlNjCjM0elpkc2Z6VXk2Ti9Vell2VnBhN1FLQmdRQ3NOZC9JSnpxajZhcmJBdlpudFRoTEFFQXR2WGNQQlZLQWJvZG0KQzFhbWhMSE9SMU50bXBCSEdzU2M4cDFmYXIzSVJhV0dyNktsRmVhZUFLZmJJNnhrRkdDcDlWNlJMMEwrcERNTQo4emJ3TXZVeWdQalRIMjNZSnFITDdpUHhXNi82NkNKWTY1a1NaVTVRYkdoNlRhTlNoUFF1YS95V3JPTTNhMzVnCkJJRGFOUUtCZ0dBSE5EOWVjcGpySElxUFgzekZUYm1uZjZORWl1SmN0aHpPN0hLZzI0Slh3V0FoRWJBaXpUYjQKRnY1VmY0d2dKc2xGSjFmNDdhVjJxSU5ncWJ5ajBMSlNjYksyOGlXVmIwZmxSbnJEZnd0amxaS2lneWRDTlZubApteUNBS2IyOTlZL1d0Y3NobjUxa29DdWtzSVA1VzJwZjk5M2pLbEw0OWNPN0l6N3VKbTEzCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg== - public_key: c3NoLXJzYSBBQUFBQjNOemFDMXljMkVBQUFBREFRQUJBQUFCQVFESE5DNlJ4RmNFWTZBUG40cW03UjJTNWxaWG1XeWpGbG02bE5vUEFTdC84Sm1UMXFQaG1EYUhMU0UvTElpMEFiNGZzN1VSWFNBcGxoTUppVHdNcHVGUHg2TEFGWUxrY21HU0pxaGdUNUZETTh2REFqdWtoK2dySFBpOWVjc1d5aGU1UnlFbzJGZTh4QjQ2SlJIRDFQdjhORU1EaTN1V1QwNXd4eGM2c2U3RDl1b3pUaE44MkZUTEVaV0dzdisyRmsvalh5ZzNWL29rTG90TEg1N3dmY3hzY1A2TlFYYlJTWTdSUUFvKzdRUzQ4ckYwcUtHYWFaVUtDcGtTRUJueVNzaFJ0VElZcFBOOXdMN0ZOS1E4TEE4eVBQem1MWTlROWNyRjlNemlxZkVCZkpiZ0VyckxQbC9MMUR6YU5RTW45UW9HZ2c2L3RkTkp0cmtrSS9CdEF2R24K + - private_key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb3dJQkFBS0NBUUVBNUhGRlVSYWg5QWpqRzBqakJIKzhybFlNaUN2M3Q3TDdPRVdhNEljTHUvWDdqSTF1ClN0YmsyVHVtSkhqU3ZwREY3U3VIYW5hK0UzbFdIMXM4ZzJPTXM3cHA3VWc2eWI3ekxwRTRSMFlGM1RnSkVidlYKeFU0L2JVa3NvZ1QyMDJwZVd1VkZaYUI1b3NVeFhZWUJWaFVFREM1b3NBd2wxSlNGaXQ5SmgzRWhXeXRJMnlMdwpZTUwwTUlWZVZ4M2lyZnNTT1BKdXhXSkcxVmVST1VUUC9sV3A1N3hqZStEc3dnZVFLVnhxSlNJeGtvU2ZpN0pBCk1HZTlSZGk3MXZnSnhOQWJhYmphQ2lpQWdZMU9Td3FoWnNIVGZ3eGpTSDZ6aG9OZE5lTEdGRks1WXB6UVROZzkKekp2dkRpalpJbHkxSmUzbm5CZVN0U2V0YWlGc3J0L0JCSVN4Z3dJREFRQUJBb0lCQURKTGtnUlpaRXpUVEJVcwp4ZmF1blA4UktPOHVKdnNGNS9PcXQzK3BtL2JGSUo0QVlZRU9zUkgyNVF4d29ZMmRXRVp3Wi84VHA2T24ra01yCkZqYWpTMDRpdzhHZlBubytsVkh5WFI2c0Z3eHVrdWlabjJZeVpScU5tc3NOSnI3RFU0VFZwNkxKWXg1b0pnYysKUXJzT0kzYi9ITU50MlVKbGRNVnZoY1BSTDVQZm1EOWpsalZqSTk5dEgyU2RINzYwWG5wZDFqNUlBQjJ6RnBWNQo4YkhLTzJpMmM5Q1pleGZkSENrazdLOVpIcE1PdFBCOTRZMHBoT3NGTTUwbzROa0twb1BRMTRKRjg4U2RzbGg2CmVLQm1PazhQVExKUjE4K0wybEtIa1E1OXFpelFxdnZNclpuNVFYUXJTRkJFd3k5cE9xTm5wVGJpcHI1UlpHWFcKY2p3STFVa0NnWUVBK2FxUWlObVdzNDc0eUxUaEczYmNDSU03bjVzUWhXM1lDMm1Rdnd0d1NMQ2p4YTIxVExERwptRVBDWitYb3dDNGRYcThvYWtKRTRkZU9mSHg5NmJLbmZGZXJHU1BHdmdCWldiNmVZV0sveThsV0svd2lhOVJjClB6TEI5NGZVRmJQVHo5N0pyRldBeHpsWkRRdUJKc09hZEF4S09KNng2Uk9KRVRLdkVDYU1MNjBDZ1lFQTZqemUKdk9LdUhxQ1N6Q1JaTWRBRktySnRIWjVaRi9rYWZwU1BUVGtuNUNLQUJvU2JUSlcvYnVmeEtTYURZQnU2RjA1YgpXY25SSXNlZWZrS2tDQ2YwYnFCZnhPemlrUG9BRkFVU2NCM2NWVnlWS3JuV1NqRE5MMlNFSnVLc09ZRitGS0U3CklRN05tUGI4MFdieG94RjMxdWZyLzhuK2d2RU9GTFZBV3hmdXkrOENnWUVBeEMwcDlONUVkRUxiYVpuM1o4VTEKajlyT2R0TTVZQjYzcS8vL0pKNndVKzI0UWhRRWFZWmVCamI0QXZ1OHI0V012bUdUdUNycVJTdERZcjNQa2xvMwpFSlV5ZEVhUVc2dWFpZEltVVE5dTlZbjJsQWxDWXNneTA5WG1ZOEh1L0Q2WktMVStjcE9jNU81Qzh1VWZUbjVVClZ1dHhScHdyMzZEaUN3bHdWWmgwZnVFQ2dZQVNlSnBYNnNnd1FobFJYOHhvMFM2WEgxcmJheEU3Z3JsRUloTHEKMUFjQlJuY3lER0x5dHh4UmNwamgxZGVtVElsd0xRMm5Gdk1XK3diVWpnekJWK1UrbEFiNVVIVE5XZW1IcXA2NQptS0UzV2dXcFNONU5HMndTd0twckpwVE9OQmZ0S0lteElhbTAxa1U1ZmhTdjkwQ3NBYjNxZmRORUlCNHNJOTdmClVCUFVvUUtCZ0VFR3pIL3hsdk1UQzBlNnhjd0pQNGIyWXNxY2FKVzB6VFRLbmUvRFVLSkQyZ04wMnJGRUp2STEKU3hxYkVHWkorSjlkQUlUdFBXeE5yN0xwNzNsRnpJZWlxSllOS0lzMXVaWXBuRElTZGcvVEg0Rm1rZU9zclVLUQpQbGwwdVpSbWUydVNrSVBGbmhUaXNVc0phK3kvVlhFQndGNmY2cVY0NmZGcDVoSmVPNUpHCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg== + public_key: c3NoLXJzYSBBQUFBQjNOemFDMXljMkVBQUFBREFRQUJBQUFCQVFEa2NVVlJGcUgwQ09NYlNPTUVmN3l1Vmd5SUsvZTNzdnM0UlpyZ2h3dTc5ZnVNalc1SzF1VFpPNllrZU5LK2tNWHRLNGRxZHI0VGVWWWZXenlEWTR5enVtbnRTRHJKdnZNdWtUaEhSZ1hkT0FrUnU5WEZUajl0U1N5aUJQYlRhbDVhNVVWbG9IbWl4VEZkaGdGV0ZRUU1MbWl3RENYVWxJV0szMG1IY1NGYkswamJJdkJnd3ZRd2hWNVhIZUt0K3hJNDhtN0ZZa2JWVjVFNVJNLytWYW5udkdONzRPekNCNUFwWEdvbElqR1NoSitMc2tBd1o3MUYyTHZXK0FuRTBCdHB1Tm9LS0lDQmpVNUxDcUZtd2ROL0RHTklmck9HZzEwMTRzWVVVcmxpbk5CTTJEM01tKzhPS05raVhMVWw3ZWVjRjVLMUo2MXFJV3l1MzhFRWhMR0QK additional_trusted_keys: {} - checking_keys: - - c3NoLXJzYSBBQUFBQjNOemFDMXljMkVBQUFBREFRQUJBQUFCQVFESE5DNlJ4RmNFWTZBUG40cW03UjJTNWxaWG1XeWpGbG02bE5vUEFTdC84Sm1UMXFQaG1EYUhMU0UvTElpMEFiNGZzN1VSWFNBcGxoTUppVHdNcHVGUHg2TEFGWUxrY21HU0pxaGdUNUZETTh2REFqdWtoK2dySFBpOWVjc1d5aGU1UnlFbzJGZTh4QjQ2SlJIRDFQdjhORU1EaTN1V1QwNXd4eGM2c2U3RDl1b3pUaE44MkZUTEVaV0dzdisyRmsvalh5ZzNWL29rTG90TEg1N3dmY3hzY1A2TlFYYlJTWTdSUUFvKzdRUzQ4ckYwcUtHYWFaVUtDcGtTRUJueVNzaFJ0VElZcFBOOXdMN0ZOS1E4TEE4eVBQem1MWTlROWNyRjlNemlxZkVCZkpiZ0VyckxQbC9MMUR6YU5RTW45UW9HZ2c2L3RkTkp0cmtrSS9CdEF2R24K cluster_name: me.localhost - signing_alg: 3 - signing_keys: - - LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb3dJQkFBS0NBUUVBeHpRdWtjUlhCR09nRDUrS3B1MGRrdVpXVjVsc294Wlp1cFRhRHdFcmYvQ1prOWFqCjRaZzJoeTBoUHl5SXRBRytIN08xRVYwZ0taWVRDWWs4REtiaFQ4ZWl3QldDNUhKaGtpYW9ZRStSUXpQTHd3STcKcElmb0t4ejR2WG5MRnNvWHVVY2hLTmhYdk1RZU9pVVJ3OVQ3L0RSREE0dDdsazlPY01jWE9ySHV3L2JxTTA0VApmTmhVeXhHVmhyTC90aFpQNDE4b04xZjZKQzZMU3grZThIM01iSEQralVGMjBVbU8wVUFLUHUwRXVQS3hkS2loCm1tbVZDZ3FaRWhBWjhrcklVYlV5R0tUemZjQyt4VFNrUEN3UE1qejg1aTJQVVBYS3hmVE00cW54QVh5VzRCSzYKeXo1Znk5UTgyalVESi9VS0JvSU92N1hUU2JhNUpDUHdiUUx4cHdJREFRQUJBb0lCQUJydU53MkYyYTNDT2pWaQpnRUFvOWtLUjJVSm1mNFZjMUN5aFN3bVVRdWs5QWNZMjBsa0JWdjNYWUJOR1ZnVGY1M0FwdjJUbGpoK1JKbW0zCm4rS2wvUGZvS1Z5R2kvZU9ieHB2RjN4TnhYbXNXdk8yTFpJRXZhSjJmRHBCYU85Znl1MUZiSG8xSlVkanpDSlkKT0pxZEJLUUgvTGRSK0JkT0NYQzl1YW81dStuS0RxZTZvaE1FZm5VUUpmeGd4QzNwMHhzRGkvNGovYWhCV3cvaApoZk02TUloaUlmZEhWNlN1MWlPQWlNbXNtcDBWSkd4OVR5SG9UZFdKWHkxYjRTNDh5L21rNjdNeThzUDJ0SXRHCksvdGxaaDFteDYwbCtscnZkTDZFVW9CVDVScXdCZDBCN0g3c1V0UkZjVVVkMVZBNXpMYVowYnhkbHVpL1dEMlcKaHVtOHJpRUNnWUVBN0hPZlN3OVRKQzIxSHFwb2kvUHRKOGZ5QjVMRXJaQTBmY21vd2VtMG55dTRyMVkxN2FSTwp6bU5qYmZtYWRrOU95RnJNaS9Ydm5pbW1wcnNmK3Z1dEVkeEJEK3JYMGJPZk52ZEl5NHNMNEFaN2JZSkdUVEk0ClVFREdPRVF2UkpUQmxhQ3hvMGVEcGVSbTZqamhjYjdmcHV6K3ZCaVB2ZFBHbExxU0JuaTczSDBDZ1lFQTE2dzYKazhzUDlCK251MFFkSVdRano0MU9wTzJlb2FKenhndFVRTnkyV0VuRi9ydk51K21ra1BtL0lWbWZvdzFOYXAwNApGL29FeHpUSWw2WkFCcUdjWUtHVDRNSjRlVS9QT2RsbWZtSE5DcThHTGs4TlRBaC9UdVFuZ0VKTDB2UE9Ta0wzCjMrWHg2N010MDhVUXNmRjlDQU8yS3BuQzhOOEw5NmhjOXp6ZTgvTUNnWUEwakptNVQ4V1ZnOGI5OHJkYmF6R28KcHFvbWZyclJLL3hPZkZQU0RNT0VvRzNpSWRISVo3elA1NHpBY3ptZDA1Qlp2THc2MnNTUExRaUpnNHJlOTdJRwpCeUk2akdHOGpDUDFUazNTVnF1ajlTelhNSjI1S0ZFVm5OK3d2NDZWdWsydm1GQUNUckYyVytWM1puN01EYlNjCjM0elpkc2Z6VXk2Ti9Vell2VnBhN1FLQmdRQ3NOZC9JSnpxajZhcmJBdlpudFRoTEFFQXR2WGNQQlZLQWJvZG0KQzFhbWhMSE9SMU50bXBCSEdzU2M4cDFmYXIzSVJhV0dyNktsRmVhZUFLZmJJNnhrRkdDcDlWNlJMMEwrcERNTQo4emJ3TXZVeWdQalRIMjNZSnFITDdpUHhXNi82NkNKWTY1a1NaVTVRYkdoNlRhTlNoUFF1YS95V3JPTTNhMzVnCkJJRGFOUUtCZ0dBSE5EOWVjcGpySElxUFgzekZUYm1uZjZORWl1SmN0aHpPN0hLZzI0Slh3V0FoRWJBaXpUYjQKRnY1VmY0d2dKc2xGSjFmNDdhVjJxSU5ncWJ5ajBMSlNjYksyOGlXVmIwZmxSbnJEZnd0amxaS2lneWRDTlZubApteUNBS2IyOTlZL1d0Y3NobjUxa29DdWtzSVA1VzJwZjk5M2pLbEw0OWNPN0l6N3VKbTEzCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg== type: openssh sub_kind: openssh version: v2` samlCAYAML = `kind: cert_authority metadata: - id: 1640648663670002000 + id: 1736815462677271000 name: me.localhost + revision: 4416cb52-14b9-4197-bae0-1c272906db18 spec: active_keys: - tls: - - cert: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURpakNDQW5LZ0F3SUJBZ0lRRU9IcEhIZkZwZ28wUndQSVJhdkdpakFOQmdrcWhraUc5dzBCQVFzRkFEQmYKTVJVd0V3WURWUVFLRXd4dFpTNXNiMk5oYkdodmMzUXhGVEFUQmdOVkJBTVRERzFsTG14dlkyRnNhRzl6ZERFdgpNQzBHQTFVRUJSTW1NakkwTkRBMk5ESTNPREkyTWpJNE5UQXdOemMzTmpVeU16STVOak15TWpNeU56VXhORFl3CkhoY05NakV4TWpJM01qTTBOREl6V2hjTk16RXhNakkxTWpNME5ESXpXakJmTVJVd0V3WURWUVFLRXd4dFpTNXMKYjJOaGJHaHZjM1F4RlRBVEJnTlZCQU1UREcxbExteHZZMkZzYUc5emRERXZNQzBHQTFVRUJSTW1NakkwTkRBMgpOREkzT0RJMk1qSTROVEF3TnpjM05qVXlNekk1TmpNeU1qTXlOelV4TkRZd2dnRWlNQTBHQ1NxR1NJYjNEUUVCCkFRVUFBNElCRHdBd2dnRUtBb0lCQVFETFRrVFkzQ0NMVStNUllkbEMwM2NUTTR6MUpiRGoxYjFQRWdING9iSmwKRjl4NWtQbzhncWNEbmp5L0x5NHdKeUR2Q2xPMkw1T0k3UnYwa1hFUXoybUVEeExnbjJYRG9ZNUh5VFNOVkZHNgpvZ3BlYmhlUFN1aWl0RUNZYUZDZVZFTGNDa1Q0ZGpqRDlwOExNTnJ4MHRPOXdQU1o1OXBLZUxCOG90RFloOHRCCkcyb2EzSGIzTWt0RGxOY0svVE94RFNzRzUrQ2ljdktTa3QrV04xaXJJQ2pvZ2hWTzJGcForRkdxWUM0Y1EwbWMKM0NRaGJwY1o2VTRkWnpGdFJZVzZPYzNucHBOSkZKWXZSSTRIS1FWY0RCM2N4VkhNTUd5Rzc3aFRzdEwvd0RuaQo4U2s5eml4VzN4S2FvUnlrV2FuWno4eC9WdHNydXJqanNzNDV4NlRoem1VWkFnTUJBQUdqUWpCQU1BNEdBMVVkCkR3RUIvd1FFQXdJQnBqQVBCZ05WSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCUmNKK2NRamFQWjZGbEIKcVhoYzYyWXZldGRpQWpBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQVdYNmxZdUhtMmQyMU41RDN1eUJJelFOdApKVFR3b0xnU3FQd09Tbk1EU0luSDkvMjBqZDNGUk9qakh1M3BQRkNLRmE4OVp0ekZxTHZsTjVOdlh2WHFuOXNKCkdudTYzSVo0TWtEZk9sSVZpWFhQWFF4YllHSkMxRVlVU28rTDdtUTY0VnN5UkFpTXdnbmVwMUxwSGhROGYzU2MKeEZoVkNybFJDMmUrNENBai8vOVZWaDdvTEdSMkNhM0xEcFc5VHFxYnB3MEh0QitNcFVqVWxCWnFVbzNVMm5HTQpia1VhSVZKcnNuYk1rYnNsUGQ2dWtVRDlVTHFuUmxJb3A4cjQ1VTdvYVBhR3g3QVFiWndzbGlsNVVJZlppRmlRCm5USk9kYnJHampVdXlRYkM4UUpZY3RhdENjbVBjZUlXMVVWWFVnZ2JsdXl4VjF1NWsyYzlSb1k2RzhiN0FRPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= - key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBeTA1RTJOd2dpMVBqRVdIWlF0TjNFek9NOVNXdzQ5VzlUeElCK0tHeVpSZmNlWkQ2ClBJS25BNTQ4dnk4dU1DY2c3d3BUdGkrVGlPMGI5SkZ4RU05cGhBOFM0SjlsdzZHT1I4azBqVlJSdXFJS1htNFgKajByb29yUkFtR2hRbmxSQzNBcEUrSFk0dy9hZkN6RGE4ZExUdmNEMG1lZmFTbml3ZktMUTJJZkxRUnRxR3R4Mgo5ekpMUTVUWEN2MHpzUTByQnVmZ29uTHlrcExmbGpkWXF5QW82SUlWVHRoYVdmaFJxbUF1SEVOSm5Od2tJVzZYCkdlbE9IV2N4YlVXRnVqbk41NmFUU1JTV0wwU09CeWtGWEF3ZDNNVlJ6REJzaHUrNFU3TFMvOEE1NHZFcFBjNHMKVnQ4U21xRWNwRm1wMmMvTWYxYmJLN3E0NDdMT09jZWs0YzVsR1FJREFRQUJBb0lCQVFDeXNLNXVkTHZkK2ZOQQpHZUtkaThQRENySS8zY3JsMWIwNFBEbWpVR3U5MHdVampEdUU1OGpuc3pMdFR3aW5waHlhUFZkcWI5S2FyTnkvClR2NHpxam14cXBZSys4Nno3ZEZpWXdSZm05YmgxUDZNRlBOOExIamdXTkhWb3dvSXYwS3NxQklLMTgzNDMxRFcKd3pBTkVDS3ZTMk14eXNqZ1g4ZXZKR092alZzbWN1SU1IWFljbVlORlo0dWpuTnc0dnVSWHhlYUtPY2ZWTGZ2ZwoxSWZMK05IYUh6UXI1YVoydkxST1NpdHVId2cvOFpZZ2hQcVFYLy92ak92M0FENzhXVGxINUZXWjExR0hoeCt1Ck9ZUXcwQ1lvTnNiV1UxeklwVTV0cHdCcDRGV0VlVy9jbTY5NXRBVVRlMzR1N3R1MlJJOVBZMEZDWVJ2ZkM2SUQKK2tDNjRFTEpBb0dCQVBSTEt5a0pjdHNGNngzN1liWXdmQm9ZK3V6YU4wV1o1d1RuRmVFaVp1ZzVVYWJUOTdqRApZTnpaYzQ0aitRbkxFUGVDak5tU1FhVHFxK2QvbUVjTnlXS244cVNFcXlOR0R6YlRXQ2tkMGtyWTVwcm9FVVJnClFqbWFwRHFNNEtOSm9jQ1RCS3lueHo2QzZ6ME9uSnhZM3lMdTdyYVBqeE9HTW5rcm9VMDhMVW56QW9HQkFOVU0KU2NsNGh1R0gxK3ZNL0RtenJoQ1NKbUZIcjE2QjhvWExaMHIyNmFKTnJVQ3AwYUFzV2FHd3JLZXZFcDkzRmg5Ygp3QlZYMHE0bXJ3cmZpTGpCYnRzdnlQM3l1ZWs5cWl6M2ZoMWIvZ0k2eWRKVFEzMEplQzB4UzUyRksvR2gwanEvCm43c2Y1bm5DbTlCRW01ZmdSeDFVUmVhOC9vL2M4cTNhbW94c0grdkRBb0dBZUVZUjU5QlpGZkJpQTQ3aVdwcWcKWHhEeGFXOCtTeXdzaTBOaWlFY3h0eCtSVGJ1S2VSTG9PNU5yeXcxMjdSVm5NeFM1Vjkwa0tKZkpMdDZwRUVKLwpaZTBlRDFXcUZHSEgxOHhSMlZ4dlRwNWZXdURxcjJsYzhaTnJTOUJVUU5CZHJMdzFUdlFEcW9rMlhBYzNuOW81CmNhK0ZJNmltWG94eGlTcXI3YVMwLzNVQ2dZQTJBWEJ1N3V1YUhocGcvc3h0UUJ2K3ZWMlhTVm11SmxpNUM4KzYKVkE3emdxZEpmZ0xTakl1SURrWW1GNTRyNkQ4bVlkYTJVbFhvcVl1endPaGlsVDRwdDlwR2JaSXRDdUdwbG05VQp0KzRTMko0eWY4TGEzbHlsY0JxUDZxTXlGR2c3VmpvQ2NGcTNRTnJJbDZ1dGV6L3JzbUlwMUh6Zk1RNGZmZ3V4ClR2Tmtpd0tCZ1FDbVhaSStvTUdQK3U4KzRVaGxjR01NYUNHZi92UVZLdVJYOHlOYVh1bUx6dk1Xajl0cVhpUzcKK1dQUlhuV01RSnd1QldYMzBTcWdFVVdDbjlzOGxWbzh2TVF4MmFtbXhhWkVEMGRoOHNMSkJDNXJoRmVqV29MbQp3cHg5MXR0S3JJODBKMDYyeW90SFpJYkRyQW1LSGZFeE85U1d4T1hUeFVMUGdvTlJVUW5qSnc9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo= + tls: + - cert: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURpakNDQW5LZ0F3SUJBZ0lRSjZkczBCMXFjVWF6R3c3L2IrRFlzekFOQmdrcWhraUc5dzBCQVFzRkFEQmYKTVJVd0V3WURWUVFLRXd4dFpTNXNiMk5oYkdodmMzUXhGVEFUQmdOVkJBTVRERzFsTG14dlkyRnNhRzl6ZERFdgpNQzBHQTFVRUJSTW1OVEkzTURreU1USXpPVGszT0RVM056ZzVOVGM0T0RrNE1EWTNOakEzTWpVM05qUXlOelV3CkhoY05NalV3TVRFME1EQTBOREl5V2hjTk16VXdNVEV5TURBME5ESXlXakJmTVJVd0V3WURWUVFLRXd4dFpTNXMKYjJOaGJHaHZjM1F4RlRBVEJnTlZCQU1UREcxbExteHZZMkZzYUc5emRERXZNQzBHQTFVRUJSTW1OVEkzTURreQpNVEl6T1RrM09EVTNOemc1TlRjNE9EazRNRFkzTmpBM01qVTNOalF5TnpVd2dnRWlNQTBHQ1NxR1NJYjNEUUVCCkFRVUFBNElCRHdBd2dnRUtBb0lCQVFENGlaUXVTc3M5RlJyWjZVNGFSc3hWWGd1UzlNVlJKRDhrcHBXbFJUSU0KTXY3RXpFQmRVcGtaNWdyU1RUQ1M4TFdodEQ4THJ1NUFJZDFVTldvRkFra1NNdlJPd1hWZFJTT0ZOejZSVkJvUApPTjZBdWlrSW5lUkpGZTBCMXc2QUxlNE01RGx6ZnJMamc4MmtqamRZSnRzaFdHS1NKY2RybTQ2TVFaWE0vLzBZCk05YlFMeDU1eVJCY1FNR25wVmxCQ0pmajZDd1F0cjVZOGxVeFZscHNMbGwrSjBMR2pvTHJtcncxZU8zVGNEelMKbzdlODdFQ0dqbGYyTGk1ei9Pb3dGcWE4RVhMaW9RRjRsRWh6U1FsRDRJdGhUMGlDL3pqR0NmcThxMDF4TjY2UAp1QTk0cm9pYU5mMDNtZWJJL2IvSW9qMEgxNTNCTGZydWlZYnFoRHlHQ0JQcEFnTUJBQUdqUWpCQU1BNEdBMVVkCkR3RUIvd1FFQXdJQnBqQVBCZ05WSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCVFM5Q25hZEFMdFJQNkkKb0ZwRWtUZVRISGhGV2pBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQVJOcjg2QnJXS2E5b3NOMmFJRTBoUVNtRwpiZ2FFY1I3WVF3aW8zWUplYXoyc3RTMHQ4VXVON3FKdkU4dnYxd2F0eCtTMXhhdGdBRWlXRER1WUYzUWhaZUE3CmJMZCtELzc5YlFnNXBmb0E4UDA1UGR5cmtzalZ2SjcrWlY0SFFoaTJOUE9PbkExL3ZMNGI3SG40UXFnRDZsbHcKeFRDS3RJOVoxTVlWN1I5dUthNllpVDlCNWVDR1NCZWdQdnNlbzV6Y2p5aGdJeklTRkp6N09MR0dQT3JyUWpLUworOWJ6bjlnOHM0dHBwd0lEWUh6UFRiOFovR0YycmV3MlM5cDBQUGlnTGIyT1dKc1M5eDcvQVVOa1NHQWxiNER4CmdVc3dsWEhtSXErWUZaeDFZL21DeWlndWdQNnR0MDJjSm0vQTUrNC8vRVMrUGRpK2xqL3o2WitJLzIra1d3PT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= + key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcFFJQkFBS0NBUUVBK0ltVUxrckxQUlVhMmVsT0drYk1WVjRMa3ZURlVTUS9KS2FWcFVVeURETCt4TXhBClhWS1pHZVlLMGswd2t2QzFvYlEvQzY3dVFDSGRWRFZxQlFKSkVqTDBUc0YxWFVVamhUYytrVlFhRHpqZWdMb3AKQ0oza1NSWHRBZGNPZ0MzdURPUTVjMzZ5NDRQTnBJNDNXQ2JiSVZoaWtpWEhhNXVPakVHVnpQLzlHRFBXMEM4ZQplY2tRWEVEQnA2VlpRUWlYNCtnc0VMYStXUEpWTVZaYWJDNVpmaWRDeG82QzY1cThOWGp0MDNBODBxTzN2T3hBCmhvNVg5aTR1Yy96cU1CYW12QkZ5NHFFQmVKUkljMGtKUStDTFlVOUlndjg0eGduNnZLdE5jVGV1ajdnUGVLNkkKbWpYOU41bm15UDIveUtJOUI5ZWR3UzM2N29tRzZvUThoZ2dUNlFJREFRQUJBb0lCQVFESGtURjdPbk9YeUtxVwo3OC9YS2FKSnFncUJKaXFLelNBbXZkekxxSlJYVjF0Yml1YmtDTDhISE1EenZTZVQxZFVDMDBrTWlKcW14SXFFClk1K09CaGZHbFVPM09ZQ1VORUFoYUFyRmgxS2xoblNqeU5mS0kzNTdjUyt1bXBENk8rYzZVc2dQQlYxL2N3WmQKYkJUa284NnhKOWQrb3ZkT1lNcEZ0U1FrU0NsaWxDaDlFZCszZlFMTmZ3dzJqOEpheVpQcE1BMkZKU1k1ZFFLbAp0OWhoM3dLa2pvV3dOTU9yMWZ5TzRzSXc3UnNGdURGNHdaejlZSmhGQ1Q5aFZhejUyQkVQTEdnSWxKS0F2bFdRCndMT0JqSzcyZncyTUZ5SzM3NElYc3YwZVk3RU54NW40eWNxREl2NnBmVEFvTDIrSk9NbkxqY3FaeEJuaG44VmsKdmQrTlZFdEJBb0dCQVBtYy9mOGw3NGlKVitxVy9iU1MwTmtHUHVoYzhBQWVzU1NQdHpENC9UNW16SUxPWXR5aQpUTlR5UkpUR3NJU1UvSEliOUpqYVdBWllDd0ZZektDREZtOG9FQnBiQTZPcDZhOGlGVzRkYUU2ODlzamJMbTBtCjc0TWhFaE9PR2grSkVLUkx5dCsxaGFKUzB0d2g5TGdiVmJuRU1jZkxhNzNNZHNqYWNqU2lGRkUvQW9HQkFQN2wKaWk1MXVWV2xtYlpZMCtOZFNmY2dsSWNWRHE5eUZlNjdCZFgybnBrV3pkRjlEK3ZlTytIeUxtMVl6QjE5bmtrMApYMDJ6T3FadVF1bFdqV01OYWdVYkQ4bkJkbmtHRkx4RkIxLzhERzdBbkFvNXo4b1J2bXJPeWhWTVJGTEdQZjM0CmZPYTFuRmU0TXJmM0lUTDlNZlRPQUh2ZUxsV0xwZ3pqVEo2dU9palhBb0dCQUk5TXlhVEpLcExBQm5EdTdnZlUKb1lGMlRIY3BvNzd0MzlTVmpSM1lVOHFYU2FGdXl1TFBhangyT1ZrUUdCYUZVY2hRdEVOc1ZreU9Ed05lNzFyVwo1dkk1bGNVTHF6TXlRSzRDYXpza050VzlOaEJwaEdXMWpKdERTUlZnNXk1amllSklnTmVkWm5LaUNkdkd3cTlQClFnKzd5cmhnMkNIR1dBdEhIWG1KOHhBUkFvR0JBSVZnclJhMGlUOVV3UU1XcGdGQ0RuTWUvRGxXL25FMXZGNUkKUkx4NktQRW9hcGhrM1pEcG4rSVNMTk1ROVBXMWhyNzloYVVOMVBIRG5vV2t3YVVFSHViL0N4cmlmZERFS3ROOQpOMmUxWnZnSkYxMk9kTGxpNFlYWUlReFY5U1p2RDM4MnFIeThxVXVKV2hqRFd2N29XRnlsOHNEZU9OYVFsVm9ICkVrK3lFVUxQQW9HQUJCNmFzWC95QzVvK2FiMTgvckdkZHNLd3JIbUJqTU5zZ3B4RHU5eVBxMHVGQmVxa0xuakMKSHBwRmlEbHNtdVl6TnZqMzAzR2ZJQ0oyMnFIajd3VE1xNmRtVTZoTTRuZ0dlVU05SGtrbjEwZnVXR1dwdWd0RgpNbHBSeHU3VFBpRDZvQ1JkQ0RnN1NlZnZ2SnptWGRIRDduWDI4R0R0bDdMTmxBbkJCTHRTVFM4PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo= additional_trusted_keys: {} cluster_name: me.localhost - signing_alg: 3 type: saml_idp sub_kind: saml_idp version: v2` diff --git a/lib/auth/middleware.go b/lib/auth/middleware.go index a5d1c43a62c92..e380e04eb0d50 100644 --- a/lib/auth/middleware.go +++ b/lib/auth/middleware.go @@ -596,7 +596,7 @@ func (a *Middleware) GetUser(connState tls.ConnectionState) (authz.IdentityGette // as the local certificate authority if certClusterName != a.ClusterName { // make sure that this user does not have system role - // the local auth server can not truste remote servers + // the local auth server can not trust remote servers // to issue certificates with system roles (e.g. Admin), // to get unrestricted access to the local cluster systemRole := findPrimarySystemRole(identity.Groups) @@ -747,58 +747,6 @@ func (a *Middleware) WrapContextWithUserFromTLSConnState(ctx context.Context, tl return ctx, nil } -// ClientCertPool returns trusted x509 certificate authority pool with CAs provided as caTypes. -// In addition, it returns the total length of all subjects added to the cert pool, allowing -// the caller to validate that the pool doesn't exceed the maximum 2-byte length prefix before -// using it. -func ClientCertPool(client authclient.AccessCache, clusterName string, caTypes ...types.CertAuthType) (*x509.CertPool, int64, error) { - if len(caTypes) == 0 { - return nil, 0, trace.BadParameter("at least one CA type is required") - } - - ctx := context.TODO() - pool := x509.NewCertPool() - var authorities []types.CertAuthority - if clusterName == "" { - for _, caType := range caTypes { - cas, err := client.GetCertAuthorities(ctx, caType, false) - if err != nil { - return nil, 0, trace.Wrap(err) - } - authorities = append(authorities, cas...) - } - } else { - for _, caType := range caTypes { - ca, err := client.GetCertAuthority( - ctx, - types.CertAuthID{Type: caType, DomainName: clusterName}, - false) - if err != nil { - return nil, 0, trace.Wrap(err) - } - - authorities = append(authorities, ca) - } - } - - var totalSubjectsLen int64 - for _, auth := range authorities { - for _, keyPair := range auth.GetTrustedTLSKeyPairs() { - cert, err := tlsca.ParseCertificatePEM(keyPair.Cert) - if err != nil { - return nil, 0, trace.Wrap(err) - } - log.Debugf("ClientCertPool -> %v", CertInfo(cert)) - pool.AddCert(cert) - - // Each subject in the list gets a separate 2-byte length prefix. - totalSubjectsLen += 2 - totalSubjectsLen += int64(len(cert.RawSubject)) - } - } - return pool, totalSubjectsLen, nil -} - // isProxyRole returns true if the certificate role is a proxy role. func isProxyRole(identity authz.IdentityGetter) bool { switch id := identity.(type) { diff --git a/lib/auth/tls_test.go b/lib/auth/tls_test.go index e61c1b7ea8d65..4544ad1a7329d 100644 --- a/lib/auth/tls_test.go +++ b/lib/auth/tls_test.go @@ -20,7 +20,9 @@ import ( "context" "crypto" "crypto/tls" + "crypto/x509" "encoding/base32" + "encoding/pem" "errors" "fmt" "net" @@ -4770,3 +4772,227 @@ func newTestTLSServer(t testing.TB, opts ...testTLSServerOption) *TestTLSServer return srv } + +func TestVerifyPeerCert(t *testing.T) { + t.Parallel() + const ( + localClusterName = "local" + remoteClusterName = "remote" + ) + s := newTestServices(t) + // Set up local cluster name in the backend. + cn, err := services.NewClusterNameWithRandomID(types.ClusterNameSpecV2{ + ClusterName: localClusterName, + }) + require.NoError(t, err) + require.NoError(t, s.UpsertClusterName(cn)) + + now := time.Date(2020, time.November, 5, 0, 0, 0, 0, time.UTC) + + var ( + localUserIdentity = tlsca.Identity{ + Username: "foo", + Groups: []string{"devs"}, + TeleportCluster: localClusterName, + Expires: now, + } + localSystemRole = tlsca.Identity{ + Username: "node", + Groups: []string{string(types.RoleNode)}, + TeleportCluster: localClusterName, + Expires: now, + } + remoteUserIdentity = tlsca.Identity{ + Username: "foo", + Groups: []string{"devs"}, + TeleportCluster: remoteClusterName, + Expires: now, + } + remoteSystemRole = tlsca.Identity{ + Username: "node", + Groups: []string{string(types.RoleNode)}, + TeleportCluster: remoteClusterName, + Expires: now, + } + ) + + localHostCA := suite.NewTestCA(types.HostCA, localClusterName) + remoteHostCA := suite.NewTestCA(types.HostCA, remoteClusterName) + localUserCA := suite.NewTestCA(types.UserCA, localClusterName) + remoteUserCA := suite.NewTestCA(types.UserCA, remoteClusterName) + + caPool := buildPoolInfo( + t, + localHostCA, + localUserCA, + remoteHostCA, + remoteUserCA, + ) + + tests := []struct { + desc string + peer *x509.Certificate + clusterName string + wantErr bool + }{ + { + desc: "local user issued from remote CA", + peer: generateTestCert(t, remoteUserCA, localUserIdentity, localClusterName), + clusterName: localClusterName, + wantErr: true, + }, + { + desc: "local system user issued from remote CA", + peer: generateTestCert(t, remoteHostCA, localSystemRole, localClusterName), + clusterName: localClusterName, + wantErr: true, + }, + { + desc: "local user issued from local host CA", + peer: generateTestCert(t, localHostCA, localUserIdentity, localClusterName), + clusterName: localClusterName, + wantErr: true, + }, + { + desc: "local system user issued from local user CA", + peer: generateTestCert(t, localUserCA, localSystemRole, localClusterName), + clusterName: localClusterName, + wantErr: true, + }, + { + desc: "local user with remote cluster name issued from local user CA", + peer: generateTestCert(t, localUserCA, localUserIdentity, remoteClusterName), + clusterName: localClusterName, + wantErr: true, + }, + { + desc: "local system user with remote cluster name issued from local host CA", + peer: generateTestCert(t, localHostCA, localSystemRole, remoteClusterName), + clusterName: localClusterName, + wantErr: true, + }, + { + desc: "local user issued from local user CA", + peer: generateTestCert(t, localUserCA, localUserIdentity, localClusterName), + clusterName: localClusterName, + wantErr: false, + }, + { + desc: "local system user issued from local host CA", + peer: generateTestCert(t, localHostCA, localSystemRole, localClusterName), + clusterName: localClusterName, + wantErr: false, + }, + { + desc: "remote user issued from local CA", + peer: generateTestCert(t, localUserCA, remoteUserIdentity, remoteClusterName), + clusterName: remoteClusterName, + wantErr: true, + }, + { + desc: "remote system user issued from local CA", + peer: generateTestCert(t, localHostCA, remoteSystemRole, remoteClusterName), + clusterName: remoteClusterName, + wantErr: true, + }, + { + desc: "remote user issued from remote host CA", + peer: generateTestCert(t, remoteHostCA, remoteUserIdentity, remoteClusterName), + clusterName: remoteClusterName, + wantErr: true, + }, + { + desc: "remote system user issued from user CA", + peer: generateTestCert(t, remoteUserCA, remoteSystemRole, remoteClusterName), + clusterName: remoteClusterName, + wantErr: true, + }, + { + desc: "remote user with local cluster name issued from remote user CA", + peer: generateTestCert(t, remoteUserCA, remoteUserIdentity, localClusterName), + clusterName: remoteClusterName, + wantErr: true, + }, + { + desc: "remote system user with local cluster name issued from host CA", + peer: generateTestCert(t, remoteHostCA, remoteSystemRole, localClusterName), + clusterName: remoteClusterName, + wantErr: true, + }, + { + desc: "remote user issued from remote user CA", + peer: generateTestCert(t, remoteUserCA, remoteUserIdentity, remoteClusterName), + clusterName: remoteClusterName, + wantErr: false, + }, + { + desc: "remote system user issued from host CA", + peer: generateTestCert(t, remoteHostCA, remoteSystemRole, remoteClusterName), + clusterName: remoteClusterName, + wantErr: false, + }, + } + + for _, tt := range tests { + t.Run(tt.desc, func(t *testing.T) { + verify := caPool.verifyPeerCert() + err := verify(nil, [][]*x509.Certificate{{tt.peer}}) + if tt.wantErr { + require.ErrorContains(t, err, "access denied: invalid client certificate") + } else { + require.NoError(t, err) + } + }) + } +} + +func buildPoolInfo(t *testing.T, ca ...types.CertAuthority) *HostAndUserCAPoolInfo { + poolInfo := HostAndUserCAPoolInfo{ + Pool: x509.NewCertPool(), + CATypes: make(authclient.HostAndUserCAInfo), + } + + for _, authority := range ca { + for _, c := range authority.GetTrustedTLSKeyPairs() { + cert, err := tlsca.ParseCertificatePEM(c.Cert) + require.NoError(t, err) + poolInfo.Pool.AddCert(cert) + + poolInfo.CATypes[string(cert.RawSubject)] = authclient.CATypeInfo{ + IsHostCA: authority.GetType() == types.HostCA, + IsUserCA: authority.GetType() == types.UserCA, + } + } + } + + return &poolInfo +} + +func generateTestCert(t *testing.T, ca types.CertAuthority, id tlsca.Identity, clusterName string) *x509.Certificate { + tlsKeyPairs := ca.GetTrustedTLSKeyPairs() + require.Len(t, tlsKeyPairs, 1) + signer, err := tlsca.FromKeys(tlsKeyPairs[0].Cert, tlsKeyPairs[0].Key) + require.NoError(t, err) + + priv, err := testauthority.New().GeneratePrivateKey() + require.NoError(t, err) + + id.TeleportCluster = clusterName + subj, err := id.Subject() + require.NoError(t, err) + + pemCert, err := signer.GenerateCertificate(tlsca.CertificateRequest{ + PublicKey: priv.Public(), + Subject: subj, + NotAfter: time.Now().Add(time.Hour), + }) + require.NoError(t, err) + block, rest := pem.Decode(pemCert) + require.NotNil(t, block) + require.Empty(t, rest) + + cert, err := x509.ParseCertificate(block.Bytes) + require.NoError(t, err) + + return cert +} diff --git a/lib/auth/trust/trustv1/service_test.go b/lib/auth/trust/trustv1/service_test.go index 19d12dd01a1e9..605d6a4fba73d 100644 --- a/lib/auth/trust/trustv1/service_test.go +++ b/lib/auth/trust/trustv1/service_test.go @@ -94,7 +94,7 @@ func newCertAuthority(t *testing.T, caType types.CertAuthType, domain string) ty priv, pub, err := ta.GenerateKeyPair() require.NoError(t, err) - key, cert, err := tlsca.GenerateSelfSignedCA(pkix.Name{CommonName: domain}, nil, time.Hour) + key, cert, err := tlsca.GenerateSelfSignedCA(pkix.Name{CommonName: domain, Organization: []string{domain}}, nil, time.Hour) require.NoError(t, err) ca, err := types.NewCertAuthority(types.CertAuthoritySpecV2{ diff --git a/lib/auth/trustedcluster.go b/lib/auth/trustedcluster.go index 1eb69eb0b958a..ff3628ab0963f 100644 --- a/lib/auth/trustedcluster.go +++ b/lib/auth/trustedcluster.go @@ -501,6 +501,9 @@ func (a *Server) validateTrustedCluster(ctx context.Context, validateRequest *au remoteCA.SetRoles(nil) remoteClusterName := remoteCA.GetName() + if remoteClusterName != remoteCA.GetClusterName() { + return nil, trace.AccessDenied("CA name does not match its cluster name") + } if remoteClusterName == domainName { return nil, trace.AccessDenied("remote cluster has same name as this cluster: %v", domainName) } @@ -511,6 +514,22 @@ func (a *Server) validateTrustedCluster(ctx context.Context, validateRequest *au return nil, trace.Wrap(err) } + // ensure the subjects of the CA certs match what the + // cluster name of this CA is supposed to be + for _, keyPair := range remoteCA.GetTrustedTLSKeyPairs() { + cert, err := tlsca.ParseCertificatePEM(keyPair.Cert) + if err != nil { + return nil, trace.Wrap(err) + } + certClusterName, err := tlsca.ClusterName(cert.Subject) + if err != nil { + return nil, trace.AccessDenied("CA certificate subject organization is invalid") + } + if certClusterName != remoteClusterName { + return nil, trace.AccessDenied("the subject organization of a CA certificate does not match the cluster name of the CA") + } + } + remoteCluster, err := types.NewRemoteCluster(remoteClusterName) if err != nil { return nil, trace.Wrap(err) diff --git a/lib/auth/trustedcluster_test.go b/lib/auth/trustedcluster_test.go index f1afbe909fab0..d00fabd3ae7ac 100644 --- a/lib/auth/trustedcluster_test.go +++ b/lib/auth/trustedcluster_test.go @@ -406,6 +406,21 @@ func TestValidateTrustedCluster(t *testing.T) { _, err := server.ValidateTrustedCluster(ctx, req) require.True(t, trace.IsNotImplemented(err), "ValidateTrustedCluster returned an unexpected error, got = %v (%T), want trace.NotImplementedError", err, err) }) + + t.Run("CA cluster name does not match subject organization", func(t *testing.T) { + _, err = a.validateTrustedCluster(ctx, &authclient.ValidateTrustedClusterRequest{ + Token: validToken, + CAs: []types.CertAuthority{ + suite.NewTestCAWithConfig(suite.TestCAConfig{ + Type: types.HostCA, + ClusterName: "remoteCluster", + SubjectOrganization: "commonName", + }), + }, + }) + require.Error(t, err) + require.Contains(t, err.Error(), "the subject organization of a CA certificate does not match the cluster name of the CA") + }) } func newTestAuthServer(ctx context.Context, t *testing.T, name ...string) *Server { diff --git a/lib/service/desktop.go b/lib/service/desktop.go index f44d9048b24e4..9d9b78545a69c 100644 --- a/lib/service/desktop.go +++ b/lib/service/desktop.go @@ -181,7 +181,7 @@ func (process *TeleportProcess) initWindowsDesktopServiceRegistered(log *logrus. log.Debugf("Ignoring unsupported cluster name %q.", info.ServerName) } } - pool, _, err := authclient.DefaultClientCertPool(info.Context(), accessPoint, clusterName) + pool, _, _, err := authclient.DefaultClientCertPool(info.Context(), accessPoint, clusterName) if err != nil { return nil, trace.Wrap(err) } diff --git a/lib/services/suite/suite.go b/lib/services/suite/suite.go index e94764b8895a0..c13060c506b70 100644 --- a/lib/services/suite/suite.go +++ b/lib/services/suite/suite.go @@ -62,9 +62,12 @@ func NewTestCA(caType types.CertAuthType, clusterName string, privateKeys ...[]b // a test certificate authority type TestCAConfig struct { Type types.CertAuthType - ClusterName string PrivateKeys [][]byte Clock clockwork.Clock + ClusterName string + // the below string fields default to ClusterName if left empty + ResourceName string + SubjectOrganization string } // NewTestCAWithConfig generates a new certificate authority with the specified @@ -72,6 +75,13 @@ type TestCAConfig struct { // Keep this function in-sync with lib/auth/auth.go:newKeySet(). // TODO(jakule): reuse keystore.KeyStore interface to match newKeySet(). func NewTestCAWithConfig(config TestCAConfig) *types.CertAuthorityV2 { + if config.ResourceName == "" { + config.ResourceName = config.ClusterName + } + if config.SubjectOrganization == "" { + config.SubjectOrganization = config.ClusterName + } + // privateKeys is to specify another RSA private key if len(config.PrivateKeys) == 0 { // db client CA gets its own private key to distinguish its pub key @@ -99,7 +109,7 @@ func NewTestCAWithConfig(config TestCAConfig) *types.CertAuthorityV2 { Signer: rsaKey.(*rsa.PrivateKey), Entity: pkix.Name{ CommonName: config.ClusterName, - Organization: []string{config.ClusterName}, + Organization: []string{config.SubjectOrganization}, }, TTL: defaults.CATTL, Clock: config.Clock, @@ -113,7 +123,7 @@ func NewTestCAWithConfig(config TestCAConfig) *types.CertAuthorityV2 { SubKind: string(config.Type), Version: types.V2, Metadata: types.Metadata{ - Name: config.ClusterName, + Name: config.ResourceName, Namespace: apidefaults.Namespace, }, Spec: types.CertAuthoritySpecV2{ diff --git a/lib/srv/app/server.go b/lib/srv/app/server.go index e97cfe5dcfbdb..c54c120634d41 100644 --- a/lib/srv/app/server.go +++ b/lib/srv/app/server.go @@ -1184,7 +1184,7 @@ func newGetConfigForClientFn(log logrus.FieldLogger, client authclient.CAGetter, // Fetch list of CAs that could have signed this certificate. If clusterName // is empty, all CAs that this cluster knows about are returned. - pool, _, err := authclient.DefaultClientCertPool(info.Context(), client, clusterName) + pool, _, _, err := authclient.DefaultClientCertPool(info.Context(), client, clusterName) if err != nil { // If this request fails, return nil and fallback to the default ClientCAs. log.Debugf("Failed to retrieve client pool: %v.", trace.DebugReport(err)) diff --git a/lib/srv/db/access_test.go b/lib/srv/db/access_test.go index 1a295c10d788b..f8be533993267 100644 --- a/lib/srv/db/access_test.go +++ b/lib/srv/db/access_test.go @@ -2161,7 +2161,7 @@ func (c *testContext) makeTLSConfig(t testing.TB) *tls.Config { conf := utils.TLSConfig(nil) conf.Certificates = append(conf.Certificates, cert) conf.ClientAuth = tls.VerifyClientCertIfGiven - conf.ClientCAs, _, err = authclient.DefaultClientCertPool(context.Background(), c.authServer, c.clusterName) + conf.ClientCAs, _, _, err = authclient.DefaultClientCertPool(context.Background(), c.authServer, c.clusterName) require.NoError(t, err) return conf } diff --git a/lib/srv/db/proxyserver.go b/lib/srv/db/proxyserver.go index 3d8778d1e648d..c44f977ed3f17 100644 --- a/lib/srv/db/proxyserver.go +++ b/lib/srv/db/proxyserver.go @@ -654,7 +654,7 @@ func (s *ProxyServer) getConfigForServer(ctx context.Context, identity tlsca.Ide }, nil } -func getConfigForClient(conf *tls.Config, ap authclient.ReadDatabaseAccessPoint, log logrus.FieldLogger, caTypes ...types.CertAuthType) func(*tls.ClientHelloInfo) (*tls.Config, error) { +func getConfigForClient(conf *tls.Config, ap authclient.ReadDatabaseAccessPoint, log logrus.FieldLogger, caType types.CertAuthType) func(*tls.ClientHelloInfo) (*tls.Config, error) { return func(info *tls.ClientHelloInfo) (*tls.Config, error) { var clusterName string var err error @@ -664,7 +664,7 @@ func getConfigForClient(conf *tls.Config, ap authclient.ReadDatabaseAccessPoint, log.Debugf("Ignoring unsupported cluster name %q.", info.ServerName) } } - pool, _, err := authclient.ClientCertPool(info.Context(), ap, clusterName, caTypes...) + pool, _, err := authclient.ClientCertPool(info.Context(), ap, clusterName, caType) if err != nil { log.WithError(err).Error("Failed to retrieve client CA pool.") return nil, nil // Fall back to the default config. diff --git a/lib/web/apiserver_test.go b/lib/web/apiserver_test.go index f038cf502625c..ef996f64db10b 100644 --- a/lib/web/apiserver_test.go +++ b/lib/web/apiserver_test.go @@ -7969,7 +7969,7 @@ func createProxy(ctx context.Context, t *testing.T, proxyID string, node *regula // Build the client CA pool containing the cluster's user CA in // order to be able to validate certificates provided by users. var err error - tlsClone.ClientCAs, _, err = authclient.DefaultClientCertPool(info.Context(), authServer.Auth(), clustername) + tlsClone.ClientCAs, _, _, err = authclient.DefaultClientCertPool(info.Context(), authServer.Auth(), clustername) if err != nil { return nil, trace.Wrap(err) }