diff --git a/lib/service/cfg.go b/lib/service/cfg.go index 4801fa45cc6b8..49823bbae70df 100644 --- a/lib/service/cfg.go +++ b/lib/service/cfg.go @@ -73,6 +73,15 @@ type Rate struct { Time time.Duration } +// RoleAndIdentityEvent is a role and its corresponding identity event. +type RoleAndIdentityEvent struct { + // Role is a system role. + Role types.SystemRole + + // IdentityEvent is the identity event associated with the above role. + IdentityEvent string +} + // JoinParams is a set of extra parameters for joining the auth server. type JoinParams struct { Azure AzureJoinParams @@ -279,6 +288,9 @@ type Config struct { // CircuitBreakerConfig configures the auth client circuit breaker. CircuitBreakerConfig breaker.Config + // AdditionalExpectedRoles are additional roles to attach to the Teleport instances. + AdditionalExpectedRoles []RoleAndIdentityEvent + // AdditionalReadyEvents are additional events to watch for to consider the Teleport instance ready. AdditionalReadyEvents []string diff --git a/lib/service/service.go b/lib/service/service.go index 2de0ca0564586..6ff4494548817 100644 --- a/lib/service/service.go +++ b/lib/service/service.go @@ -4528,6 +4528,12 @@ func (process *TeleportProcess) waitForAppDepend() { // registerExpectedServices sets up the instance role -> identity event mapping. func (process *TeleportProcess) registerExpectedServices(cfg *Config) { + // Register additional expected services for this Teleport instance. + // Meant for enterprise support. + for _, r := range cfg.AdditionalExpectedRoles { + process.SetExpectedInstanceRole(r.Role, r.IdentityEvent) + } + if cfg.Auth.Enabled { process.SetExpectedInstanceRole(types.RoleAuth, AuthIdentityEvent) } diff --git a/lib/service/service_test.go b/lib/service/service_test.go index 04a4fcac38c09..1422e57c98a98 100644 --- a/lib/service/service_test.go +++ b/lib/service/service_test.go @@ -76,6 +76,99 @@ func TestServiceSelfSignedHTTPS(t *testing.T) { require.FileExists(t, cfg.Proxy.KeyPairs[0].PrivateKey) } +func TestAdditionalExpectedRoles(t *testing.T) { + tests := []struct { + name string + cfg func() *Config + expectedRoles map[types.SystemRole]string + }{ + { + name: "everything enabled", + cfg: func() *Config { + cfg := MakeDefaultConfig() + cfg.DataDir = t.TempDir() + cfg.SetAuthServerAddress(utils.NetAddr{AddrNetwork: "tcp", Addr: "127.0.0.1:0"}) + cfg.Auth.StorageConfig.Params["path"] = t.TempDir() + cfg.DiagnosticAddr = utils.NetAddr{AddrNetwork: "tcp", Addr: "127.0.0.1:0"} + cfg.Auth.ListenAddr = utils.NetAddr{AddrNetwork: "tcp", Addr: "127.0.0.1:0"} + + cfg.Auth.Enabled = true + cfg.SSH.Enabled = true + cfg.Proxy.Enabled = true + cfg.Kube.Enabled = true + cfg.Apps.Enabled = true + cfg.Databases.Enabled = true + cfg.WindowsDesktop.Enabled = true + cfg.Discovery.Enabled = true + return cfg + }, + expectedRoles: map[types.SystemRole]string{ + types.RoleAuth: AuthIdentityEvent, + types.RoleNode: SSHIdentityEvent, + types.RoleKube: KubeIdentityEvent, + types.RoleApp: AppsIdentityEvent, + types.RoleDatabase: DatabasesIdentityEvent, + types.RoleWindowsDesktop: WindowsDesktopIdentityEvent, + types.RoleDiscovery: DiscoveryIdentityEvent, + types.RoleProxy: ProxyIdentityEvent, + }, + }, + { + name: "everything enabled with additional roles", + cfg: func() *Config { + cfg := MakeDefaultConfig() + cfg.DataDir = t.TempDir() + cfg.SetAuthServerAddress(utils.NetAddr{AddrNetwork: "tcp", Addr: "127.0.0.1:0"}) + cfg.Auth.StorageConfig.Params["path"] = t.TempDir() + cfg.DiagnosticAddr = utils.NetAddr{AddrNetwork: "tcp", Addr: "127.0.0.1:0"} + cfg.Auth.ListenAddr = utils.NetAddr{AddrNetwork: "tcp", Addr: "127.0.0.1:0"} + + cfg.Auth.Enabled = true + cfg.SSH.Enabled = true + cfg.Proxy.Enabled = true + cfg.Kube.Enabled = true + cfg.Apps.Enabled = true + cfg.Databases.Enabled = true + cfg.WindowsDesktop.Enabled = true + cfg.Discovery.Enabled = true + + cfg.AdditionalExpectedRoles = []RoleAndIdentityEvent{ + { + Role: types.RoleOkta, + IdentityEvent: "some-identity-event", + }, + { + Role: types.RoleBot, + IdentityEvent: "some-other-identity-event", + }, + } + + return cfg + }, + expectedRoles: map[types.SystemRole]string{ + types.RoleAuth: AuthIdentityEvent, + types.RoleNode: SSHIdentityEvent, + types.RoleKube: KubeIdentityEvent, + types.RoleApp: AppsIdentityEvent, + types.RoleDatabase: DatabasesIdentityEvent, + types.RoleWindowsDesktop: WindowsDesktopIdentityEvent, + types.RoleDiscovery: DiscoveryIdentityEvent, + types.RoleProxy: ProxyIdentityEvent, + types.RoleOkta: "some-identity-event", + types.RoleBot: "some-other-identity-event", + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + process, err := NewTeleport(test.cfg()) + require.NoError(t, err) + require.Equal(t, test.expectedRoles, process.instanceRoles) + }) + } +} + func TestMonitor(t *testing.T) { t.Parallel() fakeClock := clockwork.NewFakeClock()