mirror of
https://github.com/gravitational/teleport.git
synced 2026-11-02 23:31:08 +08:00
* Add a host signers callback to sshutils.Server * Lift host signers callback into regular.Server * Lift host signers callback into reversetunnel.Server
1780 lines
100 KiB
Go
1780 lines
100 KiB
Go
/*
|
|
* Teleport
|
|
* Copyright (C) 2023 Gravitational, Inc.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Affero General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Affero General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
package auth
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"math"
|
|
"slices"
|
|
"strings"
|
|
"sync"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/google/go-cmp/cmp"
|
|
"github.com/google/go-cmp/cmp/cmpopts"
|
|
"github.com/google/uuid"
|
|
"github.com/gravitational/trace"
|
|
"github.com/jonboulle/clockwork"
|
|
"github.com/stretchr/testify/mock"
|
|
"github.com/stretchr/testify/require"
|
|
"golang.org/x/crypto/ssh"
|
|
kyaml "k8s.io/apimachinery/pkg/util/yaml"
|
|
|
|
"github.com/gravitational/teleport"
|
|
"github.com/gravitational/teleport/api/constants"
|
|
"github.com/gravitational/teleport/api/types"
|
|
apisshutils "github.com/gravitational/teleport/api/utils/sshutils"
|
|
"github.com/gravitational/teleport/lib/auth/keystore"
|
|
"github.com/gravitational/teleport/lib/auth/testauthority"
|
|
"github.com/gravitational/teleport/lib/backend"
|
|
"github.com/gravitational/teleport/lib/backend/lite"
|
|
"github.com/gravitational/teleport/lib/modules"
|
|
"github.com/gravitational/teleport/lib/observability/tracing"
|
|
"github.com/gravitational/teleport/lib/services"
|
|
"github.com/gravitational/teleport/lib/sshutils"
|
|
"github.com/gravitational/teleport/lib/utils"
|
|
"github.com/gravitational/teleport/lib/utils/proxy"
|
|
)
|
|
|
|
// TestReadIdentity makes parses identity from private key and certificate
|
|
// and checks that all parameters are valid
|
|
func TestReadIdentity(t *testing.T) {
|
|
clock := clockwork.NewFakeClock()
|
|
a := testauthority.NewWithClock(clock)
|
|
priv, pub, err := a.GenerateKeyPair()
|
|
require.NoError(t, err)
|
|
caSigner, err := ssh.ParsePrivateKey(priv)
|
|
require.NoError(t, err)
|
|
|
|
cert, err := a.GenerateHostCert(services.HostCertParams{
|
|
CASigner: caSigner,
|
|
PublicHostKey: pub,
|
|
HostID: "id1",
|
|
NodeName: "node-name",
|
|
ClusterName: "example.com",
|
|
Role: types.RoleNode,
|
|
TTL: 0,
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
id, err := ReadSSHIdentityFromKeyPair(priv, cert)
|
|
require.NoError(t, err)
|
|
require.Equal(t, "example.com", id.ClusterName)
|
|
require.Equal(t, IdentityID{HostUUID: "id1.example.com", Role: types.RoleNode}, id.ID)
|
|
require.Equal(t, cert, id.CertBytes)
|
|
require.Equal(t, priv, id.KeyBytes)
|
|
|
|
// test TTL by converting the generated cert to text -> back and making sure ExpireAfter is valid
|
|
ttl := 10 * time.Second
|
|
expiryDate := clock.Now().Add(ttl)
|
|
bytes, err := a.GenerateHostCert(services.HostCertParams{
|
|
CASigner: caSigner,
|
|
PublicHostKey: pub,
|
|
HostID: "id1",
|
|
NodeName: "node-name",
|
|
ClusterName: "example.com",
|
|
Role: types.RoleNode,
|
|
TTL: ttl,
|
|
})
|
|
require.NoError(t, err)
|
|
copy, err := apisshutils.ParseCertificate(bytes)
|
|
require.NoError(t, err)
|
|
require.Equal(t, uint64(expiryDate.Unix()), copy.ValidBefore)
|
|
}
|
|
|
|
func TestBadIdentity(t *testing.T) {
|
|
a := testauthority.New()
|
|
priv, pub, err := a.GenerateKeyPair()
|
|
require.NoError(t, err)
|
|
caSigner, err := ssh.ParsePrivateKey(priv)
|
|
require.NoError(t, err)
|
|
|
|
// bad cert type
|
|
_, err = ReadSSHIdentityFromKeyPair(priv, pub)
|
|
require.IsType(t, trace.BadParameter(""), err)
|
|
|
|
// missing authority domain
|
|
cert, err := a.GenerateHostCert(services.HostCertParams{
|
|
CASigner: caSigner,
|
|
PublicHostKey: pub,
|
|
HostID: "id2",
|
|
NodeName: "",
|
|
ClusterName: "",
|
|
Role: types.RoleNode,
|
|
TTL: 0,
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
_, err = ReadSSHIdentityFromKeyPair(priv, cert)
|
|
require.IsType(t, trace.BadParameter(""), err)
|
|
|
|
// missing host uuid
|
|
cert, err = a.GenerateHostCert(services.HostCertParams{
|
|
CASigner: caSigner,
|
|
PublicHostKey: pub,
|
|
HostID: "example.com",
|
|
NodeName: "",
|
|
ClusterName: "",
|
|
Role: types.RoleNode,
|
|
TTL: 0,
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
_, err = ReadSSHIdentityFromKeyPair(priv, cert)
|
|
require.IsType(t, trace.BadParameter(""), err)
|
|
|
|
// unrecognized role
|
|
cert, err = a.GenerateHostCert(services.HostCertParams{
|
|
CASigner: caSigner,
|
|
PublicHostKey: pub,
|
|
HostID: "example.com",
|
|
NodeName: "",
|
|
ClusterName: "id1",
|
|
Role: "bad role",
|
|
TTL: 0,
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
_, err = ReadSSHIdentityFromKeyPair(priv, cert)
|
|
require.IsType(t, trace.BadParameter(""), err)
|
|
}
|
|
|
|
type testDynamicallyConfigurableParams struct {
|
|
withDefaults, withConfigFile, withAnotherConfigFile func(*testing.T, *InitConfig) types.ResourceWithOrigin
|
|
setDynamic func(*testing.T, *Server)
|
|
getStored func(*testing.T, *Server) types.ResourceWithOrigin
|
|
}
|
|
|
|
func testDynamicallyConfigurable(t *testing.T, p testDynamicallyConfigurableParams) {
|
|
initAuthServer := func(t *testing.T, conf InitConfig) *Server {
|
|
authServer, err := Init(context.Background(), conf)
|
|
require.NoError(t, err)
|
|
t.Cleanup(func() { authServer.Close() })
|
|
return authServer
|
|
}
|
|
|
|
t.Run("start with config file, reinit with defaults", func(t *testing.T) {
|
|
t.Parallel()
|
|
conf := setupConfig(t)
|
|
|
|
// Simulate a server with a config-file resource.
|
|
configFileRes := p.withConfigFile(t, &conf)
|
|
authServer := initAuthServer(t, conf)
|
|
|
|
stored := p.getStored(t, authServer)
|
|
require.Equal(t, types.OriginConfigFile, stored.Origin())
|
|
require.Empty(t, resourceDiff(configFileRes, stored))
|
|
|
|
// Reinitialize with the default resource.
|
|
defaultRes := p.withDefaults(t, &conf)
|
|
authServer = initAuthServer(t, conf)
|
|
|
|
// Verify the stored resource is now labeled as originating from defaults.
|
|
stored = p.getStored(t, authServer)
|
|
require.Equal(t, types.OriginDefaults, stored.Origin())
|
|
require.Empty(t, resourceDiff(defaultRes, stored))
|
|
})
|
|
|
|
t.Run("start with dynamic, reinit with defaults", func(t *testing.T) {
|
|
t.Parallel()
|
|
conf := setupConfig(t)
|
|
|
|
// Simulate a server with dynamic configuration.
|
|
authServer := initAuthServer(t, conf)
|
|
p.setDynamic(t, authServer)
|
|
|
|
dynamic := p.getStored(t, authServer)
|
|
require.Equal(t, types.OriginDynamic, dynamic.Origin())
|
|
|
|
// Attempt to reinitialize with the default resource should be a no-op.
|
|
p.withDefaults(t, &conf)
|
|
authServer = initAuthServer(t, conf)
|
|
|
|
// Verify the stored resource remains unchanged.
|
|
stored := p.getStored(t, authServer)
|
|
require.Equal(t, types.OriginDynamic, stored.Origin())
|
|
require.Empty(t, resourceDiff(dynamic, stored))
|
|
})
|
|
|
|
t.Run("start with dynamic, reinit with config file", func(t *testing.T) {
|
|
t.Parallel()
|
|
conf := setupConfig(t)
|
|
|
|
// Simulate a server with dynamic configuration.
|
|
authServer := initAuthServer(t, conf)
|
|
p.setDynamic(t, authServer)
|
|
|
|
dynamic := p.getStored(t, authServer)
|
|
require.Equal(t, types.OriginDynamic, dynamic.Origin())
|
|
|
|
// Reinitialize with a config-file resource.
|
|
configFileRes := p.withConfigFile(t, &conf)
|
|
authServer = initAuthServer(t, conf)
|
|
|
|
// Verify the stored resource is updated.
|
|
stored := p.getStored(t, authServer)
|
|
require.Equal(t, types.OriginConfigFile, stored.Origin())
|
|
require.Empty(t, resourceDiff(configFileRes, stored))
|
|
})
|
|
|
|
t.Run("start with defaults, reinit with config file", func(t *testing.T) {
|
|
t.Parallel()
|
|
conf := setupConfig(t)
|
|
|
|
// Simulate a server with the default resource.
|
|
defaultRes := p.withDefaults(t, &conf)
|
|
authServer := initAuthServer(t, conf)
|
|
|
|
stored := p.getStored(t, authServer)
|
|
require.Equal(t, types.OriginDefaults, stored.Origin())
|
|
require.Empty(t, resourceDiff(defaultRes, stored))
|
|
|
|
// Reinitialize with a config-file resource.
|
|
configFileRes := p.withConfigFile(t, &conf)
|
|
authServer = initAuthServer(t, conf)
|
|
|
|
// Verify the stored resource is updated.
|
|
stored = p.getStored(t, authServer)
|
|
require.Equal(t, types.OriginConfigFile, stored.Origin())
|
|
require.Empty(t, resourceDiff(configFileRes, stored))
|
|
})
|
|
|
|
t.Run("start with config file, reinit with another config file", func(t *testing.T) {
|
|
t.Parallel()
|
|
conf := setupConfig(t)
|
|
|
|
// Simulate a server with a config-file resource.
|
|
configFileRes := p.withConfigFile(t, &conf)
|
|
authServer := initAuthServer(t, conf)
|
|
|
|
stored := p.getStored(t, authServer)
|
|
require.Equal(t, types.OriginConfigFile, stored.Origin())
|
|
require.Empty(t, resourceDiff(configFileRes, stored))
|
|
|
|
// Reinitialize with another config-file resource.
|
|
anotherConfigFileRes := p.withAnotherConfigFile(t, &conf)
|
|
authServer = initAuthServer(t, conf)
|
|
|
|
// Verify the stored resource is updated.
|
|
stored = p.getStored(t, authServer)
|
|
require.Equal(t, types.OriginConfigFile, stored.Origin())
|
|
require.Empty(t, resourceDiff(anotherConfigFileRes, stored))
|
|
})
|
|
}
|
|
|
|
func TestAuthPreference(t *testing.T) {
|
|
t.Parallel()
|
|
ctx := context.Background()
|
|
|
|
testDynamicallyConfigurable(t, testDynamicallyConfigurableParams{
|
|
withDefaults: func(t *testing.T, conf *InitConfig) types.ResourceWithOrigin {
|
|
conf.AuthPreference = types.DefaultAuthPreference()
|
|
return conf.AuthPreference
|
|
},
|
|
withConfigFile: func(t *testing.T, conf *InitConfig) types.ResourceWithOrigin {
|
|
fromConfigFile, err := types.NewAuthPreferenceFromConfigFile(types.AuthPreferenceSpecV2{
|
|
Type: constants.OIDC,
|
|
})
|
|
require.NoError(t, err)
|
|
conf.AuthPreference = fromConfigFile
|
|
return conf.AuthPreference
|
|
},
|
|
withAnotherConfigFile: func(t *testing.T, conf *InitConfig) types.ResourceWithOrigin {
|
|
conf.AuthPreference = newWebauthnAuthPreferenceConfigFromFile(t)
|
|
return conf.AuthPreference
|
|
},
|
|
setDynamic: func(t *testing.T, authServer *Server) {
|
|
dynamically, err := types.NewAuthPreference(types.AuthPreferenceSpecV2{
|
|
SecondFactor: constants.SecondFactorOff,
|
|
})
|
|
require.NoError(t, err)
|
|
_, err = authServer.UpsertAuthPreference(ctx, dynamically)
|
|
require.NoError(t, err)
|
|
},
|
|
getStored: func(t *testing.T, authServer *Server) types.ResourceWithOrigin {
|
|
authPref, err := authServer.GetAuthPreference(ctx)
|
|
require.NoError(t, err)
|
|
return authPref
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestAuthPreferenceSecondFactorOnly(t *testing.T) {
|
|
modules.SetInsecureTestMode(false)
|
|
defer modules.SetInsecureTestMode(true)
|
|
ctx := context.Background()
|
|
|
|
t.Run("starting with second_factor disabled fails", func(t *testing.T) {
|
|
conf := setupConfig(t)
|
|
authPref, err := types.NewAuthPreferenceFromConfigFile(types.AuthPreferenceSpecV2{
|
|
SecondFactor: constants.SecondFactorOff,
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
conf.AuthPreference = authPref
|
|
_, err = Init(ctx, conf)
|
|
require.Error(t, err)
|
|
})
|
|
|
|
t.Run("starting with defaults and dynamically updating to disable second factor fails", func(t *testing.T) {
|
|
conf := setupConfig(t)
|
|
s, err := Init(ctx, conf)
|
|
require.NoError(t, err)
|
|
authpref, err := types.NewAuthPreference(types.AuthPreferenceSpecV2{
|
|
SecondFactor: constants.SecondFactorOff,
|
|
})
|
|
require.NoError(t, err)
|
|
_, err = s.UpsertAuthPreference(ctx, authpref)
|
|
require.Error(t, err)
|
|
})
|
|
}
|
|
|
|
func TestClusterNetworkingConfig(t *testing.T) {
|
|
t.Parallel()
|
|
ctx := context.Background()
|
|
|
|
testDynamicallyConfigurable(t, testDynamicallyConfigurableParams{
|
|
withDefaults: func(t *testing.T, conf *InitConfig) types.ResourceWithOrigin {
|
|
conf.ClusterNetworkingConfig = types.DefaultClusterNetworkingConfig()
|
|
return conf.ClusterNetworkingConfig
|
|
},
|
|
withConfigFile: func(t *testing.T, conf *InitConfig) types.ResourceWithOrigin {
|
|
fromConfigFile, err := types.NewClusterNetworkingConfigFromConfigFile(types.ClusterNetworkingConfigSpecV2{
|
|
ClientIdleTimeout: types.Duration(7 * time.Minute),
|
|
})
|
|
require.NoError(t, err)
|
|
conf.ClusterNetworkingConfig = fromConfigFile
|
|
return conf.ClusterNetworkingConfig
|
|
},
|
|
withAnotherConfigFile: func(t *testing.T, conf *InitConfig) types.ResourceWithOrigin {
|
|
anotherFromConfigFile, err := types.NewClusterNetworkingConfigFromConfigFile(types.ClusterNetworkingConfigSpecV2{
|
|
ClientIdleTimeout: types.Duration(10 * time.Minute),
|
|
KeepAliveInterval: types.Duration(3 * time.Minute),
|
|
})
|
|
require.NoError(t, err)
|
|
conf.ClusterNetworkingConfig = anotherFromConfigFile
|
|
return conf.ClusterNetworkingConfig
|
|
},
|
|
setDynamic: func(t *testing.T, authServer *Server) {
|
|
dynamically, err := types.NewClusterNetworkingConfigFromConfigFile(types.ClusterNetworkingConfigSpecV2{
|
|
KeepAliveInterval: types.Duration(4 * time.Minute),
|
|
})
|
|
require.NoError(t, err)
|
|
dynamically.SetOrigin(types.OriginDynamic)
|
|
_, err = authServer.UpsertClusterNetworkingConfig(ctx, dynamically)
|
|
require.NoError(t, err)
|
|
},
|
|
getStored: func(t *testing.T, authServer *Server) types.ResourceWithOrigin {
|
|
authPref, err := authServer.GetClusterNetworkingConfig(ctx)
|
|
require.NoError(t, err)
|
|
return authPref
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestSessionRecordingConfig(t *testing.T) {
|
|
t.Parallel()
|
|
ctx := context.Background()
|
|
|
|
testDynamicallyConfigurable(t, testDynamicallyConfigurableParams{
|
|
withDefaults: func(t *testing.T, conf *InitConfig) types.ResourceWithOrigin {
|
|
conf.SessionRecordingConfig = types.DefaultSessionRecordingConfig()
|
|
return conf.SessionRecordingConfig
|
|
},
|
|
withConfigFile: func(t *testing.T, conf *InitConfig) types.ResourceWithOrigin {
|
|
fromConfigFile, err := types.NewSessionRecordingConfigFromConfigFile(types.SessionRecordingConfigSpecV2{
|
|
Mode: types.RecordOff,
|
|
})
|
|
require.NoError(t, err)
|
|
conf.SessionRecordingConfig = fromConfigFile
|
|
return conf.SessionRecordingConfig
|
|
},
|
|
withAnotherConfigFile: func(t *testing.T, conf *InitConfig) types.ResourceWithOrigin {
|
|
anotherFromConfigFile, err := types.NewSessionRecordingConfigFromConfigFile(types.SessionRecordingConfigSpecV2{
|
|
Mode: types.RecordAtProxySync,
|
|
})
|
|
require.NoError(t, err)
|
|
conf.SessionRecordingConfig = anotherFromConfigFile
|
|
return conf.SessionRecordingConfig
|
|
},
|
|
setDynamic: func(t *testing.T, authServer *Server) {
|
|
dynamically, err := types.NewSessionRecordingConfigFromConfigFile(types.SessionRecordingConfigSpecV2{
|
|
Mode: types.RecordAtNodeSync,
|
|
})
|
|
require.NoError(t, err)
|
|
dynamically.SetOrigin(types.OriginDynamic)
|
|
_, err = authServer.UpsertSessionRecordingConfig(ctx, dynamically)
|
|
require.NoError(t, err)
|
|
},
|
|
getStored: func(t *testing.T, authServer *Server) types.ResourceWithOrigin {
|
|
authPref, err := authServer.GetSessionRecordingConfig(ctx)
|
|
require.NoError(t, err)
|
|
return authPref
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestClusterID(t *testing.T) {
|
|
conf := setupConfig(t)
|
|
authServer, err := Init(context.Background(), conf)
|
|
require.NoError(t, err)
|
|
defer authServer.Close()
|
|
|
|
cc, err := authServer.GetClusterName()
|
|
require.NoError(t, err)
|
|
clusterID := cc.GetClusterID()
|
|
require.NotEmpty(t, clusterID)
|
|
|
|
// do it again and make sure cluster ID hasn't changed
|
|
authServer, err = Init(context.Background(), conf)
|
|
require.NoError(t, err)
|
|
defer authServer.Close()
|
|
|
|
cc, err = authServer.GetClusterName()
|
|
require.NoError(t, err)
|
|
require.Equal(t, clusterID, cc.GetClusterID())
|
|
}
|
|
|
|
// TestClusterName ensures that a cluster can not be renamed.
|
|
func TestClusterName(t *testing.T) {
|
|
conf := setupConfig(t)
|
|
authServer, err := Init(context.Background(), conf)
|
|
require.NoError(t, err)
|
|
defer authServer.Close()
|
|
|
|
// Start the auth server with a different cluster name. The auth server
|
|
// should start, but with the original name.
|
|
newConfig := conf
|
|
newConfig.ClusterName, err = services.NewClusterNameWithRandomID(types.ClusterNameSpecV2{
|
|
ClusterName: "dev.localhost",
|
|
})
|
|
require.NoError(t, err)
|
|
authServer, err = Init(context.Background(), newConfig)
|
|
require.NoError(t, err)
|
|
defer authServer.Close()
|
|
|
|
cn, err := authServer.GetClusterName()
|
|
require.NoError(t, err)
|
|
require.NotEqual(t, newConfig.ClusterName.GetClusterName(), cn.GetClusterName())
|
|
require.Equal(t, conf.ClusterName.GetClusterName(), cn.GetClusterName())
|
|
}
|
|
|
|
func keysIn[K comparable, V any](m map[K]V) []K {
|
|
result := make([]K, 0, len(m))
|
|
for k := range m {
|
|
result = append(result, k)
|
|
}
|
|
return result
|
|
}
|
|
|
|
// TestPresets tests behavior of presets
|
|
func TestPresets(t *testing.T) {
|
|
ctx := context.Background()
|
|
|
|
presetRoleNames := []string{
|
|
teleport.PresetEditorRoleName,
|
|
teleport.PresetAccessRoleName,
|
|
teleport.PresetAuditorRoleName,
|
|
}
|
|
|
|
t.Run("EmptyCluster", func(t *testing.T) {
|
|
as := newTestAuthServer(ctx, t)
|
|
clock := clockwork.NewFakeClock()
|
|
as.SetClock(clock)
|
|
|
|
err := createPresetRoles(ctx, as)
|
|
require.NoError(t, err)
|
|
|
|
// Second call should not fail
|
|
err = createPresetRoles(ctx, as)
|
|
require.NoError(t, err)
|
|
|
|
// Presets were created
|
|
for _, role := range presetRoleNames {
|
|
_, err := as.GetRole(ctx, role)
|
|
require.NoError(t, err)
|
|
}
|
|
})
|
|
|
|
// Makes sure that existing role with the same name is not modified
|
|
t.Run("ExistingRole", func(t *testing.T) {
|
|
as := newTestAuthServer(ctx, t)
|
|
clock := clockwork.NewFakeClock()
|
|
as.SetClock(clock)
|
|
|
|
access := services.NewPresetEditorRole()
|
|
access.SetLogins(types.Allow, []string{"root"})
|
|
access, err := as.CreateRole(ctx, access)
|
|
require.NoError(t, err)
|
|
|
|
err = createPresetRoles(ctx, as)
|
|
require.NoError(t, err)
|
|
|
|
// Presets were created
|
|
for _, role := range presetRoleNames {
|
|
_, err := as.GetRole(ctx, role)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
out, err := as.GetRole(ctx, access.GetName())
|
|
require.NoError(t, err)
|
|
require.Equal(t, access.GetLogins(types.Allow), out.GetLogins(types.Allow))
|
|
})
|
|
|
|
// If a default allow condition is not present, ensure it gets added.
|
|
t.Run("AddDefaultAllowConditions", func(t *testing.T) {
|
|
as := newTestAuthServer(ctx, t)
|
|
clock := clockwork.NewFakeClock()
|
|
as.SetClock(clock)
|
|
|
|
editorRole := services.NewPresetEditorRole()
|
|
rules := editorRole.GetRules(types.Allow)
|
|
|
|
// Create a new set of rules based on the Editor Role, excluding the ConnectionDiagnostic.
|
|
// ConnectionDiagnostic is part of the default allow rules
|
|
var outdatedRules []types.Rule
|
|
for _, r := range rules {
|
|
if slices.Contains(r.Resources, types.KindConnectionDiagnostic) {
|
|
continue
|
|
}
|
|
outdatedRules = append(outdatedRules, r)
|
|
}
|
|
editorRole.SetRules(types.Allow, outdatedRules)
|
|
editorRole, err := as.CreateRole(ctx, editorRole)
|
|
require.NoError(t, err)
|
|
|
|
// Set up an old Access Role.
|
|
// Remove the new DatabaseServiceLabels default
|
|
accessRole := services.NewPresetAccessRole()
|
|
accessRole.SetDatabaseServiceLabels(types.Allow, types.Labels{})
|
|
accessRole, err = as.CreateRole(ctx, accessRole)
|
|
require.NoError(t, err)
|
|
|
|
err = createPresetRoles(ctx, as)
|
|
require.NoError(t, err)
|
|
|
|
outEditor, err := as.GetRole(ctx, editorRole.GetName())
|
|
require.NoError(t, err)
|
|
|
|
allowRules := outEditor.GetRules(types.Allow)
|
|
require.Condition(t, func() (success bool) {
|
|
for _, r := range allowRules {
|
|
if slices.Contains(r.Resources, types.KindConnectionDiagnostic) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}, "missing default rule")
|
|
|
|
outAccess, err := as.GetRole(ctx, accessRole.GetName())
|
|
require.NoError(t, err)
|
|
allowedDatabaseServiceLabels := outAccess.GetDatabaseServiceLabels(types.Allow)
|
|
require.Equal(t, types.Labels{types.Wildcard: []string{types.Wildcard}}, allowedDatabaseServiceLabels, "missing default DatabaseServiceLabels")
|
|
})
|
|
|
|
// Don't set a default allow rule if the resource is present in the role.
|
|
// Either as part of allowing or denying rules.
|
|
t.Run("DefaultAllowRulesNotAppliedIfExplicitlyDefined", func(t *testing.T) {
|
|
as := newTestAuthServer(ctx, t)
|
|
clock := clockwork.NewFakeClock()
|
|
as.SetClock(clock)
|
|
|
|
// Set up a changed Editor Role
|
|
editorRole := services.NewPresetEditorRole()
|
|
allowRules := editorRole.GetRules(types.Allow)
|
|
|
|
// Create a new set of rules based on the Editor Role,
|
|
// setting a deny rule for a default allow rule
|
|
var outdateAllowRules []types.Rule
|
|
for _, r := range allowRules {
|
|
if slices.Contains(r.Resources, types.KindConnectionDiagnostic) {
|
|
continue
|
|
}
|
|
outdateAllowRules = append(outdateAllowRules, r)
|
|
}
|
|
editorRole.SetRules(types.Allow, outdateAllowRules)
|
|
|
|
// Explicitly deny Create to ConnectionDiagnostic
|
|
denyRules := editorRole.GetRules(types.Deny)
|
|
denyConnectionDiagnosticRule := types.NewRule(types.KindConnectionDiagnostic, []string{types.VerbCreate})
|
|
denyRules = append(denyRules, denyConnectionDiagnosticRule)
|
|
editorRole.SetRules(types.Deny, denyRules)
|
|
|
|
editorRole, err := as.CreateRole(ctx, editorRole)
|
|
require.NoError(t, err)
|
|
|
|
// Set up a changed Access Role
|
|
accessRole := services.NewPresetAccessRole()
|
|
// Remove a default allow label as well.
|
|
accessRole.SetDatabaseServiceLabels(types.Allow, types.Labels{})
|
|
// Explicitly deny DatabaseServiceLabels
|
|
accessRole.SetDatabaseServiceLabels(types.Deny, types.Labels{types.Wildcard: []string{types.Wildcard}})
|
|
|
|
accessRole, err = as.CreateRole(ctx, accessRole)
|
|
require.NoError(t, err)
|
|
|
|
// Apply defaults.
|
|
err = createPresetRoles(ctx, as)
|
|
require.NoError(t, err)
|
|
|
|
outEditor, err := as.GetRole(ctx, editorRole.GetName())
|
|
require.NoError(t, err)
|
|
|
|
allowRules = outEditor.GetRules(types.Allow)
|
|
require.Condition(t, func() (success bool) {
|
|
for _, r := range allowRules {
|
|
if slices.Contains(r.Resources, types.KindConnectionDiagnostic) {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}, "missing default rule")
|
|
|
|
outAccess, err := as.GetRole(ctx, accessRole.GetName())
|
|
require.NoError(t, err)
|
|
allowedDatabaseServiceLabels := outAccess.GetDatabaseServiceLabels(types.Allow)
|
|
require.Nil(t, allowedDatabaseServiceLabels, "does not set Allowed DatabaseService Labels")
|
|
deniedDatabaseServiceLabels := outAccess.GetDatabaseServiceLabels(types.Deny)
|
|
require.Equal(t, types.Labels{types.Wildcard: []string{types.Wildcard}}, deniedDatabaseServiceLabels, "keeps the deny label for DatabaseService")
|
|
})
|
|
|
|
upsertRoleTest := func(t *testing.T, expectedPresetRoles []string, expectedSystemRoles []string) {
|
|
// test state
|
|
ctx := context.Background()
|
|
// mu protects created resource maps
|
|
var mu sync.Mutex
|
|
createdSystemRoles := make(map[string]types.Role)
|
|
createdPresets := make(map[string]types.Role)
|
|
|
|
//
|
|
// Test #1 - populating an empty cluster
|
|
//
|
|
roleManager := newMockRoleManager(t)
|
|
|
|
// EXPECT that non-system resources will be created once
|
|
// and once only.
|
|
roleManager.
|
|
On("CreateRole", mock.Anything, mock.Anything).
|
|
Run(func(args mock.Arguments) {
|
|
r := args[1].(types.Role)
|
|
mu.Lock()
|
|
defer mu.Unlock()
|
|
require.Contains(t, expectedPresetRoles, r.GetName())
|
|
require.NotContains(t, createdPresets, r.GetName())
|
|
require.False(t, types.IsSystemResource(r) && r.GetName() != teleport.SystemOktaRequesterRoleName)
|
|
createdPresets[r.GetName()] = r
|
|
}).
|
|
Return(func(_ context.Context, r types.Role) (types.Role, error) {
|
|
return r, nil
|
|
})
|
|
|
|
// EXPECT that any (and ONLY) system resources will be upserted
|
|
roleManager.
|
|
On("UpsertRole", mock.Anything, mock.Anything).
|
|
Run(func(args mock.Arguments) {
|
|
r := args[1].(types.Role)
|
|
mu.Lock()
|
|
defer mu.Unlock()
|
|
require.True(t, types.IsSystemResource(r))
|
|
require.Contains(t, expectedSystemRoles, r.GetName())
|
|
require.NotContains(t, keysIn(createdSystemRoles), r.GetName())
|
|
createdSystemRoles[r.GetName()] = r
|
|
}).
|
|
Maybe().
|
|
Return(func(_ context.Context, r types.Role) (types.Role, error) {
|
|
return r, nil
|
|
})
|
|
|
|
err := createPresetRoles(ctx, roleManager)
|
|
require.NoError(t, err)
|
|
require.ElementsMatch(t, keysIn(createdPresets), expectedPresetRoles)
|
|
require.ElementsMatch(t, keysIn(createdSystemRoles), expectedSystemRoles)
|
|
roleManager.AssertExpectations(t)
|
|
|
|
//
|
|
// Test #2 - populating an already-populated cluster
|
|
//
|
|
roleManager = newMockRoleManager(t)
|
|
|
|
// EXPECT that createPresets will try to create all expected
|
|
// non-system roles
|
|
roleManager.
|
|
On("CreateRole", mock.Anything, mock.Anything).
|
|
Run(func(args mock.Arguments) {
|
|
mu.Lock()
|
|
defer mu.Unlock()
|
|
require.Contains(t, createdPresets, args[1].(types.Role).GetName())
|
|
}).
|
|
Return(nil, trace.AlreadyExists("dupe"))
|
|
|
|
// EXPECT that any (and ONLY) expected system roles will be
|
|
// automatically upserted
|
|
roleManager.
|
|
On("UpsertRole", mock.Anything, mock.Anything).
|
|
Run(requireSystemResource(t, 1)).
|
|
Maybe().
|
|
Return(func(_ context.Context, r types.Role) (types.Role, error) {
|
|
return r, nil
|
|
})
|
|
|
|
// EXPECT that all of the roles created in the previous step (and ONLY the
|
|
// roles created in the previous step will be queried.
|
|
for name, role := range createdPresets {
|
|
roleManager.
|
|
On("GetRole", mock.Anything, name).
|
|
Return(role, nil)
|
|
}
|
|
|
|
err = createPresetRoles(ctx, roleManager)
|
|
require.NoError(t, err)
|
|
roleManager.AssertExpectations(t)
|
|
|
|
//
|
|
// Test #3 - populating an already-populated cluster with updated presets
|
|
//
|
|
roleManager = newMockRoleManager(t)
|
|
|
|
// Removing a specific resource which is part of the Default Allow Rules
|
|
// should trigger an UpsertRole call
|
|
editorRole := createdPresets[teleport.PresetEditorRoleName]
|
|
var allowRulesWithoutConnectionDiag []types.Rule
|
|
|
|
for _, r := range editorRole.GetRules(types.Allow) {
|
|
if slices.Contains(r.Resources, types.KindConnectionDiagnostic) {
|
|
continue
|
|
}
|
|
allowRulesWithoutConnectionDiag = append(allowRulesWithoutConnectionDiag, r)
|
|
}
|
|
editorRole.SetRules(types.Allow, allowRulesWithoutConnectionDiag)
|
|
|
|
// EXPECT that createPresets will try to create all expected
|
|
// non-system roles
|
|
remainingPresets := toSet(expectedPresetRoles)
|
|
roleManager.
|
|
On("CreateRole", mock.Anything, mock.Anything).
|
|
Run(func(args mock.Arguments) {
|
|
mu.Lock()
|
|
defer mu.Unlock()
|
|
r := args[1].(types.Role)
|
|
require.Contains(t, createdPresets, r.GetName())
|
|
delete(remainingPresets, r.GetName())
|
|
}).
|
|
Return(nil, trace.AlreadyExists("dupe"))
|
|
|
|
// EXPECT that all of the roles created in the first step (and ONLY the
|
|
// roles created in the first step will be queried.
|
|
for name, role := range createdPresets {
|
|
roleManager.
|
|
On("GetRole", mock.Anything, name).
|
|
Return(role, nil)
|
|
}
|
|
|
|
// EXPECT that any system roles will be automatically upserted
|
|
// AND our modified editor resource will be updated using an upsert
|
|
roleManager.
|
|
On("UpsertRole", mock.Anything, mock.Anything).
|
|
Return(func(_ context.Context, r types.Role) (types.Role, error) {
|
|
if types.IsSystemResource(r) {
|
|
require.Contains(t, expectedSystemRoles, r.GetName())
|
|
return r, nil
|
|
}
|
|
require.Equal(t, teleport.PresetEditorRoleName, r.GetName())
|
|
return r, nil
|
|
})
|
|
|
|
err = createPresetRoles(ctx, roleManager)
|
|
require.NoError(t, err)
|
|
require.Empty(t, remainingPresets)
|
|
roleManager.AssertExpectations(t)
|
|
}
|
|
|
|
t.Run("Does not upsert roles if nothing changes", func(t *testing.T) {
|
|
upsertRoleTest(t, presetRoleNames, nil)
|
|
})
|
|
|
|
t.Run("Enterprise", func(t *testing.T) {
|
|
modules.SetTestModules(t, &modules.TestModules{
|
|
TestBuildType: modules.BuildEnterprise,
|
|
})
|
|
|
|
enterprisePresetRoleNames := append([]string{
|
|
teleport.PresetGroupAccessRoleName,
|
|
teleport.PresetRequesterRoleName,
|
|
teleport.PresetReviewerRoleName,
|
|
teleport.PresetDeviceAdminRoleName,
|
|
teleport.PresetDeviceEnrollRoleName,
|
|
teleport.PresetRequireTrustedDeviceRoleName,
|
|
teleport.SystemOktaRequesterRoleName, // This is treated as a preset
|
|
}, presetRoleNames...)
|
|
|
|
enterpriseSystemRoleNames := []string{
|
|
teleport.SystemAutomaticAccessApprovalRoleName,
|
|
teleport.SystemOktaAccessRoleName,
|
|
}
|
|
|
|
enterpriseUsers := []types.User{
|
|
services.NewSystemAutomaticAccessBotUser(),
|
|
}
|
|
|
|
t.Run("EmptyCluster", func(t *testing.T) {
|
|
as := newTestAuthServer(ctx, t)
|
|
clock := clockwork.NewFakeClock()
|
|
as.SetClock(clock)
|
|
|
|
// Run multiple times to simulate starting auth on an
|
|
// existing cluster and asserting that everything still
|
|
// returns success
|
|
for i := 0; i < 2; i++ {
|
|
err := createPresetRoles(ctx, as)
|
|
require.NoError(t, err)
|
|
|
|
err = createPresetUsers(ctx, as)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
// Preset Roles were created
|
|
for _, role := range append(enterprisePresetRoleNames, enterpriseSystemRoleNames...) {
|
|
_, err := as.GetRole(ctx, role)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
// Preset Users were created
|
|
for _, user := range enterpriseUsers {
|
|
_, err := as.GetUser(ctx, user.GetName(), false)
|
|
require.NoError(t, err)
|
|
}
|
|
})
|
|
|
|
t.Run("Does not upsert roles if nothing changes", func(t *testing.T) {
|
|
upsertRoleTest(t, enterprisePresetRoleNames, enterpriseSystemRoleNames)
|
|
})
|
|
|
|
t.Run("System users are always upserted", func(t *testing.T) {
|
|
ctx := context.Background()
|
|
sysUser := services.NewSystemAutomaticAccessBotUser().(*types.UserV2)
|
|
|
|
// GIVEN a user database...
|
|
auth := newMockUserManager(t)
|
|
|
|
// Set the expectation that all user creations will succeed EXCEPT
|
|
// for our known system user
|
|
auth.On("CreateUser", mock.Anything, mock.Anything).
|
|
Run(requireSystemResource(t, 1)).
|
|
Maybe().
|
|
Return(sysUser, nil)
|
|
|
|
// All attempts to upsert should succeed, and record the being upserted
|
|
var upsertedUsers []string
|
|
auth.On("UpsertUser", mock.Anything, mock.Anything).
|
|
Run(func(args mock.Arguments) {
|
|
u := args.Get(1).(types.User)
|
|
upsertedUsers = append(upsertedUsers, u.GetName())
|
|
}).
|
|
Return(sysUser, nil)
|
|
|
|
// WHEN I attempt to create the preset users...
|
|
err := createPresetUsers(ctx, auth)
|
|
|
|
// EXPECT that the process succeeds and the system user was upserted
|
|
require.NoError(t, err)
|
|
auth.AssertExpectations(t)
|
|
require.Contains(t, upsertedUsers, sysUser.Metadata.Name)
|
|
})
|
|
})
|
|
}
|
|
|
|
type mockUserManager struct {
|
|
mock.Mock
|
|
}
|
|
|
|
func newMockUserManager(t *testing.T) *mockUserManager {
|
|
m := &mockUserManager{}
|
|
m.Test(t)
|
|
return m
|
|
}
|
|
|
|
func (m *mockUserManager) CreateUser(ctx context.Context, user types.User) (types.User, error) {
|
|
type delegateFn = func(context.Context, types.User) (types.User, error)
|
|
args := m.Called(ctx, user)
|
|
if delegate, ok := args.Get(0).(delegateFn); ok {
|
|
return delegate(ctx, user)
|
|
}
|
|
return args.Get(0).(types.User), args.Error(1)
|
|
}
|
|
|
|
func (m *mockUserManager) GetUser(ctx context.Context, username string, withSecrets bool) (types.User, error) {
|
|
type delegateFn = func(ctx context.Context, username string, withSecrets bool) (types.User, error)
|
|
args := m.Called(ctx, username, withSecrets)
|
|
if delegate, ok := args.Get(0).(delegateFn); ok {
|
|
return delegate(ctx, username, withSecrets)
|
|
}
|
|
return args.Get(0).(types.User), args.Error(1)
|
|
}
|
|
|
|
func (m *mockUserManager) UpsertUser(ctx context.Context, user types.User) (types.User, error) {
|
|
type delegateFn = func(context.Context, types.User) (types.User, error)
|
|
args := m.Called(ctx, user)
|
|
if delegate, ok := args.Get(0).(delegateFn); ok {
|
|
return delegate(ctx, user)
|
|
}
|
|
return args.Get(0).(types.User), args.Error(1)
|
|
}
|
|
|
|
var _ PresetUsers = &mockUserManager{}
|
|
|
|
type mockRoleManager struct {
|
|
mock.Mock
|
|
}
|
|
|
|
var _ PresetRoleManager = &mockRoleManager{}
|
|
|
|
func newMockRoleManager(t *testing.T) *mockRoleManager {
|
|
m := &mockRoleManager{}
|
|
m.Test(t)
|
|
return m
|
|
}
|
|
|
|
// CreateRole creates a role.
|
|
func (m *mockRoleManager) CreateRole(ctx context.Context, role types.Role) (types.Role, error) {
|
|
type delegateFn = func(context.Context, types.Role) (types.Role, error)
|
|
args := m.Called(ctx, role)
|
|
if delegate, ok := args[0].(delegateFn); ok {
|
|
return delegate(ctx, role)
|
|
}
|
|
if args[0] == nil {
|
|
return nil, args.Error(1)
|
|
}
|
|
return args[0].(types.Role), args.Error(1)
|
|
}
|
|
|
|
func (m *mockRoleManager) GetRole(ctx context.Context, name string) (types.Role, error) {
|
|
type delegateFn = func(context.Context, string) (types.Role, error)
|
|
args := m.Called(ctx, name)
|
|
if delegate, ok := args[0].(delegateFn); ok {
|
|
return delegate(ctx, name)
|
|
}
|
|
if args[0] == nil {
|
|
return nil, args.Error(1)
|
|
}
|
|
return args[0].(types.Role), args.Error(1)
|
|
}
|
|
|
|
func (m *mockRoleManager) UpsertRole(ctx context.Context, role types.Role) (types.Role, error) {
|
|
type delegateFn = func(context.Context, types.Role) (types.Role, error)
|
|
args := m.Called(ctx, role)
|
|
if delegate, ok := args[0].(delegateFn); ok {
|
|
return delegate(ctx, role)
|
|
}
|
|
return args[0].(types.Role), args.Error(1)
|
|
}
|
|
|
|
func requireSystemResource(t *testing.T, argno int) func(mock.Arguments) {
|
|
return func(args mock.Arguments) {
|
|
argOfInterest := args[argno]
|
|
require.Implements(t, (*types.Resource)(nil), argOfInterest)
|
|
require.True(t, types.IsSystemResource(argOfInterest.(types.Resource)))
|
|
}
|
|
}
|
|
|
|
func toSet(items []string) map[string]struct{} {
|
|
result := make(map[string]struct{})
|
|
for _, v := range items {
|
|
result[v] = struct{}{}
|
|
}
|
|
return result
|
|
}
|
|
|
|
func setupConfig(t *testing.T) InitConfig {
|
|
tempDir := t.TempDir()
|
|
|
|
bk, err := lite.New(context.TODO(), backend.Params{"path": tempDir})
|
|
require.NoError(t, err)
|
|
|
|
clusterName, err := services.NewClusterNameWithRandomID(types.ClusterNameSpecV2{
|
|
ClusterName: "me.localhost",
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
return InitConfig{
|
|
DataDir: tempDir,
|
|
HostUUID: "00000000-0000-0000-0000-000000000000",
|
|
NodeName: "foo",
|
|
Backend: bk,
|
|
Authority: testauthority.New(),
|
|
ClusterAuditConfig: types.DefaultClusterAuditConfig(),
|
|
ClusterNetworkingConfig: types.DefaultClusterNetworkingConfig(),
|
|
SessionRecordingConfig: types.DefaultSessionRecordingConfig(),
|
|
ClusterName: clusterName,
|
|
StaticTokens: types.DefaultStaticTokens(),
|
|
AuthPreference: types.DefaultAuthPreference(),
|
|
SkipPeriodicOperations: true,
|
|
KeyStoreConfig: keystore.Config{
|
|
Software: keystore.SoftwareConfig{
|
|
RSAKeyPairSource: testauthority.New().GenerateKeyPair,
|
|
},
|
|
},
|
|
Tracer: tracing.NoopTracer(teleport.ComponentAuth),
|
|
}
|
|
}
|
|
|
|
func newWebauthnAuthPreferenceConfigFromFile(t *testing.T) types.AuthPreference {
|
|
ap, err := types.NewAuthPreferenceFromConfigFile(types.AuthPreferenceSpecV2{
|
|
Type: constants.Local,
|
|
SecondFactor: constants.SecondFactorWebauthn,
|
|
Webauthn: &types.Webauthn{
|
|
RPID: "localhost",
|
|
},
|
|
})
|
|
require.NoError(t, err)
|
|
return ap
|
|
}
|
|
|
|
// Example resources generated using `tctl get all --with-secrets`.
|
|
const (
|
|
hostCAYAML = `kind: cert_authority
|
|
metadata:
|
|
id: 1630515580178991000
|
|
name: me.localhost
|
|
spec:
|
|
active_keys:
|
|
ssh:
|
|
- private_key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcFFJQkFBS0NBUUVBMGpYWHA5SmM3amFVVThydC9NUXZyZjY3TXZoZnk3ZG5ldHoyenBKWFFNNmJQUG5PCjdQVGdIV1o1TFFndVVJTldXLzN6ci9xa2V6UHhmU0lXaUVlcDlRTy9HSytBWHVNWTdmUThNTEc2cS93ckM3UU8KeWxaY3htWGZuS2ZXSkV5RUdralA5VlZmakd3UEdxRUNGWmZtT1pJdXFMVWVadEJKVzduZTZWbkYvWnYzbUhBZwpkc1FFRHphTjdlQnN2NHJyOVhQeHI4anh4Tzg5TjZZN0lsRStoUXNiT3FNSVVsSUVvSk0xYjBOcVFldlhHLzhVClBWWXJLK21hR2dNclNqZHppTjl6VHUzRzNCKzJ3SkJNZzd3VitMQjlJRUU0Y2NHYVVDbUM0QzBuZlByM283emgKTE1UNTZpdGZLdGw0TlkrN1NjRHVSSkN2TkFra3IrNkZtVUc5NXdJREFRQUJBb0lCQVFEUUVJTVlsVnR1WFkrTApNTDFIQjFpNk8veEdneGt1cHFaQ01od0ljMGp4Mkk1SFdHdThsdFNOeFRRRG9xbFUvK3FtdTBKTTJTV2MzTmtXCkpudHZBSi8wNkhScGxxelZQcXNhUERpbmFnTiszK1lyZTFsNFpPc0haU1prQkt3czJaK1g5S0lDRHpLMzV1MDgKU2ttcDNlUCs3L1pHL3A3TTNUVC9HWWJPS2hHUzV0VXdTY291NXV3aFMxQjFJOFNQQW05UGdsMmkyTjVib2s2YgpQTHBqT0xwOUZPVmpVMlNXYUhVa0ZiUUc2TENzOGlJdVdlVzdvMEtkY3B1QndXeGQxd0p3bm5nbjlJVzJ0aUdyCnZLTGlsYzJLR2xITnJxZldiRWw4Z2N5eXBKeUNqZEIvVXkvOFFBOG9uOHBnK1hldThrcnFyRjNTZm5iZHNOaDQKVmNKV09zTUJBb0dCQVBvY1E1ZWd0enZSL1djR0ZtbUxNbTUxTEVDMytPOWxVSUMwMGZ0Q1lkYW5vK0NGUTdEbgpQd0IyLzUyZWZMeUhLUlpjc0lrd2IreXZjYXp3eG9BWlNzMnRlV1FqRUJoOXdRbGlzWlNacVJIVEVMbnY0WjdvCkFMM3JmUjNtM3FHR0tmMm9UQnQ3dEVCcEMwZEVITDlxOVRpbkJJVDVKWGVSSVNzZUcyOGFKUG9IQW9HQkFOY3AKREtjc2hVKzJnaSs2V3p4eThOU3gyMkV5Y29FdUFKbWlSdm1jcExNNE9OTW03dUlQQ2RDYWYyY0UxYzJjVUg5OAppRGw2ZzBYN1ViUjQ4NzdJeVluMi9TU2hiOG56R3ZBNmVBbGJYZk9PYlYvTkIrczUxQzduTGFVSUE1ZEkyTE1WClRJL2xRTnV4cDhieXZDNjU3UVFQZk9jVXlGMVZIVVo5VzNPbU1hVWhBb0dCQU5RREZZRDQ2Wm81M1RaeHdKbmoKTnZMUFBKMzMxWHNKUlA1MVNQSldTUjF1cWNudTdYeU42YWY1TjZGaThaWFdkUXZSc292NGxVZnJTTTh5b3ZGLwpmeHR1aTlKSXJxSTBKMmhQVXYwR2JIMEJqOUl0OS9GOTlQTUpKZHd0RWxlVnBRNnlsU0ZPOFhNUUdGRm0rWCtCCnFURkcwdHZ0WHNkR0xQbWg0ZHVDTEFvTkFvR0FLSS9aamM2TDEwbzk0c2VNR2FwRmtxTnhDekxhZVZYMTBRRFIKeG83c1Vja2dsVlg2cE8xVzJWZTIrdkhqYUo2MllrSlU0QmtqbEZiYndWMG4vbWlWN2dkOUU2SEhsRmZiVlR5QQprcXNCM0QrV2lQLzdKVEpDdVJEbC92Mnl4NXQ1RnRIR0hENkk2cUhrVWxKQ2ZjQ1pXVEdlUjJZWW05Zkc3Qm9ICjJwYVROMkVDZ1lFQXRUQ2o1M253M213RDE1ZjAyZ2pKcWNjeHBkRk1lYlJpNUltMXJ5RUFaSzhwTmNlL2xNclgKVXM1KzM2eFpHWG1CR1ByMVl0UmxIVThQL1owWFdJM3ZDOFpLRHB6SnB4dnB6QmRFV0pUZGlPZEhpV2J4TzZOOQpiYjh3ZUM4STl4ZDlwd0cyMHdYNUVnR0krekdjMlNGa1VDTWROd1JkV3NSTWNCMklMeVV0MmZzPQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo=
|
|
public_key: c3NoLXJzYSBBQUFBQjNOemFDMXljMkVBQUFBREFRQUJBQUFCQVFEU05kZW4wbHp1TnBSVHl1Mzh4Qyt0L3JzeStGL0x0MmQ2M1BiT2tsZEF6cHM4K2M3czlPQWRabmt0Q0M1UWcxWmIvZk92K3FSN00vRjlJaGFJUjZuMUE3OFlyNEJlNHhqdDlEd3dzYnFyL0NzTHRBN0tWbHpHWmQrY3A5WWtUSVFhU00vMVZWK01iQThhb1FJVmwrWTVraTZvdFI1bTBFbGJ1ZDdwV2NYOW0vZVljQ0IyeEFRUE5vM3Q0R3kvaXV2MWMvR3Z5UEhFN3owM3Bqc2lVVDZGQ3hzNm93aFNVZ1Nna3pWdlEycEI2OWNiL3hROVZpc3I2Wm9hQXl0S04zT0kzM05PN2NiY0g3YkFrRXlEdkJYNHNIMGdRVGh4d1pwUUtZTGdMU2Q4K3ZlanZPRXN4UG5xSzE4cTJYZzFqN3RKd081RWtLODBDU1N2N29XWlFiM24K
|
|
tls:
|
|
- cert: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURlVENDQW1HZ0F3SUJBZ0lSQUlvWW1QRUhNV0wwZmp6VkZVZ2l2Ykl3RFFZSktvWklodmNOQVFFTEJRQXcKVmpFUU1BNEdBMVVFQ2hNSGVtRnljWFZ2YmpFUU1BNEdBMVVFQXhNSGVtRnljWFZ2YmpFd01DNEdBMVVFQlJNbgpNVGd6TlRZeE1UZ3dOVFkxTXprMk1qUTNNRFV4TXpRM05qa3pOREV5TmpNME56Y3dPRFkyTUI0WERUSXhNRGt3Ck1URTJOVGswTUZvWERUTXhNRGd6TURFMk5UazBNRm93VmpFUU1BNEdBMVVFQ2hNSGVtRnljWFZ2YmpFUU1BNEcKQTFVRUF4TUhlbUZ5Y1hWdmJqRXdNQzRHQTFVRUJSTW5NVGd6TlRZeE1UZ3dOVFkxTXprMk1qUTNNRFV4TXpRMwpOamt6TkRFeU5qTTBOemN3T0RZMk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBCjlzNGgrUTlpKzBlQ0c0VWNtSThFbEg1MHBlWmFkV2JzdzZDUStCZmF0em1NQWJEa016WGpSTHlNZy8xNFdSRGsKWTU4OUpCWVgrTzRBYXBRNno5MFRhTzhHamN1RmxvcWlFcTZOci9VTjJMYnc2am9KdTYvQ0dmcWIzNXZKT1NDdApKMWp5am5Cc2ZVNTRzRGFGcWpPRG1BL2l3YjNsSlZSV1pmYUdQSGZtRTRUcHJCSzdXV2FHbmlDZktUdGQza3lHCnkzWXpGZEJzSDU0OU9Lc1BFUlJOdTVCdlpzcmZWazRDdnlKNWVxREE1NlBaU1pmSVptZEk4VUdsRmk0V3lhMHEKUHRtWmg4bURGSnpVNnNXZWY5bTRqM3grMmF1UFEra2M3cjJneFdLZ2lTR1FBT2hLU0VhaEZDUW9UU3NzemVReApoZG9xamZUK1NsUWlQQlhJbDhTbzlRSURBUUFCbzBJd1FEQU9CZ05WSFE4QkFmOEVCQU1DQXFRd0R3WURWUjBUCkFRSC9CQVV3QXdFQi96QWRCZ05WSFE0RUZnUVVlSDJQTUhjRmwwTnkvQmozcE4xTExlSStPZTB3RFFZSktvWkkKaHZjTkFRRUxCUUFEZ2dFQkFMeU5aRXByOWtWbk5ORERiWWxWd0M1bnRlUEU2Z0ZQdGRjU3JjYmcyU01temtMMgppSjhCQnJ1ZVBmTllrMVE0c2xlN0FDeTRQL1dzU2xYZThqQkY0bm5KaUkxM2kvaUtQOEJzNVVIQWwwUTJ6RnlMCmp0Sk9JRlFuT1hiUmxQU1RQY21jcWdVUUcrL3lGOGhQVndHNnRwOVZoeXlCVkdlMDRlWU44eVNnbkZKTUloNGcKeDEzcytTWjE1RFkzSERnTGNCSjA5dXA4Q3NJdGV1RG05aG1jbGJ1bUc4OVEyQ3I4T25TcmYzTDNFSVhyelZBbwp3eEUwN21IWnkxSjBvNnljdWJXOWVuS2J3bTRKRHRhaHc4QzlERitvQXJlUEdaSXJXdVZpWFZYeTV6S2NOQW9LCjVXY0Q5RHdjcTFFUnVreGNFWWlrV05BV1FFNnVaMGVYZ0pKWlJ2OD0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
|
|
key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb3dJQkFBS0NBUUVBOXM0aCtROWkrMGVDRzRVY21JOEVsSDUwcGVaYWRXYnN3NkNRK0JmYXR6bU1BYkRrCk16WGpSTHlNZy8xNFdSRGtZNTg5SkJZWCtPNEFhcFE2ejkwVGFPOEdqY3VGbG9xaUVxNk5yL1VOMkxidzZqb0oKdTYvQ0dmcWIzNXZKT1NDdEoxanlqbkJzZlU1NHNEYUZxak9EbUEvaXdiM2xKVlJXWmZhR1BIZm1FNFRwckJLNwpXV2FHbmlDZktUdGQza3lHeTNZekZkQnNINTQ5T0tzUEVSUk51NUJ2WnNyZlZrNEN2eUo1ZXFEQTU2UFpTWmZJClptZEk4VUdsRmk0V3lhMHFQdG1aaDhtREZKelU2c1dlZjltNGozeCsyYXVQUStrYzdyMmd4V0tnaVNHUUFPaEsKU0VhaEZDUW9UU3NzemVReGhkb3FqZlQrU2xRaVBCWElsOFNvOVFJREFRQUJBb0lCQUhkODZ1TzYrRS94bWVNYQorZkkrWTVoRTlOS1JDTUNJT1I2cE1TWjczZzhSRkdDSk5LSTZkN0tDbW9FWWlWaU5uaFZCTmdldmpxR2RFS1NJCjZVUlRveDhOZ2gzS0ovM3ZWbkkzQWkvck0yMzFmQVBhWDNYM3JNQ0pIVWdRRTBiT05DYTFvSkVuaXM3TDNCQnMKQlNDVzJpSVhwcy9uMFBYV3RCR2ZYZlFPbEZ4ajdKbXdwdDlqYTYyankxa3hlTVdMemlqQUZ1QzRwRTl3WUVaVApGa0ovb2FVdzR4WXM5N0pnelRNUHFJSlUzMStNYTNoNGFPQ2lPK2RzSExhK2tRUkZIN0tHOUtRaWlRYzdrTmdGCnljN2s3L2s3UVJSbG1mZmZLN3E3YUtVNkNueHVxOG05UThob2Q5QVdjQ3ZyTm9jSmVjSzcvSzFzNlhMYXhSTFgKRGFLc0xRMENnWUVBK0lBOGNRVmcveU5xbGQ5c2lHZ0NETy9DVUNwM21uZjdxZTNQeEZIWHVSdFNzaHJheE9qVQpRVXFtbHV5VWRCZTZLQnA4ZWxoVmFlYlZsdFNNd2xyWXNpUlIxaTV0SDNnRGUybXRheE5VZ0xtTGoyZUhVWGN3Cmk1UW1yQ1AyTzY4V0xQZjg4SkkwQWtOWWx3em5aWUg2VEZKbFp0MkxoU3ZRTG1qeFArWDZTT01DZ1lFQS9rREwKNndJMjVoYU1DbTBSWitrQWM1T2FJcUx0OUNWeWNTaGdzblBjK2xBQll0ZVRkclhjVW1FaklQYW1uZ1pKZUpvSgpoUDNxaHBja1JVcWwrSldhN3lXRnJocTdyTHlpTVNBb0VwaXdQMkRUMkxROWFXR0lONjdwSU9ObWtpamU2NmNNCjBsd05hQTBtL3Q5ZWZUZ2RLOUpHYnNoaTVnRFFiTFVtMW5Gd1prY0NnWUFMenJ3UWVycnpKSkdwOFdYTXpYUmIKZlFEMG9pL3dyUWJPT2ppSEVZUjRqUzNPdkt2c2MwdXlsb04zNUdIaGFrYzBKSjRKaWl6MHpUMFUzNkNZazR4OApXbkZ4QmQrMWdSUlpSdG93bmtpRG5VMWVVUU1EQWZEU2tRV05aR0FNMGZMeHpBNit0NU8xRDlJanl6OHJlWk9WCkVNMDBxQTQ3RTZ2ZXFLbmQ2V1dORlFLQmdBa3Z6aTV2cGd3cVJHVWNDOFQxWms3R3hvcjUyQjg2T3loYmpTTGwKak5aK2pZNUV1ODlPUXVlM0dzM1dHNjhhQ3cyUWcwZUs1UzUzeDVlNVdzWGdvZmlDSXBKbjVPQVk4TU5WcGgwRgo1MWhpNTBTdFBvclFPMXZIdGlTNkVycTFQMWpFY0hJcFlWS2hKd2VPaXB0N3E1SXB4dUc1MjlqenJwUSs5MmhJCk1RZUJBb0dCQUkrNnE2OGFvdW41bE5sU3NoTVg0citoZlNtbFhXYmcvdU1OQXROdWhtZndmSE0zWmR3SU9ZWlYKRTloalFNQXh6RFduZkx1ajljRkJQM2NER0s0NytoU0U2N082eHBrYk9BYzk4dUlXZVEzb3lyWEd5akQ3TGdrYwpxajFRa2ZiZE4wMU1BdEN0MDhaSlRwZzR1OUdXUUVVQWY2ckJaKzJPN2ZVdEJuUG40TXpsCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg==
|
|
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
|
|
name: me.localhost
|
|
spec:
|
|
active_keys:
|
|
ssh:
|
|
- private_key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb3dJQkFBS0NBUUVBMnZ1ekRQRHZWTElYZTdicDZIc1ZiM3NHak0xZ3lFa2hkWVBUMVVzZ01Kd1JuL1VSCk5EQTZST2pya2NUSEhyRXhnL002dVlQaGN2K2UweUFOZk9JMXROWVgvQ3hGcWdCcGFpRE5YRGpRajdyV2E4RDQKWmNyNkdIVXoza3VDN0k0QTJaUlJXK2M3ajhlZDFEbTlzZ0lpOW1BU3NXL0M2RTZTblEvVGlXVk9hTEdqdEVTdwo5L0lpenc1S2pPYnJLMGRXUXZiMXY1SW8rTUpVbko1NE5jWUlMRm9pYk9WeDdQU1FzWCtDK1JwQ3BIbFIrWnNWClVmSzFrd0l4eXg1Q25BTEMzcnlkOUFaSnY2aVdoci9uczZyWmU5b21xMHd6VUpnT045VE5aQjdZTjRhUmlYSmMKNkpsZmpjdUpnZ2ZDbVZaSWNyRm9wd3kzdnp4LzBxNVVCOVRNRFFJREFRQUJBb0lCQUhVNHkyNGdBMTJwUDl6ZgoyM0t4Z0pYK20xRUFGOURmSk9RTlAzWXNFdjB5YmxUY0VPdUk3WWc1enZCbkQ5Z2tMa2RlQ28rSVEwVVdCT1VyCmdVemFvcms4NmZYNWxRa2QwMUFXWXhmODZkZ213ZVZJbFMrWWFpeHhnT1I4TTRlQnRIN0VZSkQ3eE95QWhNSTQKYm8wOWk0MnJmQll6cDNoSHAwQWdXckp2NG5zenJtVGl2d2s4b0JRS2pGbDZ5VjU2L0g4K3VxaWlSS28vRDlPTApXSU51M1JXRTd4RVpJdlNBZlFMYUFyVG1XaXVVMkhrTklTSmJqRGxrd1phMmtjQ1VQUnVkbFJsOWw2WVM0ZUpSClhNU3RaVmQrcVRpVHhFc29TcTBjRmI3dTlYcEs0a3U3TXR5dDFHY0V0MnIvQzRrcXJFNFAyK3c3RmkvalN2VjYKdUZoWW41a0NnWUVBM3VuK0JMN21hSUhsOGxNclVrcG5SUFJNenllOGFyREplbnM4RXYzTUNyVkxLR0p5NUV6cwppc2ZmVythYTJSejhGOFk0U09aZjZaTk9CS3RzOHFYbkVxL0RhVEgyY3NxMFZXUWxNOFZQNkl3SHpTemNXaThwCnVVRUFOTFg3aG9maTFmZERGNnE2cTFrcmJtdjREa085RGdnRVpxVUR6KzB1dWZhTFNWWG05TzhDZ1lFQSszeFoKTGRJdjVjbXNHWTZhL0xXVjgwRjZHMVMxYUVJVDlBdXNpTThFcnhybEZpbjRSL2dDcEMzSjJod0ZKYldzUjN0OApMVUgxdWxqdE82Mmk2enkzUUlJa1RFNDRveUo0V1RVSEpWQ0VEYXFvcldySklWWTZxMFBlWGs5VDVwa1dzRFpOCldGeDRKQzZhdDZDcEtSTEJPSHdoSm1mYU53K1daamVob251L1pzTUNnWUJpMGI2UFlnV0luTlZRYUxoU3diTW8KS1ZrSG1LajVieWZTU1dGblZlV25kWms4N08vYjc1SUpML1AvcktwR3g0ZW1EblNUTkxXZU9YUWpzODhYZnA2QwpkVEtlcHN5SE5QOWV2NGVTZk0wZzNUcjBKUWdHWHRRVFVSS0RTNDJXcFJUVkg4azVhN0ZYRnErZlF2UHpkdW9QCmwxUkVJTEVnOHhkOHp5UU9QYXVtTndLQmdRREprZXlrMW5DL3ZMcXRyV2k2bncwMmNjZmVlaklCQTkyY1lYTUUKSVBJL0s4NXN5bTBQdWxEYnFUdStEM0ZzdlVYOThaTWhiMW4yNStvV1NHRnFMVHN3Z0Y5NXJjU2x0UzVEU2thVQorUWt2THhlT0VDWndDdjV4WWErdFplWDQwY0dtc1krakFGTG5wVmNyVWFIa292eXVPb2dUa1hBTmEvZi9yQjFvCjc4a0ZJd0tCZ0Q1cHVRd3NodXRYdmNOOCs1bUZDc2d6YW5hckYxSllPdTE2MkhVU2ZPQ2k4aS9VRDNWSUpYQmwKbWpNQVN4elhRamFSa2dQZXNqTmtsTEoyekJsK3ZLaG1jb3NJelNOdzM5b1ZMcC9ObTBiRzlpZmdUdmlha1N6MwpHNFhLYUdNczdRQ3h4bjZsc2ptYTRxYlFlU3JwWmVSMXVtOXJ4TVhLaVdGSUtERXN5TUpNCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg==
|
|
public_key: c3NoLXJzYSBBQUFBQjNOemFDMXljMkVBQUFBREFRQUJBQUFCQVFEYSs3TU04TzlVc2hkN3R1bm9leFZ2ZXdhTXpXRElTU0YxZzlQVlN5QXduQkdmOVJFME1EcEU2T3VSeE1jZXNUR0Q4enE1ZytGeS81N1RJQTE4NGpXMDFoZjhMRVdxQUdscUlNMWNPTkNQdXRacndQaGx5dm9ZZFRQZVM0THNqZ0RabEZGYjV6dVB4NTNVT2IyeUFpTDJZQkt4YjhMb1RwS2REOU9KWlU1b3NhTzBSTEQzOGlMUERrcU01dXNyUjFaQzl2Vy9raWo0d2xTY25uZzF4Z2dzV2lKczVYSHM5SkN4ZjRMNUdrS2tlVkg1bXhWUjhyV1RBakhMSGtLY0FzTGV2SjMwQmttL3FKYUd2K2V6cXRsNzJpYXJURE5RbUE0MzFNMWtIdGczaHBHSmNsem9tVitOeTRtQ0I4S1pWa2h5c1dpbkRMZS9QSC9TcmxRSDFNd04K
|
|
tls:
|
|
- cert: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURlRENDQW1DZ0F3SUJBZ0lRVENnQUVvV3BBa2U4YWdHandmVmtkVEFOQmdrcWhraUc5dzBCQVFzRkFEQlcKTVJBd0RnWURWUVFLRXdkNllYSnhkVzl1TVJBd0RnWURWUVFERXdkNllYSnhkVzl1TVRBd0xnWURWUVFGRXljeApNREV5TWprd01qRXdNakUwTmpjM05UQXlOREF6TnpBNE5qQXpPVEV6TmpNd056Y3lNemN3SGhjTk1qRXdPVEF4Ck1UWTFPVE01V2hjTk16RXdPRE13TVRZMU9UTTVXakJXTVJBd0RnWURWUVFLRXdkNllYSnhkVzl1TVJBd0RnWUQKVlFRREV3ZDZZWEp4ZFc5dU1UQXdMZ1lEVlFRRkV5Y3hNREV5TWprd01qRXdNakUwTmpjM05UQXlOREF6TnpBNApOakF6T1RFek5qTXdOemN5TXpjd2dnRWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUJEd0F3Z2dFS0FvSUJBUUM5Cjg5dFE1YTB0bzQ5dkN3dmxFTUpYTnBiYkpzUVIram96QzJScFFTLzZBSHlHbytueXRKUTZSclp6UWlZeTVkb2UKUTArUmhPTGM0R1Q4R0JQdTBrRmUwejk4Zlp4TC8wb2kvZ0trVTgrM0VOaDFuN1krbjV0RVBvbHZsZTBZUm5lWAp3NWpna1lDZG1TTjFMZXVqYW96OUpyYXVUMzRPSGwzdFNoZ3pBUkV1ZlBVVDJQNXlaQXNCdW9nYzBHd055MUo4Cml1UXpDb0tNektOM2ZidFhYU2llU3pubWxQeWMyeXpIcW1UZGdQNnVDNWFrVXpnT3E5ZGFjUkpxVWJRVXlXOUUKVk80MWRQK2wrMXdzNmdSaFNuK29Sc0JLOG1TVW1JNjc4VjE2b3RxT1I2ZDl5VnZKVTZSbjEvMWIzYk5ES3I2awpYSWwwR1FYczNtajd0QUEzVHNCRkFnTUJBQUdqUWpCQU1BNEdBMVVkRHdFQi93UUVBd0lDcERBUEJnTlZIUk1CCkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCVFovZGxCRDdncWpKTU9rR2laSitGL0NXbkh5akFOQmdrcWhraUcKOXcwQkFRc0ZBQU9DQVFFQXU4cVZUZTYzZnd4UkM3cFU2bzRscldSby9ldnB3VkhkV04yT1NES0t4UU5ISURhbQovRDlnamhtdnphQWFKY3E2UmdkaTNCWlRuZDhsSDYzUlZuVHk4RzljUTNTYmFBMHlSQzMyQnQ3bjh6aUYxTTNqCkFxck5zV0hIWkZydkJKWkx2UDBqbms5RmRtSmFYc3o0cGgyRndYQjFTUkdFT3lVcFAvSS9OeVUyNFovRGFvOG4KWlRSazAvbHBVUis2SGp0UGliUTdJejkxcWtxNmsxcEY0SXdlbG5xU1Vqc2FjLzBGa1lib1I0UHkvT1BUbmtIRgpVR2doRUFHRzNnZXFsaGI4Q3FUYmRwKzhLb0R6RzNBOUtRUURBWUlMNkh5Mm9nVEJmU241Uk5WY2pLdHI0QS9UClhnSnlUdjdHZ0FabkZHT1dMc3B2TDhJQVdGYmN4T2hwV2hEaDNRPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
|
|
key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBdmZQYlVPV3RMYU9QYndzTDVSRENWemFXMnliRUVmbzZNd3RrYVVFditnQjhocVBwCjhyU1VPa2EyYzBJbU11WGFIa05Qa1lUaTNPQmsvQmdUN3RKQlh0TS9mSDJjUy85S0l2NENwRlBQdHhEWWRaKzIKUHArYlJENkpiNVh0R0VaM2w4T1k0SkdBblpramRTM3JvMnFNL1NhMnJrOStEaDVkN1VvWU13RVJMbnoxRTlqKwpjbVFMQWJxSUhOQnNEY3RTZklya013cUNqTXlqZDMyN1YxMG9ua3M1NXBUOG5Oc3N4NnBrM1lEK3JndVdwRk00CkRxdlhXbkVTYWxHMEZNbHZSRlR1TlhUL3BmdGNMT29FWVVwL3FFYkFTdkprbEppT3UvRmRlcUxhamtlbmZjbGIKeVZPa1o5ZjlXOTJ6UXlxK3BGeUpkQmtGN041bys3UUFOMDdBUlFJREFRQUJBb0lCQVFDWkFiTHBxUGdrU1JtaQpncTFrS0duQ3dwQWxtMFpZak0wUWpONm5BZ0ZaU2NjRTFVZi9Yb0gvcHpJVUNYYW5qUXB6VWhqbnlMak0zbHU1CnpOTlJqajlsMkpmTStZbEtsaXJyb053VDdnYmxHVWFqQ0xGT0pGWjNWRUIwaDduaDBmRkhhQ0RlMDVWY1hSeDQKcVRLa0FaSHI0S0ZLSzNJSWdXRjdZREc1OCtRWkl0N01BdDQyc1NrUlhaenNyaUVzVWxZNU9xT1dlVHlkYy93dQpDK292V1FlOUU2bnRSc0EvY25nS0M1bnp6T0pCano3SlVTMGQ2UnBGK1Zodk9SRlZ6YTZKMnpRRXJsWWtFdVVUCkJYdThsVmhhcDVOU09nd3ByZXVmb2tNZVY4eGRNdUxuVEthdHVjajIwT3JFRUlHZVFrb08yTzhTeDJtNitOS0kKbzBTT2kzU0pBb0dCQU5LVkk4R0JHQUpSUlV2NVBnVkNDQ1VHSkFBRmtxY0FMTFlaZ0NMZCtLYStBVW41L2VONwpWemR4b2VqNG1UcnFOb0RLTnk5b0N2Z1RBWTlWZ3RZZllpdlNQbW5ZZk9FbTJUR2pLRTJSYzhBd0R5UWdHWFJVCm5WOUVueHRUUHF5dU9tQTFqa0ladXBLeUU0b0drdTE4MDRVaTB2d2pJUWI3cDdML0ZGYksvaGlmQW9HQkFPYnIKclBrOHdicnBlVk9QWmVudzVzbjVhTUpjdDM3emt4dHZzejVSVWlsZnZtVkdja1lyMU41SGpmZjVVVGcwNmNWdgp1N0dGY0NLQmhncFdqSXM3dHZ4cDhUVFM1VEZaWHZqY2VhRC91ZkFiN3ZUVnR0L1hRMFUwQ28rcDdzMENKWlZKCjY2MUtUU1RCYlFtR0xYYmNqNmFYdVM3bzFJM1FRU1l4NW5LV1F5aWJBb0dCQUtBTWZocUtGVWRkb1g5MnRhNmwKV3k5WWxXLzJ6RmxsQnBaNGx5em83QjArK0JmVGl5V2tEc3V5NzgzemMvS1ZKRXVLWlpzQVJxWDVQQXhHZjZSaQpRZWp3YUVObUtMT3ZKUkJXNDBEaE5jcHlQRy9HZmRJdXBWVk5BR2h5UW9aWC9VSTJNaU1IRHdpRGs5b3AyTzNyCkc1QnF3VlNsRm1zS1JaRUQwZCtOZE1ZZEFvR0FkVDNQRXJQd1FHL3RzNmtvdTBBZVRRbWVVS0EyWWZSVkNpY0sKUUdlVmFZQTg4THAxcG43Mmt1eU5mZ3ROVzFZeUlwWDZHOFYrQzJicm9UQVVKMVRvTVB1eEJYclY5dHBEUitMWQp0ZzlnWGpJd2ZvcExVUmJBQnRESFUrMlpXdWp1SC8vcDhvKzQzeUo5czhvMkp4VVFzaXB5VVFqUmNqYjcvT0owCitGU21RR1VDZ1lBdU5XcFhrbVkzbGtRSEFpU3RlblhTT2Zqc0xsbm5XWFJoTDVBYTZqRVZRT3FnUldVQnZ2YWkKK1RQRTNUTHQ5MGwveTZOdjU0dDdrT1QvSlEvREU4WmFiMERlTjdBRzRwRjMwNkxpYlpZNmswc3M1UDNXME8vbAozekJzQ0lEY3BHOWw4bDZSNkUwdHN0Z0I1c25hOE4rRzA2V3Q1R0M0UitRSVd1YTVpUmtVTXc9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo=
|
|
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
|
|
metadata:
|
|
id: 1696989861240620000
|
|
name: me.localhost
|
|
spec:
|
|
active_keys:
|
|
tls:
|
|
- cert: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURqVENDQW5XZ0F3SUJBZ0lSQU5XcUtsOWR3WGYrVTBWUmhxNGEyaTB3RFFZSktvWklodmNOQVFFTEJRQXcKWURFVk1CTUdBMVVFQ2hNTWJXVXViRzlqWVd4b2IzTjBNUlV3RXdZRFZRUURFd3h0WlM1c2IyTmhiR2h2YzNReApNREF1QmdOVkJBVVRKekk0TkRBd09URXhNams0TlRBek1qYzRPVEV3TURJNE5qUXlPREV6TmpRMk9UQTVNamt3Ck9UQWVGdzB5TXpFd01URXdNakEwTWpGYUZ3MHpNekV3TURnd01qQTBNakZhTUdBeEZUQVRCZ05WQkFvVERHMWwKTG14dlkyRnNhRzl6ZERFVk1CTUdBMVVFQXhNTWJXVXViRzlqWVd4b2IzTjBNVEF3TGdZRFZRUUZFeWN5T0RRdwpNRGt4TVRJNU9EVXdNekkzT0RreE1EQXlPRFkwTWpneE16WTBOamt3T1RJNU1Ea3dnZ0VpTUEwR0NTcUdTSWIzCkRRRUJBUVVBQTRJQkR3QXdnZ0VLQW9JQkFRRGlDNU5GVDhmUy9hSzdSSVVRVnFjVmFxaFBzMFNuU0prTmd3azEKUHZkeFV1OWZZMlNwek5NaUUzSGZlb0Y4S1h2YUU0aHJzMEFGOVRmYlpJTnM1RjNHNTNzOUg3Q2JXWHpOWVRtZApCN0gyWEVxVGp3N0xGL2pzYzkwcTN4ZnZqMkk0Z29tOUdYK3dGMXdaRldjZXVJRkJTdXdCRkV6a1Yzc1o5NEVqClBsWUIxK2lnNlJoWGhvUjdhRlJUNDFvZmtMUUovMDdBVmR4blUranp5VkVFSVk3SjUwUWU3bFc2Nk9wL3BncmwKR1FBSnkwbnowUVpVYVJjVmZrODVHK3NwMnhjcUJ6clJHbXNybmw1TmhMdGJqcUJIUkZ2cU5XS1pLa1V2M0NjUApiTytWT1krV1FmV0UzRThhekxUQ2ppcnJXYWVXeTNLR0RTZGF5YktOK0FKbVpqU3hBZ01CQUFHalFqQkFNQTRHCkExVWREd0VCL3dRRUF3SUJwakFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlFhVmMzdXlYWnoKdDBWLzFnNzE3MzMrRjFhaHNqQU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUF6NTVkVnVFdmVLdnJtYThzL0dWSQo2Q0t5akNNYXNjWmhwV1JIT3QxRjQ1T0pjcXg1RDBQeVhSenZXS2NTYzlZTkN0M1BzSi8yNGp3VDlLaElqK2NiClQ5Z0h5WXNkb3pWY2NzMXNZTkFjK3VFSmRSOEsydHJqa1JJN0Q5VmZvTEJJVFlHUkJGTWpSOEE1bENlUzVnTkgKRG42V09rSlpRUi9UQS9IbFFlUmttMW5teUp3VVVQOVA0aUVWVlVSS0lMRVVNTS9EdERXdTZuNnM2K0pVVXNDNwp5QmI2T3JQeVRGbkV4TFljN2RhYUM1bm5UVDZHY2xUSm4wYkJ2UmtXdUFVa1FtWXJyYkpBMnhEVjFBL0JOcmp3Ci9aU2ErU1ZlVWJxSW05ZEVESE4zQUhXcmJzbWwyVjI3YUtrMHVUK0JmeUJBZ3NSdGpMN0U2YUdJanlNcStlOW4KYmc9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
|
|
key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb3dJQkFBS0NBUUVBNGd1VFJVL0gwdjJpdTBTRkVGYW5GV3FvVDdORXAwaVpEWU1KTlQ3M2NWTHZYMk5rCnFjelRJaE54MzNxQmZDbDcyaE9JYTdOQUJmVTMyMlNEYk9SZHh1ZDdQUit3bTFsOHpXRTVuUWV4OWx4S2s0OE8KeXhmNDdIUGRLdDhYNzQ5aU9JS0p2Umwvc0JkY0dSVm5IcmlCUVVyc0FSUk01RmQ3R2ZlQkl6NVdBZGZvb09rWQpWNGFFZTJoVVUrTmFINUMwQ2Y5T3dGWGNaMVBvODhsUkJDR095ZWRFSHU1VnV1anFmNllLNVJrQUNjdEo4OUVHClZHa1hGWDVQT1J2cktkc1hLZ2M2MFJwcks1NWVUWVM3VzQ2Z1IwUmI2alZpbVNwRkw5d25EMnp2bFRtUGxrSDEKaE54UEdzeTB3bzRxNjFtbmxzdHloZzBuV3NteWpmZ0NabVkwc1FJREFRQUJBb0lCQUQ5R01EWkJxOVRDek0rUQowWktPUHZ6K3V4aDhQT1o2cXVVZVhmQjZyTGNiR1FoaGdTY0t2N3NWS0ZYL0s4bStydjJQWkN1SnBJMUdaQmxVCm5IbFp2MnBURjZzM2VLOHpzSHlwRDRDR1MrbURVaGpWL2JVYUE4TGtkKzl0UFgwQWJPVVduVW5Dbm55RFBYT0UKQ3phTlBSa3l5TGRRb0dsMmwyM2dXMVNyT1ZZUVBEUjZncWVJZVFYa3pHYUFUQ2twZWYrOVk4US9pTkZUR05oZAppamtXSUZOdEYzQjdIODUwdnR0VFFRckE3QXQ3ZnN2bmo2YVVDUkQ3MmFYZGJmeHIwK0VQbUR6WGNhejM3U20yClg3ZkJrakRFa0pCa0gwVnBnZHdvMDh3cmtzbnBieUNpbE95alp4Z3lhUWw2NGFKcGVUN1FHbEMxcm1kUEFmTU4KSEdweFBwVUNnWUVBK21vbllBVW1oSVpTR0R6VjI0NFc0QVRnVFdGb2gxb24wKzlZZ2xxR1RUZFFBM2dXYy9ReQowSmJ6QXpOVFZnODNibWhvU3NtbUMwZ1BoSytBb3BCZXc5ZlVxMmhIOVptUzVjZE1CaTJ6cFdvZHQrWXMvNys1Ckk3d3d2bGgvY3llelQvU0ZyazVCVVB0azZFR1pLZk1KdGZlNDcvb05uUzRmc3lmYlAyWDVUWHNDZ1lFQTV4WkcKSmhiYkwwWFljL0plc0JucXBuRFZHNXhkbkh6aGx0aVB3QzdGbHRDRUpuNFdhTUNpSUtsL0o3VGUzbndqMHk0YQpSVzFTWGN6anc5dHZxY0V3aE9CQUZBUHlsd0FWWjUyOTRzdWZzMnk4SHBFcFhhMjlIRXNReW50TE9JRFZyYkVsClJCV1pEb0xhbllVRTNtWml5WnZ0ZU9TT0hTajVhUnIzRTg1UmtNTUNnWUFweUVLUG8reGNXbWtpUUN4U3VPK2EKSzFZZHN5NFV2M2M3eG9qWEh6R2ZlcVl3SGY1cEZJclNBUTNGTC9Bc3dOYzM1ZFhZL0xKbTJYdzFZRzh2TUxXUApLZGtEVEtBTkc3WEYveTN4TGZqMmxiRWx1Uk16RFJOZ0lndGtCeklremEvK25FY2Q0VkxHcDF1YjRTNGtNTGdqCkU1VlkvVGorUys3Z0hydFhaYlZtTndLQmdET3A2eTBBMXlnT2VZSVNvZERGT296VGxSR0ROL3FRZ083MG84N1gKcGgwOXFRM2lDcWlJeUxaOHJvejJCdzIrdTFPdmJ2Z3VwTWVMMHpBcWt5QmtyTEJJWW9zWEJ0bHpqMVdIRXJqdAp4VnFiNk1MOHVUN1VaUDg2V1JxcnpmbG45RjNNeVFRYndBaGFnUDNPaTNRZGQrQ1RGOWg3WUxwc09yYWc3TFJrCjRCOTVBb0dCQU9maHNVSzVSZm1RU1ZzN08wMmMrdWFVelB2dnEwaXNqNW45dWlOaFQxdjFDUGY4YStZdkkyTisKcWV5bHkwRjN3L2sxbElaUzFjWlMwRDVWMUd6bmVHTUgreWYwVFAvNmlUcElHTC94N1pTNGJEZjE3dEc5dklDdgoya1JBTno5WHpzVzFETm9CRkJmZXg5NDFmT0RzdHlvdThvYmF3dDdJWThTdU1GMHV3aDlBCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg==
|
|
additional_trusted_keys: {}
|
|
cluster_name: me.localhost
|
|
type: db_client
|
|
sub_kind: db_client
|
|
version: v2`
|
|
databaseCAYAML = `kind: cert_authority
|
|
metadata:
|
|
id: 1640648663670001000
|
|
name: me.localhost
|
|
spec:
|
|
active_keys:
|
|
tls:
|
|
- cert: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURpakNDQW5LZ0F3SUJBZ0lRRU9IcEhIZkZwZ28wUndQSVJhdkdpakFOQmdrcWhraUc5dzBCQVFzRkFEQmYKTVJVd0V3WURWUVFLRXd4dFpTNXNiMk5oYkdodmMzUXhGVEFUQmdOVkJBTVRERzFsTG14dlkyRnNhRzl6ZERFdgpNQzBHQTFVRUJSTW1NakkwTkRBMk5ESTNPREkyTWpJNE5UQXdOemMzTmpVeU16STVOak15TWpNeU56VXhORFl3CkhoY05NakV4TWpJM01qTTBOREl6V2hjTk16RXhNakkxTWpNME5ESXpXakJmTVJVd0V3WURWUVFLRXd4dFpTNXMKYjJOaGJHaHZjM1F4RlRBVEJnTlZCQU1UREcxbExteHZZMkZzYUc5emRERXZNQzBHQTFVRUJSTW1NakkwTkRBMgpOREkzT0RJMk1qSTROVEF3TnpjM05qVXlNekk1TmpNeU1qTXlOelV4TkRZd2dnRWlNQTBHQ1NxR1NJYjNEUUVCCkFRVUFBNElCRHdBd2dnRUtBb0lCQVFETFRrVFkzQ0NMVStNUllkbEMwM2NUTTR6MUpiRGoxYjFQRWdING9iSmwKRjl4NWtQbzhncWNEbmp5L0x5NHdKeUR2Q2xPMkw1T0k3UnYwa1hFUXoybUVEeExnbjJYRG9ZNUh5VFNOVkZHNgpvZ3BlYmhlUFN1aWl0RUNZYUZDZVZFTGNDa1Q0ZGpqRDlwOExNTnJ4MHRPOXdQU1o1OXBLZUxCOG90RFloOHRCCkcyb2EzSGIzTWt0RGxOY0svVE94RFNzRzUrQ2ljdktTa3QrV04xaXJJQ2pvZ2hWTzJGcForRkdxWUM0Y1EwbWMKM0NRaGJwY1o2VTRkWnpGdFJZVzZPYzNucHBOSkZKWXZSSTRIS1FWY0RCM2N4VkhNTUd5Rzc3aFRzdEwvd0RuaQo4U2s5eml4VzN4S2FvUnlrV2FuWno4eC9WdHNydXJqanNzNDV4NlRoem1VWkFnTUJBQUdqUWpCQU1BNEdBMVVkCkR3RUIvd1FFQXdJQnBqQVBCZ05WSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCUmNKK2NRamFQWjZGbEIKcVhoYzYyWXZldGRpQWpBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQVdYNmxZdUhtMmQyMU41RDN1eUJJelFOdApKVFR3b0xnU3FQd09Tbk1EU0luSDkvMjBqZDNGUk9qakh1M3BQRkNLRmE4OVp0ekZxTHZsTjVOdlh2WHFuOXNKCkdudTYzSVo0TWtEZk9sSVZpWFhQWFF4YllHSkMxRVlVU28rTDdtUTY0VnN5UkFpTXdnbmVwMUxwSGhROGYzU2MKeEZoVkNybFJDMmUrNENBai8vOVZWaDdvTEdSMkNhM0xEcFc5VHFxYnB3MEh0QitNcFVqVWxCWnFVbzNVMm5HTQpia1VhSVZKcnNuYk1rYnNsUGQ2dWtVRDlVTHFuUmxJb3A4cjQ1VTdvYVBhR3g3QVFiWndzbGlsNVVJZlppRmlRCm5USk9kYnJHampVdXlRYkM4UUpZY3RhdENjbVBjZUlXMVVWWFVnZ2JsdXl4VjF1NWsyYzlSb1k2RzhiN0FRPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
|
|
key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBeTA1RTJOd2dpMVBqRVdIWlF0TjNFek9NOVNXdzQ5VzlUeElCK0tHeVpSZmNlWkQ2ClBJS25BNTQ4dnk4dU1DY2c3d3BUdGkrVGlPMGI5SkZ4RU05cGhBOFM0SjlsdzZHT1I4azBqVlJSdXFJS1htNFgKajByb29yUkFtR2hRbmxSQzNBcEUrSFk0dy9hZkN6RGE4ZExUdmNEMG1lZmFTbml3ZktMUTJJZkxRUnRxR3R4Mgo5ekpMUTVUWEN2MHpzUTByQnVmZ29uTHlrcExmbGpkWXF5QW82SUlWVHRoYVdmaFJxbUF1SEVOSm5Od2tJVzZYCkdlbE9IV2N4YlVXRnVqbk41NmFUU1JTV0wwU09CeWtGWEF3ZDNNVlJ6REJzaHUrNFU3TFMvOEE1NHZFcFBjNHMKVnQ4U21xRWNwRm1wMmMvTWYxYmJLN3E0NDdMT09jZWs0YzVsR1FJREFRQUJBb0lCQVFDeXNLNXVkTHZkK2ZOQQpHZUtkaThQRENySS8zY3JsMWIwNFBEbWpVR3U5MHdVampEdUU1OGpuc3pMdFR3aW5waHlhUFZkcWI5S2FyTnkvClR2NHpxam14cXBZSys4Nno3ZEZpWXdSZm05YmgxUDZNRlBOOExIamdXTkhWb3dvSXYwS3NxQklLMTgzNDMxRFcKd3pBTkVDS3ZTMk14eXNqZ1g4ZXZKR092alZzbWN1SU1IWFljbVlORlo0dWpuTnc0dnVSWHhlYUtPY2ZWTGZ2ZwoxSWZMK05IYUh6UXI1YVoydkxST1NpdHVId2cvOFpZZ2hQcVFYLy92ak92M0FENzhXVGxINUZXWjExR0hoeCt1Ck9ZUXcwQ1lvTnNiV1UxeklwVTV0cHdCcDRGV0VlVy9jbTY5NXRBVVRlMzR1N3R1MlJJOVBZMEZDWVJ2ZkM2SUQKK2tDNjRFTEpBb0dCQVBSTEt5a0pjdHNGNngzN1liWXdmQm9ZK3V6YU4wV1o1d1RuRmVFaVp1ZzVVYWJUOTdqRApZTnpaYzQ0aitRbkxFUGVDak5tU1FhVHFxK2QvbUVjTnlXS244cVNFcXlOR0R6YlRXQ2tkMGtyWTVwcm9FVVJnClFqbWFwRHFNNEtOSm9jQ1RCS3lueHo2QzZ6ME9uSnhZM3lMdTdyYVBqeE9HTW5rcm9VMDhMVW56QW9HQkFOVU0KU2NsNGh1R0gxK3ZNL0RtenJoQ1NKbUZIcjE2QjhvWExaMHIyNmFKTnJVQ3AwYUFzV2FHd3JLZXZFcDkzRmg5Ygp3QlZYMHE0bXJ3cmZpTGpCYnRzdnlQM3l1ZWs5cWl6M2ZoMWIvZ0k2eWRKVFEzMEplQzB4UzUyRksvR2gwanEvCm43c2Y1bm5DbTlCRW01ZmdSeDFVUmVhOC9vL2M4cTNhbW94c0grdkRBb0dBZUVZUjU5QlpGZkJpQTQ3aVdwcWcKWHhEeGFXOCtTeXdzaTBOaWlFY3h0eCtSVGJ1S2VSTG9PNU5yeXcxMjdSVm5NeFM1Vjkwa0tKZkpMdDZwRUVKLwpaZTBlRDFXcUZHSEgxOHhSMlZ4dlRwNWZXdURxcjJsYzhaTnJTOUJVUU5CZHJMdzFUdlFEcW9rMlhBYzNuOW81CmNhK0ZJNmltWG94eGlTcXI3YVMwLzNVQ2dZQTJBWEJ1N3V1YUhocGcvc3h0UUJ2K3ZWMlhTVm11SmxpNUM4KzYKVkE3emdxZEpmZ0xTakl1SURrWW1GNTRyNkQ4bVlkYTJVbFhvcVl1endPaGlsVDRwdDlwR2JaSXRDdUdwbG05VQp0KzRTMko0eWY4TGEzbHlsY0JxUDZxTXlGR2c3VmpvQ2NGcTNRTnJJbDZ1dGV6L3JzbUlwMUh6Zk1RNGZmZ3V4ClR2Tmtpd0tCZ1FDbVhaSStvTUdQK3U4KzRVaGxjR01NYUNHZi92UVZLdVJYOHlOYVh1bUx6dk1Xajl0cVhpUzcKK1dQUlhuV01RSnd1QldYMzBTcWdFVVdDbjlzOGxWbzh2TVF4MmFtbXhhWkVEMGRoOHNMSkJDNXJoRmVqV29MbQp3cHg5MXR0S3JJODBKMDYyeW90SFpJYkRyQW1LSGZFeE85U1d4T1hUeFVMUGdvTlJVUW5qSnc9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo=
|
|
additional_trusted_keys: {}
|
|
cluster_name: me.localhost
|
|
signing_alg: 3
|
|
type: db
|
|
sub_kind: db
|
|
version: v2`
|
|
jwtCAYAML = `kind: cert_authority
|
|
metadata:
|
|
id: 1630515580249460000
|
|
name: me.localhost
|
|
spec:
|
|
active_keys:
|
|
jwt:
|
|
- private_key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBNWNQaFordnk2N05NbDhwbDJ4SllvSDVFOTl0a1UzVlByTGhnVkhOMmpuZmoyRlhNCm9RdVRKbUJOdWVEd3FiVFpKREJmQ0d1bTU2RVczK1YrQUtsY3pFNVdFS2NBR0wxL3ZvOGU0NDNBRmwzQXRHVVEKSWRHVzRoL0o0Q3BTNG9idVVlMGt3K0JiZnlocUJ2a2lTNmxtUUpjV0hLbzd2aWZhRTJKc1hmZStESklSMS80eApvYjlrbkw1QWVoRS9XV25CY0RiWXROcHlFOHBoQzdGaDgzYmFUdldqbXNWTEZaaWEzKzJqL255aWRzUmUxNGMyCnR4czRWRXp6UVpaYTMwMlpESFRpRmM4MzJtY3lCTEFzRnMycHNsSkxiUnZLdllBS1dLTnRRcnRlSHIwUFBmamEKQjM3cmNWMXlLYTJONjNRTnZrd2FRMWlnbllqSmE3blRQYWpVSndJREFRQUJBb0lCQUY0b1ZMSUt2bVVhK0RObwpMUytHcUMwMU1ieEUreXM4Y3VjOE03WElEM2k0NXZWYnk5emZhbkVhbkIrbGI5cU1FMFJDVWwrWUJqRDhFZXkxCkZscmREUHRveXRwT0picjl4V0RwTStaYXk3SWV2Mzd0djV1c1VXSGZWeEozSmJwUlEwN3RtTmh3ays1Yk9JQWQKRHBIbEhOTXhWMDF0OGNldWV5N2djYnBjY1ZTaXJNYy9ERTlGcFNONFRRWFloMlRDSnVZcTdncFo1SGJ2MlpleApDOHFTTnZqVVlVTithTGlDZ2pBRFhZdGdmV2RUVWN0YkhldVUrL2Ftb3cyUitOVjFWMGpML3lOQm0rdmZUVXNuCmprNFMxQWx1U3FrT0FFaHJhZjM2UzRNcWZQWm8zbXhFOC96TVZTdEY5MTdvQVRKMlZrNzVZaGxINnMzM1BKN1kKMXdDeVdZa0NnWUVBOFRoT1E4M01xTjFTL1VVcUJWeGRaaS9HZFBldmQrbFUvY2FIQVhTNmJyd2RYNEpITTkrbApaczZVWFdocWJHUXFSVlRvZ1dna2VBSHp4R3I1S2QvSTlRRnhEZHE2am1vRUhmU3VNNnNiNU4yVjgyQTVSaUhHCmduS3IzMUpWQS9FdEt3Vk5sZUY3L1VUM0tzWTJzajRZNFkxRnI3amRkOS9tdTVaNWVwODFidFVDZ1lFQTg5Zm0KSE9tc0JYZUQ0M0FHVmltSFhEWWVGckI3UWRhY3hOQ3R4NjZuTk5jMFpxM0pDZGtDMjVaTG1nQytON2JEbkRjMApNZ2NPUGdyUWxVdWpRbWl1d1daeFlXcDAvWDh3STFHZ2p4RkEvRkJvNjFnd3lwR2tqbjJlS3lVM1ovWlJBRTBjCmlxaW5UTVc5TFBlV1k0MEhOUzFic3E2YmFoeXg1bTFVV0gxclRRc0NnWUF3bE1WMmRHbEdqU1NjcTZSVjVnOU4KZUV2QTNPMXkrZ1JMQkFQR3NFcW42SzBGd2tneTAxVU5pb2RvOUpHU2VPM21mcjVBNmNlR2YrWW5aZC8rcGZwawpGY0UrS0JJd2dudUh5UEtZcDFwNzBvRFR2a3Bxckh5OVl2am9oajFuQ05pdTlHZDJ5eTNjaVZvNlBDZGg2STI4ClIyYUVpSGZhSDdicGl0bTJiNEFrYlFLQmdRQ2tmUUpraEppZkEzVTdpa2tyL0Uyc1BYRmttdDQ2bG53Z0pDam0KSjRIeG1pNW1DVnN4UW11MEZ4bWVwRnVzbDZReWorYXN6S2VsNElPK0FrejZNa1dZZnZPQzVGNVExbWh4bXRHMQpVTTFHcHpOdmRvbExUSjMxNVBVNlk1dVJqTTR0WnRjWERoZjFLUHFwQjhjeUZtTkRVdnFsZVRXcmlmblQxL0pxCjB3Zjc2d0tCZ1FDN3hIK3NXbTR6cjVRb1VvMWlrYlRMSHRBaVFETWE2TlpWTTk0MHcxZHExUWk4YXpMTE1lMUcKUVduU1ZqTDVLaVlSY0toSjVYOGpoQjF5a2U1OTR1ZU1CSFJRdjFRU3RCalRkSzIxN2tnTTFTRmZEbzFFQWpRdgpMWk5pWHROYXVDeG9BMi96SHJrZ0d0NGQzQldKZk5ENkJPQ1RKK2lSRnNWc1VvcjhITzJQR2c9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo=
|
|
public_key: LS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1JSUJDZ0tDQVFFQTVjUGhaK3Z5NjdOTWw4cGwyeEpZb0g1RTk5dGtVM1ZQckxoZ1ZITjJqbmZqMkZYTW9RdVQKSm1CTnVlRHdxYlRaSkRCZkNHdW01NkVXMytWK0FLbGN6RTVXRUtjQUdMMS92bzhlNDQzQUZsM0F0R1VRSWRHVwo0aC9KNENwUzRvYnVVZTBrdytCYmZ5aHFCdmtpUzZsbVFKY1dIS283dmlmYUUySnNYZmUrREpJUjEvNHhvYjlrCm5MNUFlaEUvV1duQmNEYll0TnB5RThwaEM3Rmg4M2JhVHZXam1zVkxGWmlhMysyai9ueWlkc1JlMTRjMnR4czQKVkV6elFaWmEzMDJaREhUaUZjODMybWN5QkxBc0ZzMnBzbEpMYlJ2S3ZZQUtXS050UXJ0ZUhyMFBQZmphQjM3cgpjVjF5S2EyTjYzUU52a3dhUTFpZ25ZakphN25UUGFqVUp3SURBUUFCCi0tLS0tRU5EIFJTQSBQVUJMSUMgS0VZLS0tLS0K
|
|
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
|
|
name: me.localhost
|
|
spec:
|
|
active_keys:
|
|
ssh:
|
|
- private_key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb3dJQkFBS0NBUUVBeHpRdWtjUlhCR09nRDUrS3B1MGRrdVpXVjVsc294Wlp1cFRhRHdFcmYvQ1prOWFqCjRaZzJoeTBoUHl5SXRBRytIN08xRVYwZ0taWVRDWWs4REtiaFQ4ZWl3QldDNUhKaGtpYW9ZRStSUXpQTHd3STcKcElmb0t4ejR2WG5MRnNvWHVVY2hLTmhYdk1RZU9pVVJ3OVQ3L0RSREE0dDdsazlPY01jWE9ySHV3L2JxTTA0VApmTmhVeXhHVmhyTC90aFpQNDE4b04xZjZKQzZMU3grZThIM01iSEQralVGMjBVbU8wVUFLUHUwRXVQS3hkS2loCm1tbVZDZ3FaRWhBWjhrcklVYlV5R0tUemZjQyt4VFNrUEN3UE1qejg1aTJQVVBYS3hmVE00cW54QVh5VzRCSzYKeXo1Znk5UTgyalVESi9VS0JvSU92N1hUU2JhNUpDUHdiUUx4cHdJREFRQUJBb0lCQUJydU53MkYyYTNDT2pWaQpnRUFvOWtLUjJVSm1mNFZjMUN5aFN3bVVRdWs5QWNZMjBsa0JWdjNYWUJOR1ZnVGY1M0FwdjJUbGpoK1JKbW0zCm4rS2wvUGZvS1Z5R2kvZU9ieHB2RjN4TnhYbXNXdk8yTFpJRXZhSjJmRHBCYU85Znl1MUZiSG8xSlVkanpDSlkKT0pxZEJLUUgvTGRSK0JkT0NYQzl1YW81dStuS0RxZTZvaE1FZm5VUUpmeGd4QzNwMHhzRGkvNGovYWhCV3cvaApoZk02TUloaUlmZEhWNlN1MWlPQWlNbXNtcDBWSkd4OVR5SG9UZFdKWHkxYjRTNDh5L21rNjdNeThzUDJ0SXRHCksvdGxaaDFteDYwbCtscnZkTDZFVW9CVDVScXdCZDBCN0g3c1V0UkZjVVVkMVZBNXpMYVowYnhkbHVpL1dEMlcKaHVtOHJpRUNnWUVBN0hPZlN3OVRKQzIxSHFwb2kvUHRKOGZ5QjVMRXJaQTBmY21vd2VtMG55dTRyMVkxN2FSTwp6bU5qYmZtYWRrOU95RnJNaS9Ydm5pbW1wcnNmK3Z1dEVkeEJEK3JYMGJPZk52ZEl5NHNMNEFaN2JZSkdUVEk0ClVFREdPRVF2UkpUQmxhQ3hvMGVEcGVSbTZqamhjYjdmcHV6K3ZCaVB2ZFBHbExxU0JuaTczSDBDZ1lFQTE2dzYKazhzUDlCK251MFFkSVdRano0MU9wTzJlb2FKenhndFVRTnkyV0VuRi9ydk51K21ra1BtL0lWbWZvdzFOYXAwNApGL29FeHpUSWw2WkFCcUdjWUtHVDRNSjRlVS9QT2RsbWZtSE5DcThHTGs4TlRBaC9UdVFuZ0VKTDB2UE9Ta0wzCjMrWHg2N010MDhVUXNmRjlDQU8yS3BuQzhOOEw5NmhjOXp6ZTgvTUNnWUEwakptNVQ4V1ZnOGI5OHJkYmF6R28KcHFvbWZyclJLL3hPZkZQU0RNT0VvRzNpSWRISVo3elA1NHpBY3ptZDA1Qlp2THc2MnNTUExRaUpnNHJlOTdJRwpCeUk2akdHOGpDUDFUazNTVnF1ajlTelhNSjI1S0ZFVm5OK3d2NDZWdWsydm1GQUNUckYyVytWM1puN01EYlNjCjM0elpkc2Z6VXk2Ti9Vell2VnBhN1FLQmdRQ3NOZC9JSnpxajZhcmJBdlpudFRoTEFFQXR2WGNQQlZLQWJvZG0KQzFhbWhMSE9SMU50bXBCSEdzU2M4cDFmYXIzSVJhV0dyNktsRmVhZUFLZmJJNnhrRkdDcDlWNlJMMEwrcERNTQo4emJ3TXZVeWdQalRIMjNZSnFITDdpUHhXNi82NkNKWTY1a1NaVTVRYkdoNlRhTlNoUFF1YS95V3JPTTNhMzVnCkJJRGFOUUtCZ0dBSE5EOWVjcGpySElxUFgzekZUYm1uZjZORWl1SmN0aHpPN0hLZzI0Slh3V0FoRWJBaXpUYjQKRnY1VmY0d2dKc2xGSjFmNDdhVjJxSU5ncWJ5ajBMSlNjYksyOGlXVmIwZmxSbnJEZnd0amxaS2lneWRDTlZubApteUNBS2IyOTlZL1d0Y3NobjUxa29DdWtzSVA1VzJwZjk5M2pLbEw0OWNPN0l6N3VKbTEzCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg==
|
|
public_key: c3NoLXJzYSBBQUFBQjNOemFDMXljMkVBQUFBREFRQUJBQUFCQVFESE5DNlJ4RmNFWTZBUG40cW03UjJTNWxaWG1XeWpGbG02bE5vUEFTdC84Sm1UMXFQaG1EYUhMU0UvTElpMEFiNGZzN1VSWFNBcGxoTUppVHdNcHVGUHg2TEFGWUxrY21HU0pxaGdUNUZETTh2REFqdWtoK2dySFBpOWVjc1d5aGU1UnlFbzJGZTh4QjQ2SlJIRDFQdjhORU1EaTN1V1QwNXd4eGM2c2U3RDl1b3pUaE44MkZUTEVaV0dzdisyRmsvalh5ZzNWL29rTG90TEg1N3dmY3hzY1A2TlFYYlJTWTdSUUFvKzdRUzQ4ckYwcUtHYWFaVUtDcGtTRUJueVNzaFJ0VElZcFBOOXdMN0ZOS1E4TEE4eVBQem1MWTlROWNyRjlNemlxZkVCZkpiZ0VyckxQbC9MMUR6YU5RTW45UW9HZ2c2L3RkTkp0cmtrSS9CdEF2R24K
|
|
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
|
|
name: me.localhost
|
|
spec:
|
|
active_keys:
|
|
tls:
|
|
- cert: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURpakNDQW5LZ0F3SUJBZ0lRRU9IcEhIZkZwZ28wUndQSVJhdkdpakFOQmdrcWhraUc5dzBCQVFzRkFEQmYKTVJVd0V3WURWUVFLRXd4dFpTNXNiMk5oYkdodmMzUXhGVEFUQmdOVkJBTVRERzFsTG14dlkyRnNhRzl6ZERFdgpNQzBHQTFVRUJSTW1NakkwTkRBMk5ESTNPREkyTWpJNE5UQXdOemMzTmpVeU16STVOak15TWpNeU56VXhORFl3CkhoY05NakV4TWpJM01qTTBOREl6V2hjTk16RXhNakkxTWpNME5ESXpXakJmTVJVd0V3WURWUVFLRXd4dFpTNXMKYjJOaGJHaHZjM1F4RlRBVEJnTlZCQU1UREcxbExteHZZMkZzYUc5emRERXZNQzBHQTFVRUJSTW1NakkwTkRBMgpOREkzT0RJMk1qSTROVEF3TnpjM05qVXlNekk1TmpNeU1qTXlOelV4TkRZd2dnRWlNQTBHQ1NxR1NJYjNEUUVCCkFRVUFBNElCRHdBd2dnRUtBb0lCQVFETFRrVFkzQ0NMVStNUllkbEMwM2NUTTR6MUpiRGoxYjFQRWdING9iSmwKRjl4NWtQbzhncWNEbmp5L0x5NHdKeUR2Q2xPMkw1T0k3UnYwa1hFUXoybUVEeExnbjJYRG9ZNUh5VFNOVkZHNgpvZ3BlYmhlUFN1aWl0RUNZYUZDZVZFTGNDa1Q0ZGpqRDlwOExNTnJ4MHRPOXdQU1o1OXBLZUxCOG90RFloOHRCCkcyb2EzSGIzTWt0RGxOY0svVE94RFNzRzUrQ2ljdktTa3QrV04xaXJJQ2pvZ2hWTzJGcForRkdxWUM0Y1EwbWMKM0NRaGJwY1o2VTRkWnpGdFJZVzZPYzNucHBOSkZKWXZSSTRIS1FWY0RCM2N4VkhNTUd5Rzc3aFRzdEwvd0RuaQo4U2s5eml4VzN4S2FvUnlrV2FuWno4eC9WdHNydXJqanNzNDV4NlRoem1VWkFnTUJBQUdqUWpCQU1BNEdBMVVkCkR3RUIvd1FFQXdJQnBqQVBCZ05WSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCUmNKK2NRamFQWjZGbEIKcVhoYzYyWXZldGRpQWpBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQVdYNmxZdUhtMmQyMU41RDN1eUJJelFOdApKVFR3b0xnU3FQd09Tbk1EU0luSDkvMjBqZDNGUk9qakh1M3BQRkNLRmE4OVp0ekZxTHZsTjVOdlh2WHFuOXNKCkdudTYzSVo0TWtEZk9sSVZpWFhQWFF4YllHSkMxRVlVU28rTDdtUTY0VnN5UkFpTXdnbmVwMUxwSGhROGYzU2MKeEZoVkNybFJDMmUrNENBai8vOVZWaDdvTEdSMkNhM0xEcFc5VHFxYnB3MEh0QitNcFVqVWxCWnFVbzNVMm5HTQpia1VhSVZKcnNuYk1rYnNsUGQ2dWtVRDlVTHFuUmxJb3A4cjQ1VTdvYVBhR3g3QVFiWndzbGlsNVVJZlppRmlRCm5USk9kYnJHampVdXlRYkM4UUpZY3RhdENjbVBjZUlXMVVWWFVnZ2JsdXl4VjF1NWsyYzlSb1k2RzhiN0FRPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
|
|
key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBeTA1RTJOd2dpMVBqRVdIWlF0TjNFek9NOVNXdzQ5VzlUeElCK0tHeVpSZmNlWkQ2ClBJS25BNTQ4dnk4dU1DY2c3d3BUdGkrVGlPMGI5SkZ4RU05cGhBOFM0SjlsdzZHT1I4azBqVlJSdXFJS1htNFgKajByb29yUkFtR2hRbmxSQzNBcEUrSFk0dy9hZkN6RGE4ZExUdmNEMG1lZmFTbml3ZktMUTJJZkxRUnRxR3R4Mgo5ekpMUTVUWEN2MHpzUTByQnVmZ29uTHlrcExmbGpkWXF5QW82SUlWVHRoYVdmaFJxbUF1SEVOSm5Od2tJVzZYCkdlbE9IV2N4YlVXRnVqbk41NmFUU1JTV0wwU09CeWtGWEF3ZDNNVlJ6REJzaHUrNFU3TFMvOEE1NHZFcFBjNHMKVnQ4U21xRWNwRm1wMmMvTWYxYmJLN3E0NDdMT09jZWs0YzVsR1FJREFRQUJBb0lCQVFDeXNLNXVkTHZkK2ZOQQpHZUtkaThQRENySS8zY3JsMWIwNFBEbWpVR3U5MHdVampEdUU1OGpuc3pMdFR3aW5waHlhUFZkcWI5S2FyTnkvClR2NHpxam14cXBZSys4Nno3ZEZpWXdSZm05YmgxUDZNRlBOOExIamdXTkhWb3dvSXYwS3NxQklLMTgzNDMxRFcKd3pBTkVDS3ZTMk14eXNqZ1g4ZXZKR092alZzbWN1SU1IWFljbVlORlo0dWpuTnc0dnVSWHhlYUtPY2ZWTGZ2ZwoxSWZMK05IYUh6UXI1YVoydkxST1NpdHVId2cvOFpZZ2hQcVFYLy92ak92M0FENzhXVGxINUZXWjExR0hoeCt1Ck9ZUXcwQ1lvTnNiV1UxeklwVTV0cHdCcDRGV0VlVy9jbTY5NXRBVVRlMzR1N3R1MlJJOVBZMEZDWVJ2ZkM2SUQKK2tDNjRFTEpBb0dCQVBSTEt5a0pjdHNGNngzN1liWXdmQm9ZK3V6YU4wV1o1d1RuRmVFaVp1ZzVVYWJUOTdqRApZTnpaYzQ0aitRbkxFUGVDak5tU1FhVHFxK2QvbUVjTnlXS244cVNFcXlOR0R6YlRXQ2tkMGtyWTVwcm9FVVJnClFqbWFwRHFNNEtOSm9jQ1RCS3lueHo2QzZ6ME9uSnhZM3lMdTdyYVBqeE9HTW5rcm9VMDhMVW56QW9HQkFOVU0KU2NsNGh1R0gxK3ZNL0RtenJoQ1NKbUZIcjE2QjhvWExaMHIyNmFKTnJVQ3AwYUFzV2FHd3JLZXZFcDkzRmg5Ygp3QlZYMHE0bXJ3cmZpTGpCYnRzdnlQM3l1ZWs5cWl6M2ZoMWIvZ0k2eWRKVFEzMEplQzB4UzUyRksvR2gwanEvCm43c2Y1bm5DbTlCRW01ZmdSeDFVUmVhOC9vL2M4cTNhbW94c0grdkRBb0dBZUVZUjU5QlpGZkJpQTQ3aVdwcWcKWHhEeGFXOCtTeXdzaTBOaWlFY3h0eCtSVGJ1S2VSTG9PNU5yeXcxMjdSVm5NeFM1Vjkwa0tKZkpMdDZwRUVKLwpaZTBlRDFXcUZHSEgxOHhSMlZ4dlRwNWZXdURxcjJsYzhaTnJTOUJVUU5CZHJMdzFUdlFEcW9rMlhBYzNuOW81CmNhK0ZJNmltWG94eGlTcXI3YVMwLzNVQ2dZQTJBWEJ1N3V1YUhocGcvc3h0UUJ2K3ZWMlhTVm11SmxpNUM4KzYKVkE3emdxZEpmZ0xTakl1SURrWW1GNTRyNkQ4bVlkYTJVbFhvcVl1endPaGlsVDRwdDlwR2JaSXRDdUdwbG05VQp0KzRTMko0eWY4TGEzbHlsY0JxUDZxTXlGR2c3VmpvQ2NGcTNRTnJJbDZ1dGV6L3JzbUlwMUh6Zk1RNGZmZ3V4ClR2Tmtpd0tCZ1FDbVhaSStvTUdQK3U4KzRVaGxjR01NYUNHZi92UVZLdVJYOHlOYVh1bUx6dk1Xajl0cVhpUzcKK1dQUlhuV01RSnd1QldYMzBTcWdFVVdDbjlzOGxWbzh2TVF4MmFtbXhhWkVEMGRoOHNMSkJDNXJoRmVqV29MbQp3cHg5MXR0S3JJODBKMDYyeW90SFpJYkRyQW1LSGZFeE85U1d4T1hUeFVMUGdvTlJVUW5qSnc9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo=
|
|
additional_trusted_keys: {}
|
|
cluster_name: me.localhost
|
|
signing_alg: 3
|
|
type: saml_idp
|
|
sub_kind: saml_idp
|
|
version: v2`
|
|
)
|
|
|
|
func TestInit_bootstrap(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
hostCA := resourceFromYAML(t, hostCAYAML).(types.CertAuthority)
|
|
userCA := resourceFromYAML(t, userCAYAML).(types.CertAuthority)
|
|
jwtCA := resourceFromYAML(t, jwtCAYAML).(types.CertAuthority)
|
|
dbServerCA := resourceFromYAML(t, databaseCAYAML).(types.CertAuthority)
|
|
dbClientCA := resourceFromYAML(t, databaseClientCAYAML).(types.CertAuthority)
|
|
osshCA := resourceFromYAML(t, openSSHCAYAML).(types.CertAuthority)
|
|
samlCA := resourceFromYAML(t, samlCAYAML).(types.CertAuthority)
|
|
|
|
invalidHostCA := resourceFromYAML(t, hostCAYAML).(types.CertAuthority)
|
|
invalidHostCA.(*types.CertAuthorityV2).Spec.ActiveKeys.SSH = nil
|
|
invalidUserCA := resourceFromYAML(t, userCAYAML).(types.CertAuthority)
|
|
invalidUserCA.(*types.CertAuthorityV2).Spec.ActiveKeys.SSH = nil
|
|
invalidJWTCA := resourceFromYAML(t, jwtCAYAML).(types.CertAuthority)
|
|
invalidJWTCA.(*types.CertAuthorityV2).Spec.ActiveKeys.JWT = nil
|
|
invalidDBServerCA := resourceFromYAML(t, databaseCAYAML).(types.CertAuthority)
|
|
invalidDBServerCA.(*types.CertAuthorityV2).Spec.ActiveKeys.TLS = nil
|
|
invalidDBClientCA := resourceFromYAML(t, databaseClientCAYAML).(types.CertAuthority)
|
|
invalidDBClientCA.(*types.CertAuthorityV2).Spec.ActiveKeys.TLS = nil
|
|
invalidOSSHCA := resourceFromYAML(t, openSSHCAYAML).(types.CertAuthority)
|
|
invalidOSSHCA.(*types.CertAuthorityV2).Spec.ActiveKeys.SSH = nil
|
|
invalidSAMLCA := resourceFromYAML(t, samlCAYAML).(types.CertAuthority)
|
|
invalidSAMLCA.(*types.CertAuthorityV2).Spec.ActiveKeys.TLS = nil
|
|
|
|
tests := []struct {
|
|
name string
|
|
modifyConfig func(*InitConfig)
|
|
assertError require.ErrorAssertionFunc
|
|
}{
|
|
{
|
|
// Issue https://github.com/gravitational/teleport/issues/7853.
|
|
name: "OK bootstrap CAs",
|
|
modifyConfig: func(cfg *InitConfig) {
|
|
cfg.BootstrapResources = append(
|
|
cfg.BootstrapResources,
|
|
hostCA.Clone(),
|
|
userCA.Clone(),
|
|
jwtCA.Clone(),
|
|
dbServerCA.Clone(),
|
|
dbClientCA.Clone(),
|
|
osshCA.Clone(),
|
|
samlCA.Clone(),
|
|
)
|
|
},
|
|
assertError: require.NoError,
|
|
},
|
|
{
|
|
name: "NOK bootstrap Host CA missing keys",
|
|
modifyConfig: func(cfg *InitConfig) {
|
|
cfg.BootstrapResources = append(
|
|
cfg.BootstrapResources,
|
|
invalidHostCA.Clone(),
|
|
userCA.Clone(),
|
|
jwtCA.Clone(),
|
|
dbServerCA.Clone(),
|
|
dbClientCA.Clone(),
|
|
osshCA.Clone(),
|
|
samlCA.Clone(),
|
|
)
|
|
},
|
|
assertError: require.Error,
|
|
},
|
|
{
|
|
name: "NOK bootstrap User CA missing keys",
|
|
modifyConfig: func(cfg *InitConfig) {
|
|
cfg.BootstrapResources = append(
|
|
cfg.BootstrapResources,
|
|
hostCA.Clone(),
|
|
invalidUserCA.Clone(),
|
|
jwtCA.Clone(),
|
|
dbServerCA.Clone(),
|
|
dbClientCA.Clone(),
|
|
osshCA.Clone(),
|
|
samlCA.Clone(),
|
|
)
|
|
},
|
|
assertError: require.Error,
|
|
},
|
|
{
|
|
name: "NOK bootstrap JWT CA missing keys",
|
|
modifyConfig: func(cfg *InitConfig) {
|
|
cfg.BootstrapResources = append(
|
|
cfg.BootstrapResources,
|
|
hostCA.Clone(),
|
|
userCA.Clone(),
|
|
invalidJWTCA.Clone(),
|
|
dbServerCA.Clone(),
|
|
dbClientCA.Clone(),
|
|
osshCA.Clone(),
|
|
samlCA.Clone(),
|
|
)
|
|
},
|
|
assertError: require.Error,
|
|
},
|
|
{
|
|
name: "NOK bootstrap Database CA missing keys",
|
|
modifyConfig: func(cfg *InitConfig) {
|
|
cfg.BootstrapResources = append(
|
|
cfg.BootstrapResources,
|
|
hostCA.Clone(),
|
|
userCA.Clone(),
|
|
jwtCA.Clone(),
|
|
invalidDBServerCA.Clone(),
|
|
osshCA.Clone(),
|
|
samlCA.Clone(),
|
|
)
|
|
},
|
|
assertError: require.Error,
|
|
},
|
|
{
|
|
name: "NOK bootstrap Database Client CA missing keys",
|
|
modifyConfig: func(cfg *InitConfig) {
|
|
cfg.BootstrapResources = append(
|
|
cfg.BootstrapResources,
|
|
hostCA.Clone(),
|
|
userCA.Clone(),
|
|
jwtCA.Clone(),
|
|
dbServerCA.Clone(),
|
|
invalidDBClientCA.Clone(),
|
|
osshCA.Clone(),
|
|
samlCA.Clone(),
|
|
)
|
|
},
|
|
assertError: require.Error,
|
|
},
|
|
{
|
|
name: "NOK bootstrap OpenSSH CA missing keys",
|
|
modifyConfig: func(cfg *InitConfig) {
|
|
cfg.BootstrapResources = append(
|
|
cfg.BootstrapResources,
|
|
hostCA.Clone(),
|
|
userCA.Clone(),
|
|
jwtCA.Clone(),
|
|
dbServerCA.Clone(),
|
|
dbClientCA.Clone(),
|
|
invalidOSSHCA.Clone(),
|
|
samlCA.Clone(),
|
|
)
|
|
},
|
|
assertError: require.Error,
|
|
},
|
|
{
|
|
name: "NOK bootstrap SAML IdP CA missing keys",
|
|
modifyConfig: func(cfg *InitConfig) {
|
|
cfg.BootstrapResources = append(
|
|
cfg.BootstrapResources,
|
|
hostCA.Clone(),
|
|
userCA.Clone(),
|
|
jwtCA.Clone(),
|
|
dbServerCA.Clone(),
|
|
dbClientCA.Clone(),
|
|
osshCA.Clone(),
|
|
invalidSAMLCA.Clone(),
|
|
)
|
|
},
|
|
assertError: require.Error,
|
|
},
|
|
}
|
|
for _, test := range tests {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
cfg := setupConfig(t)
|
|
test.modifyConfig(&cfg)
|
|
|
|
_, err := Init(context.Background(), cfg)
|
|
test.assertError(t, err)
|
|
})
|
|
}
|
|
}
|
|
|
|
const (
|
|
userYAML = `kind: user
|
|
version: v2
|
|
metadata:
|
|
name: myuser
|
|
spec:
|
|
roles: ["admin"]`
|
|
tokenYAML = `kind: token
|
|
version: v2
|
|
metadata:
|
|
name: github-token
|
|
expires: "3000-01-01T00:00:00Z"
|
|
spec:
|
|
roles: [Bot]
|
|
join_method: github
|
|
bot_name: github-demo
|
|
github:
|
|
allow:
|
|
- repository: gravitational/example`
|
|
roleYAML = `kind: role
|
|
version: v7
|
|
metadata:
|
|
name: admin
|
|
expires: "3000-01-01T00:00:00Z"
|
|
spec:
|
|
allow:
|
|
logins: ['admin']
|
|
kubernetes_groups: ['edit']
|
|
node_labels:
|
|
'*': '*'
|
|
kubernetes_labels:
|
|
'*': '*'
|
|
kubernetes_resources:
|
|
- kind: '*'
|
|
namespace: '*'
|
|
name: '*'
|
|
verbs: ['*']`
|
|
lockYAML = `
|
|
kind: lock
|
|
version: v2
|
|
metadata:
|
|
name: b1c785d8-8165-41fc-8dd6-252d534334d3
|
|
spec:
|
|
created_at: "2023-11-07T18:44:35.361806Z"
|
|
created_by: Admin
|
|
target:
|
|
user: myuser
|
|
`
|
|
clusterNetworkingConfYAML = `
|
|
kind: cluster_networking_config
|
|
metadata:
|
|
name: cluster-networking-config
|
|
spec:
|
|
proxy_listener_mode: 1
|
|
`
|
|
authPrefYAML = `
|
|
kind: cluster_auth_preference
|
|
metadata:
|
|
name: cluster-auth-preference
|
|
spec:
|
|
second_factor: off
|
|
type: local
|
|
version: v2
|
|
`
|
|
)
|
|
|
|
func TestInit_ApplyOnStartup(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
user := resourceFromYAML(t, userYAML).(types.User)
|
|
token := resourceFromYAML(t, tokenYAML).(types.ProvisionToken)
|
|
role := resourceFromYAML(t, roleYAML).(types.Role)
|
|
lock := resourceFromYAML(t, lockYAML).(types.Lock)
|
|
clusterNetworkingConfig := resourceFromYAML(t, clusterNetworkingConfYAML).(types.ClusterNetworkingConfig)
|
|
authPref := resourceFromYAML(t, authPrefYAML).(types.AuthPreference)
|
|
|
|
tests := []struct {
|
|
name string
|
|
modifyConfig func(*InitConfig)
|
|
assertError require.ErrorAssertionFunc
|
|
}{
|
|
{
|
|
name: "Apply unsupported resource",
|
|
modifyConfig: func(cfg *InitConfig) {
|
|
cfg.ApplyOnStartupResources = append(cfg.ApplyOnStartupResources, lock)
|
|
cfg.ApplyOnStartupResources = append(cfg.ApplyOnStartupResources, user)
|
|
cfg.ApplyOnStartupResources = append(cfg.ApplyOnStartupResources, role)
|
|
cfg.ApplyOnStartupResources = append(cfg.ApplyOnStartupResources, token)
|
|
},
|
|
assertError: require.Error,
|
|
},
|
|
{
|
|
name: "Apply ProvisionToken",
|
|
modifyConfig: func(cfg *InitConfig) {
|
|
cfg.ApplyOnStartupResources = append(cfg.ApplyOnStartupResources, token)
|
|
},
|
|
assertError: require.NoError,
|
|
},
|
|
{
|
|
name: "Apply User (invalid, missing role)",
|
|
modifyConfig: func(cfg *InitConfig) {
|
|
cfg.ApplyOnStartupResources = append(cfg.ApplyOnStartupResources, user)
|
|
},
|
|
assertError: require.Error,
|
|
},
|
|
// We test both user+role and role+user to validate that ordering doesn't matter
|
|
{
|
|
name: "Apply User+Role",
|
|
modifyConfig: func(cfg *InitConfig) {
|
|
cfg.ApplyOnStartupResources = append(cfg.ApplyOnStartupResources, user)
|
|
cfg.ApplyOnStartupResources = append(cfg.ApplyOnStartupResources, role)
|
|
},
|
|
assertError: require.NoError,
|
|
},
|
|
{
|
|
name: "Apply Role+User",
|
|
modifyConfig: func(cfg *InitConfig) {
|
|
cfg.ApplyOnStartupResources = append(cfg.ApplyOnStartupResources, user)
|
|
cfg.ApplyOnStartupResources = append(cfg.ApplyOnStartupResources, role)
|
|
},
|
|
assertError: require.NoError,
|
|
},
|
|
{
|
|
name: "Apply Role",
|
|
modifyConfig: func(cfg *InitConfig) {
|
|
cfg.ApplyOnStartupResources = append(cfg.ApplyOnStartupResources, role)
|
|
},
|
|
assertError: require.NoError,
|
|
},
|
|
{
|
|
name: "Apply ClusterNetworkingConfig",
|
|
modifyConfig: func(cfg *InitConfig) {
|
|
cfg.ApplyOnStartupResources = append(cfg.ApplyOnStartupResources, clusterNetworkingConfig)
|
|
},
|
|
assertError: require.NoError,
|
|
},
|
|
{
|
|
name: "Apply AuthPreference",
|
|
modifyConfig: func(cfg *InitConfig) {
|
|
cfg.ApplyOnStartupResources = append(cfg.ApplyOnStartupResources, authPref)
|
|
},
|
|
assertError: require.NoError,
|
|
},
|
|
}
|
|
for _, test := range tests {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
cfg := setupConfig(t)
|
|
test.modifyConfig(&cfg)
|
|
|
|
_, err := Init(context.Background(), cfg)
|
|
test.assertError(t, err)
|
|
})
|
|
}
|
|
}
|
|
|
|
func resourceFromYAML(t *testing.T, value string) types.Resource {
|
|
t.Helper()
|
|
|
|
ur := &services.UnknownResource{}
|
|
err := kyaml.NewYAMLToJSONDecoder(strings.NewReader(value)).Decode(ur)
|
|
require.NoError(t, err)
|
|
|
|
resource, err := services.UnmarshalResource(ur.Kind, ur.Raw)
|
|
require.NoError(t, err)
|
|
return resource
|
|
}
|
|
|
|
func resourceDiff(res1, res2 types.Resource) string {
|
|
return cmp.Diff(res1, res2,
|
|
cmpopts.IgnoreFields(types.Metadata{}, "ID", "Revision", "Namespace"),
|
|
cmpopts.EquateEmpty())
|
|
}
|
|
|
|
// TestSyncUpgadeWindowStartHour verifies the core logic of the upgrade window start
|
|
// hour behavior.
|
|
func TestSyncUpgradeWindowStartHour(t *testing.T) {
|
|
ctx := context.Background()
|
|
|
|
conf := setupConfig(t)
|
|
authServer, err := Init(ctx, conf)
|
|
require.NoError(t, err)
|
|
t.Cleanup(func() { authServer.Close() })
|
|
|
|
// no getter is registered, sync should fail
|
|
require.Error(t, authServer.syncUpgradeWindowStartHour(ctx))
|
|
|
|
// maintenance config does not exist yet
|
|
cmc, err := authServer.GetClusterMaintenanceConfig(ctx)
|
|
require.Error(t, err)
|
|
require.True(t, trace.IsNotFound(err))
|
|
require.Nil(t, cmc)
|
|
|
|
// set up fake getter
|
|
var mu sync.Mutex
|
|
var fakeHour int64
|
|
var fakeError error
|
|
authServer.SetUpgradeWindowStartHourGetter(func(ctx context.Context) (int64, error) {
|
|
mu.Lock()
|
|
defer mu.Unlock()
|
|
return fakeHour, fakeError
|
|
})
|
|
|
|
// sync should now succeed
|
|
require.NoError(t, authServer.syncUpgradeWindowStartHour(ctx))
|
|
|
|
cmc, err = authServer.GetClusterMaintenanceConfig(ctx)
|
|
require.NoError(t, err)
|
|
|
|
agentWindow, ok := cmc.GetAgentUpgradeWindow()
|
|
require.True(t, ok)
|
|
|
|
require.Equal(t, uint32(0), agentWindow.UTCStartHour)
|
|
|
|
// change the served hour
|
|
mu.Lock()
|
|
fakeHour = 16
|
|
mu.Unlock()
|
|
|
|
require.NoError(t, authServer.syncUpgradeWindowStartHour(ctx))
|
|
|
|
cmc, err = authServer.GetClusterMaintenanceConfig(ctx)
|
|
require.NoError(t, err)
|
|
|
|
agentWindow, ok = cmc.GetAgentUpgradeWindow()
|
|
require.True(t, ok)
|
|
|
|
require.Equal(t, uint32(16), agentWindow.UTCStartHour)
|
|
|
|
// set sync to fail with out of range hour
|
|
mu.Lock()
|
|
fakeHour = 36
|
|
mu.Unlock()
|
|
|
|
require.Error(t, authServer.syncUpgradeWindowStartHour(ctx))
|
|
|
|
cmc, err = authServer.GetClusterMaintenanceConfig(ctx)
|
|
require.NoError(t, err)
|
|
|
|
agentWindow, ok = cmc.GetAgentUpgradeWindow()
|
|
require.True(t, ok)
|
|
|
|
// verify that the old hour value persists since the sync failed
|
|
require.Equal(t, uint32(16), agentWindow.UTCStartHour)
|
|
|
|
// set sync to fail with impossible int type-cast
|
|
mu.Lock()
|
|
fakeHour = math.MaxInt64
|
|
mu.Unlock()
|
|
|
|
require.Error(t, authServer.syncUpgradeWindowStartHour(ctx))
|
|
|
|
cmc, err = authServer.GetClusterMaintenanceConfig(ctx)
|
|
require.NoError(t, err)
|
|
|
|
agentWindow, ok = cmc.GetAgentUpgradeWindow()
|
|
require.True(t, ok)
|
|
|
|
// verify that the old hour value persists since the sync failed
|
|
require.Equal(t, uint32(16), agentWindow.UTCStartHour)
|
|
|
|
mu.Lock()
|
|
fakeHour = 18
|
|
mu.Unlock()
|
|
|
|
// sync should now succeed again
|
|
require.NoError(t, authServer.syncUpgradeWindowStartHour(ctx))
|
|
|
|
cmc, err = authServer.GetClusterMaintenanceConfig(ctx)
|
|
require.NoError(t, err)
|
|
|
|
agentWindow, ok = cmc.GetAgentUpgradeWindow()
|
|
require.True(t, ok)
|
|
|
|
// verify that we got the new hour value
|
|
require.Equal(t, uint32(18), agentWindow.UTCStartHour)
|
|
|
|
// set sync to fail with error
|
|
mu.Lock()
|
|
fakeHour = 12
|
|
fakeError = fmt.Errorf("uh-oh")
|
|
mu.Unlock()
|
|
|
|
require.Error(t, authServer.syncUpgradeWindowStartHour(ctx))
|
|
|
|
cmc, err = authServer.GetClusterMaintenanceConfig(ctx)
|
|
require.NoError(t, err)
|
|
|
|
agentWindow, ok = cmc.GetAgentUpgradeWindow()
|
|
require.True(t, ok)
|
|
|
|
// verify that the old hour value persists since the sync failed
|
|
require.Equal(t, uint32(18), agentWindow.UTCStartHour)
|
|
|
|
// recover and set hour to zero
|
|
mu.Lock()
|
|
fakeHour = 0
|
|
fakeError = nil
|
|
mu.Unlock()
|
|
|
|
// sync should now succeed again
|
|
require.NoError(t, authServer.syncUpgradeWindowStartHour(ctx))
|
|
|
|
cmc, err = authServer.GetClusterMaintenanceConfig(ctx)
|
|
require.NoError(t, err)
|
|
|
|
agentWindow, ok = cmc.GetAgentUpgradeWindow()
|
|
require.True(t, ok)
|
|
|
|
// verify that we got the new hour value
|
|
require.Equal(t, uint32(0), agentWindow.UTCStartHour)
|
|
}
|
|
|
|
// TestIdentityChecker verifies auth identity properly validates host
|
|
// certificates when connecting to an SSH server.
|
|
func TestIdentityChecker(t *testing.T) {
|
|
ctx := context.Background()
|
|
|
|
conf := setupConfig(t)
|
|
authServer, err := Init(ctx, conf)
|
|
require.NoError(t, err)
|
|
t.Cleanup(func() { authServer.Close() })
|
|
|
|
lockWatcher, err := services.NewLockWatcher(ctx, services.LockWatcherConfig{
|
|
ResourceWatcherConfig: services.ResourceWatcherConfig{
|
|
Component: teleport.ComponentAuth,
|
|
Client: authServer,
|
|
},
|
|
})
|
|
require.NoError(t, err)
|
|
authServer.SetLockWatcher(lockWatcher)
|
|
|
|
clusterName, err := authServer.GetDomainName()
|
|
require.NoError(t, err)
|
|
|
|
ca, err := authServer.GetCertAuthority(ctx, types.CertAuthID{
|
|
Type: types.HostCA,
|
|
DomainName: clusterName,
|
|
}, true)
|
|
require.NoError(t, err)
|
|
|
|
signers, err := sshutils.GetSigners(ca)
|
|
require.NoError(t, err)
|
|
require.Len(t, signers, 1)
|
|
|
|
realCert, err := apisshutils.MakeRealHostCert(signers[0])
|
|
require.NoError(t, err)
|
|
|
|
spoofedCert, err := apisshutils.MakeSpoofedHostCert(signers[0])
|
|
require.NoError(t, err)
|
|
|
|
tests := []struct {
|
|
desc string
|
|
cert ssh.Signer
|
|
err bool
|
|
}{
|
|
{
|
|
desc: "should be able to connect with real cert",
|
|
cert: realCert,
|
|
err: false,
|
|
},
|
|
{
|
|
desc: "should not be able to connect with spoofed cert",
|
|
cert: spoofedCert,
|
|
err: true,
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.desc, func(t *testing.T) {
|
|
handler := sshutils.NewChanHandlerFunc(func(_ context.Context, ccx *sshutils.ConnectionContext, nch ssh.NewChannel) {
|
|
ch, _, err := nch.Accept()
|
|
require.NoError(t, err)
|
|
require.NoError(t, ch.Close())
|
|
})
|
|
sshServer, err := sshutils.NewServer(
|
|
"test",
|
|
utils.NetAddr{AddrNetwork: "tcp", Addr: "localhost:0"},
|
|
handler,
|
|
sshutils.StaticHostSigners(test.cert),
|
|
sshutils.AuthMethods{NoClient: true},
|
|
sshutils.SetInsecureSkipHostValidation(),
|
|
)
|
|
require.NoError(t, err)
|
|
t.Cleanup(func() { sshServer.Close() })
|
|
require.NoError(t, sshServer.Start())
|
|
|
|
identity, err := GenerateIdentity(authServer, IdentityID{
|
|
Role: types.RoleNode,
|
|
HostUUID: uuid.New().String(),
|
|
NodeName: "node-1",
|
|
}, nil, nil)
|
|
require.NoError(t, err)
|
|
|
|
sshClientConfig, err := identity.SSHClientConfig(false)
|
|
require.NoError(t, err)
|
|
|
|
dialer := proxy.DialerFromEnvironment(sshServer.Addr())
|
|
sconn, err := dialer.Dial(ctx, "tcp", sshServer.Addr(), sshClientConfig)
|
|
if test.err {
|
|
require.Error(t, err)
|
|
} else {
|
|
require.NoError(t, err)
|
|
require.NoError(t, sconn.Close())
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestInitCreatesCertsIfMissing(t *testing.T) {
|
|
ctx := context.Background()
|
|
conf := setupConfig(t)
|
|
auth, err := Init(ctx, conf)
|
|
require.NoError(t, err)
|
|
t.Cleanup(func() {
|
|
err = auth.Close()
|
|
require.NoError(t, err)
|
|
})
|
|
|
|
for _, caType := range types.CertAuthTypes {
|
|
cert, err := auth.GetCertAuthorities(ctx, caType, false)
|
|
require.NoError(t, err)
|
|
require.Len(t, cert, 1)
|
|
}
|
|
}
|