diff --git a/lib/auth/auth_with_roles.go b/lib/auth/auth_with_roles.go index 18ab0f4662ed7..df47965982b65 100644 --- a/lib/auth/auth_with_roles.go +++ b/lib/auth/auth_with_roles.go @@ -201,8 +201,8 @@ func (a *ServerWithRoles) actionForKindSession(namespace string, sid session.ID) return trace.Wrap(a.actionWithExtendedContext(namespace, types.KindSession, types.VerbRead, extendContext)) } -// serverAction returns an access denied error if the role is not one of the builtin server roles. -func (a *ServerWithRoles) serverAction() error { +// localServerAction returns an access denied error if the role is not one of the builtin server roles. +func (a *ServerWithRoles) localServerAction() error { role, ok := a.context.Identity.(authz.BuiltinRole) if !ok || !role.IsServer() { return trace.AccessDenied("this request can be only executed by a teleport built-in server") @@ -210,6 +210,22 @@ func (a *ServerWithRoles) serverAction() error { return nil } +// remoteServerAction returns an access denied error if the role is not one of the remote builtin server roles. +func (a *ServerWithRoles) remoteServerAction() error { + role, ok := a.context.UnmappedIdentity.(authz.RemoteBuiltinRole) + if !ok || !role.IsRemoteServer() { + return trace.AccessDenied("this request can be only executed by a teleport remote server") + } + return nil +} + +// isLocalOrRemoteServerAction returns true if the role is one of the builtin server roles (local or remote). +func (a *ServerWithRoles) isLocalOrRemoteServerAction() bool { + errLocal := a.localServerAction() + errRemote := a.remoteServerAction() + return errLocal == nil || errRemote == nil +} + // hasBuiltinRole checks that the attached identity is a builtin role and // whether any of the given roles match the role set. func (a *ServerWithRoles) hasBuiltinRole(roles ...types.SystemRole) bool { @@ -445,7 +461,7 @@ func (a *ServerWithRoles) GenerateAWSOIDCToken(ctx context.Context, req types.Ge // CreateSessionTracker creates a tracker resource for an active session. func (a *ServerWithRoles) CreateSessionTracker(ctx context.Context, tracker types.SessionTracker) (types.SessionTracker, error) { - if err := a.serverAction(); err != nil { + if err := a.localServerAction(); err != nil { return nil, trace.Wrap(err) } @@ -602,7 +618,7 @@ func (a *ServerWithRoles) GetSessionTracker(ctx context.Context, sessionID strin return nil, trace.Wrap(err) } - if err := a.serverAction(); err == nil { + if err := a.localServerAction(); err == nil { return tracker, nil } @@ -627,7 +643,7 @@ func (a *ServerWithRoles) GetActiveSessionTrackers(ctx context.Context) ([]types return nil, trace.Wrap(err) } - if err := a.serverAction(); err == nil { + if err := a.localServerAction(); err == nil { return sessions, nil } @@ -655,7 +671,7 @@ func (a *ServerWithRoles) GetActiveSessionTrackersWithFilter(ctx context.Context return nil, trace.Wrap(err) } - if err := a.serverAction(); err == nil { + if err := a.localServerAction(); err == nil { return sessions, nil } @@ -678,7 +694,7 @@ func (a *ServerWithRoles) GetActiveSessionTrackersWithFilter(ctx context.Context // RemoveSessionTracker removes a tracker resource for an active session. func (a *ServerWithRoles) RemoveSessionTracker(ctx context.Context, sessionID string) error { - if err := a.serverAction(); err != nil { + if err := a.localServerAction(); err != nil { return trace.Wrap(err) } @@ -687,7 +703,7 @@ func (a *ServerWithRoles) RemoveSessionTracker(ctx context.Context, sessionID st // UpdateSessionTracker updates a tracker resource for an active session. func (a *ServerWithRoles) UpdateSessionTracker(ctx context.Context, req *proto.UpdateSessionTrackerRequest) error { - if err := a.serverAction(); err != nil { + if err := a.localServerAction(); err != nil { return trace.Wrap(err) } @@ -1525,12 +1541,12 @@ func (a *ServerWithRoles) ListResources(ctx context.Context, req proto.ListResou } // Check if auth server has a license for this resource type but only return an - // error if the user is not a builtin proxy or kube role. - // Builtin proxy and kube roles are allowed to list resources to avoid crashes + // error if the requester is not a builtin or remote server. + // Builtin and remote server roles are allowed to list resources to avoid crashes // even if the license is missing. // Users with other roles will get an error if the license is missing so they // can request a license with the correct features. - if err := enforceLicense(req.ResourceType); err != nil && !a.hasBuiltinRole(types.RoleProxy, types.RoleKube) { + if err := enforceLicense(req.ResourceType); err != nil && !a.isLocalOrRemoteServerAction() { return nil, trace.Wrap(err) } @@ -4918,7 +4934,7 @@ func (a *ServerWithRoles) StreamSessionEvents(ctx context.Context, sessionID ses return nil, e } - err := a.serverAction() + err := a.localServerAction() isTeleportServer := err == nil if !isTeleportServer { diff --git a/lib/authz/permissions.go b/lib/authz/permissions.go index 0355d5fa684fe..ecd204c0538c4 100644 --- a/lib/authz/permissions.go +++ b/lib/authz/permissions.go @@ -1240,6 +1240,12 @@ func (r RemoteBuiltinRole) GetIdentity() tlsca.Identity { return r.Identity } +// IsRemoteServer returns true if the primary role is either RoleRemoteProxy, or one of +// the local service roles (e.g. proxy) from the remote cluster. +func (r RemoteBuiltinRole) IsRemoteServer() bool { + return r.Role == types.RoleInstance || r.Role == types.RoleRemoteProxy || r.Role.IsLocalService() +} + // RemoteUser defines encoded remote user. type RemoteUser struct { // Username is a name of the remote user diff --git a/lib/service/kubernetes.go b/lib/service/kubernetes.go index 8b4087f4b5c7f..4ca205e5a1adb 100644 --- a/lib/service/kubernetes.go +++ b/lib/service/kubernetes.go @@ -46,7 +46,11 @@ func (process *TeleportProcess) initKubernetes() { if conn == nil { return trace.Wrap(err) } - + if !process.getClusterFeatures().Kubernetes { + log.Warn("Warning: Kubernetes service not intialized because Teleport Auth Server is not licensed for Kubernetes Access. ", + "Please contact the cluster administrator to enable it.") + return nil + } if err := process.initKubernetesService(log, conn); err != nil { warnOnErr(conn.Close(), log) return trace.Wrap(err)