diff --git a/lib/auth/auth_with_roles.go b/lib/auth/auth_with_roles.go index 344a3ed2e3a..401a06c94e4 100644 --- a/lib/auth/auth_with_roles.go +++ b/lib/auth/auth_with_roles.go @@ -1120,6 +1120,8 @@ func (a *ScopedServerWithRoles) UpsertNode(ctx context.Context, s types.Server) // Note: UpsertNode doesn't allow any namespaces but "default". // The Decision API only checks on the default namespace. if err := a.scopedContext.CheckerContext.Decision(ctx, s.GetScope(), func(checker *services.ScopedAccessChecker) error { + // The OpenSSH registration join flow uses direct UpsertNode rather than + // a control stream, so RoleNode needs permission to self-upsert. if err := a.scopedContext.AgentOwnedResourceAction(s.GetScope(), s.GetName(), types.RoleNode); err == nil { return nil } @@ -1142,40 +1144,16 @@ func (a *ScopedServerWithRoles) UpsertNode(ctx context.Context, s types.Server) func (a *ServerWithRoles) KeepAliveServer(ctx context.Context, handle types.KeepAlive) error { scopedServer := a.ScopedServerWithRoles() switch handle.GetType() { - case constants.KeepAliveNode: - if err := scopedServer.scopedContext.AgentOwnedResourceAction(handle.Scope, handle.Name, types.RoleNode); err != nil { - return trace.Wrap(err) - } - case constants.KeepAliveApp: - hostID := handle.HostID - if hostID == "" { // DELETE IN 9.0. Legacy app server is heartbeating back. - hostID = handle.Name - } - if err := scopedServer.scopedContext.AgentOwnedResourceAction("", hostID, types.RoleApp, types.RoleOkta); err != nil { - return trace.Wrap(err) - } - case constants.KeepAliveDatabase: - // There can be multiple database servers per host so they send their - // host ID in a separate field because unlike SSH nodes the resource - // name cannot be the host ID. - if err := scopedServer.scopedContext.AgentOwnedResourceAction("", handle.HostID, types.RoleDatabase); err != nil { - return trace.Wrap(err) - } case constants.KeepAliveWindowsDesktopService: if err := scopedServer.scopedContext.AgentOwnedResourceAction("", handle.Name, types.RoleWindowsDesktop); err != nil { return trace.Wrap(err) } - case constants.KeepAliveKube: - // Legacy kube proxy can heartbeat kube servers from the proxy itself so - // we need to check if the host has the Kube or Proxy role. - if err := scopedServer.scopedContext.AgentOwnedResourceAction("", handle.HostID, types.RoleKube, types.RoleProxy); err != nil { - return trace.Wrap(err) - } case constants.KeepAliveDatabaseService: if err := scopedServer.scopedContext.AgentOwnedResourceAction("", handle.Name, types.RoleDatabase); err != nil { return trace.Wrap(err) } default: + // Node/App/Database/Kube keepalives were a HeartbeatV1 mechanism; all v18+ agents use HeartbeatV2. return trace.BadParameter("unknown keep alive type %q", handle.Type) } @@ -6496,6 +6474,8 @@ func (a *ServerWithRoles) GetDatabaseServers(ctx context.Context, namespace stri // UpsertDatabaseServer creates or updates a new database proxy server. func (a *ServerWithRoles) UpsertDatabaseServer(ctx context.Context, server types.DatabaseServer) (*types.KeepAlive, error) { + // TODO(Joerger): DELETE IN v20.0.0 - remove the RoleDatabase agent-owned path. + // Only v18 agents attempt to fallback to upsert. if err := a.ScopedServerWithRoles().scopedContext.AgentOwnedResourceAction("", server.GetHostID(), types.RoleDatabase); err != nil { if err := a.actionNamespace(server.GetNamespace(), types.KindDatabaseServer, types.VerbCreate, types.VerbUpdate); err != nil { return nil, trace.Wrap(err) @@ -6659,10 +6639,8 @@ func (a *ServerWithRoles) checkAccessToApp(app types.Application) error { // UpsertApplicationServer registers an application server. func (a *ServerWithRoles) UpsertApplicationServer(ctx context.Context, server types.AppServer) (*types.KeepAlive, error) { - if err := a.ScopedServerWithRoles().scopedContext.AgentOwnedResourceAction("", server.GetHostID(), types.RoleApp); err != nil { - if err := a.actionNamespace(server.GetNamespace(), types.KindAppServer, types.VerbCreate, types.VerbUpdate); err != nil { - return nil, trace.Wrap(err) - } + if err := a.actionNamespace(server.GetNamespace(), types.KindAppServer, types.VerbCreate, types.VerbUpdate); err != nil { + return nil, trace.Wrap(err) } if server.GetScope() != "" { return nil, trace.BadParameter("scoped app server must register a control stream") @@ -7136,6 +7114,8 @@ func (a *ScopedServerWithRoles) GetApplicationServers(ctx context.Context, names // UpsertKubernetesServer creates or updates a Server representing a teleport // kubernetes server. func (a *ServerWithRoles) UpsertKubernetesServer(ctx context.Context, s types.KubeServer) (*types.KeepAlive, error) { + // TODO(Joerger): DELETE IN v20.0.0 - remove the RoleKube agent-owned path. + // Only v18 agents attempt to fallback to upsert. if err := a.ScopedServerWithRoles().scopedContext.AgentOwnedResourceAction("", s.GetHostID(), types.RoleKube); err != nil { if err := a.authorizeAction(types.KindKubeServer, types.VerbCreate, types.VerbUpdate); err != nil { return nil, trace.Wrap(err) diff --git a/lib/auth/grpcserver.go b/lib/auth/grpcserver.go index 1a9e5dc2768..185f49b6ed2 100644 --- a/lib/auth/grpcserver.go +++ b/lib/auth/grpcserver.go @@ -1694,20 +1694,6 @@ func (g *GRPCServer) UpsertApplicationServer(ctx context.Context, req *authpb.Up } } - // Two callers reach this RPC: - // 1. App-service agents heartbeating (have builtin role RoleApp - // or RoleInstance). Legacy agents may still send mixed-case - // names or URL-shaped public_addr; normalize so the heartbeat - // passes validation and the apps keep showing up in the - // cluster. - // 2. Admin users creating an app_server YAML (no builtin role). - // Do NOT normalize - admin writes follow strict validation; - // reject malformed input rather than silently rewriting it. - if authz.HasBuiltinRole(auth.context, string(types.RoleApp)) || - authz.HasBuiltinRole(auth.context, string(types.RoleInstance)) { - services.NormalizeAppServerForHeartbeat(server) - } - keepAlive, err := auth.UpsertApplicationServer(ctx, server) if err != nil { return nil, trace.Wrap(err) diff --git a/lib/authz/permissions.go b/lib/authz/permissions.go index 359ed399901..c352048fd1e 100644 --- a/lib/authz/permissions.go +++ b/lib/authz/permissions.go @@ -1069,7 +1069,6 @@ func scopedDefinitionForBuiltinRole(clusterName string, recConfig readonly.Sessi Namespaces: []string{types.Wildcard}, KubernetesLabels: types.Labels{types.Wildcard: []string{types.Wildcard}}, Rules: []types.Rule{ - // Kube agents have implicit permission to write their own cluster resource. types.NewRule(types.KindKubernetesCluster, services.RO()), types.NewRule(types.KindEvent, services.RW()), types.NewRule(types.KindCertAuthority, services.ReadNoSecrets()), @@ -1124,7 +1123,6 @@ func unscopedDefinitionForBuiltinRole(clusterName string, recConfig readonly.Ses Namespaces: []string{types.Wildcard}, NodeLabels: types.Labels{types.Wildcard: []string{types.Wildcard}}, Rules: []types.Rule{ - // Node agents have implicit permission to write their own node resource. types.NewRule(types.KindNode, services.RO()), types.NewRule(types.KindSSHSession, services.RW()), types.NewRule(types.KindEvent, services.WO()), @@ -1177,9 +1175,7 @@ func unscopedDefinitionForBuiltinRole(clusterName string, recConfig readonly.Ses types.NewRule(types.KindClusterNetworkingConfig, services.RO()), types.NewRule(types.KindSessionRecordingConfig, services.RO()), types.NewRule(types.KindClusterAuthPreference, services.RO()), - // App agents have implicit permission to write their own server resources. types.NewRule(types.KindAppServer, services.RO()), - // App agents have implicit permission to write their own App resource. types.NewRule(types.KindApp, services.RO()), types.NewRule(types.KindJWT, services.RW()), types.NewRule(types.KindLock, services.RO()), @@ -1213,9 +1209,7 @@ func unscopedDefinitionForBuiltinRole(clusterName string, recConfig readonly.Ses types.NewRule(types.KindClusterNetworkingConfig, services.RO()), types.NewRule(types.KindSessionRecordingConfig, services.RO()), types.NewRule(types.KindClusterAuthPreference, services.RO()), - // Databases agents have implicit permission to write their own server resources. types.NewRule(types.KindDatabaseServer, services.RO()), - // Databases agents have implicit permission to write their own service resource. types.NewRule(types.KindDatabaseService, services.RO()), types.NewRule(types.KindDatabase, services.RO()), types.NewRule(types.KindSemaphore, services.RW()), @@ -1325,7 +1319,6 @@ func unscopedDefinitionForBuiltinRole(clusterName string, recConfig readonly.Ses Namespaces: []string{types.Wildcard}, KubernetesLabels: types.Labels{types.Wildcard: []string{types.Wildcard}}, Rules: []types.Rule{ - // Kube agents have implicit permission to write their own server resources. types.NewRule(types.KindKubeServer, services.RO()), types.NewRule(types.KindKubeWaitingContainer, services.RW()), types.NewRule(types.KindEvent, services.WO()), @@ -1339,7 +1332,6 @@ func unscopedDefinitionForBuiltinRole(clusterName string, recConfig readonly.Ses types.NewRule(types.KindRole, services.RO()), types.NewRule(types.KindNamespace, services.RO()), types.NewRule(types.KindLock, services.RO()), - // Kube agents have implicit permission to write their own cluster resource. types.NewRule(types.KindKubernetesCluster, services.RO()), types.NewRule(types.KindSemaphore, services.RW()), types.NewRule(types.KindHealthCheckConfig, services.RO()), @@ -1366,9 +1358,7 @@ func unscopedDefinitionForBuiltinRole(clusterName string, recConfig readonly.Ses types.NewRule(types.KindRole, services.RO()), types.NewRule(types.KindNamespace, services.RO()), types.NewRule(types.KindLock, services.RO()), - // Desktop agents have implicit permission to write their own service resource. types.NewRule(types.KindWindowsDesktopService, services.RO()), - // Desktop agents have implicit permission to write their own desktop resources. types.NewRule(types.KindWindowsDesktop, services.RO()), types.NewRule(types.KindDynamicWindowsDesktop, services.RW()), }, diff --git a/lib/srv/desktop/linux_server.go b/lib/srv/desktop/linux_server.go index ca334f0e311..4e6f3f6ed83 100644 --- a/lib/srv/desktop/linux_server.go +++ b/lib/srv/desktop/linux_server.go @@ -221,7 +221,6 @@ func NewLinuxService(cfg LinuxServiceConfig) (*LinuxService, error) { func (s *LinuxService) startServiceHeartbeat() error { heartbeat, err := srv.NewLinuxDesktopHeartbeat(srv.HeartbeatV2Config[*linuxdesktopv1pb.LinuxDesktop]{ InventoryHandle: s.cfg.InventoryHandle, - Announcer: s.cfg.AccessPoint, GetResource: func(ctx context.Context) (*linuxdesktopv1pb.LinuxDesktop, error) { desktop, err := linuxdesktopv1.NewLinuxDesktop(s.cfg.Heartbeat.HostUUID, linuxdesktopv1pb.LinuxDesktopSpec_builder{ Addr: s.cfg.Heartbeat.PublicAddr,