diff --git a/lib/auth/api.go b/lib/auth/api.go index 0cecace7d87b1..362c33778068c 100644 --- a/lib/auth/api.go +++ b/lib/auth/api.go @@ -22,57 +22,644 @@ import ( "github.com/gravitational/teleport/api/client/proto" "github.com/gravitational/teleport/api/types" - apievents "github.com/gravitational/teleport/api/types/events" "github.com/gravitational/teleport/lib/events" "github.com/gravitational/teleport/lib/services" - "github.com/gravitational/teleport/lib/session" + "github.com/gravitational/trace" +) + +// Announcer specifies interface responsible for announcing presence +type Announcer interface { + // UpsertNode registers node presence, permanently if ttl is 0 or + // for the specified duration with second resolution if it's >= 1 second + UpsertNode(ctx context.Context, s types.Server) (*types.KeepAlive, error) + + // UpsertProxy registers proxy presence, permanently if ttl is 0 or + // for the specified duration with second resolution if it's >= 1 second + UpsertProxy(s types.Server) error + + // UpsertAuthServer registers auth server presence, permanently if ttl is 0 or + // for the specified duration with second resolution if it's >= 1 second + UpsertAuthServer(s types.Server) error + + // UpsertKubeService registers kubernetes presence, permanently if ttl is 0 + // or for the specified duration with second resolution if it's >= 1 second + UpsertKubeService(context.Context, types.Server) error + + // NewKeepAliver returns a new instance of keep aliver + NewKeepAliver(ctx context.Context) (types.KeepAliver, error) + + // UpsertAppServer adds an application server. + // + // DELETE IN 9.0. Deprecated, use UpsertApplicationServer. + UpsertAppServer(context.Context, types.Server) (*types.KeepAlive, error) + + // UpsertApplicationServer registers an application server. + UpsertApplicationServer(context.Context, types.AppServer) (*types.KeepAlive, error) + + // UpsertDatabaseServer registers a database proxy server. + UpsertDatabaseServer(context.Context, types.DatabaseServer) (*types.KeepAlive, error) + + // UpsertWindowsDesktopService registers a Windows desktop service. + UpsertWindowsDesktopService(context.Context, types.WindowsDesktopService) (*types.KeepAlive, error) + + // CreateWindowsDesktop registers a Windows desktop host. + CreateWindowsDesktop(context.Context, types.WindowsDesktop) error + // UpdateWindowsDesktop updates a Windows desktop host. + UpdateWindowsDesktop(context.Context, types.WindowsDesktop) error +} + +// accessPoint is an API interface implemented by a certificate authority (CA) +type accessPoint interface { + // Announcer adds methods used to announce presence + Announcer + // Streamer creates and manages audit streams + events.Streamer + + // Semaphores provides semaphore operations + types.Semaphores + + // UpsertTunnelConnection upserts tunnel connection + UpsertTunnelConnection(conn types.TunnelConnection) error + + // DeleteTunnelConnection deletes tunnel connection + DeleteTunnelConnection(clusterName, connName string) error + + // GenerateCertAuthorityCRL returns an empty CRL for a CA. + GenerateCertAuthorityCRL(ctx context.Context, caType types.CertAuthType) ([]byte, error) +} + +// ReadNodeAccessPoint is a read only API interface implemented by a certificate authority (CA) to be +// used by a teleport.ComponentNode. +// +// NOTE: This interface must match the resources replicated in cache.ForNode. +type ReadNodeAccessPoint interface { + // Closer closes all the resources + io.Closer + + // NewWatcher returns a new event watcher. + NewWatcher(ctx context.Context, watch types.Watch) (types.Watcher, error) + + // GetCertAuthority returns cert authority by id + GetCertAuthority(id types.CertAuthID, loadKeys bool, opts ...services.MarshalOption) (types.CertAuthority, error) + + // GetCertAuthorities returns a list of cert authorities + GetCertAuthorities(caType types.CertAuthType, loadKeys bool, opts ...services.MarshalOption) ([]types.CertAuthority, error) + + // GetClusterName gets the name of the cluster from the backend. + GetClusterName(opts ...services.MarshalOption) (types.ClusterName, error) + + // GetClusterAuditConfig returns cluster audit configuration. + GetClusterAuditConfig(ctx context.Context, opts ...services.MarshalOption) (types.ClusterAuditConfig, error) + + // GetClusterNetworkingConfig returns cluster networking configuration. + GetClusterNetworkingConfig(ctx context.Context, opts ...services.MarshalOption) (types.ClusterNetworkingConfig, error) + + // GetAuthPreference returns the cluster authentication configuration. + GetAuthPreference(ctx context.Context) (types.AuthPreference, error) + + // GetSessionRecordingConfig returns session recording configuration. + GetSessionRecordingConfig(ctx context.Context, opts ...services.MarshalOption) (types.SessionRecordingConfig, error) + + // GetRole returns role by name + GetRole(ctx context.Context, name string) (types.Role, error) + + // GetRoles returns a list of roles + GetRoles(ctx context.Context) ([]types.Role, error) + + // GetNamespaces returns a list of namespaces + GetNamespaces() ([]types.Namespace, error) + + // GetNamespace returns namespace by name + GetNamespace(name string) (*types.Namespace, error) + + // GetNetworkRestrictions returns networking restrictions for restricted shell to enforce + GetNetworkRestrictions(ctx context.Context) (types.NetworkRestrictions, error) +} + +// NodeAccessPoint is an API interface implemented by a certificate authority (CA) to be +// used by teleport.ComponentNode. +type NodeAccessPoint interface { + // ReadNodeAccessPoint provides methods to read data + ReadNodeAccessPoint + + // accessPoint provides common access point functionality + accessPoint +} + +// ReadProxyAccessPoint is a read only API interface implemented by a certificate authority (CA) to be +// used by a teleport.ComponentProxy. +// +// NOTE: This interface must match the resources replicated in cache.ForProxy. +type ReadProxyAccessPoint interface { + // Closer closes all the resources + io.Closer + + // NewWatcher returns a new event watcher. + NewWatcher(ctx context.Context, watch types.Watch) (types.Watcher, error) + + // GetCertAuthority returns cert authority by id + GetCertAuthority(id types.CertAuthID, loadKeys bool, opts ...services.MarshalOption) (types.CertAuthority, error) + + // GetCertAuthorities returns a list of cert authorities + GetCertAuthorities(caType types.CertAuthType, loadKeys bool, opts ...services.MarshalOption) ([]types.CertAuthority, error) + + // GetClusterName gets the name of the cluster from the backend. + GetClusterName(opts ...services.MarshalOption) (types.ClusterName, error) + + // GetClusterAuditConfig returns cluster audit configuration. + GetClusterAuditConfig(ctx context.Context, opts ...services.MarshalOption) (types.ClusterAuditConfig, error) + + // GetClusterNetworkingConfig returns cluster networking configuration. + GetClusterNetworkingConfig(ctx context.Context, opts ...services.MarshalOption) (types.ClusterNetworkingConfig, error) + + // GetAuthPreference returns the cluster authentication configuration. + GetAuthPreference(ctx context.Context) (types.AuthPreference, error) + + // GetSessionRecordingConfig returns session recording configuration. + GetSessionRecordingConfig(ctx context.Context, opts ...services.MarshalOption) (types.SessionRecordingConfig, error) + + // GetRole returns role by name + GetRole(ctx context.Context, name string) (types.Role, error) + + // GetRoles returns a list of roles + GetRoles(ctx context.Context) ([]types.Role, error) + + // GetUser returns a services.User for this cluster. + GetUser(name string, withSecrets bool) (types.User, error) + + // GetNamespaces returns a list of namespaces + GetNamespaces() ([]types.Namespace, error) + + // GetNamespace returns namespace by name + GetNamespace(name string) (*types.Namespace, error) + + // GetNode returns a node by name and namespace. + GetNode(ctx context.Context, namespace, name string) (types.Server, error) + + // GetNodes returns a list of registered servers for this cluster. + GetNodes(ctx context.Context, namespace string, opts ...services.MarshalOption) ([]types.Server, error) + + // GetProxies returns a list of proxy servers registered in the cluster + GetProxies() ([]types.Server, error) + + // GetAuthServers returns a list of auth servers registered in the cluster + GetAuthServers() ([]types.Server, error) + + // GetReverseTunnels returns a list of reverse tunnels + GetReverseTunnels(opts ...services.MarshalOption) ([]types.ReverseTunnel, error) + + // GetAllTunnelConnections returns all tunnel connections + GetAllTunnelConnections(opts ...services.MarshalOption) ([]types.TunnelConnection, error) + + // GetTunnelConnections returns tunnel connections for a given cluster + GetTunnelConnections(clusterName string, opts ...services.MarshalOption) ([]types.TunnelConnection, error) + + // GetApplicationServers returns all registered application servers. + GetApplicationServers(ctx context.Context, namespace string) ([]types.AppServer, error) + + // GetAppServers gets all application servers. + // + // DELETE IN 9.0. Deprecated, use GetApplicationServers. + GetAppServers(ctx context.Context, namespace string, opts ...services.MarshalOption) ([]types.Server, error) + + // GetApps returns all application resources. + GetApps(ctx context.Context) ([]types.Application, error) + + // GetApp returns the specified application resource. + GetApp(ctx context.Context, name string) (types.Application, error) + + // GetNetworkRestrictions returns networking restrictions for restricted shell to enforce + GetNetworkRestrictions(ctx context.Context) (types.NetworkRestrictions, error) + + // GetAppSession gets an application web session. + GetAppSession(context.Context, types.GetAppSessionRequest) (types.WebSession, error) + + // GetWebSession gets a web session for the given request + GetWebSession(context.Context, types.GetWebSessionRequest) (types.WebSession, error) + + // GetWebToken gets a web token for the given request + GetWebToken(context.Context, types.GetWebTokenRequest) (types.WebToken, error) + + // GetRemoteClusters returns a list of remote clusters + GetRemoteClusters(opts ...services.MarshalOption) ([]types.RemoteCluster, error) + + // GetRemoteCluster returns a remote cluster by name + GetRemoteCluster(clusterName string) (types.RemoteCluster, error) + + // GetKubeServices returns a list of kubernetes services registered in the cluster + GetKubeServices(context.Context) ([]types.Server, error) + + // GetDatabaseServers returns all registered database proxy servers. + GetDatabaseServers(ctx context.Context, namespace string, opts ...services.MarshalOption) ([]types.DatabaseServer, error) + + // GetDatabases returns all database resources. + GetDatabases(ctx context.Context) ([]types.Database, error) + + // GetDatabase returns the specified database resource. + GetDatabase(ctx context.Context, name string) (types.Database, error) + + // GetWindowsDesktops returns windows desktop hosts. + GetWindowsDesktops(ctx context.Context) ([]types.WindowsDesktop, error) + + // GetWindowsDesktop returns a named windows desktop host. + GetWindowsDesktop(ctx context.Context, name string) (types.WindowsDesktop, error) + + // GetWindowsDesktopServices returns windows desktop hosts. + GetWindowsDesktopServices(ctx context.Context) ([]types.WindowsDesktopService, error) +} + +// ProxyAccessPoint is an API interface implemented by a certificate authority (CA) to be +// used by a teleport.ComponentProxy. +type ProxyAccessPoint interface { + // ReadProxyAccessPoint provides methods to read data + ReadProxyAccessPoint + + // accessPoint provides common access point functionality + accessPoint +} + +// ReadRemoteProxyAccessPoint is a read only API interface implemented by a certificate authority (CA) to be +// used by a teleport.ComponentProxy. +// +// NOTE: This interface must match the resources replicated in cache.ForRemoteProxy. +type ReadRemoteProxyAccessPoint interface { + // Closer closes all the resources + io.Closer + + // NewWatcher returns a new event watcher. + NewWatcher(ctx context.Context, watch types.Watch) (types.Watcher, error) + + // GetCertAuthority returns cert authority by id + GetCertAuthority(id types.CertAuthID, loadKeys bool, opts ...services.MarshalOption) (types.CertAuthority, error) + + // GetCertAuthorities returns a list of cert authorities + GetCertAuthorities(caType types.CertAuthType, loadKeys bool, opts ...services.MarshalOption) ([]types.CertAuthority, error) + + // GetClusterName gets the name of the cluster from the backend. + GetClusterName(opts ...services.MarshalOption) (types.ClusterName, error) + + // GetClusterAuditConfig returns cluster audit configuration. + GetClusterAuditConfig(ctx context.Context, opts ...services.MarshalOption) (types.ClusterAuditConfig, error) + + // GetClusterNetworkingConfig returns cluster networking configuration. + GetClusterNetworkingConfig(ctx context.Context, opts ...services.MarshalOption) (types.ClusterNetworkingConfig, error) + + // GetAuthPreference returns the cluster authentication configuration. + GetAuthPreference(ctx context.Context) (types.AuthPreference, error) + + // GetSessionRecordingConfig returns session recording configuration. + GetSessionRecordingConfig(ctx context.Context, opts ...services.MarshalOption) (types.SessionRecordingConfig, error) + + // GetRole returns role by name + GetRole(ctx context.Context, name string) (types.Role, error) + + // GetRoles returns a list of roles + GetRoles(ctx context.Context) ([]types.Role, error) + + // GetNamespaces returns a list of namespaces + GetNamespaces() ([]types.Namespace, error) + + // GetNamespace returns namespace by name + GetNamespace(name string) (*types.Namespace, error) + + // GetNode returns a node by name and namespace. + GetNode(ctx context.Context, namespace, name string) (types.Server, error) + + // GetNodes returns a list of registered servers for this cluster. + GetNodes(ctx context.Context, namespace string, opts ...services.MarshalOption) ([]types.Server, error) + + // GetProxies returns a list of proxy servers registered in the cluster + GetProxies() ([]types.Server, error) + + // GetAuthServers returns a list of auth servers registered in the cluster + GetAuthServers() ([]types.Server, error) + + // GetReverseTunnels returns a list of reverse tunnels + GetReverseTunnels(opts ...services.MarshalOption) ([]types.ReverseTunnel, error) + + // GetAllTunnelConnections returns all tunnel connections + GetAllTunnelConnections(opts ...services.MarshalOption) ([]types.TunnelConnection, error) + + // GetTunnelConnections returns tunnel connections for a given cluster + GetTunnelConnections(clusterName string, opts ...services.MarshalOption) ([]types.TunnelConnection, error) + + // GetAppServers gets all application servers. + // + // DELETE IN 9.0. Deprecated, use GetApplicationServers. + GetAppServers(ctx context.Context, namespace string, opts ...services.MarshalOption) ([]types.Server, error) + + // GetApplicationServers returns all registered application servers. + GetApplicationServers(ctx context.Context, namespace string) ([]types.AppServer, error) + + // GetRemoteClusters returns a list of remote clusters + GetRemoteClusters(opts ...services.MarshalOption) ([]types.RemoteCluster, error) + + // GetRemoteCluster returns a remote cluster by name + GetRemoteCluster(clusterName string) (types.RemoteCluster, error) + + // GetKubeServices returns a list of kubernetes services registered in the cluster + GetKubeServices(context.Context) ([]types.Server, error) + + // GetDatabaseServers returns all registered database proxy servers. + GetDatabaseServers(ctx context.Context, namespace string, opts ...services.MarshalOption) ([]types.DatabaseServer, error) +} + +// RemoteProxyAccessPoint is an API interface implemented by a certificate authority (CA) to be +// used by a teleport.ComponentProxy. +type RemoteProxyAccessPoint interface { + // ReadRemoteProxyAccessPoint provides methods to read data + ReadRemoteProxyAccessPoint + + // accessPoint provides common access point functionality + accessPoint +} + +// ReadKubernetesAccessPoint is an API interface implemented by a certificate authority (CA) to be +// used by a teleport.ComponentKube. +// +// NOTE: This interface must match the resources replicated in cache.ForKubernetes. +type ReadKubernetesAccessPoint interface { + // Closer closes all the resources + io.Closer + + // NewWatcher returns a new event watcher. + NewWatcher(ctx context.Context, watch types.Watch) (types.Watcher, error) + + // GetCertAuthority returns cert authority by id + GetCertAuthority(id types.CertAuthID, loadKeys bool, opts ...services.MarshalOption) (types.CertAuthority, error) + + // GetCertAuthorities returns a list of cert authorities + GetCertAuthorities(caType types.CertAuthType, loadKeys bool, opts ...services.MarshalOption) ([]types.CertAuthority, error) + + // GetClusterName gets the name of the cluster from the backend. + GetClusterName(opts ...services.MarshalOption) (types.ClusterName, error) + + // GetClusterAuditConfig returns cluster audit configuration. + GetClusterAuditConfig(ctx context.Context, opts ...services.MarshalOption) (types.ClusterAuditConfig, error) + + // GetClusterNetworkingConfig returns cluster networking configuration. + GetClusterNetworkingConfig(ctx context.Context, opts ...services.MarshalOption) (types.ClusterNetworkingConfig, error) + + // GetAuthPreference returns the cluster authentication configuration. + GetAuthPreference(ctx context.Context) (types.AuthPreference, error) + + // GetSessionRecordingConfig returns session recording configuration. + GetSessionRecordingConfig(ctx context.Context, opts ...services.MarshalOption) (types.SessionRecordingConfig, error) + + // GetUser returns a services.User for this cluster. + GetUser(name string, withSecrets bool) (types.User, error) + + // GetRole returns role by name + GetRole(ctx context.Context, name string) (types.Role, error) + + // GetRoles returns a list of roles + GetRoles(ctx context.Context) ([]types.Role, error) + + // GetNamespaces returns a list of namespaces + GetNamespaces() ([]types.Namespace, error) + + // GetNamespace returns namespace by name + GetNamespace(name string) (*types.Namespace, error) + + // GetKubeServices returns a list of kubernetes services registered in the cluster + GetKubeServices(context.Context) ([]types.Server, error) +} + +// KubernetesAccessPoint is an API interface implemented by a certificate authority (CA) to be +// used by a teleport.ComponentKube. +type KubernetesAccessPoint interface { + // ReadKubernetesAccessPoint provides methods to read data + ReadKubernetesAccessPoint + + // accessPoint provides common access point functionality + accessPoint +} + +// ReadAppsAccessPoint is a read only API interface implemented by a certificate authority (CA) to be +// used by a teleport.ComponentApp. +// +// NOTE: This interface must match the resources replicated in cache.ForApps. +type ReadAppsAccessPoint interface { + // Closer closes all the resources + io.Closer + + // NewWatcher returns a new event watcher. + NewWatcher(ctx context.Context, watch types.Watch) (types.Watcher, error) + + // GetCertAuthority returns cert authority by id + GetCertAuthority(id types.CertAuthID, loadKeys bool, opts ...services.MarshalOption) (types.CertAuthority, error) + + // GetCertAuthorities returns a list of cert authorities + GetCertAuthorities(caType types.CertAuthType, loadKeys bool, opts ...services.MarshalOption) ([]types.CertAuthority, error) + + // GetClusterName gets the name of the cluster from the backend. + GetClusterName(opts ...services.MarshalOption) (types.ClusterName, error) + + // GetClusterAuditConfig returns cluster audit configuration. + GetClusterAuditConfig(ctx context.Context, opts ...services.MarshalOption) (types.ClusterAuditConfig, error) + + // GetClusterNetworkingConfig returns cluster networking configuration. + GetClusterNetworkingConfig(ctx context.Context, opts ...services.MarshalOption) (types.ClusterNetworkingConfig, error) + + // GetAuthPreference returns the cluster authentication configuration. + GetAuthPreference(ctx context.Context) (types.AuthPreference, error) + + // GetSessionRecordingConfig returns session recording configuration. + GetSessionRecordingConfig(ctx context.Context, opts ...services.MarshalOption) (types.SessionRecordingConfig, error) + + // GetUser returns a services.User for this cluster. + GetUser(name string, withSecrets bool) (types.User, error) + + // GetRole returns role by name + GetRole(ctx context.Context, name string) (types.Role, error) - "github.com/gravitational/trace" -) + // GetRoles returns a list of roles + GetRoles(ctx context.Context) ([]types.Role, error) -// Announcer specifies interface responsible for announcing presence -type Announcer interface { - // UpsertNode registers node presence, permanently if ttl is 0 or - // for the specified duration with second resolution if it's >= 1 second - UpsertNode(ctx context.Context, s types.Server) (*types.KeepAlive, error) + // GetProxies returns a list of proxy servers registered in the cluster + GetProxies() ([]types.Server, error) - // UpsertProxy registers proxy presence, permanently if ttl is 0 or - // for the specified duration with second resolution if it's >= 1 second - UpsertProxy(s types.Server) error + // GetNamespaces returns a list of namespaces + GetNamespaces() ([]types.Namespace, error) - // UpsertAuthServer registers auth server presence, permanently if ttl is 0 or - // for the specified duration with second resolution if it's >= 1 second - UpsertAuthServer(s types.Server) error + // GetNamespace returns namespace by name + GetNamespace(name string) (*types.Namespace, error) - // UpsertKubeService registers kubernetes presence, permanently if ttl is 0 - // or for the specified duration with second resolution if it's >= 1 second - UpsertKubeService(context.Context, types.Server) error + // GetApps returns all application resources. + GetApps(ctx context.Context) ([]types.Application, error) - // NewKeepAliver returns a new instance of keep aliver - NewKeepAliver(ctx context.Context) (types.KeepAliver, error) + // GetApp returns the specified application resource. + GetApp(ctx context.Context, name string) (types.Application, error) +} - // UpsertAppServer adds an application server. - // - // DELETE IN 9.0. Deprecated, use UpsertApplicationServer. - UpsertAppServer(context.Context, types.Server) (*types.KeepAlive, error) +// AppsAccessPoint is an API interface implemented by a certificate authority (CA) to be +// used by a teleport.ComponentApp. +type AppsAccessPoint interface { + // ReadAppsAccessPoint provides methods to read data + ReadAppsAccessPoint - // UpsertApplicationServer registers an application server. - UpsertApplicationServer(context.Context, types.AppServer) (*types.KeepAlive, error) + // accessPoint provides common access point functionality + accessPoint +} - // UpsertDatabaseServer registers a database proxy server. - UpsertDatabaseServer(context.Context, types.DatabaseServer) (*types.KeepAlive, error) +// ReadDatabaseAccessPoint is an API interface implemented by a certificate authority (CA) to be +// used by a teleport.ComponentDatabase. +// +// NOTE: This interface must match the resources replicated in cache.ForDatabases. +type ReadDatabaseAccessPoint interface { + // Closer closes all the resources + io.Closer - // UpsertWindowsDesktopService registers a Windows desktop service. - UpsertWindowsDesktopService(context.Context, types.WindowsDesktopService) (*types.KeepAlive, error) + // NewWatcher returns a new event watcher. + NewWatcher(ctx context.Context, watch types.Watch) (types.Watcher, error) - // CreateWindowsDesktop registers a Windows desktop host. - CreateWindowsDesktop(context.Context, types.WindowsDesktop) error - // UpdateWindowsDesktop updates a Windows desktop host. - UpdateWindowsDesktop(context.Context, types.WindowsDesktop) error + // GetCertAuthority returns cert authority by id + GetCertAuthority(id types.CertAuthID, loadKeys bool, opts ...services.MarshalOption) (types.CertAuthority, error) + + // GetCertAuthorities returns a list of cert authorities + GetCertAuthorities(caType types.CertAuthType, loadKeys bool, opts ...services.MarshalOption) ([]types.CertAuthority, error) + + // GetClusterName gets the name of the cluster from the backend. + GetClusterName(opts ...services.MarshalOption) (types.ClusterName, error) + + // GetClusterAuditConfig returns cluster audit configuration. + GetClusterAuditConfig(ctx context.Context, opts ...services.MarshalOption) (types.ClusterAuditConfig, error) + + // GetClusterNetworkingConfig returns cluster networking configuration. + GetClusterNetworkingConfig(ctx context.Context, opts ...services.MarshalOption) (types.ClusterNetworkingConfig, error) + + // GetAuthPreference returns the cluster authentication configuration. + GetAuthPreference(ctx context.Context) (types.AuthPreference, error) + + // GetSessionRecordingConfig returns session recording configuration. + GetSessionRecordingConfig(ctx context.Context, opts ...services.MarshalOption) (types.SessionRecordingConfig, error) + + // GetUser returns a services.User for this cluster. + GetUser(name string, withSecrets bool) (types.User, error) + + // GetRole returns role by name + GetRole(ctx context.Context, name string) (types.Role, error) + + // GetRoles returns a list of roles + GetRoles(ctx context.Context) ([]types.Role, error) + + // GetProxies returns a list of proxy servers registered in the cluster + GetProxies() ([]types.Server, error) + + // GetNamespaces returns a list of namespaces + GetNamespaces() ([]types.Namespace, error) + + // GetNamespace returns namespace by name + GetNamespace(name string) (*types.Namespace, error) + + // GetDatabases returns all database resources. + GetDatabases(ctx context.Context) ([]types.Database, error) + + // GetDatabase returns the specified database resource. + GetDatabase(ctx context.Context, name string) (types.Database, error) +} + +// DatabaseAccessPoint is an API interface implemented by a certificate authority (CA) to be +// used by a teleport.ComponentDatabase. +type DatabaseAccessPoint interface { + // ReadDatabaseAccessPoint provides methods to read data + ReadDatabaseAccessPoint + + // accessPoint provides common access point functionality + accessPoint +} + +// ReadWindowsDesktopAccessPoint is an API interface implemented by a certificate authority (CA) to be +// used by a teleport.ComponentWindowsDesktop. +// +// NOTE: This interface must match the resources replicated in cache.ForWindowsDesktop. +type ReadWindowsDesktopAccessPoint interface { + // Closer closes all the resources + io.Closer + + // NewWatcher returns a new event watcher. + NewWatcher(ctx context.Context, watch types.Watch) (types.Watcher, error) + + // GetCertAuthority returns cert authority by id + GetCertAuthority(id types.CertAuthID, loadKeys bool, opts ...services.MarshalOption) (types.CertAuthority, error) + + // GetCertAuthorities returns a list of cert authorities + GetCertAuthorities(caType types.CertAuthType, loadKeys bool, opts ...services.MarshalOption) ([]types.CertAuthority, error) + + // GetClusterName gets the name of the cluster from the backend. + GetClusterName(opts ...services.MarshalOption) (types.ClusterName, error) + + // GetClusterAuditConfig returns cluster audit configuration. + GetClusterAuditConfig(ctx context.Context, opts ...services.MarshalOption) (types.ClusterAuditConfig, error) + + // GetClusterNetworkingConfig returns cluster networking configuration. + GetClusterNetworkingConfig(ctx context.Context, opts ...services.MarshalOption) (types.ClusterNetworkingConfig, error) + + // GetAuthPreference returns the cluster authentication configuration. + GetAuthPreference(ctx context.Context) (types.AuthPreference, error) + + // GetSessionRecordingConfig returns session recording configuration. + GetSessionRecordingConfig(ctx context.Context, opts ...services.MarshalOption) (types.SessionRecordingConfig, error) + + // GetUser returns a services.User for this cluster. + GetUser(name string, withSecrets bool) (types.User, error) + + // GetRole returns role by name + GetRole(ctx context.Context, name string) (types.Role, error) + + // GetRoles returns a list of roles + GetRoles(ctx context.Context) ([]types.Role, error) + + // GetNamespaces returns a list of namespaces + GetNamespaces() ([]types.Namespace, error) + + // GetNamespace returns namespace by name + GetNamespace(name string) (*types.Namespace, error) + + // GetWindowsDesktops returns windows desktop hosts. + GetWindowsDesktops(ctx context.Context) ([]types.WindowsDesktop, error) + + // GetWindowsDesktop returns a named windows desktop host. + GetWindowsDesktop(ctx context.Context, name string) (types.WindowsDesktop, error) + + // GetWindowsDesktopServices returns windows desktop hosts. + GetWindowsDesktopServices(ctx context.Context) ([]types.WindowsDesktopService, error) +} + +// WindowsDesktopAccessPoint is an API interface implemented by a certificate authority (CA) to be +// used by a teleport.ComponentWindowsDesktop. +type WindowsDesktopAccessPoint interface { + // ReadWindowsDesktopAccessPoint provides methods to read data + ReadWindowsDesktopAccessPoint + + // accessPoint provides common access point functionality + accessPoint +} + +// AccessCache is a subset of the interface working on the certificate authorities +type AccessCache interface { + // GetCertAuthority returns cert authority by id + GetCertAuthority(id types.CertAuthID, loadKeys bool, opts ...services.MarshalOption) (types.CertAuthority, error) + + // GetCertAuthorities returns a list of cert authorities + GetCertAuthorities(caType types.CertAuthType, loadKeys bool, opts ...services.MarshalOption) ([]types.CertAuthority, error) + + // GetClusterAuditConfig returns cluster audit configuration. + GetClusterAuditConfig(ctx context.Context, opts ...services.MarshalOption) (types.ClusterAuditConfig, error) + + // GetClusterNetworkingConfig returns cluster networking configuration. + GetClusterNetworkingConfig(ctx context.Context, opts ...services.MarshalOption) (types.ClusterNetworkingConfig, error) + + // GetSessionRecordingConfig returns session recording configuration. + GetSessionRecordingConfig(ctx context.Context, opts ...services.MarshalOption) (types.SessionRecordingConfig, error) + + // GetClusterName gets the name of the cluster from the backend. + GetClusterName(opts ...services.MarshalOption) (types.ClusterName, error) } -// ReadAccessPoint is an API interface implemented by a certificate authority (CA) -type ReadAccessPoint interface { +// Cache is a subset of the auth interface handling +// access to the discovery API and static tokens +type Cache interface { // Closer closes all the resources io.Closer @@ -192,57 +779,8 @@ type ReadAccessPoint interface { // GetWindowsDesktop returns a named windows desktop host. GetWindowsDesktop(ctx context.Context, name string) (types.WindowsDesktop, error) - // GetWindowsDesktops returns windows desktop hosts. + // GetWindowsDesktopServices returns windows desktop hosts. GetWindowsDesktopServices(ctx context.Context) ([]types.WindowsDesktopService, error) -} - -// AccessPoint is an API interface implemented by a certificate authority (CA) -type AccessPoint interface { - // ReadAccessPoint provides methods to read data - ReadAccessPoint - // Announcer adds methods used to announce presence - Announcer - // Streamer creates and manages audit streams - events.Streamer - - // Semaphores provides semaphore operations - types.Semaphores - - // UpsertTunnelConnection upserts tunnel connection - UpsertTunnelConnection(conn types.TunnelConnection) error - - // DeleteTunnelConnection deletes tunnel connection - DeleteTunnelConnection(clusterName, connName string) error - - // GenerateCertAuthority returns an empty CRL for a CA. - GenerateCertAuthorityCRL(ctx context.Context, caType types.CertAuthType) ([]byte, error) -} - -// AccessCache is a subset of the interface working on the certificate authorities -type AccessCache interface { - // GetCertAuthority returns cert authority by id - GetCertAuthority(id types.CertAuthID, loadKeys bool, opts ...services.MarshalOption) (types.CertAuthority, error) - - // GetCertAuthorities returns a list of cert authorities - GetCertAuthorities(caType types.CertAuthType, loadKeys bool, opts ...services.MarshalOption) ([]types.CertAuthority, error) - - // GetClusterAuditConfig returns cluster audit configuration. - GetClusterAuditConfig(ctx context.Context, opts ...services.MarshalOption) (types.ClusterAuditConfig, error) - - // GetClusterNetworkingConfig returns cluster networking configuration. - GetClusterNetworkingConfig(ctx context.Context, opts ...services.MarshalOption) (types.ClusterNetworkingConfig, error) - - // GetSessionRecordingConfig returns session recording configuration. - GetSessionRecordingConfig(ctx context.Context, opts ...services.MarshalOption) (types.SessionRecordingConfig, error) - - // GetClusterName gets the name of the cluster from the backend. - GetClusterName(opts ...services.MarshalOption) (types.ClusterName, error) -} - -// Cache is a subset of the auth interface hanlding -// access to the discovery API and static tokens -type Cache interface { - ReadAccessPoint // GetStaticTokens gets the list of static tokens used to provision nodes. GetStaticTokens() (types.StaticTokens, error) @@ -265,149 +803,158 @@ type Cache interface { // cache, the other Teleport components should make use of // services.LockWatcher that provides the necessary freshness guarantees. GetLocks(ctx context.Context, inForceOnly bool, targets ...types.LockTarget) ([]types.Lock, error) - - // NewWatcher returns a new event watcher - NewWatcher(ctx context.Context, watch types.Watch) (types.Watcher, error) -} - -// NewWrapper returns new access point wrapper -func NewWrapper(base AccessPoint, cache ReadAccessPoint) AccessPoint { - return &Wrapper{ - NoCache: base, - ReadAccessPoint: cache, - } } -// Wrapper wraps access point and auth cache in one client -// so that reads of cached values can be intercepted. -type Wrapper struct { - ReadAccessPoint - NoCache AccessPoint +type NodeWrapper struct { + ReadNodeAccessPoint + accessPoint + NoCache NodeAccessPoint } -// ResumeAuditStream resumes existing audit stream -func (w *Wrapper) ResumeAuditStream(ctx context.Context, sid session.ID, uploadID string) (apievents.Stream, error) { - return w.NoCache.ResumeAuditStream(ctx, sid, uploadID) -} - -// CreateAuditStream creates new audit stream -func (w *Wrapper) CreateAuditStream(ctx context.Context, sid session.ID) (apievents.Stream, error) { - return w.NoCache.CreateAuditStream(ctx, sid) +func NewNodeWrapper(base NodeAccessPoint, cache ReadNodeAccessPoint) NodeAccessPoint { + return &NodeWrapper{ + NoCache: base, + accessPoint: base, + ReadNodeAccessPoint: cache, + } } // Close closes all associated resources -func (w *Wrapper) Close() error { +func (w *NodeWrapper) Close() error { err := w.NoCache.Close() - err2 := w.ReadAccessPoint.Close() + err2 := w.ReadNodeAccessPoint.Close() return trace.NewAggregate(err, err2) } -// UpsertNode is part of auth.AccessPoint implementation -func (w *Wrapper) UpsertNode(ctx context.Context, s types.Server) (*types.KeepAlive, error) { - return w.NoCache.UpsertNode(ctx, s) -} - -// UpsertAuthServer is part of auth.AccessPoint implementation -func (w *Wrapper) UpsertAuthServer(s types.Server) error { - return w.NoCache.UpsertAuthServer(s) +type ProxyWrapper struct { + ReadProxyAccessPoint + accessPoint + NoCache ProxyAccessPoint } -// NewKeepAliver returns a new instance of keep aliver -func (w *Wrapper) NewKeepAliver(ctx context.Context) (types.KeepAliver, error) { - return w.NoCache.NewKeepAliver(ctx) +func NewProxyWrapper(base ProxyAccessPoint, cache ReadProxyAccessPoint) ProxyAccessPoint { + return &ProxyWrapper{ + NoCache: base, + accessPoint: base, + ReadProxyAccessPoint: cache, + } } -// UpsertProxy is part of auth.AccessPoint implementation -func (w *Wrapper) UpsertProxy(s types.Server) error { - return w.NoCache.UpsertProxy(s) +// Close closes all associated resources +func (w *ProxyWrapper) Close() error { + err := w.NoCache.Close() + err2 := w.ReadProxyAccessPoint.Close() + return trace.NewAggregate(err, err2) } -// UpsertTunnelConnection is a part of auth.AccessPoint implementation -func (w *Wrapper) UpsertTunnelConnection(conn types.TunnelConnection) error { - return w.NoCache.UpsertTunnelConnection(conn) +type RemoteProxyWrapper struct { + ReadRemoteProxyAccessPoint + accessPoint + NoCache RemoteProxyAccessPoint } -// DeleteTunnelConnection is a part of auth.AccessPoint implementation -func (w *Wrapper) DeleteTunnelConnection(clusterName, connName string) error { - return w.NoCache.DeleteTunnelConnection(clusterName, connName) +func NewRemoteProxyWrapper(base RemoteProxyAccessPoint, cache ReadRemoteProxyAccessPoint) RemoteProxyAccessPoint { + return &RemoteProxyWrapper{ + NoCache: base, + accessPoint: base, + ReadRemoteProxyAccessPoint: cache, + } } -// AcquireSemaphore acquires lease with requested resources from semaphore -func (w *Wrapper) AcquireSemaphore(ctx context.Context, params types.AcquireSemaphoreRequest) (*types.SemaphoreLease, error) { - return w.NoCache.AcquireSemaphore(ctx, params) +// Close closes all associated resources +func (w *RemoteProxyWrapper) Close() error { + err := w.NoCache.Close() + err2 := w.ReadRemoteProxyAccessPoint.Close() + return trace.NewAggregate(err, err2) } -// KeepAliveSemaphoreLease updates semaphore lease -func (w *Wrapper) KeepAliveSemaphoreLease(ctx context.Context, lease types.SemaphoreLease) error { - return w.NoCache.KeepAliveSemaphoreLease(ctx, lease) +type KubernetesWrapper struct { + ReadKubernetesAccessPoint + accessPoint + NoCache KubernetesAccessPoint } -// CancelSemaphoreLease cancels semaphore lease early -func (w *Wrapper) CancelSemaphoreLease(ctx context.Context, lease types.SemaphoreLease) error { - return w.NoCache.CancelSemaphoreLease(ctx, lease) +func NewKubernetesWrapper(base KubernetesAccessPoint, cache ReadKubernetesAccessPoint) KubernetesAccessPoint { + return &KubernetesWrapper{ + NoCache: base, + accessPoint: base, + ReadKubernetesAccessPoint: cache, + } } -// GetSemaphores returns a list of semaphores matching supplied filter. -func (w *Wrapper) GetSemaphores(ctx context.Context, filter types.SemaphoreFilter) ([]types.Semaphore, error) { - return w.NoCache.GetSemaphores(ctx, filter) +// Close closes all associated resources +func (w *KubernetesWrapper) Close() error { + err := w.NoCache.Close() + err2 := w.ReadKubernetesAccessPoint.Close() + return trace.NewAggregate(err, err2) } -// DeleteSemaphore deletes a semaphore matching supplied filter. -func (w *Wrapper) DeleteSemaphore(ctx context.Context, filter types.SemaphoreFilter) error { - return w.NoCache.DeleteSemaphore(ctx, filter) +type DatabaseWrapper struct { + ReadDatabaseAccessPoint + accessPoint + NoCache DatabaseAccessPoint } -// UpsertKubeService is part of auth.AccessPoint implementation -func (w *Wrapper) UpsertKubeService(ctx context.Context, s types.Server) error { - return w.NoCache.UpsertKubeService(ctx, s) +func NewDatabaseWrapper(base DatabaseAccessPoint, cache ReadDatabaseAccessPoint) DatabaseAccessPoint { + return &DatabaseWrapper{ + NoCache: base, + accessPoint: base, + ReadDatabaseAccessPoint: cache, + } } -// UpsertAppServer adds an application server. -// -// DELETE IN 9.0. Deprecated, use UpsertAppServer. -func (w *Wrapper) UpsertAppServer(ctx context.Context, server types.Server) (*types.KeepAlive, error) { - return w.NoCache.UpsertAppServer(ctx, server) +// Close closes all associated resources +func (w *DatabaseWrapper) Close() error { + err := w.NoCache.Close() + err2 := w.ReadDatabaseAccessPoint.Close() + return trace.NewAggregate(err, err2) } -// UpsertApplicationServer registers an application server. -func (w *Wrapper) UpsertApplicationServer(ctx context.Context, server types.AppServer) (*types.KeepAlive, error) { - return w.NoCache.UpsertApplicationServer(ctx, server) +type AppsWrapper struct { + ReadAppsAccessPoint + accessPoint + NoCache AppsAccessPoint } -// UpsertDatabaseServer registers a database proxy server. -func (w *Wrapper) UpsertDatabaseServer(ctx context.Context, server types.DatabaseServer) (*types.KeepAlive, error) { - return w.NoCache.UpsertDatabaseServer(ctx, server) +func NewAppsWrapper(base AppsAccessPoint, cache ReadAppsAccessPoint) AppsAccessPoint { + return &AppsWrapper{ + NoCache: base, + accessPoint: base, + ReadAppsAccessPoint: cache, + } } -// UpsertWindowsDesktopService registers a Windows desktop service. -func (w *Wrapper) UpsertWindowsDesktopService(ctx context.Context, s types.WindowsDesktopService) (*types.KeepAlive, error) { - return w.NoCache.UpsertWindowsDesktopService(ctx, s) +// Close closes all associated resources +func (w *AppsWrapper) Close() error { + err := w.NoCache.Close() + err2 := w.ReadAppsAccessPoint.Close() + return trace.NewAggregate(err, err2) } -// CreateWindowsDesktop registers a Windows desktop host. -func (w *Wrapper) CreateWindowsDesktop(ctx context.Context, d types.WindowsDesktop) error { - return w.NoCache.CreateWindowsDesktop(ctx, d) +type WindowsDesktopWrapper struct { + ReadWindowsDesktopAccessPoint + accessPoint + NoCache WindowsDesktopAccessPoint } -// UpdateWindowsDesktop updates a Windows desktop host. -func (w *Wrapper) UpdateWindowsDesktop(ctx context.Context, d types.WindowsDesktop) error { - return w.NoCache.UpdateWindowsDesktop(ctx, d) +func NewWindowsDesktopWrapper(base WindowsDesktopAccessPoint, cache ReadWindowsDesktopAccessPoint) WindowsDesktopAccessPoint { + return &WindowsDesktopWrapper{ + NoCache: base, + accessPoint: base, + ReadWindowsDesktopAccessPoint: cache, + } } -// GenerateCertAuthorityCRL generates an empty CRL for a CA. -func (w *Wrapper) GenerateCertAuthorityCRL(ctx context.Context, caType types.CertAuthType) ([]byte, error) { - crl, err := w.NoCache.GenerateCertAuthorityCRL(ctx, caType) - return crl, trace.Wrap(err) +// Close closes all associated resources +func (w *WindowsDesktopWrapper) Close() error { + err := w.NoCache.Close() + err2 := w.ReadWindowsDesktopAccessPoint.Close() + return trace.NewAggregate(err, err2) } -// NewCachingAcessPoint returns new caching access point using +// NewRemoteProxyCachingAccessPoint returns new caching access point using // access point policy -type NewCachingAccessPoint func(clt ClientI, cacheName []string) (AccessPoint, error) - -// NoCache is a no cache used for access point -func NoCache(clt ClientI, cacheName []string) (AccessPoint, error) { - return clt, nil -} +type NewRemoteProxyCachingAccessPoint func(clt ClientI, cacheName []string) (RemoteProxyAccessPoint, error) // notImplementedMessage is the message to return for endpoints that are not // implemented. This is due to how service interfaces are used with Teleport. diff --git a/lib/auth/auth.go b/lib/auth/auth.go index c67880d309ea0..ff1f068627118 100644 --- a/lib/auth/auth.go +++ b/lib/auth/auth.go @@ -2644,32 +2644,32 @@ func (a *Server) GetToken(ctx context.Context, token string) (types.ProvisionTok return a.GetCache().GetToken(ctx, token) } -// GetRoles is a part of auth.AccessPoint implementation +// GetRoles returns roles from the cache func (a *Server) GetRoles(ctx context.Context) ([]types.Role, error) { return a.GetCache().GetRoles(ctx) } -// GetRole is a part of auth.AccessPoint implementation +// GetRole returns a role from the cache func (a *Server) GetRole(ctx context.Context, name string) (types.Role, error) { return a.GetCache().GetRole(ctx, name) } -// GetNamespace returns namespace +// GetNamespace returns a namespace from the cache func (a *Server) GetNamespace(name string) (*types.Namespace, error) { return a.GetCache().GetNamespace(name) } -// GetNamespaces is a part of auth.AccessPoint implementation +// GetNamespaces returns namespaces from the cache func (a *Server) GetNamespaces() ([]types.Namespace, error) { return a.GetCache().GetNamespaces() } -// GetNodes is a part of auth.AccessPoint implementation +// GetNodes returns nodes from the cache func (a *Server) GetNodes(ctx context.Context, namespace string, opts ...services.MarshalOption) ([]types.Server, error) { return a.GetCache().GetNodes(ctx, namespace, opts...) } -// ListNodes is a part of auth.AccessPoint implementation +// ListNodes lists nodes from the cache func (a *Server) ListNodes(ctx context.Context, req proto.ListNodesRequest) ([]types.Server, string, error) { return a.GetCache().ListNodes(ctx, req) } @@ -2700,34 +2700,32 @@ func (a *Server) IterateNodePages(ctx context.Context, req proto.ListNodesReques } } -// GetReverseTunnels is a part of auth.AccessPoint implementation +// GetReverseTunnels returns reverse tunnels from the cache func (a *Server) GetReverseTunnels(opts ...services.MarshalOption) ([]types.ReverseTunnel, error) { return a.GetCache().GetReverseTunnels(opts...) } -// GetProxies is a part of auth.AccessPoint implementation +// GetProxies returns proxies from the cache func (a *Server) GetProxies() ([]types.Server, error) { return a.GetCache().GetProxies() } -// GetUser is a part of auth.AccessPoint implementation. +// GetUser returns a user from the cache func (a *Server) GetUser(name string, withSecrets bool) (user types.User, err error) { return a.GetCache().GetUser(name, withSecrets) } -// GetUsers is a part of auth.AccessPoint implementation +// GetUsers returns users from the cache func (a *Server) GetUsers(withSecrets bool) (users []types.User, err error) { return a.GetCache().GetUsers(withSecrets) } -// GetTunnelConnections is a part of auth.AccessPoint implementation // GetTunnelConnections are not using recent cache as they are designed // to be called periodically and always return fresh data func (a *Server) GetTunnelConnections(clusterName string, opts ...services.MarshalOption) ([]types.TunnelConnection, error) { return a.GetCache().GetTunnelConnections(clusterName, opts...) } -// GetAllTunnelConnections is a part of auth.AccessPoint implementation // GetAllTunnelConnections are not using recent cache, as they are designed // to be called periodically and always return fresh data func (a *Server) GetAllTunnelConnections(opts ...services.MarshalOption) (conns []types.TunnelConnection, err error) { @@ -2770,12 +2768,12 @@ func (a *Server) modeStreamer(ctx context.Context) (events.Streamer, error) { return a.streamer, nil } -// GetAppServers is a part of the auth.AccessPoint implementation. +// GetAppServers returns app servers from the cache func (a *Server) GetAppServers(ctx context.Context, namespace string, opts ...services.MarshalOption) ([]types.Server, error) { return a.GetCache().GetAppServers(ctx, namespace, opts...) } -// GetAppSession is a part of the auth.AccessPoint implementation. +// GetAppSession returns app sessions from the cache func (a *Server) GetAppSession(ctx context.Context, req types.GetAppSessionRequest) (types.WebSession, error) { return a.GetCache().GetAppSession(ctx, req) } @@ -3663,7 +3661,7 @@ func isHTTPS(u string) error { // WithClusterCAs returns a TLS hello callback that returns a copy of the provided // TLS config with client CAs pool of the specified cluster. -func WithClusterCAs(tlsConfig *tls.Config, ap AccessPoint, currentClusterName string, log logrus.FieldLogger) func(*tls.ClientHelloInfo) (*tls.Config, error) { +func WithClusterCAs(tlsConfig *tls.Config, ap AccessCache, currentClusterName string, log logrus.FieldLogger) func(*tls.ClientHelloInfo) (*tls.Config, error) { return func(info *tls.ClientHelloInfo) (*tls.Config, error) { var clusterName string var err error diff --git a/lib/auth/permissions.go b/lib/auth/permissions.go index f639b618a40fc..af99b393fa82c 100644 --- a/lib/auth/permissions.go +++ b/lib/auth/permissions.go @@ -48,7 +48,7 @@ func NewBuiltinRoleContext(role types.SystemRole) (*Context, error) { } // NewAuthorizer returns new authorizer using backends -func NewAuthorizer(clusterName string, accessPoint ReadAccessPoint, lockWatcher *services.LockWatcher) (Authorizer, error) { +func NewAuthorizer(clusterName string, accessPoint AuthorizerAccessPoint, lockWatcher *services.LockWatcher) (Authorizer, error) { if clusterName == "" { return nil, trace.BadParameter("missing parameter clusterName") } @@ -68,16 +68,43 @@ type Authorizer interface { Authorize(ctx context.Context) (*Context, error) } +// AuthorizerAccessPoint is the access point contract required by an Authorizer +type AuthorizerAccessPoint interface { + // GetAuthPreference returns the cluster authentication configuration. + GetAuthPreference(ctx context.Context) (types.AuthPreference, error) + + // GetRole returns role by name + GetRole(ctx context.Context, name string) (types.Role, error) + + // GetUser returns a services.User for this cluster. + GetUser(name string, withSecrets bool) (types.User, error) + + // GetCertAuthority returns cert authority by id + GetCertAuthority(id types.CertAuthID, loadKeys bool, opts ...services.MarshalOption) (types.CertAuthority, error) + + // GetCertAuthorities returns a list of cert authorities + GetCertAuthorities(caType types.CertAuthType, loadKeys bool, opts ...services.MarshalOption) ([]types.CertAuthority, error) + + // GetClusterAuditConfig returns cluster audit configuration. + GetClusterAuditConfig(ctx context.Context, opts ...services.MarshalOption) (types.ClusterAuditConfig, error) + + // GetClusterNetworkingConfig returns cluster networking configuration. + GetClusterNetworkingConfig(ctx context.Context, opts ...services.MarshalOption) (types.ClusterNetworkingConfig, error) + + // GetSessionRecordingConfig returns session recording configuration. + GetSessionRecordingConfig(ctx context.Context, opts ...services.MarshalOption) (types.SessionRecordingConfig, error) +} + // authorizer creates new local authorizer type authorizer struct { clusterName string - accessPoint ReadAccessPoint + accessPoint AuthorizerAccessPoint lockWatcher *services.LockWatcher } // Context is authorization context type Context struct { - // User is the user name + // User is the username User types.User // Checker is access checker Checker services.AccessChecker @@ -669,7 +696,7 @@ func contextForBuiltinRole(r BuiltinRole, recConfig types.SessionRecordingConfig }, nil } -func contextForLocalUser(u LocalUser, accessPoint ReadAccessPoint) (*Context, error) { +func contextForLocalUser(u LocalUser, accessPoint AuthorizerAccessPoint) (*Context, error) { // User has to be fetched to check if it's a blocked username user, err := accessPoint.GetUser(u.Username, false) if err != nil { @@ -684,7 +711,7 @@ func contextForLocalUser(u LocalUser, accessPoint ReadAccessPoint) (*Context, er return nil, trace.Wrap(err) } // Override roles and traits from the local user based on the identity roles - // and traits, this is done to prevent potential conflict. Imagine a scenairo + // and traits, this is done to prevent potential conflict. Imagine a scenario // when SSO user has left the company, but local user entry remained with old // privileged roles. New user with the same name has been onboarded and would // have derived the roles from the stale user entry. This code prevents diff --git a/lib/auth/sessions.go b/lib/auth/sessions.go index 531c4eb081a24..004085cdee657 100644 --- a/lib/auth/sessions.go +++ b/lib/auth/sessions.go @@ -108,7 +108,7 @@ func (s *Server) CreateAppSession(ctx context.Context, req types.CreateAppSessio // WaitForAppSession will block until the requested application session shows up in the // cache or a timeout occurs. -func WaitForAppSession(ctx context.Context, sessionID, user string, ap AccessPoint) error { +func WaitForAppSession(ctx context.Context, sessionID, user string, ap ReadProxyAccessPoint) error { _, err := ap.GetAppSession(ctx, types.GetAppSessionRequest{SessionID: sessionID}) if err == nil { return nil diff --git a/lib/auth/tls_test.go b/lib/auth/tls_test.go index 582112dd95f35..47e204f30659a 100644 --- a/lib/auth/tls_test.go +++ b/lib/auth/tls_test.go @@ -1532,7 +1532,7 @@ func (s *TLSSuite) TestWebSessionWithApprovedAccessRequestAndSwitchback(c *check c.Assert(err, check.IsNil) // Roles extracted from cert should contain the initial role and the role assigned with access request. - roles, _, err := services.ExtractFromCertificate(clt, sshcert) + roles, _, err := services.ExtractFromCertificate(sshcert) c.Assert(err, check.IsNil) c.Assert(roles, check.HasLen, 2) @@ -1560,7 +1560,7 @@ func (s *TLSSuite) TestWebSessionWithApprovedAccessRequestAndSwitchback(c *check sshcert, err = sshutils.ParseCertificate(sess2.GetPub()) c.Assert(err, check.IsNil) - roles, _, err = services.ExtractFromCertificate(clt, sshcert) + roles, _, err = services.ExtractFromCertificate(sshcert) c.Assert(err, check.IsNil) c.Assert(roles, check.DeepEquals, []string{initialRole}) } diff --git a/lib/cache/cache.go b/lib/cache/cache.go index 3a08dab5ca17a..e957547b49a6d 100644 --- a/lib/cache/cache.go +++ b/lib/cache/cache.go @@ -184,7 +184,6 @@ func ForNode(cfg Config) Config { {Kind: types.KindClusterNetworkingConfig}, {Kind: types.KindClusterAuthPreference}, {Kind: types.KindSessionRecordingConfig}, - {Kind: types.KindUser}, {Kind: types.KindRole}, // Node only needs to "know" about default // namespace events to avoid matching too much @@ -282,7 +281,7 @@ func ForWindowsDesktop(cfg Config) Config { // for cache type SetupConfigFn func(c Config) Config -// Cache implements auth.AccessPoint interface and remembers +// Cache implements auth.Cache interface and remembers // the previously returned upstream value for each API call. // // This which can be used if the upstream AccessPoint goes offline @@ -1197,7 +1196,7 @@ func (c *Cache) GetClusterName(opts ...services.MarshalOption) (types.ClusterNam return rg.clusterConfig.GetClusterName(opts...) } -// GetRoles is a part of auth.AccessPoint implementation +// GetRoles is a part of auth.Cache implementation func (c *Cache) GetRoles(ctx context.Context) ([]types.Role, error) { rg, err := c.read() if err != nil { @@ -1207,7 +1206,7 @@ func (c *Cache) GetRoles(ctx context.Context) ([]types.Role, error) { return rg.access.GetRoles(ctx) } -// GetRole is a part of auth.AccessPoint implementation +// GetRole is a part of auth.Cache implementation func (c *Cache) GetRole(ctx context.Context, name string) (types.Role, error) { rg, err := c.read() if err != nil { @@ -1237,7 +1236,7 @@ func (c *Cache) GetNamespace(name string) (*types.Namespace, error) { return rg.presence.GetNamespace(name) } -// GetNamespaces is a part of auth.AccessPoint implementation +// GetNamespaces is a part of auth.Cache implementation func (c *Cache) GetNamespaces() ([]types.Namespace, error) { rg, err := c.read() if err != nil { @@ -1263,7 +1262,7 @@ type getNodesCacheKey struct { var _ map[getNodesCacheKey]struct{} // compile-time hashability check -// GetNodes is a part of auth.AccessPoint implementation +// GetNodes is a part of auth.Cache implementation func (c *Cache) GetNodes(ctx context.Context, namespace string, opts ...services.MarshalOption) ([]types.Server, error) { rg, err := c.read() if err != nil { @@ -1295,7 +1294,7 @@ func (c *Cache) GetNodes(ctx context.Context, namespace string, opts ...services return rg.presence.GetNodes(ctx, namespace, opts...) } -// ListNodes is a part of auth.AccessPoint implementation +// ListNodes is a part of auth.Cache implementation func (c *Cache) ListNodes(ctx context.Context, req proto.ListNodesRequest) ([]types.Server, string, error) { // NOTE: we "fake" the ListNodes API here in order to take advantage of TTL-based caching of // the GetNodes endpoint, since performing TTL-based caching on a paginated endpoint is nightmarish. @@ -1353,7 +1352,7 @@ func (c *Cache) GetAuthServers() ([]types.Server, error) { return rg.presence.GetAuthServers() } -// GetReverseTunnels is a part of auth.AccessPoint implementation +// GetReverseTunnels is a part of auth.Cache implementation func (c *Cache) GetReverseTunnels(opts ...services.MarshalOption) ([]types.ReverseTunnel, error) { rg, err := c.read() if err != nil { @@ -1363,7 +1362,7 @@ func (c *Cache) GetReverseTunnels(opts ...services.MarshalOption) ([]types.Rever return rg.presence.GetReverseTunnels(opts...) } -// GetProxies is a part of auth.AccessPoint implementation +// GetProxies is a part of auth.Cache implementation func (c *Cache) GetProxies() ([]types.Server, error) { rg, err := c.read() if err != nil { @@ -1431,7 +1430,7 @@ func (c *Cache) GetRemoteCluster(clusterName string) (types.RemoteCluster, error return rg.presence.GetRemoteCluster(clusterName) } -// GetUser is a part of auth.AccessPoint implementation. +// GetUser is a part of auth.Cache implementation. func (c *Cache) GetUser(name string, withSecrets bool) (user types.User, err error) { if withSecrets { // cache never tracks user secrets return c.Config.Users.GetUser(name, withSecrets) @@ -1455,7 +1454,7 @@ func (c *Cache) GetUser(name string, withSecrets bool) (user types.User, err err return user, trace.Wrap(err) } -// GetUsers is a part of auth.AccessPoint implementation +// GetUsers is a part of auth.Cache implementation func (c *Cache) GetUsers(withSecrets bool) (users []types.User, err error) { if withSecrets { // cache never tracks user secrets return c.Users.GetUsers(withSecrets) @@ -1468,9 +1467,7 @@ func (c *Cache) GetUsers(withSecrets bool) (users []types.User, err error) { return rg.users.GetUsers(withSecrets) } -// GetTunnelConnections is a part of auth.AccessPoint implementation -// GetTunnelConnections are not using recent cache as they are designed -// to be called periodically and always return fresh data +// GetTunnelConnections is a part of auth.Cache implementation func (c *Cache) GetTunnelConnections(clusterName string, opts ...services.MarshalOption) ([]types.TunnelConnection, error) { rg, err := c.read() if err != nil { @@ -1480,9 +1477,7 @@ func (c *Cache) GetTunnelConnections(clusterName string, opts ...services.Marsha return rg.presence.GetTunnelConnections(clusterName, opts...) } -// GetAllTunnelConnections is a part of auth.AccessPoint implementation -// GetAllTunnelConnections are not using recent cache, as they are designed -// to be called periodically and always return fresh data +// GetAllTunnelConnections is a part of auth.Cache implementation func (c *Cache) GetAllTunnelConnections(opts ...services.MarshalOption) (conns []types.TunnelConnection, err error) { rg, err := c.read() if err != nil { @@ -1492,7 +1487,7 @@ func (c *Cache) GetAllTunnelConnections(opts ...services.MarshalOption) (conns [ return rg.presence.GetAllTunnelConnections(opts...) } -// GetKubeServices is a part of auth.AccessPoint implementation +// GetKubeServices is a part of auth.Cache implementation func (c *Cache) GetKubeServices(ctx context.Context) ([]types.Server, error) { rg, err := c.read() if err != nil { diff --git a/lib/client/api.go b/lib/client/api.go index 7fafbda89721f..dffb9025e27b8 100644 --- a/lib/client/api.go +++ b/lib/client/api.go @@ -1167,18 +1167,6 @@ func (tc *TeleportClient) LoadKeyForClusterWithReissue(ctx context.Context, clus return nil } -// accessPoint returns access point based on the cache policy -func (tc *TeleportClient) accessPoint(clt auth.AccessPoint, proxyHostPort string, clusterName string) (auth.AccessPoint, error) { - // If no caching policy was set or on Windows (where Teleport does not - // support file locking at the moment), return direct access to the access - // point. - if tc.CachePolicy == nil || runtime.GOOS == constants.WindowsOS { - log.Debugf("not using caching access point") - return clt, nil - } - return clt, nil -} - // LocalAgent is a getter function for the client's local agent func (tc *TeleportClient) LocalAgent() *LocalKeyAgent { return tc.localAgent diff --git a/lib/client/client.go b/lib/client/client.go index a97911ebaf55b..57cc8e50fdf75 100644 --- a/lib/client/client.go +++ b/lib/client/client.go @@ -624,7 +624,7 @@ func (proxy *ProxyClient) GetDatabaseServers(ctx context.Context, namespace stri // CurrentClusterAccessPoint returns cluster access point to the currently // selected cluster and is used for discovery // and could be cached based on the access policy -func (proxy *ProxyClient) CurrentClusterAccessPoint(ctx context.Context, quiet bool) (auth.AccessPoint, error) { +func (proxy *ProxyClient) CurrentClusterAccessPoint(ctx context.Context, quiet bool) (auth.ClientI, error) { // get the current cluster: cluster, err := proxy.currentCluster() if err != nil { @@ -635,7 +635,7 @@ func (proxy *ProxyClient) CurrentClusterAccessPoint(ctx context.Context, quiet b // ClusterAccessPoint returns cluster access point used for discovery // and could be cached based on the access policy -func (proxy *ProxyClient) ClusterAccessPoint(ctx context.Context, clusterName string, quiet bool) (auth.AccessPoint, error) { +func (proxy *ProxyClient) ClusterAccessPoint(ctx context.Context, clusterName string, quiet bool) (auth.ClientI, error) { if clusterName == "" { return nil, trace.BadParameter("parameter clusterName is missing") } @@ -643,7 +643,7 @@ func (proxy *ProxyClient) ClusterAccessPoint(ctx context.Context, clusterName st if err != nil { return nil, trace.Wrap(err) } - return proxy.teleportClient.accessPoint(clt, proxy.proxyAddress, clusterName) + return clt, nil } // ConnectToCurrentCluster connects to the auth server of the currently selected diff --git a/lib/kube/proxy/forwarder.go b/lib/kube/proxy/forwarder.go index 509d8c4021462..09f43010895bd 100644 --- a/lib/kube/proxy/forwarder.go +++ b/lib/kube/proxy/forwarder.go @@ -97,7 +97,7 @@ type ForwarderConfig struct { // AuthClient is a auth server client. AuthClient auth.ClientI // CachingAuthClient is a caching auth server client for read-only access. - CachingAuthClient auth.AccessPoint + CachingAuthClient auth.ReadKubernetesAccessPoint // StreamEmitter is used to create audit streams // and emit audit events StreamEmitter events.StreamEmitter diff --git a/lib/kube/proxy/forwarder_test.go b/lib/kube/proxy/forwarder_test.go index 82333e0d9d633..ba0aeefbc3240 100644 --- a/lib/kube/proxy/forwarder_test.go +++ b/lib/kube/proxy/forwarder_test.go @@ -845,7 +845,7 @@ type mockRemoteSite struct { func (s mockRemoteSite) GetName() string { return s.name } type mockAccessPoint struct { - auth.AccessPoint + auth.KubernetesAccessPoint netConfig types.ClusterNetworkingConfig recordingConfig types.SessionRecordingConfig diff --git a/lib/kube/proxy/server.go b/lib/kube/proxy/server.go index 734e16b9a87b1..801588668018a 100644 --- a/lib/kube/proxy/server.go +++ b/lib/kube/proxy/server.go @@ -45,7 +45,7 @@ type TLSServerConfig struct { // LimiterConfig is limiter config LimiterConfig limiter.Config // AccessPoint is caching access point - AccessPoint auth.AccessPoint + AccessPoint auth.ReadKubernetesAccessPoint // OnHeartbeat is a callback for kubernetes_service heartbeats. OnHeartbeat func(error) // Log is the logger. diff --git a/lib/reversetunnel/agent.go b/lib/reversetunnel/agent.go index 62398e1bd1509..317428dff6c84 100644 --- a/lib/reversetunnel/agent.go +++ b/lib/reversetunnel/agent.go @@ -69,7 +69,7 @@ type AgentConfig struct { // Client is a client to the local auth servers Client auth.ClientI // AccessPoint is a caching access point to the local auth servers - AccessPoint auth.AccessPoint + AccessPoint auth.AccessCache // Context is a parent context Context context.Context // Username is the name of this client used to authenticate on SSH diff --git a/lib/reversetunnel/agentpool.go b/lib/reversetunnel/agentpool.go index ad04829b36e91..4342b83fc6aeb 100644 --- a/lib/reversetunnel/agentpool.go +++ b/lib/reversetunnel/agentpool.go @@ -66,7 +66,7 @@ type AgentPoolConfig struct { Client auth.ClientI // AccessPoint is a lightweight access point // that can optionally cache some values - AccessPoint auth.AccessPoint + AccessPoint auth.AccessCache // HostSigner is a host signer this agent presents itself as HostSigner ssh.Signer // HostUUID is a unique ID of this host diff --git a/lib/reversetunnel/api.go b/lib/reversetunnel/api.go index 6a803ae3f7f44..34fc9d572700a 100644 --- a/lib/reversetunnel/api.go +++ b/lib/reversetunnel/api.go @@ -18,7 +18,6 @@ package reversetunnel import ( "context" - "fmt" "net" "time" @@ -93,7 +92,7 @@ type RemoteSite interface { GetClient() (auth.ClientI, error) // CachingAccessPoint returns access point that is lightweight // but is resilient to auth server crashes - CachingAccessPoint() (auth.AccessPoint, error) + CachingAccessPoint() (auth.RemoteProxyAccessPoint, error) // GetTunnelsCount returns the amount of active inbound tunnels // from the remote cluster GetTunnelsCount() int diff --git a/lib/reversetunnel/api_with_roles.go b/lib/reversetunnel/api_with_roles.go index 561e5b2a8a1b9..f9d9587468182 100644 --- a/lib/reversetunnel/api_with_roles.go +++ b/lib/reversetunnel/api_with_roles.go @@ -17,7 +17,7 @@ limitations under the License. package reversetunnel import ( - "github.com/gravitational/teleport/lib/auth" + "github.com/gravitational/teleport/api/types" "github.com/gravitational/teleport/lib/services" "github.com/gravitational/teleport/lib/utils" @@ -25,12 +25,18 @@ import ( "github.com/sirupsen/logrus" ) +// ClusterGetter is an interface that defines GetRemoteCluster method +type ClusterGetter interface { + // GetRemoteCluster returns a remote cluster by name + GetRemoteCluster(clusterName string) (types.RemoteCluster, error) +} + // NewTunnelWithRoles returns new authorizing tunnel -func NewTunnelWithRoles(tunnel Tunnel, roles services.RoleSet, ap auth.AccessPoint) *TunnelWithRoles { +func NewTunnelWithRoles(tunnel Tunnel, roles services.RoleSet, access ClusterGetter) *TunnelWithRoles { return &TunnelWithRoles{ tunnel: tunnel, roles: roles, - ap: ap, + access: access, } } @@ -41,7 +47,7 @@ type TunnelWithRoles struct { // roles is a set of roles used to check RBAC permissions. roles services.RoleSet - ap auth.AccessPoint + access ClusterGetter } // GetSites returns a list of connected remote sites @@ -56,7 +62,7 @@ func (t *TunnelWithRoles) GetSites() ([]RemoteSite, error) { out = append(out, cluster) continue } - rc, err := t.ap.GetRemoteCluster(cluster.GetName()) + rc, err := t.access.GetRemoteCluster(cluster.GetName()) if err != nil { if !trace.IsNotFound(err) { return nil, trace.Wrap(err) @@ -84,7 +90,7 @@ func (t *TunnelWithRoles) GetSite(clusterName string) (RemoteSite, error) { if _, ok := cluster.(*localSite); ok { return cluster, nil } - rc, err := t.ap.GetRemoteCluster(clusterName) + rc, err := t.access.GetRemoteCluster(clusterName) if err != nil { return nil, trace.Wrap(err) } diff --git a/lib/reversetunnel/conn.go b/lib/reversetunnel/conn.go index 0da13e92edf87..63b58a148391d 100644 --- a/lib/reversetunnel/conn.go +++ b/lib/reversetunnel/conn.go @@ -28,8 +28,6 @@ import ( "github.com/gravitational/teleport/api/types" "github.com/gravitational/teleport/api/utils/sshutils" - "github.com/gravitational/teleport/lib/auth" - "github.com/gravitational/trace" "github.com/jonboulle/clockwork" "github.com/sirupsen/logrus" @@ -89,9 +87,6 @@ type connConfig struct { // sconn is the underlying SSH connection. sconn ssh.Conn - // accessPoint provides access to the Auth Server API. - accessPoint auth.AccessPoint - // tunnelType is the type of tunnel connection, either proxy or node. tunnelType string diff --git a/lib/reversetunnel/fake.go b/lib/reversetunnel/fake.go index 895029315de4c..ab01542329d30 100644 --- a/lib/reversetunnel/fake.go +++ b/lib/reversetunnel/fake.go @@ -54,13 +54,13 @@ type FakeRemoteSite struct { // ConnCh receives the connection when dialing this site. ConnCh chan net.Conn // AccessPoint is the auth server client. - AccessPoint auth.AccessPoint + AccessPoint auth.RemoteProxyAccessPoint // OfflineTunnels is a list of server IDs that will return connection error. OfflineTunnels map[string]struct{} } // CachingAccessPoint returns caching auth server client. -func (s *FakeRemoteSite) CachingAccessPoint() (auth.AccessPoint, error) { +func (s *FakeRemoteSite) CachingAccessPoint() (auth.RemoteProxyAccessPoint, error) { return s.AccessPoint, nil } diff --git a/lib/reversetunnel/localsite.go b/lib/reversetunnel/localsite.go index f9c949c38de96..2ec1c6fa43a72 100644 --- a/lib/reversetunnel/localsite.go +++ b/lib/reversetunnel/localsite.go @@ -99,7 +99,7 @@ type localSite struct { client auth.ClientI // accessPoint provides access to a cached subset of the Auth Server API of // the local cluster. - accessPoint auth.AccessPoint + accessPoint auth.RemoteProxyAccessPoint // certificateCache caches host certificates for the forwarding server. certificateCache *certificateCache @@ -123,8 +123,8 @@ func (s *localSite) GetTunnelsCount() int { return len(s.remoteConns) } -// CachingAccessPoint returns a auth.AccessPoint for this cluster. -func (s *localSite) CachingAccessPoint() (auth.AccessPoint, error) { +// CachingAccessPoint returns an auth.RemoteProxyAccessPoint for this cluster. +func (s *localSite) CachingAccessPoint() (auth.RemoteProxyAccessPoint, error) { return s.accessPoint, nil } @@ -355,7 +355,6 @@ func (s *localSite) addConn(nodeID string, connType types.TunnelType, conn net.C rconn := newRemoteConn(&connConfig{ conn: conn, sconn: sconn, - accessPoint: s.accessPoint, tunnelType: string(connType), proxyName: s.srv.ID, clusterName: s.domainName, diff --git a/lib/reversetunnel/peer.go b/lib/reversetunnel/peer.go index 962a60111d6ba..b7b6aedeb115c 100644 --- a/lib/reversetunnel/peer.go +++ b/lib/reversetunnel/peer.go @@ -79,7 +79,7 @@ func (p *clusterPeers) removePeer(connInfo types.TunnelConnection) { delete(p.peers, connInfo.GetName()) } -func (p *clusterPeers) CachingAccessPoint() (auth.AccessPoint, error) { +func (p *clusterPeers) CachingAccessPoint() (auth.RemoteProxyAccessPoint, error) { peer, err := p.pickPeer() if err != nil { return nil, trace.Wrap(err) @@ -184,7 +184,7 @@ func (s *clusterPeer) setConnInfo(ci types.TunnelConnection) { s.connInfo = ci } -func (s *clusterPeer) CachingAccessPoint() (auth.AccessPoint, error) { +func (s *clusterPeer) CachingAccessPoint() (auth.RemoteProxyAccessPoint, error) { return nil, trace.ConnectionProblem(nil, "unable to fetch access point, this proxy %v has not been discovered yet, try again later", s) } diff --git a/lib/reversetunnel/rc_manager.go b/lib/reversetunnel/rc_manager.go index a9d8876e5caa8..be3c4f8d41b57 100644 --- a/lib/reversetunnel/rc_manager.go +++ b/lib/reversetunnel/rc_manager.go @@ -60,7 +60,7 @@ type RemoteClusterTunnelManagerConfig struct { AuthClient auth.ClientI // AccessPoint is a lightweight access point that can optionally cache some // values. - AccessPoint auth.AccessPoint + AccessPoint auth.ProxyAccessPoint // HostSigners is a signer for the host private key. HostSigner ssh.Signer // HostUUID is a unique ID of this host diff --git a/lib/reversetunnel/remotesite.go b/lib/reversetunnel/remotesite.go index 014a6c4635613..3346c32525889 100644 --- a/lib/reversetunnel/remotesite.go +++ b/lib/reversetunnel/remotesite.go @@ -76,10 +76,10 @@ type remoteSite struct { remoteClient auth.ClientI // localAccessPoint provides access to a cached subset of the Auth Server API of // the local cluster. - localAccessPoint auth.AccessPoint + localAccessPoint auth.ProxyAccessPoint // remoteAccessPoint provides access to a cached subset of the Auth Server API of // the remote cluster this site belongs to. - remoteAccessPoint auth.AccessPoint + remoteAccessPoint auth.RemoteProxyAccessPoint // remoteCA is the last remote certificate authority recorded by the client. // It is used to detect CA rotation status changes. If the rotation @@ -138,7 +138,7 @@ func (s *remoteSite) GetTunnelsCount() int { return s.connectionCount() } -func (s *remoteSite) CachingAccessPoint() (auth.AccessPoint, error) { +func (s *remoteSite) CachingAccessPoint() (auth.RemoteProxyAccessPoint, error) { return s.remoteAccessPoint, nil } @@ -168,7 +168,7 @@ func (s *remoteSite) hasValidConnections() bool { return false } -// Clos closes remote cluster connections +// Close closes remote cluster connections func (s *remoteSite) Close() error { s.Lock() defer s.Unlock() @@ -251,7 +251,6 @@ func (s *remoteSite) addConn(conn net.Conn, sconn ssh.Conn) (*remoteConn, error) rconn := newRemoteConn(&connConfig{ conn: conn, sconn: sconn, - accessPoint: s.localAccessPoint, tunnelType: string(types.ProxyTunnel), proxyName: s.connInfo.GetProxyName(), clusterName: s.domainName, diff --git a/lib/reversetunnel/srv.go b/lib/reversetunnel/srv.go index d4626e1067eeb..bc4e17128aa9e 100644 --- a/lib/reversetunnel/srv.go +++ b/lib/reversetunnel/srv.go @@ -78,7 +78,7 @@ type server struct { localAuthClient auth.ClientI // localAccessPoint provides access to a cached subset of the Auth // Server API. - localAccessPoint auth.AccessPoint + localAccessPoint auth.ProxyAccessPoint // srv is the "base class" i.e. the underlying SSH server srv *sshutils.Server @@ -96,7 +96,7 @@ type server struct { clusterPeers map[string]*clusterPeers // newAccessPoint returns new caching access point - newAccessPoint auth.NewCachingAccessPoint + newAccessPoint auth.NewRemoteProxyCachingAccessPoint // cancel function will cancel the cancel context.CancelFunc @@ -145,10 +145,10 @@ type Config struct { // AccessPoint provides access to a subset of AuthClient of the cluster. // AccessPoint caches values and can still return results during connection // problems. - LocalAccessPoint auth.AccessPoint + LocalAccessPoint auth.ProxyAccessPoint // NewCachingAccessPoint returns new caching access points // per remote cluster - NewCachingAccessPoint auth.NewCachingAccessPoint + NewCachingAccessPoint auth.NewRemoteProxyCachingAccessPoint // DirectClusters is a list of clusters accessed directly DirectClusters []DirectCluster // Context is a signalling context @@ -198,7 +198,7 @@ type Config struct { // NewCachingAccessPointOldProxy is an access point that can be configured // with the old access point policy until all clusters are migrated to 7.0.0 // and above. - NewCachingAccessPointOldProxy auth.NewCachingAccessPoint + NewCachingAccessPointOldProxy auth.NewRemoteProxyCachingAccessPoint // LockWatcher is a lock watcher. LockWatcher *services.LockWatcher @@ -1040,7 +1040,7 @@ func newRemoteSite(srv *server, domainName string, sconn ssh.Conn) (*remoteSite, // don't assume the newer organization of cluster configuration resources // (RFD 28) because older proxy servers will reject that causing the cache // to go into a re-sync loop. - var accessPointFunc auth.NewCachingAccessPoint + var accessPointFunc auth.NewRemoteProxyCachingAccessPoint ok, err := isPreV8Cluster(closeContext, sconn) if err != nil { return nil, trace.Wrap(err) diff --git a/lib/reversetunnel/srv_test.go b/lib/reversetunnel/srv_test.go index 0f4ed6c7e89c1..346fd478746d0 100644 --- a/lib/reversetunnel/srv_test.go +++ b/lib/reversetunnel/srv_test.go @@ -152,7 +152,7 @@ func (mockSSHConnMetadata) User() string { return "conn-user" } func (mockSSHConnMetadata) RemoteAddr() net.Addr { return &net.TCPAddr{} } type mockAccessPoint struct { - auth.AccessPoint + auth.ProxyAccessPoint ca types.CertAuthority } diff --git a/lib/reversetunnel/transport.go b/lib/reversetunnel/transport.go index f2ee4c5673ca2..772bb4abe7b78 100644 --- a/lib/reversetunnel/transport.go +++ b/lib/reversetunnel/transport.go @@ -133,7 +133,7 @@ type transport struct { component string log logrus.FieldLogger closeContext context.Context - authClient auth.AccessPoint + authClient auth.ProxyAccessPoint channel ssh.Channel requestCh <-chan *ssh.Request diff --git a/lib/service/db.go b/lib/service/db.go index 3070dd772a4e7..625bd8502b394 100644 --- a/lib/service/db.go +++ b/lib/service/db.go @@ -20,7 +20,6 @@ import ( "github.com/gravitational/teleport" "github.com/gravitational/teleport/api/types" "github.com/gravitational/teleport/lib/auth" - "github.com/gravitational/teleport/lib/cache" "github.com/gravitational/teleport/lib/events" "github.com/gravitational/teleport/lib/reversetunnel" "github.com/gravitational/teleport/lib/services" @@ -60,7 +59,7 @@ func (process *TeleportProcess) initDatabaseService() (retErr error) { if !ok { return trace.BadParameter("unsupported event payload type %q", event.Payload) } - accessPoint, err := process.newLocalCache(conn.Client, cache.ForDatabases, []string{teleport.ComponentDatabase}) + accessPoint, err := process.newLocalCacheForDatabase(conn.Client, []string{teleport.ComponentDatabase}) if err != nil { return trace.Wrap(err) } diff --git a/lib/service/desktop.go b/lib/service/desktop.go index b140dca61b02d..f4c41e8d08e67 100644 --- a/lib/service/desktop.go +++ b/lib/service/desktop.go @@ -29,7 +29,6 @@ import ( "github.com/gravitational/teleport/api/types" apiutils "github.com/gravitational/teleport/api/utils" "github.com/gravitational/teleport/lib/auth" - "github.com/gravitational/teleport/lib/cache" "github.com/gravitational/teleport/lib/defaults" "github.com/gravitational/teleport/lib/limiter" "github.com/gravitational/teleport/lib/reversetunnel" @@ -79,7 +78,7 @@ func (process *TeleportProcess) initWindowsDesktopServiceRegistered(log *logrus. cfg := process.Config // Create a caching auth client. - accessPoint, err := process.newLocalCache(conn.Client, cache.ForWindowsDesktop, []string{teleport.ComponentWindowsDesktop}) + accessPoint, err := process.newLocalCacheForWindowsDesktop(conn.Client, []string{teleport.ComponentWindowsDesktop}) if err != nil { return trace.Wrap(err) } diff --git a/lib/service/kubernetes.go b/lib/service/kubernetes.go index 42a054402b967..98e18fdefd819 100644 --- a/lib/service/kubernetes.go +++ b/lib/service/kubernetes.go @@ -24,7 +24,6 @@ import ( apidefaults "github.com/gravitational/teleport/api/defaults" "github.com/gravitational/teleport/api/types" "github.com/gravitational/teleport/lib/auth" - "github.com/gravitational/teleport/lib/cache" "github.com/gravitational/teleport/lib/events" kubeproxy "github.com/gravitational/teleport/lib/kube/proxy" "github.com/gravitational/teleport/lib/labels" @@ -78,7 +77,7 @@ func (process *TeleportProcess) initKubernetesService(log *logrus.Entry, conn *C cfg := process.Config // Create a caching auth client. - accessPoint, err := process.newLocalCache(conn.Client, cache.ForKubernetes, []string{teleport.ComponentKube}) + accessPoint, err := process.newLocalCacheForKubernetes(conn.Client, []string{teleport.ComponentKube}) if err != nil { return trace.Wrap(err) } diff --git a/lib/service/proxy_settings.go b/lib/service/proxy_settings.go index a21da6bab6c70..a833ba851a0dc 100644 --- a/lib/service/proxy_settings.go +++ b/lib/service/proxy_settings.go @@ -36,7 +36,7 @@ type proxySettings struct { // proxy listener address to a random port (e.g. `127.0.0.1:0`). proxySSHAddr utils.NetAddr // accessPoint is the caching client connected to the auth server. - accessPoint auth.AccessPoint + accessPoint auth.ProxyAccessPoint } // GetProxySettings allows returns current proxy configuration. diff --git a/lib/service/service.go b/lib/service/service.go index 76560a33dd9d8..9618c4732f114 100644 --- a/lib/service/service.go +++ b/lib/service/service.go @@ -1598,41 +1598,137 @@ func (process *TeleportProcess) newAccessCache(cfg accessCacheConfig) (*cache.Ca })) } +// newLocalCacheForNode returns new instance of access point configured for a local proxy. +func (process *TeleportProcess) newLocalCacheForNode(clt auth.ClientI, cacheName []string) (auth.NodeAccessPoint, error) { + // if caching is disabled, return access point + if !process.Config.CachePolicy.Enabled { + return clt, nil + } + + cache, err := process.newLocalCache(clt, cache.ForNode, cacheName) + if err != nil { + return nil, trace.Wrap(err) + } + + return auth.NewNodeWrapper(clt, cache), nil +} + +// newLocalCacheForKubernetes returns new instance of access point configured for a kubernetes service. +func (process *TeleportProcess) newLocalCacheForKubernetes(clt auth.ClientI, cacheName []string) (auth.KubernetesAccessPoint, error) { + // if caching is disabled, return access point + if !process.Config.CachePolicy.Enabled { + return clt, nil + } + + cache, err := process.newLocalCache(clt, cache.ForKubernetes, cacheName) + if err != nil { + return nil, trace.Wrap(err) + } + + return auth.NewKubernetesWrapper(clt, cache), nil +} + +// newLocalCacheForDatabase returns new instance of access point configured for a database service. +func (process *TeleportProcess) newLocalCacheForDatabase(clt auth.ClientI, cacheName []string) (auth.DatabaseAccessPoint, error) { + // if caching is disabled, return access point + if !process.Config.CachePolicy.Enabled { + return clt, nil + } + + cache, err := process.newLocalCache(clt, cache.ForDatabases, cacheName) + if err != nil { + return nil, trace.Wrap(err) + } + + return auth.NewDatabaseWrapper(clt, cache), nil +} + // newLocalCacheForProxy returns new instance of access point configured for a local proxy. -func (process *TeleportProcess) newLocalCacheForProxy(clt auth.ClientI, cacheName []string) (auth.AccessPoint, error) { - return process.newLocalCache(clt, cache.ForProxy, cacheName) +func (process *TeleportProcess) newLocalCacheForProxy(clt auth.ClientI, cacheName []string) (auth.ProxyAccessPoint, error) { + // if caching is disabled, return access point + if !process.Config.CachePolicy.Enabled { + return clt, nil + } + + cache, err := process.newLocalCache(clt, cache.ForProxy, cacheName) + if err != nil { + return nil, trace.Wrap(err) + } + + return auth.NewProxyWrapper(clt, cache), nil } -// newLocalCacheForRemoteProxy returns new instance of access point configured -// for a remote proxy. -func (process *TeleportProcess) newLocalCacheForRemoteProxy(clt auth.ClientI, cacheName []string) (auth.AccessPoint, error) { - return process.newLocalCache(clt, cache.ForRemoteProxy, cacheName) +// newLocalCacheForRemoteProxy returns new instance of access point configured for a remote proxy. +func (process *TeleportProcess) newLocalCacheForRemoteProxy(clt auth.ClientI, cacheName []string) (auth.RemoteProxyAccessPoint, error) { + // if caching is disabled, return access point + if !process.Config.CachePolicy.Enabled { + return clt, nil + } + + cache, err := process.newLocalCache(clt, cache.ForRemoteProxy, cacheName) + if err != nil { + return nil, trace.Wrap(err) + } + + return auth.NewRemoteProxyWrapper(clt, cache), nil } // DELETE IN: 8.0.0 // // newLocalCacheForOldRemoteProxy returns new instance of access point // configured for an old remote proxy. -func (process *TeleportProcess) newLocalCacheForOldRemoteProxy(clt auth.ClientI, cacheName []string) (auth.AccessPoint, error) { - return process.newLocalCache(clt, cache.ForOldRemoteProxy, cacheName) +func (process *TeleportProcess) newLocalCacheForOldRemoteProxy(clt auth.ClientI, cacheName []string) (auth.RemoteProxyAccessPoint, error) { + // if caching is disabled, return access point + if !process.Config.CachePolicy.Enabled { + return clt, nil + } + + cache, err := process.newLocalCache(clt, cache.ForOldRemoteProxy, cacheName) + if err != nil { + return nil, trace.Wrap(err) + } + + return auth.NewRemoteProxyWrapper(clt, cache), nil } -// newLocalCache returns new instance of access point -func (process *TeleportProcess) newLocalCache(clt auth.ClientI, setupConfig cache.SetupConfigFn, cacheName []string) (auth.AccessPoint, error) { +// newLocalCacheForApps returns new instance of access point configured for a remote proxy. +func (process *TeleportProcess) newLocalCacheForApps(clt auth.ClientI, cacheName []string) (auth.AppsAccessPoint, error) { + // if caching is disabled, return access point + if !process.Config.CachePolicy.Enabled { + return clt, nil + } + + cache, err := process.newLocalCache(clt, cache.ForApps, cacheName) + if err != nil { + return nil, trace.Wrap(err) + } + + return auth.NewAppsWrapper(clt, cache), nil +} + +// newLocalCacheForApps returns new instance of access point configured for a windows desktop service. +func (process *TeleportProcess) newLocalCacheForWindowsDesktop(clt auth.ClientI, cacheName []string) (auth.WindowsDesktopAccessPoint, error) { // if caching is disabled, return access point if !process.Config.CachePolicy.Enabled { return clt, nil } - cache, err := process.newAccessCache(accessCacheConfig{ + + cache, err := process.newLocalCache(clt, cache.ForWindowsDesktop, cacheName) + if err != nil { + return nil, trace.Wrap(err) + } + + return auth.NewWindowsDesktopWrapper(clt, cache), nil +} + +// newLocalCache returns new instance of access point +func (process *TeleportProcess) newLocalCache(clt auth.ClientI, setupConfig cache.SetupConfigFn, cacheName []string) (*cache.Cache, error) { + return process.newAccessCache(accessCacheConfig{ inMemory: process.Config.CachePolicy.Type == memory.GetName(), services: clt, setup: setupConfig, cacheName: cacheName, }) - if err != nil { - return nil, trace.Wrap(err) - } - return auth.NewWrapper(clt, cache), nil } func (process *TeleportProcess) getRotation(role types.SystemRole) (*types.Rotation, error) { @@ -1709,7 +1805,7 @@ func (process *TeleportProcess) initSSH() error { return trace.Wrap(err) } - authClient, err := process.newLocalCache(conn.Client, cache.ForNode, []string{teleport.ComponentNode}) + authClient, err := process.newLocalCacheForNode(conn.Client, []string{teleport.ComponentNode}) if err != nil { return trace.Wrap(err) } @@ -1976,7 +2072,7 @@ func (process *TeleportProcess) registerWithAuthServer(role types.SystemRole, ev }) } -func (process *TeleportProcess) initUploaderService(accessPoint auth.AccessPoint, auditLog events.IAuditLog) error { +func (process *TeleportProcess) initUploaderService(streamer events.Streamer, auditLog events.IAuditLog) error { log := process.log.WithFields(logrus.Fields{ trace.Component: teleport.Component(teleport.ComponentAuditLog, process.id), }) @@ -2047,7 +2143,7 @@ func (process *TeleportProcess) initUploaderService(accessPoint auth.AccessPoint // Delete this comment once the uploader above is phased out. fileUploader, err := filesessions.NewUploader(filesessions.UploaderConfig{ ScanDir: filepath.Join(streamingDir...), - Streamer: accessPoint, + Streamer: streamer, AuditLog: auditLog, EventsC: process.Config.UploadEventsC, }) @@ -2844,7 +2940,7 @@ func (process *TeleportProcess) initProxyEndpoint(conn *Connector) error { "", process.proxyPublicAddr(), regular.SetLimiter(proxyLimiter), - regular.SetProxyMode(tsrv), + regular.SetProxyMode(tsrv, accessPoint), regular.SetSessionServer(conn.Client), regular.SetCiphers(cfg.Ciphers), regular.SetKEXAlgorithms(cfg.KEXAlgorithms), @@ -3139,7 +3235,7 @@ func (process *TeleportProcess) initProxyEndpoint(conn *Connector) error { return nil } -func (process *TeleportProcess) setupProxyTLSConfig(conn *Connector, tsrv reversetunnel.Server, accessPoint auth.AccessPoint, clusterName string) (*tls.Config, error) { +func (process *TeleportProcess) setupProxyTLSConfig(conn *Connector, tsrv reversetunnel.Server, accessPoint auth.ReadProxyAccessPoint, clusterName string) (*tls.Config, error) { cfg := process.Config var tlsConfig *tls.Config acmeCfg := process.Config.Proxy.ACME @@ -3337,7 +3433,7 @@ func (process *TeleportProcess) initApps() { } // Create a caching client to the Auth Server. It is to reduce load on // the Auth Server. - accessPoint, err := process.newLocalCache(conn.Client, cache.ForApps, []string{component}) + accessPoint, err := process.newLocalCacheForApps(conn.Client, []string{component}) if err != nil { return trace.Wrap(err) } @@ -3796,7 +3892,7 @@ func dumperHandler(w http.ResponseWriter, r *http.Request) { } // getPublicAddr waits for a proxy to be registered with Teleport. -func getPublicAddr(authClient auth.AccessPoint, a App) (string, error) { +func getPublicAddr(authClient auth.ReadAppsAccessPoint, a App) (string, error) { ticker := time.NewTicker(500 * time.Millisecond) defer ticker.Stop() timeout := time.NewTimer(5 * time.Second) @@ -3816,7 +3912,7 @@ func getPublicAddr(authClient auth.AccessPoint, a App) (string, error) { } // findPublicAddr tries to resolve the public address of the proxy of this cluster. -func findPublicAddr(authClient auth.AccessPoint, a App) (string, error) { +func findPublicAddr(authClient auth.ReadAppsAccessPoint, a App) (string, error) { // If the application has a public address already set, use it. if a.PublicAddr != "" { return a.PublicAddr, nil diff --git a/lib/services/role.go b/lib/services/role.go index bb1d125aec4fa..1e28c2eb5e47c 100644 --- a/lib/services/role.go +++ b/lib/services/role.go @@ -719,24 +719,8 @@ type RoleGetter interface { GetRole(ctx context.Context, name string) (types.Role, error) } -// ExtractFromCertificate will extract roles and traits from a *ssh.Certificate -// or from the backend if they do not exist in the certificate. -func ExtractFromCertificate(access UserGetter, cert *ssh.Certificate) ([]string, wrappers.Traits, error) { - // For legacy certificates, fetch roles and traits from the services.User - // object in the backend. - if isFormatOld(cert) { - u, err := access.GetUser(cert.KeyId, false) - if err != nil { - return nil, nil, trace.Wrap(err) - } - log.Warnf("User %v using old style SSH certificate, fetching roles and traits "+ - "from backend. If the identity provider allows username changes, this can "+ - "potentially allow an attacker to change the role of the existing user. "+ - "It's recommended to upgrade to standard SSH certificates.", cert.KeyId) - return u.GetRoles(), u.GetTraits(), nil - } - - // Standard certificates have the roles and traits embedded in them. +// ExtractFromCertificate will extract roles and traits from a *ssh.Certificate. +func ExtractFromCertificate(cert *ssh.Certificate) ([]string, wrappers.Traits, error) { roles, err := ExtractRolesFromCert(cert) if err != nil { return nil, nil, trace.Wrap(err) @@ -798,18 +782,6 @@ func FetchRoles(roleNames []string, access RoleGetter, traits map[string][]strin return NewRoleSet(roles...), nil } -// isFormatOld returns true if roles and traits were not found in the -// *ssh.Certificate. -func isFormatOld(cert *ssh.Certificate) bool { - _, hasRoles := cert.Extensions[teleport.CertExtensionTeleportRoles] - _, hasTraits := cert.Extensions[teleport.CertExtensionTeleportTraits] - - if hasRoles || hasTraits { - return false - } - return true -} - // missingIdentity returns true if the identity is missing or the identity // has no roles or traits. func missingIdentity(identity tlsca.Identity) bool { diff --git a/lib/services/role_test.go b/lib/services/role_test.go index d54bed6e5a661..94c2c45f78aa6 100644 --- a/lib/services/role_test.go +++ b/lib/services/role_test.go @@ -2081,10 +2081,7 @@ func TestExtractFrom(t *testing.T) { // At this point, services.User and the certificate/identity are still in // sync. The roles and traits returned should be the same as the original. - roles, traits, err := ExtractFromCertificate(&userGetter{ - roles: origRoles, - traits: origTraits, - }, cert) + roles, traits, err := ExtractFromCertificate(cert) require.NoError(t, err) require.Equal(t, roles, origRoles) require.Equal(t, traits, origTraits) @@ -2100,53 +2097,11 @@ func TestExtractFrom(t *testing.T) { // The backend now returns new roles and traits, however because the roles // and traits are extracted from the certificate/identity, the original // roles and traits will be returned. - roles, traits, err = ExtractFromCertificate(&userGetter{ - roles: []string{"intern"}, - traits: wrappers.Traits(map[string][]string{ - "login": {"bar"}, - }), - }, cert) - require.NoError(t, err) - require.Equal(t, roles, origRoles) - require.Equal(t, traits, origTraits) - - roles, traits, err = ExtractFromIdentity(&userGetter{ - roles: origRoles, - traits: origTraits, - }, *identity) + roles, traits, err = ExtractFromCertificate(cert) require.NoError(t, err) require.Equal(t, roles, origRoles) require.Equal(t, traits, origTraits) -} - -// TestExtractFromLegacy verifies that roles and traits are fetched -// from services.User for SSH certificates is the legacy format and TLS -// certificates that don't contain traits. -func TestExtractFromLegacy(t *testing.T) { - origRoles := []string{"admin"} - origTraits := wrappers.Traits(map[string][]string{ - "login": {"foo"}, - }) - - // Create a SSH certificate in the legacy format. - cert, err := sshutils.ParseCertificate([]byte(fixtures.UserCertificateLegacy)) - require.NoError(t, err) - // Create a TLS identity with only roles. - identity := &tlsca.Identity{ - Username: "foo", - Groups: origRoles, - } - - // At this point, services.User and the certificate/identity are still in - // sync. The roles and traits returned should be the same as the original. - roles, traits, err := ExtractFromCertificate(&userGetter{ - roles: origRoles, - traits: origTraits, - }, cert) - require.NoError(t, err) - require.Equal(t, roles, origRoles) - require.Equal(t, traits, origTraits) roles, traits, err = ExtractFromIdentity(&userGetter{ roles: origRoles, traits: origTraits, @@ -2154,27 +2109,6 @@ func TestExtractFromLegacy(t *testing.T) { require.NoError(t, err) require.Equal(t, roles, origRoles) require.Equal(t, traits, origTraits) - - // The backend now returns new roles and traits, because the SSH certificate - // is in the old standard format and the TLS identity is missing traits. - newRoles := []string{"intern"} - newTraits := wrappers.Traits(map[string][]string{ - "login": {"bar"}, - }) - roles, traits, err = ExtractFromCertificate(&userGetter{ - roles: newRoles, - traits: newTraits, - }, cert) - require.NoError(t, err) - require.Equal(t, roles, newRoles) - require.Equal(t, traits, newTraits) - roles, traits, err = ExtractFromIdentity(&userGetter{ - roles: newRoles, - traits: newTraits, - }, *identity) - require.NoError(t, err) - require.Equal(t, roles, newRoles) - require.Equal(t, traits, newTraits) } // TestBoolOptions makes sure that bool options (like agent forwarding and diff --git a/lib/srv/alpnproxy/proxy.go b/lib/srv/alpnproxy/proxy.go index 33b8e698b46d1..3de9ec73ddf39 100644 --- a/lib/srv/alpnproxy/proxy.go +++ b/lib/srv/alpnproxy/proxy.go @@ -63,7 +63,7 @@ type ProxyConfig struct { // IdentityTLSConfig is the TLS ProxyRole identity used in servers with localhost SANs values. IdentityTLSConfig *tls.Config // AccessPoint is the auth server client. - AccessPoint auth.AccessPoint + AccessPoint auth.ReadProxyAccessPoint // ClusterName is the name of the teleport cluster. ClusterName string } diff --git a/lib/srv/app/server.go b/lib/srv/app/server.go index 66738a68b478d..d185fa6e5b5c7 100644 --- a/lib/srv/app/server.go +++ b/lib/srv/app/server.go @@ -61,7 +61,7 @@ type Config struct { AuthClient *auth.Client // AccessPoint is a caching client connected to the Auth Server. - AccessPoint auth.AccessPoint + AccessPoint auth.AppsAccessPoint // TLSConfig is the *tls.Config for this server. TLSConfig *tls.Config diff --git a/lib/srv/authhandlers.go b/lib/srv/authhandlers.go index 3394890b18af5..2bec02265d39b 100644 --- a/lib/srv/authhandlers.go +++ b/lib/srv/authhandlers.go @@ -28,7 +28,6 @@ import ( "github.com/gravitational/teleport/api/types" apievents "github.com/gravitational/teleport/api/types/events" apisshutils "github.com/gravitational/teleport/api/utils/sshutils" - "github.com/gravitational/teleport/lib/auth" "github.com/gravitational/teleport/lib/events" "github.com/gravitational/teleport/lib/services" "github.com/gravitational/teleport/lib/sshutils" @@ -72,7 +71,7 @@ type AuthHandlerConfig struct { Emitter apievents.Emitter // AccessPoint is used to access the Auth Server. - AccessPoint auth.AccessPoint + AccessPoint AccessPoint // FIPS mode means Teleport started in a FedRAMP/FIPS 140-2 compliant // configuration. @@ -445,7 +444,7 @@ func (h *AuthHandlers) fetchRoleSet(cert *ssh.Certificate, ca types.CertAuthorit if clusterName == ca.GetClusterName() { // Extract roles and traits either from the certificate or from // services.User and create a services.RoleSet with all runtime roles. - roles, traits, err := services.ExtractFromCertificate(h.c.AccessPoint, cert) + roles, traits, err := services.ExtractFromCertificate(cert) if err != nil { return nil, nil, trace.Wrap(err) } diff --git a/lib/srv/ctx.go b/lib/srv/ctx.go index fe23b3dd71374..d1360079bdca4 100644 --- a/lib/srv/ctx.go +++ b/lib/srv/ctx.go @@ -35,7 +35,6 @@ import ( apiutils "github.com/gravitational/teleport/api/utils" "github.com/gravitational/teleport/lib/auth" "github.com/gravitational/teleport/lib/bpf" - "github.com/gravitational/teleport/lib/defaults" "github.com/gravitational/teleport/lib/events" "github.com/gravitational/teleport/lib/pam" restricted "github.com/gravitational/teleport/lib/restrictedsession" @@ -74,16 +73,43 @@ func init() { prometheus.MustRegister(serverRX) } +// AccessPoint is the access point contract required by a Server +type AccessPoint interface { + // Announcer adds methods used to announce presence + auth.Announcer + + // Semaphores provides semaphore operations + types.Semaphores + + // GetClusterName returns cluster name + GetClusterName(opts ...services.MarshalOption) (types.ClusterName, error) + + // GetClusterNetworkingConfig returns cluster networking configuration. + GetClusterNetworkingConfig(ctx context.Context, opts ...services.MarshalOption) (types.ClusterNetworkingConfig, error) + + // GetSessionRecordingConfig returns session recording configuration. + GetSessionRecordingConfig(ctx context.Context, opts ...services.MarshalOption) (types.SessionRecordingConfig, error) + + // GetAuthPreference returns the cluster authentication configuration. + GetAuthPreference(ctx context.Context) (types.AuthPreference, error) + + // GetRole returns role by name + GetRole(ctx context.Context, name string) (types.Role, error) + + // GetCertAuthorities returns a list of cert authorities + GetCertAuthorities(caType types.CertAuthType, loadKeys bool, opts ...services.MarshalOption) ([]types.CertAuthority, error) +} + // Server is regular or forwarding SSH server. type Server interface { - // Emitter allows server to emit audit events and create + // StreamEmitter allows server to emit audit events and create // event streams for recording sessions events.StreamEmitter // ID is the unique ID of the server. ID() string - // HostUUID is the UUID of the underlying host. For the the forwarding + // HostUUID is the UUID of the underlying host. For the forwarding // server this is the proxy the forwarding server is running in. HostUUID() string @@ -100,8 +126,8 @@ type Server interface { // startup is allowed. PermitUserEnvironment() bool - // GetAccessPoint returns an auth.AccessPoint for this cluster. - GetAccessPoint() auth.AccessPoint + // GetAccessPoint returns an AccessPoint for this cluster. + GetAccessPoint() AccessPoint // GetSessionServer returns a session server. GetSessionServer() rsession.Service @@ -685,26 +711,8 @@ func (c *ServerContext) SendSubsystemResult(r SubsystemResult) { // available proxy. if public_address is not set, fall back to the hostname // of the first proxy we get back. func (c *ServerContext) ProxyPublicAddress() string { - proxyHost := ":3080" - - if c.srv == nil { - return proxyHost - } - - proxies, err := c.srv.GetAccessPoint().GetProxies() - if err != nil { - c.Errorf("Unable to retrieve proxy list: %v", err) - } - - if len(proxies) > 0 { - proxyHost = proxies[0].GetPublicAddr() - if proxyHost == "" { - proxyHost = fmt.Sprintf("%v:%v", proxies[0].GetHostname(), defaults.HTTPListenPort) - c.Debugf("public_address not set for proxy, returning proxyHost: %q", proxyHost) - } - } - - return proxyHost + //TODO(tross): Get the proxy address somehow - types.KindProxy is not replicated to Nodes + return ":3080" } func (c *ServerContext) String() string { @@ -739,13 +747,11 @@ func getPAMConfig(c *ServerContext) (*PAMConfig, error) { environment["TELEPORT_LOGIN"] = c.Identity.Login environment["TELEPORT_ROLES"] = strings.Join(roleNames, " ") if localPAMConfig.Environment != nil { - user, err := c.srv.GetAccessPoint().GetUser(c.Identity.TeleportUser, false) + traits, err := services.ExtractTraitsFromCert(c.Identity.Certificate) if err != nil { return nil, trace.Wrap(err) } - traits := user.GetTraits() - for key, value := range localPAMConfig.Environment { expr, err := parse.NewExpression(value) if err != nil { diff --git a/lib/srv/db/proxyserver.go b/lib/srv/db/proxyserver.go index 424890a4e6f2f..a758959cef9d7 100644 --- a/lib/srv/db/proxyserver.go +++ b/lib/srv/db/proxyserver.go @@ -68,7 +68,7 @@ type ProxyServerConfig struct { // AuthClient is the authenticated client to the auth server. AuthClient *auth.Client // AccessPoint is the caching client connected to the auth server. - AccessPoint auth.AccessPoint + AccessPoint auth.ReadDatabaseAccessPoint // Authorizer is responsible for authorizing user identities. Authorizer auth.Authorizer // Tunnel is the reverse tunnel server. @@ -558,7 +558,7 @@ func (s *ProxyServer) getConfigForServer(ctx context.Context, identity tlsca.Ide }, nil } -func getConfigForClient(conf *tls.Config, ap auth.AccessPoint, log logrus.FieldLogger) func(*tls.ClientHelloInfo) (*tls.Config, error) { +func getConfigForClient(conf *tls.Config, ap auth.ReadDatabaseAccessPoint, log logrus.FieldLogger) func(*tls.ClientHelloInfo) (*tls.Config, error) { return func(info *tls.ClientHelloInfo) (*tls.Config, error) { var clusterName string var err error diff --git a/lib/srv/db/server.go b/lib/srv/db/server.go index f4d4b5f91e343..dd849fbc23a05 100644 --- a/lib/srv/db/server.go +++ b/lib/srv/db/server.go @@ -54,7 +54,7 @@ type Config struct { // AuthClient is a client directly connected to the Auth server. AuthClient *auth.Client // AccessPoint is a caching client connected to the Auth Server. - AccessPoint auth.AccessPoint + AccessPoint auth.DatabaseAccessPoint // StreamEmitter is a non-blocking audit events emitter. StreamEmitter events.StreamEmitter // NewAudit allows to override audit logger in tests. diff --git a/lib/srv/desktop/windows_server.go b/lib/srv/desktop/windows_server.go index a2807542f867a..eb80512dc0c7f 100644 --- a/lib/srv/desktop/windows_server.go +++ b/lib/srv/desktop/windows_server.go @@ -105,7 +105,7 @@ type WindowsServiceConfig struct { // TLS is the TLS server configuration. TLS *tls.Config // AccessPoint is the Auth API client (with caching). - AccessPoint auth.AccessPoint + AccessPoint auth.WindowsDesktopAccessPoint // AuthClient is the Auth API client (without caching). AuthClient auth.ClientI // ConnLimiter limits the number of active connections per client IP. diff --git a/lib/srv/exec_test.go b/lib/srv/exec_test.go index cf924298e152d..c026010d60e82 100644 --- a/lib/srv/exec_test.go +++ b/lib/srv/exec_test.go @@ -426,7 +426,7 @@ func (f *fakeTerminal) SetTermType(string) { type fakeServer struct { auditLog events.IAuditLog events.MockEmitter - accessPoint auth.AccessPoint + accessPoint AccessPoint id string } @@ -458,7 +458,7 @@ func (f *fakeServer) PermitUserEnvironment() bool { return true } -func (f *fakeServer) GetAccessPoint() auth.AccessPoint { +func (f *fakeServer) GetAccessPoint() AccessPoint { return f.accessPoint } diff --git a/lib/srv/forward/sshserver.go b/lib/srv/forward/sshserver.go index 7725359f501b2..b3861053aecdc 100644 --- a/lib/srv/forward/sshserver.go +++ b/lib/srv/forward/sshserver.go @@ -134,7 +134,7 @@ type Server struct { macAlgorithms []string authClient auth.ClientI - authService auth.AccessPoint + authService srv.AccessPoint sessionRegistry *srv.SessionRegistry sessionServer session.Service dataDir string @@ -372,8 +372,8 @@ func (s *Server) PermitUserEnvironment() bool { return false } -// GetAccessPoint returns an auth.AccessPoint for this cluster. -func (s *Server) GetAccessPoint() auth.AccessPoint { +// GetAccessPoint returns a srv.AccessPoint for this cluster. +func (s *Server) GetAccessPoint() srv.AccessPoint { return s.authService } diff --git a/lib/srv/regular/proxy.go b/lib/srv/regular/proxy.go index 31f8f3503a309..fb81d4a930727 100644 --- a/lib/srv/regular/proxy.go +++ b/lib/srv/regular/proxy.go @@ -318,11 +318,11 @@ func (t *proxySubsys) proxyToHost( servers []types.Server err error ) - localCluster, _ := t.srv.authService.GetClusterName() - // going to "local" CA? let's use the caching 'auth service' directly and avoid + localCluster, _ := t.srv.proxyAccessPoint.GetClusterName() + // going to "local" CA? lets use the caching 'auth service' directly and avoid // hitting the reverse tunnel link (it can be offline if the CA is down) if site.GetName() == localCluster.GetName() { - servers, err = t.srv.authService.GetNodes(ctx.CancelContext(), t.namespace) + servers, err = t.srv.proxyAccessPoint.GetNodes(ctx.CancelContext(), t.namespace) if err != nil { t.log.Warn(err) } diff --git a/lib/srv/regular/sshserver.go b/lib/srv/regular/sshserver.go index 2d3ff53748466..c5bbd16c68cb8 100644 --- a/lib/srv/regular/sshserver.go +++ b/lib/srv/regular/sshserver.go @@ -87,7 +87,7 @@ type Server struct { srv *sshutils.Server shell string getRotation RotationGetter - authService auth.AccessPoint + authService srv.AccessPoint reg *srv.SessionRegistry sessionServer rsession.Service limiter *limiter.Limiter @@ -98,8 +98,9 @@ type Server struct { // dynamicLabels are the result of command execution. dynamicLabels *labels.Dynamic - proxyMode bool - proxyTun reversetunnel.Tunnel + proxyMode bool + proxyTun reversetunnel.Tunnel + proxyAccessPoint auth.ReadProxyAccessPoint advertiseAddr *utils.NetAddr proxyPublicAddr utils.NetAddr @@ -199,7 +200,7 @@ func (s *Server) GetNamespace() string { return s.namespace } -func (s *Server) GetAccessPoint() auth.AccessPoint { +func (s *Server) GetAccessPoint() srv.AccessPoint { return s.authService } @@ -387,13 +388,14 @@ func SetSessionServer(sessionServer rsession.Service) ServerOption { } // SetProxyMode starts this server in SSH proxying mode -func SetProxyMode(tsrv reversetunnel.Tunnel) ServerOption { +func SetProxyMode(tsrv reversetunnel.Tunnel, ap auth.ReadProxyAccessPoint) ServerOption { return func(s *Server) error { // always set proxy mode to true, // because in some tests reverse tunnel is disabled, // but proxy is still used without it. s.proxyMode = true s.proxyTun = tsrv + s.proxyAccessPoint = ap return nil } } @@ -553,7 +555,7 @@ func SetLockWatcher(lockWatcher *services.LockWatcher) ServerOption { func New(addr utils.NetAddr, hostname string, signers []ssh.Signer, - authService auth.AccessPoint, + authService srv.AccessPoint, dataDir string, advertiseAddr string, proxyPublicAddr utils.NetAddr, @@ -699,7 +701,7 @@ func (s *Server) getNamespace() string { } func (s *Server) tunnelWithRoles(ctx *srv.ServerContext) reversetunnel.Tunnel { - return reversetunnel.NewTunnelWithRoles(s.proxyTun, ctx.Identity.RoleSet, s.authService) + return reversetunnel.NewTunnelWithRoles(s.proxyTun, ctx.Identity.RoleSet, s.proxyAccessPoint) } // Context returns server shutdown context diff --git a/lib/srv/regular/sshserver_test.go b/lib/srv/regular/sshserver_test.go index 8cdf72081ace9..e433a99913f34 100644 --- a/lib/srv/regular/sshserver_test.go +++ b/lib/srv/regular/sshserver_test.go @@ -935,6 +935,10 @@ func mustListen(t *testing.T) (net.Listener, utils.NetAddr) { return l, addr } +func noCache(clt auth.ClientI, cacheName []string) (auth.RemoteProxyAccessPoint, error) { + return clt, nil +} + func TestProxyReverseTunnel(t *testing.T) { t.Parallel() @@ -977,8 +981,8 @@ func TestProxyReverseTunnel(t *testing.T) { HostSigners: []ssh.Signer{proxySigner}, LocalAuthClient: proxyClient, LocalAccessPoint: proxyClient, - NewCachingAccessPoint: auth.NoCache, - NewCachingAccessPointOldProxy: auth.NoCache, + NewCachingAccessPoint: noCache, + NewCachingAccessPointOldProxy: noCache, DirectClusters: []reversetunnel.DirectCluster{{Name: f.testSrv.ClusterName(), Client: proxyClient}}, DataDir: t.TempDir(), Component: teleport.ComponentProxy, @@ -1000,7 +1004,7 @@ func TestProxyReverseTunnel(t *testing.T) { "", utils.NetAddr{}, SetUUID(proxyID), - SetProxyMode(reverseTunnelServer), + SetProxyMode(reverseTunnelServer, proxyClient), SetSessionServer(proxyClient), SetEmitter(nodeClient), SetNamespace(apidefaults.Namespace), @@ -1168,8 +1172,8 @@ func TestProxyRoundRobin(t *testing.T) { HostSigners: []ssh.Signer{f.signer}, LocalAuthClient: proxyClient, LocalAccessPoint: proxyClient, - NewCachingAccessPoint: auth.NoCache, - NewCachingAccessPointOldProxy: auth.NoCache, + NewCachingAccessPoint: noCache, + NewCachingAccessPointOldProxy: noCache, DirectClusters: []reversetunnel.DirectCluster{{Name: f.testSrv.ClusterName(), Client: proxyClient}}, DataDir: t.TempDir(), Emitter: proxyClient, @@ -1190,7 +1194,7 @@ func TestProxyRoundRobin(t *testing.T) { t.TempDir(), "", utils.NetAddr{}, - SetProxyMode(reverseTunnelServer), + SetProxyMode(reverseTunnelServer, proxyClient), SetSessionServer(proxyClient), SetEmitter(nodeClient), SetNamespace(apidefaults.Namespace), @@ -1290,8 +1294,8 @@ func TestProxyDirectAccess(t *testing.T) { HostSigners: []ssh.Signer{f.signer}, LocalAuthClient: proxyClient, LocalAccessPoint: proxyClient, - NewCachingAccessPoint: auth.NoCache, - NewCachingAccessPointOldProxy: auth.NoCache, + NewCachingAccessPoint: noCache, + NewCachingAccessPointOldProxy: noCache, DirectClusters: []reversetunnel.DirectCluster{{Name: f.testSrv.ClusterName(), Client: proxyClient}}, DataDir: t.TempDir(), Emitter: proxyClient, @@ -1313,7 +1317,7 @@ func TestProxyDirectAccess(t *testing.T) { t.TempDir(), "", utils.NetAddr{}, - SetProxyMode(reverseTunnelServer), + SetProxyMode(reverseTunnelServer, proxyClient), SetSessionServer(proxyClient), SetEmitter(nodeClient), SetNamespace(apidefaults.Namespace), diff --git a/lib/web/apiserver.go b/lib/web/apiserver.go index d6a8900a284a6..4f7148aa2205c 100644 --- a/lib/web/apiserver.go +++ b/lib/web/apiserver.go @@ -149,7 +149,7 @@ type Config struct { FIPS bool // AccessPoint holds a cache to the Auth Server. - AccessPoint auth.AccessPoint + AccessPoint auth.ProxyAccessPoint // Emitter is event emitter Emitter events.StreamEmitter diff --git a/lib/web/apiserver_test.go b/lib/web/apiserver_test.go index 7adf646831a93..d5bdf8febee76 100644 --- a/lib/web/apiserver_test.go +++ b/lib/web/apiserver_test.go @@ -144,6 +144,10 @@ func (s *WebSuite) SetUpSuite(c *C) { c.Assert(s.mockU2F, NotNil) } +func noCache(clt auth.ClientI, cacheName []string) (auth.RemoteProxyAccessPoint, error) { + return clt, nil +} + func (s *WebSuite) SetUpTest(c *C) { s.ctx, s.cancel = context.WithCancel(context.Background()) @@ -273,7 +277,7 @@ func (s *WebSuite) SetUpTest(c *C) { LocalAuthClient: s.proxyClient, LocalAccessPoint: s.proxyClient, Emitter: s.proxyClient, - NewCachingAccessPoint: auth.NoCache, + NewCachingAccessPoint: noCache, DirectClusters: []reversetunnel.DirectCluster{{Name: s.server.ClusterName(), Client: s.proxyClient}}, DataDir: c.MkDir(), LockWatcher: proxyLockWatcher, @@ -291,7 +295,7 @@ func (s *WebSuite) SetUpTest(c *C) { "", utils.NetAddr{}, regular.SetUUID(proxyID), - regular.SetProxyMode(revTunServer), + regular.SetProxyMode(revTunServer, s.proxyClient), regular.SetSessionServer(s.proxyClient), regular.SetEmitter(s.proxyClient), regular.SetNamespace(apidefaults.Namespace), @@ -3251,7 +3255,7 @@ func createProxy(ctx context.Context, t *testing.T, proxyID string, node *regula LocalAuthClient: client, LocalAccessPoint: client, Emitter: client, - NewCachingAccessPoint: auth.NoCache, + NewCachingAccessPoint: noCache, DirectClusters: []reversetunnel.DirectCluster{{Name: authServer.ClusterName(), Client: client}}, DataDir: t.TempDir(), LockWatcher: proxyLockWatcher, @@ -3268,7 +3272,7 @@ func createProxy(ctx context.Context, t *testing.T, proxyID string, node *regula "", utils.NetAddr{}, regular.SetUUID(proxyID), - regular.SetProxyMode(revTunServer), + regular.SetProxyMode(revTunServer, client), regular.SetSessionServer(client), regular.SetEmitter(client), regular.SetNamespace(apidefaults.Namespace), diff --git a/lib/web/app/handler.go b/lib/web/app/handler.go index 2fd787191311d..c4ac69c92e2ab 100644 --- a/lib/web/app/handler.go +++ b/lib/web/app/handler.go @@ -46,7 +46,7 @@ type HandlerConfig struct { // AuthClient is a direct client to auth. AuthClient auth.ClientI // AccessPoint is caching client to auth. - AccessPoint auth.AccessPoint + AccessPoint auth.ProxyAccessPoint // ProxyClient holds connections to leaf clusters. ProxyClient reversetunnel.Tunnel // CipherSuites is the list of TLS cipher suites that have been configured diff --git a/lib/web/app/transport.go b/lib/web/app/transport.go index 522aa199423f3..b0e8d81dc0efb 100644 --- a/lib/web/app/transport.go +++ b/lib/web/app/transport.go @@ -40,7 +40,7 @@ import ( // transportConfig is configuration for a rewriting transport. type transportConfig struct { proxyClient reversetunnel.Tunnel - accessPoint auth.AccessPoint + accessPoint auth.ReadProxyAccessPoint cipherSuites []uint16 identity *tlsca.Identity server types.AppServer diff --git a/lib/web/sessions.go b/lib/web/sessions.go index 5008a418d3c51..a4fca307fbd87 100644 --- a/lib/web/sessions.go +++ b/lib/web/sessions.go @@ -69,7 +69,7 @@ type SessionContext struct { // This access point should only be used if the identity of the caller will // not affect the result of the RPC. For example, never use it to call // "GetNodes". - unsafeCachedAuthClient auth.ReadAccessPoint + unsafeCachedAuthClient auth.ReadProxyAccessPoint parent *sessionCache // resources is persistent resource store this context is bound to. @@ -341,7 +341,7 @@ func (c *SessionContext) GetUserRoles() (services.RoleSet, error) { if err != nil { return nil, trace.Wrap(err) } - roles, traits, err := services.ExtractFromCertificate(c.clt, cert) + roles, traits, err := services.ExtractFromCertificate(cert) if err != nil { return nil, trace.Wrap(err) } @@ -457,7 +457,7 @@ const cachedSessionLingeringThreshold = 2 * time.Minute type sessionCacheOptions struct { proxyClient auth.ClientI - accessPoint auth.ReadAccessPoint + accessPoint auth.ReadProxyAccessPoint servers []utils.NetAddr cipherSuites []uint16 clock clockwork.Clock @@ -499,7 +499,7 @@ type sessionCache struct { log logrus.FieldLogger proxyClient auth.ClientI authServers []utils.NetAddr - accessPoint auth.ReadAccessPoint + accessPoint auth.ReadProxyAccessPoint closer *utils.CloseBroadcaster clusterName string clock clockwork.Clock diff --git a/lib/web/ui/perf_test.go b/lib/web/ui/perf_test.go index f45976057286c..ffd7cace9807e 100644 --- a/lib/web/ui/perf_test.go +++ b/lib/web/ui/perf_test.go @@ -164,10 +164,10 @@ func benchmarkGetClusterDetails(ctx context.Context, b *testing.B, site reverset type mockRemoteSite struct { reversetunnel.RemoteSite - accessPoint auth.AccessPoint + accessPoint auth.ProxyAccessPoint } -func (m *mockRemoteSite) CachingAccessPoint() (auth.AccessPoint, error) { +func (m *mockRemoteSite) CachingAccessPoint() (auth.RemoteProxyAccessPoint, error) { return m.accessPoint, nil } @@ -184,7 +184,7 @@ func (m *mockRemoteSite) GetStatus() string { } type mockAccessPoint struct { - auth.AccessPoint + auth.ProxyAccessPoint presence *local.PresenceService }