mirror of
https://github.com/gravitational/teleport.git
synced 2026-10-31 20:39:37 +08:00
Adds `UpsertCertAuthority` to the `teleport.v1.trust.TrustService` and deprecates the HTTP api. The `services.Trust` interface was also updated to include a `context.Context` in both `CreateCertAuthority` and `UpsertCertAuthority. To ensure backwards compatibility the `auth.Client` will first attempt to use the gRPC client and if that fails with a not implemented error it will fallback to using HTTP. Part of #6394
1478 lines
52 KiB
Go
1478 lines
52 KiB
Go
/*
|
|
Copyright 2018-2019 Gravitational, Inc.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
//nolint:unused // Because the executors generate a large amount of false positives.
|
|
package cache
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/gravitational/trace"
|
|
|
|
"github.com/gravitational/teleport/api/client"
|
|
"github.com/gravitational/teleport/api/client/proto"
|
|
apidefaults "github.com/gravitational/teleport/api/defaults"
|
|
"github.com/gravitational/teleport/api/types"
|
|
)
|
|
|
|
// collection is responsible for managing collection
|
|
// of resources updates
|
|
type collection interface {
|
|
// fetch fetches resources and returns a function which
|
|
// will apply said resources to the cache. fetch *must*
|
|
// not mutate cache state outside of the apply function.
|
|
fetch(ctx context.Context) (apply func(ctx context.Context) error, err error)
|
|
// processEvent processes event
|
|
processEvent(ctx context.Context, e types.Event) error
|
|
// watchKind returns a watch
|
|
// required for this collection
|
|
watchKind() types.WatchKind
|
|
}
|
|
|
|
// executor[R] is a specific way to run the collector operations that we need
|
|
// for the genericCollector for a generic resource type R.
|
|
type executor[R types.Resource] interface {
|
|
// getAll returns all of the target resources from the auth server.
|
|
// For singleton objects, this should be a size-1 slice.
|
|
getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]R, error)
|
|
|
|
// upsert will create or update a target resource in the cache.
|
|
upsert(ctx context.Context, cache *Cache, value R) error
|
|
|
|
// deleteAll will delete all target resources of the type in the cache.
|
|
deleteAll(ctx context.Context, cache *Cache) error
|
|
|
|
// delete will delete a single target resource from the cache. For
|
|
// singletons, this is usually an alias to deleteAll.
|
|
delete(ctx context.Context, cache *Cache, resource types.Resource) error
|
|
|
|
// isSingleton will return true if the target resource is a singleton.
|
|
isSingleton() bool
|
|
}
|
|
|
|
type genericCollection[R types.Resource, E executor[R]] struct {
|
|
cache *Cache
|
|
watch types.WatchKind
|
|
exec E
|
|
}
|
|
|
|
// fetch implements collection
|
|
func (g *genericCollection[_, _]) fetch(ctx context.Context) (apply func(ctx context.Context) error, err error) {
|
|
// Singleton objects will only get deleted or updated, not both
|
|
deleteSingleton := false
|
|
resources, err := g.exec.getAll(ctx, g.cache, g.watch.LoadSecrets)
|
|
if err != nil {
|
|
if !trace.IsNotFound(err) {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
deleteSingleton = true
|
|
}
|
|
return func(ctx context.Context) error {
|
|
// Always perform the delete if this is not a singleton, otherwise
|
|
// only perform the delete if the singleton wasn't found.
|
|
if !g.exec.isSingleton() || deleteSingleton {
|
|
if err := g.exec.deleteAll(ctx, g.cache); err != nil {
|
|
if !trace.IsNotFound(err) {
|
|
return trace.Wrap(err)
|
|
}
|
|
}
|
|
}
|
|
// If this is a singleton and we performed a deletion, return here
|
|
// because we only want to update or delete a singleton, not both.
|
|
if g.exec.isSingleton() && deleteSingleton {
|
|
return nil
|
|
}
|
|
for _, resource := range resources {
|
|
if err := g.exec.upsert(ctx, g.cache, resource); err != nil {
|
|
return trace.Wrap(err)
|
|
}
|
|
}
|
|
return nil
|
|
}, nil
|
|
}
|
|
|
|
// processEvent implements collection
|
|
func (g *genericCollection[R, _]) processEvent(ctx context.Context, event types.Event) error {
|
|
switch event.Type {
|
|
case types.OpDelete:
|
|
if err := g.exec.delete(ctx, g.cache, event.Resource); err != nil {
|
|
if !trace.IsNotFound(err) {
|
|
g.cache.Logger.WithError(err).Warn("Failed to delete resource.")
|
|
return trace.Wrap(err)
|
|
}
|
|
}
|
|
case types.OpPut:
|
|
resource, ok := event.Resource.(R)
|
|
if !ok {
|
|
return trace.BadParameter("unexpected type %T", event.Resource)
|
|
}
|
|
if err := g.exec.upsert(ctx, g.cache, resource); err != nil {
|
|
return trace.Wrap(err)
|
|
}
|
|
default:
|
|
g.cache.Logger.WithField("event", event.Type).Warn("Skipping unsupported event type.")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// watchKind implements collection
|
|
func (g *genericCollection[_, _]) watchKind() types.WatchKind {
|
|
return g.watch
|
|
}
|
|
|
|
var _ collection = (*genericCollection[types.Resource, executor[types.Resource]])(nil)
|
|
|
|
// setupCollections returns a mapping of collections
|
|
func setupCollections(c *Cache, watches []types.WatchKind) (map[resourceKind]collection, error) {
|
|
collections := make(map[resourceKind]collection, len(watches))
|
|
for _, watch := range watches {
|
|
resourceKind := resourceKindFromWatchKind(watch)
|
|
switch watch.Kind {
|
|
case types.KindCertAuthority:
|
|
if c.Trust == nil {
|
|
return nil, trace.BadParameter("missing parameter Trust")
|
|
}
|
|
var filter types.CertAuthorityFilter
|
|
filter.FromMap(watch.Filter)
|
|
collections[resourceKind] = &genericCollection[types.CertAuthority, certAuthorityExecutor]{
|
|
cache: c,
|
|
watch: watch,
|
|
exec: certAuthorityExecutor{filter: filter},
|
|
}
|
|
case types.KindStaticTokens:
|
|
if c.ClusterConfig == nil {
|
|
return nil, trace.BadParameter("missing parameter ClusterConfig")
|
|
}
|
|
collections[resourceKind] = &genericCollection[types.StaticTokens, staticTokensExecutor]{cache: c, watch: watch}
|
|
case types.KindToken:
|
|
if c.Provisioner == nil {
|
|
return nil, trace.BadParameter("missing parameter Provisioner")
|
|
}
|
|
collections[resourceKind] = &genericCollection[types.ProvisionToken, provisionTokenExecutor]{cache: c, watch: watch}
|
|
case types.KindClusterName:
|
|
if c.ClusterConfig == nil {
|
|
return nil, trace.BadParameter("missing parameter ClusterConfig")
|
|
}
|
|
collections[resourceKind] = &genericCollection[types.ClusterName, clusterNameExecutor]{cache: c, watch: watch}
|
|
case types.KindClusterAuditConfig:
|
|
if c.ClusterConfig == nil {
|
|
return nil, trace.BadParameter("missing parameter ClusterConfig")
|
|
}
|
|
collections[resourceKind] = &genericCollection[types.ClusterAuditConfig, clusterAuditConfigExecutor]{cache: c, watch: watch}
|
|
case types.KindClusterNetworkingConfig:
|
|
if c.ClusterConfig == nil {
|
|
return nil, trace.BadParameter("missing parameter ClusterConfig")
|
|
}
|
|
collections[resourceKind] = &genericCollection[types.ClusterNetworkingConfig, clusterNetworkingConfigExecutor]{cache: c, watch: watch}
|
|
case types.KindClusterAuthPreference:
|
|
if c.ClusterConfig == nil {
|
|
return nil, trace.BadParameter("missing parameter ClusterConfig")
|
|
}
|
|
collections[resourceKind] = &genericCollection[types.AuthPreference, authPreferenceExecutor]{cache: c, watch: watch}
|
|
case types.KindSessionRecordingConfig:
|
|
if c.ClusterConfig == nil {
|
|
return nil, trace.BadParameter("missing parameter ClusterConfig")
|
|
}
|
|
collections[resourceKind] = &genericCollection[types.SessionRecordingConfig, sessionRecordingConfigExecutor]{cache: c, watch: watch}
|
|
case types.KindInstaller:
|
|
if c.ClusterConfig == nil {
|
|
return nil, trace.BadParameter("missing parameter ClusterConfig")
|
|
}
|
|
collections[resourceKind] = &genericCollection[types.Installer, installerConfigExecutor]{cache: c, watch: watch}
|
|
case types.KindUIConfig:
|
|
if c.ClusterConfig == nil {
|
|
return nil, trace.BadParameter("missing parameter ClusterConfig")
|
|
}
|
|
collections[resourceKind] = &genericCollection[types.UIConfig, uiConfigExecutor]{cache: c, watch: watch}
|
|
case types.KindUser:
|
|
if c.Users == nil {
|
|
return nil, trace.BadParameter("missing parameter Users")
|
|
}
|
|
collections[resourceKind] = &genericCollection[types.User, userExecutor]{cache: c, watch: watch}
|
|
case types.KindRole:
|
|
if c.Access == nil {
|
|
return nil, trace.BadParameter("missing parameter Access")
|
|
}
|
|
collections[resourceKind] = &genericCollection[types.Role, roleExecutor]{cache: c, watch: watch}
|
|
case types.KindNamespace:
|
|
if c.Presence == nil {
|
|
return nil, trace.BadParameter("missing parameter Presence")
|
|
}
|
|
collections[resourceKind] = &genericCollection[*types.Namespace, namespaceExecutor]{cache: c, watch: watch}
|
|
case types.KindNode:
|
|
if c.Presence == nil {
|
|
return nil, trace.BadParameter("missing parameter Presence")
|
|
}
|
|
collections[resourceKind] = &genericCollection[types.Server, nodeExecutor]{cache: c, watch: watch}
|
|
case types.KindProxy:
|
|
if c.Presence == nil {
|
|
return nil, trace.BadParameter("missing parameter Presence")
|
|
}
|
|
collections[resourceKind] = &genericCollection[types.Server, proxyExecutor]{cache: c, watch: watch}
|
|
case types.KindAuthServer:
|
|
if c.Presence == nil {
|
|
return nil, trace.BadParameter("missing parameter Presence")
|
|
}
|
|
collections[resourceKind] = &genericCollection[types.Server, authServerExecutor]{cache: c, watch: watch}
|
|
case types.KindReverseTunnel:
|
|
if c.Presence == nil {
|
|
return nil, trace.BadParameter("missing parameter Presence")
|
|
}
|
|
collections[resourceKind] = &genericCollection[types.ReverseTunnel, reverseTunnelExecutor]{cache: c, watch: watch}
|
|
case types.KindTunnelConnection:
|
|
if c.Presence == nil {
|
|
return nil, trace.BadParameter("missing parameter Presence")
|
|
}
|
|
collections[resourceKind] = &genericCollection[types.TunnelConnection, tunnelConnectionExecutor]{cache: c, watch: watch}
|
|
case types.KindRemoteCluster:
|
|
if c.Presence == nil {
|
|
return nil, trace.BadParameter("missing parameter Presence")
|
|
}
|
|
collections[resourceKind] = &genericCollection[types.RemoteCluster, remoteClusterExecutor]{cache: c, watch: watch}
|
|
case types.KindAccessRequest:
|
|
if c.DynamicAccess == nil {
|
|
return nil, trace.BadParameter("missing parameter DynamicAccess")
|
|
}
|
|
collections[resourceKind] = &genericCollection[types.AccessRequest, accessRequestExecutor]{cache: c, watch: watch}
|
|
case types.KindAppServer:
|
|
if c.Presence == nil {
|
|
return nil, trace.BadParameter("missing parameter Presence")
|
|
}
|
|
collections[resourceKind] = &genericCollection[types.AppServer, appServerExecutor]{cache: c, watch: watch}
|
|
case types.KindWebSession:
|
|
switch watch.SubKind {
|
|
case types.KindAppSession:
|
|
if c.AppSession == nil {
|
|
return nil, trace.BadParameter("missing parameter AppSession")
|
|
}
|
|
collections[resourceKind] = &genericCollection[types.WebSession, appSessionExecutor]{cache: c, watch: watch}
|
|
case types.KindSnowflakeSession:
|
|
if c.SnowflakeSession == nil {
|
|
return nil, trace.BadParameter("missing parameter SnowflakeSession")
|
|
}
|
|
collections[resourceKind] = &genericCollection[types.WebSession, snowflakeSessionExecutor]{cache: c, watch: watch}
|
|
case types.KindSAMLIdPSession:
|
|
if c.SAMLIdPSession == nil {
|
|
return nil, trace.BadParameter("missing parameter SAMLIdPSession")
|
|
}
|
|
collections[resourceKind] = &genericCollection[types.WebSession, samlIdPSessionExecutor]{cache: c, watch: watch}
|
|
case types.KindWebSession:
|
|
if c.WebSession == nil {
|
|
return nil, trace.BadParameter("missing parameter WebSession")
|
|
}
|
|
collections[resourceKind] = &genericCollection[types.WebSession, webSessionExecutor]{cache: c, watch: watch}
|
|
}
|
|
case types.KindWebToken:
|
|
if c.WebToken == nil {
|
|
return nil, trace.BadParameter("missing parameter WebToken")
|
|
}
|
|
collections[resourceKind] = &genericCollection[types.WebToken, webTokenExecutor]{cache: c, watch: watch}
|
|
case types.KindKubeServer:
|
|
if c.Presence == nil {
|
|
return nil, trace.BadParameter("missing parameter Presence")
|
|
}
|
|
collections[resourceKind] = &genericCollection[types.KubeServer, kubeServerExecutor]{cache: c, watch: watch}
|
|
case types.KindDatabaseServer:
|
|
if c.Presence == nil {
|
|
return nil, trace.BadParameter("missing parameter Presence")
|
|
}
|
|
collections[resourceKind] = &genericCollection[types.DatabaseServer, databaseServerExecutor]{cache: c, watch: watch}
|
|
case types.KindDatabaseService:
|
|
if c.DatabaseServices == nil {
|
|
return nil, trace.BadParameter("missing parameter DatabaseServices")
|
|
}
|
|
if c.Presence == nil {
|
|
return nil, trace.BadParameter("missing parameter Presence")
|
|
}
|
|
collections[resourceKind] = &genericCollection[types.DatabaseService, databaseServiceExecutor]{cache: c, watch: watch}
|
|
case types.KindApp:
|
|
if c.Apps == nil {
|
|
return nil, trace.BadParameter("missing parameter Apps")
|
|
}
|
|
collections[resourceKind] = &genericCollection[types.Application, appExecutor]{cache: c, watch: watch}
|
|
case types.KindDatabase:
|
|
if c.Databases == nil {
|
|
return nil, trace.BadParameter("missing parameter Databases")
|
|
}
|
|
collections[resourceKind] = &genericCollection[types.Database, databaseExecutor]{cache: c, watch: watch}
|
|
case types.KindKubernetesCluster:
|
|
if c.Kubernetes == nil {
|
|
return nil, trace.BadParameter("missing parameter Kubernetes")
|
|
}
|
|
collections[resourceKind] = &genericCollection[types.KubeCluster, kubeClusterExecutor]{cache: c, watch: watch}
|
|
case types.KindNetworkRestrictions:
|
|
if c.Restrictions == nil {
|
|
return nil, trace.BadParameter("missing parameter Restrictions")
|
|
}
|
|
collections[resourceKind] = &genericCollection[types.NetworkRestrictions, networkRestrictionsExecutor]{cache: c, watch: watch}
|
|
case types.KindLock:
|
|
if c.Access == nil {
|
|
return nil, trace.BadParameter("missing parameter Access")
|
|
}
|
|
collections[resourceKind] = &genericCollection[types.Lock, lockExecutor]{cache: c, watch: watch}
|
|
case types.KindWindowsDesktopService:
|
|
if c.Presence == nil {
|
|
return nil, trace.BadParameter("missing parameter Presence")
|
|
}
|
|
collections[resourceKind] = &genericCollection[types.WindowsDesktopService, windowsDesktopServicesExecutor]{cache: c, watch: watch}
|
|
case types.KindWindowsDesktop:
|
|
if c.WindowsDesktops == nil {
|
|
return nil, trace.BadParameter("missing parameter WindowsDesktops")
|
|
}
|
|
collections[resourceKind] = &genericCollection[types.WindowsDesktop, windowsDesktopsExecutor]{cache: c, watch: watch}
|
|
case types.KindSAMLIdPServiceProvider:
|
|
if c.SAMLIdPServiceProviders == nil {
|
|
return nil, trace.BadParameter("missing parameter SAMLIdPServiceProviders")
|
|
}
|
|
collections[resourceKind] = &genericCollection[types.SAMLIdPServiceProvider, samlIdPServiceProvidersExecutor]{cache: c, watch: watch}
|
|
case types.KindUserGroup:
|
|
if c.UserGroups == nil {
|
|
return nil, trace.BadParameter("missing parameter UserGroups")
|
|
}
|
|
collections[resourceKind] = &genericCollection[types.UserGroup, userGroupsExecutor]{cache: c, watch: watch}
|
|
default:
|
|
return nil, trace.BadParameter("resource %q is not supported", watch.Kind)
|
|
}
|
|
}
|
|
return collections, nil
|
|
}
|
|
|
|
func resourceKindFromWatchKind(wk types.WatchKind) resourceKind {
|
|
switch wk.Kind {
|
|
case types.KindWebSession:
|
|
// Web sessions use subkind to differentiate between
|
|
// the types of sessions
|
|
return resourceKind{
|
|
kind: wk.Kind,
|
|
subkind: wk.SubKind,
|
|
version: wk.Version,
|
|
}
|
|
}
|
|
return resourceKind{
|
|
kind: wk.Kind,
|
|
version: wk.Version,
|
|
}
|
|
}
|
|
|
|
func resourceKindFromResource(res types.Resource) resourceKind {
|
|
switch res.GetKind() {
|
|
case types.KindWebSession:
|
|
// Web sessions use subkind to differentiate between
|
|
// the types of sessions
|
|
return resourceKind{
|
|
kind: res.GetKind(),
|
|
subkind: res.GetSubKind(),
|
|
}
|
|
case types.KindAppServer:
|
|
// DELETE IN 9.0.
|
|
switch res.GetVersion() {
|
|
case types.V2:
|
|
return resourceKind{
|
|
kind: res.GetKind(),
|
|
version: res.GetVersion(),
|
|
}
|
|
}
|
|
}
|
|
return resourceKind{
|
|
kind: res.GetKind(),
|
|
}
|
|
}
|
|
|
|
type resourceKind struct {
|
|
kind string
|
|
subkind string
|
|
version string
|
|
}
|
|
|
|
func (r resourceKind) String() string {
|
|
if r.subkind == "" {
|
|
return r.kind
|
|
}
|
|
return fmt.Sprintf("%s/%s", r.kind, r.subkind)
|
|
}
|
|
|
|
type accessRequestExecutor struct{}
|
|
|
|
func (accessRequestExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]types.AccessRequest, error) {
|
|
return cache.DynamicAccess.GetAccessRequests(ctx, types.AccessRequestFilter{})
|
|
}
|
|
|
|
func (accessRequestExecutor) upsert(ctx context.Context, cache *Cache, resource types.AccessRequest) error {
|
|
return cache.dynamicAccessCache.UpsertAccessRequest(ctx, resource)
|
|
}
|
|
|
|
func (accessRequestExecutor) deleteAll(ctx context.Context, cache *Cache) error {
|
|
return cache.dynamicAccessCache.DeleteAllAccessRequests(ctx)
|
|
}
|
|
|
|
func (accessRequestExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error {
|
|
return cache.dynamicAccessCache.DeleteAccessRequest(ctx, resource.GetName())
|
|
}
|
|
|
|
func (accessRequestExecutor) isSingleton() bool { return false }
|
|
|
|
var _ executor[types.AccessRequest] = accessRequestExecutor{}
|
|
|
|
type tunnelConnectionExecutor struct{}
|
|
|
|
func (tunnelConnectionExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]types.TunnelConnection, error) {
|
|
return cache.Presence.GetAllTunnelConnections()
|
|
}
|
|
|
|
func (tunnelConnectionExecutor) upsert(ctx context.Context, cache *Cache, resource types.TunnelConnection) error {
|
|
return cache.presenceCache.UpsertTunnelConnection(resource)
|
|
}
|
|
|
|
func (tunnelConnectionExecutor) deleteAll(ctx context.Context, cache *Cache) error {
|
|
return cache.presenceCache.DeleteAllTunnelConnections()
|
|
}
|
|
|
|
func (tunnelConnectionExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error {
|
|
return cache.presenceCache.DeleteTunnelConnection(resource.GetSubKind(), resource.GetName())
|
|
}
|
|
|
|
func (tunnelConnectionExecutor) isSingleton() bool { return false }
|
|
|
|
var _ executor[types.TunnelConnection] = tunnelConnectionExecutor{}
|
|
|
|
type remoteClusterExecutor struct{}
|
|
|
|
func (remoteClusterExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]types.RemoteCluster, error) {
|
|
return cache.Presence.GetRemoteClusters()
|
|
}
|
|
|
|
func (remoteClusterExecutor) upsert(ctx context.Context, cache *Cache, resource types.RemoteCluster) error {
|
|
err := cache.presenceCache.DeleteRemoteCluster(ctx, resource.GetName())
|
|
if err != nil {
|
|
if !trace.IsNotFound(err) {
|
|
cache.Logger.WithError(err).Warnf("Failed to delete remote cluster %v.", resource.GetName())
|
|
return trace.Wrap(err)
|
|
}
|
|
}
|
|
return trace.Wrap(cache.presenceCache.CreateRemoteCluster(resource))
|
|
}
|
|
|
|
func (remoteClusterExecutor) deleteAll(ctx context.Context, cache *Cache) error {
|
|
return cache.presenceCache.DeleteAllRemoteClusters()
|
|
}
|
|
|
|
func (remoteClusterExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error {
|
|
return cache.presenceCache.DeleteRemoteCluster(ctx, resource.GetName())
|
|
}
|
|
|
|
func (remoteClusterExecutor) isSingleton() bool { return false }
|
|
|
|
var _ executor[types.RemoteCluster] = remoteClusterExecutor{}
|
|
|
|
type reverseTunnelExecutor struct{}
|
|
|
|
func (reverseTunnelExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]types.ReverseTunnel, error) {
|
|
return cache.Presence.GetReverseTunnels(ctx)
|
|
}
|
|
|
|
func (reverseTunnelExecutor) upsert(ctx context.Context, cache *Cache, resource types.ReverseTunnel) error {
|
|
return cache.presenceCache.UpsertReverseTunnel(resource)
|
|
}
|
|
|
|
func (reverseTunnelExecutor) deleteAll(ctx context.Context, cache *Cache) error {
|
|
return cache.presenceCache.DeleteAllReverseTunnels()
|
|
}
|
|
|
|
func (reverseTunnelExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error {
|
|
return cache.presenceCache.DeleteReverseTunnel(resource.GetName())
|
|
}
|
|
|
|
func (reverseTunnelExecutor) isSingleton() bool { return false }
|
|
|
|
var _ executor[types.ReverseTunnel] = reverseTunnelExecutor{}
|
|
|
|
type proxyExecutor struct{}
|
|
|
|
func (proxyExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]types.Server, error) {
|
|
return cache.Presence.GetProxies()
|
|
}
|
|
|
|
func (proxyExecutor) upsert(ctx context.Context, cache *Cache, resource types.Server) error {
|
|
return cache.presenceCache.UpsertProxy(resource)
|
|
}
|
|
|
|
func (proxyExecutor) deleteAll(ctx context.Context, cache *Cache) error {
|
|
return cache.presenceCache.DeleteAllProxies()
|
|
}
|
|
|
|
func (proxyExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error {
|
|
return cache.presenceCache.DeleteProxy(resource.GetName())
|
|
}
|
|
|
|
func (proxyExecutor) isSingleton() bool { return false }
|
|
|
|
var _ executor[types.Server] = proxyExecutor{}
|
|
|
|
type authServerExecutor struct{}
|
|
|
|
func (authServerExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]types.Server, error) {
|
|
return cache.Presence.GetAuthServers()
|
|
}
|
|
|
|
func (authServerExecutor) upsert(ctx context.Context, cache *Cache, resource types.Server) error {
|
|
return cache.presenceCache.UpsertAuthServer(resource)
|
|
}
|
|
|
|
func (authServerExecutor) deleteAll(ctx context.Context, cache *Cache) error {
|
|
return cache.presenceCache.DeleteAllAuthServers()
|
|
}
|
|
|
|
func (authServerExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error {
|
|
return cache.presenceCache.DeleteAuthServer(resource.GetName())
|
|
}
|
|
|
|
func (authServerExecutor) isSingleton() bool { return false }
|
|
|
|
var _ executor[types.Server] = authServerExecutor{}
|
|
|
|
type nodeExecutor struct{}
|
|
|
|
func (nodeExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]types.Server, error) {
|
|
return cache.Presence.GetNodes(ctx, apidefaults.Namespace)
|
|
}
|
|
|
|
func (nodeExecutor) upsert(ctx context.Context, cache *Cache, resource types.Server) error {
|
|
_, err := cache.presenceCache.UpsertNode(ctx, resource)
|
|
return trace.Wrap(err)
|
|
}
|
|
|
|
func (nodeExecutor) deleteAll(ctx context.Context, cache *Cache) error {
|
|
return cache.presenceCache.DeleteAllNodes(ctx, apidefaults.Namespace)
|
|
}
|
|
|
|
func (nodeExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error {
|
|
return cache.presenceCache.DeleteNode(ctx, resource.GetMetadata().Namespace, resource.GetName())
|
|
}
|
|
|
|
func (nodeExecutor) isSingleton() bool { return false }
|
|
|
|
var _ executor[types.Server] = nodeExecutor{}
|
|
|
|
type namespaceExecutor struct{}
|
|
|
|
func (namespaceExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]*types.Namespace, error) {
|
|
namespaces, err := cache.Presence.GetNamespaces()
|
|
if err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
|
|
derefNamespaces := make([]*types.Namespace, len(namespaces))
|
|
for i, namespace := range namespaces {
|
|
derefNamespaces[i] = &namespace
|
|
}
|
|
return derefNamespaces, nil
|
|
}
|
|
|
|
func (namespaceExecutor) upsert(ctx context.Context, cache *Cache, resource *types.Namespace) error {
|
|
return cache.presenceCache.UpsertNamespace(*resource)
|
|
}
|
|
|
|
func (namespaceExecutor) deleteAll(ctx context.Context, cache *Cache) error {
|
|
return cache.presenceCache.DeleteAllNamespaces()
|
|
}
|
|
|
|
func (namespaceExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error {
|
|
return cache.presenceCache.DeleteNamespace(resource.GetName())
|
|
}
|
|
|
|
func (namespaceExecutor) isSingleton() bool { return false }
|
|
|
|
var _ executor[*types.Namespace] = namespaceExecutor{}
|
|
|
|
type certAuthorityExecutor struct {
|
|
// extracted from watch.Filter, to avoid rebuilding on every event
|
|
filter types.CertAuthorityFilter
|
|
}
|
|
|
|
// delete implements executor[types.CertAuthority]
|
|
func (certAuthorityExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error {
|
|
err := cache.trustCache.DeleteCertAuthority(ctx, types.CertAuthID{
|
|
Type: types.CertAuthType(resource.GetSubKind()),
|
|
DomainName: resource.GetName(),
|
|
})
|
|
return trace.Wrap(err)
|
|
}
|
|
|
|
// deleteAll implements executor[types.CertAuthority]
|
|
func (certAuthorityExecutor) deleteAll(ctx context.Context, cache *Cache) error {
|
|
for _, caType := range types.CertAuthTypes {
|
|
if err := cache.trustCache.DeleteAllCertAuthorities(caType); err != nil {
|
|
return trace.Wrap(err)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// getAll implements executor[types.CertAuthority]
|
|
func (e certAuthorityExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]types.CertAuthority, error) {
|
|
var authorities []types.CertAuthority
|
|
for _, caType := range types.CertAuthTypes {
|
|
cas, err := cache.Trust.GetCertAuthorities(ctx, caType, loadSecrets)
|
|
// if caType was added in this major version we might get a BadParameter
|
|
// error if we're connecting to an older upstream that doesn't know about it
|
|
if err != nil && !(caType.NewlyAdded() && trace.IsBadParameter(err)) {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
|
|
// this can be removed once we get the ability to fetch CAs with a filter,
|
|
// but it should be harmless, and it could be kept as additional safety
|
|
if !e.filter.IsEmpty() {
|
|
filtered := cas[:0]
|
|
for _, ca := range cas {
|
|
if e.filter.Match(ca) {
|
|
filtered = append(filtered, ca)
|
|
}
|
|
}
|
|
cas = filtered
|
|
}
|
|
|
|
authorities = append(authorities, cas...)
|
|
}
|
|
|
|
return authorities, nil
|
|
}
|
|
|
|
// upsert implements executor[types.CertAuthority]
|
|
func (e certAuthorityExecutor) upsert(ctx context.Context, cache *Cache, value types.CertAuthority) error {
|
|
if !e.filter.Match(value) {
|
|
return nil
|
|
}
|
|
|
|
return cache.trustCache.UpsertCertAuthority(ctx, value)
|
|
}
|
|
|
|
func (certAuthorityExecutor) isSingleton() bool { return false }
|
|
|
|
var _ executor[types.CertAuthority] = certAuthorityExecutor{}
|
|
|
|
type staticTokensExecutor struct{}
|
|
|
|
func (staticTokensExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]types.StaticTokens, error) {
|
|
token, err := cache.ClusterConfig.GetStaticTokens()
|
|
if err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
return []types.StaticTokens{token}, nil
|
|
}
|
|
|
|
func (staticTokensExecutor) upsert(ctx context.Context, cache *Cache, resource types.StaticTokens) error {
|
|
return cache.clusterConfigCache.SetStaticTokens(resource)
|
|
}
|
|
|
|
func (staticTokensExecutor) deleteAll(ctx context.Context, cache *Cache) error {
|
|
return cache.clusterConfigCache.DeleteStaticTokens()
|
|
}
|
|
|
|
func (staticTokensExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error {
|
|
return cache.clusterConfigCache.DeleteStaticTokens()
|
|
}
|
|
|
|
func (staticTokensExecutor) isSingleton() bool { return true }
|
|
|
|
var _ executor[types.StaticTokens] = staticTokensExecutor{}
|
|
|
|
type provisionTokenExecutor struct{}
|
|
|
|
func (provisionTokenExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]types.ProvisionToken, error) {
|
|
return cache.Provisioner.GetTokens(ctx)
|
|
}
|
|
|
|
func (provisionTokenExecutor) upsert(ctx context.Context, cache *Cache, resource types.ProvisionToken) error {
|
|
return cache.provisionerCache.UpsertToken(ctx, resource)
|
|
}
|
|
|
|
func (provisionTokenExecutor) deleteAll(ctx context.Context, cache *Cache) error {
|
|
return cache.provisionerCache.DeleteAllTokens()
|
|
}
|
|
|
|
func (provisionTokenExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error {
|
|
return cache.provisionerCache.DeleteToken(ctx, resource.GetName())
|
|
}
|
|
|
|
func (provisionTokenExecutor) isSingleton() bool { return false }
|
|
|
|
var _ executor[types.ProvisionToken] = provisionTokenExecutor{}
|
|
|
|
type clusterNameExecutor struct{}
|
|
|
|
func (clusterNameExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]types.ClusterName, error) {
|
|
name, err := cache.ClusterConfig.GetClusterName()
|
|
return []types.ClusterName{name}, trace.Wrap(err)
|
|
}
|
|
|
|
func (clusterNameExecutor) upsert(ctx context.Context, cache *Cache, resource types.ClusterName) error {
|
|
return cache.clusterConfigCache.UpsertClusterName(resource)
|
|
}
|
|
|
|
func (clusterNameExecutor) deleteAll(ctx context.Context, cache *Cache) error {
|
|
return cache.clusterConfigCache.DeleteClusterName()
|
|
}
|
|
|
|
func (clusterNameExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error {
|
|
return cache.clusterConfigCache.DeleteClusterName()
|
|
}
|
|
|
|
func (clusterNameExecutor) isSingleton() bool { return true }
|
|
|
|
var _ executor[types.ClusterName] = clusterNameExecutor{}
|
|
|
|
type userExecutor struct{}
|
|
|
|
func (userExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]types.User, error) {
|
|
return cache.Users.GetUsers(loadSecrets)
|
|
}
|
|
|
|
func (userExecutor) upsert(ctx context.Context, cache *Cache, resource types.User) error {
|
|
return cache.usersCache.UpsertUser(resource)
|
|
}
|
|
|
|
func (userExecutor) deleteAll(ctx context.Context, cache *Cache) error {
|
|
return cache.usersCache.DeleteAllUsers()
|
|
}
|
|
|
|
func (userExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error {
|
|
return cache.usersCache.DeleteUser(ctx, resource.GetName())
|
|
}
|
|
|
|
func (userExecutor) isSingleton() bool { return false }
|
|
|
|
var _ executor[types.User] = userExecutor{}
|
|
|
|
type roleExecutor struct{}
|
|
|
|
func (roleExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]types.Role, error) {
|
|
return cache.Access.GetRoles(ctx)
|
|
}
|
|
|
|
func (roleExecutor) upsert(ctx context.Context, cache *Cache, resource types.Role) error {
|
|
return cache.accessCache.UpsertRole(ctx, resource)
|
|
}
|
|
|
|
func (roleExecutor) deleteAll(ctx context.Context, cache *Cache) error {
|
|
return cache.accessCache.DeleteAllRoles()
|
|
}
|
|
|
|
func (roleExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error {
|
|
return cache.accessCache.DeleteRole(ctx, resource.GetName())
|
|
}
|
|
|
|
func (roleExecutor) isSingleton() bool { return false }
|
|
|
|
var _ executor[types.Role] = roleExecutor{}
|
|
|
|
type databaseServerExecutor struct{}
|
|
|
|
func (databaseServerExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]types.DatabaseServer, error) {
|
|
return cache.Presence.GetDatabaseServers(ctx, apidefaults.Namespace)
|
|
}
|
|
|
|
func (databaseServerExecutor) upsert(ctx context.Context, cache *Cache, resource types.DatabaseServer) error {
|
|
_, err := cache.presenceCache.UpsertDatabaseServer(ctx, resource)
|
|
return trace.Wrap(err)
|
|
}
|
|
|
|
func (databaseServerExecutor) deleteAll(ctx context.Context, cache *Cache) error {
|
|
return cache.presenceCache.DeleteAllDatabaseServers(ctx, apidefaults.Namespace)
|
|
}
|
|
|
|
func (databaseServerExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error {
|
|
return cache.presenceCache.DeleteDatabaseServer(ctx,
|
|
resource.GetMetadata().Namespace,
|
|
resource.GetMetadata().Description, // Cache passes host ID via description field.
|
|
resource.GetName())
|
|
}
|
|
|
|
func (databaseServerExecutor) isSingleton() bool { return false }
|
|
|
|
var _ executor[types.DatabaseServer] = databaseServerExecutor{}
|
|
|
|
type databaseServiceExecutor struct{}
|
|
|
|
func (databaseServiceExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]types.DatabaseService, error) {
|
|
resources, err := client.GetResourcesWithFilters(ctx, cache.Presence, proto.ListResourcesRequest{ResourceType: types.KindDatabaseService})
|
|
if err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
|
|
dbsvcs := make([]types.DatabaseService, len(resources))
|
|
for i, resource := range resources {
|
|
dbsvc, ok := resource.(types.DatabaseService)
|
|
if !ok {
|
|
return nil, trace.BadParameter("unexpected resource %T", resource)
|
|
}
|
|
dbsvcs[i] = dbsvc
|
|
}
|
|
|
|
return dbsvcs, nil
|
|
}
|
|
|
|
func (databaseServiceExecutor) upsert(ctx context.Context, cache *Cache, resource types.DatabaseService) error {
|
|
_, err := cache.databaseServicesCache.UpsertDatabaseService(ctx, resource)
|
|
return trace.Wrap(err)
|
|
}
|
|
|
|
func (databaseServiceExecutor) deleteAll(ctx context.Context, cache *Cache) error {
|
|
return cache.databaseServicesCache.DeleteAllDatabaseServices(ctx)
|
|
}
|
|
|
|
func (databaseServiceExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error {
|
|
return cache.databaseServicesCache.DeleteDatabaseService(ctx, resource.GetName())
|
|
}
|
|
|
|
func (databaseServiceExecutor) isSingleton() bool { return false }
|
|
|
|
var _ executor[types.DatabaseService] = databaseServiceExecutor{}
|
|
|
|
type databaseExecutor struct{}
|
|
|
|
func (databaseExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]types.Database, error) {
|
|
return cache.Databases.GetDatabases(ctx)
|
|
}
|
|
|
|
func (databaseExecutor) upsert(ctx context.Context, cache *Cache, resource types.Database) error {
|
|
if err := cache.databasesCache.CreateDatabase(ctx, resource); err != nil {
|
|
if !trace.IsAlreadyExists(err) {
|
|
return trace.Wrap(err)
|
|
}
|
|
return trace.Wrap(cache.databasesCache.UpdateDatabase(ctx, resource))
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (databaseExecutor) deleteAll(ctx context.Context, cache *Cache) error {
|
|
return cache.databasesCache.DeleteAllDatabases(ctx)
|
|
}
|
|
|
|
func (databaseExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error {
|
|
return cache.databasesCache.DeleteDatabase(ctx, resource.GetName())
|
|
}
|
|
|
|
func (databaseExecutor) isSingleton() bool { return false }
|
|
|
|
var _ executor[types.Database] = databaseExecutor{}
|
|
|
|
type appExecutor struct{}
|
|
|
|
func (appExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]types.Application, error) {
|
|
return cache.Apps.GetApps(ctx)
|
|
}
|
|
|
|
func (appExecutor) upsert(ctx context.Context, cache *Cache, resource types.Application) error {
|
|
if err := cache.appsCache.CreateApp(ctx, resource); err != nil {
|
|
if !trace.IsAlreadyExists(err) {
|
|
return trace.Wrap(err)
|
|
}
|
|
return trace.Wrap(cache.appsCache.UpdateApp(ctx, resource))
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (appExecutor) deleteAll(ctx context.Context, cache *Cache) error {
|
|
return cache.appsCache.DeleteAllApps(ctx)
|
|
}
|
|
|
|
func (appExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error {
|
|
return cache.appsCache.DeleteApp(ctx, resource.GetName())
|
|
}
|
|
|
|
func (appExecutor) isSingleton() bool { return false }
|
|
|
|
var _ executor[types.Application] = appExecutor{}
|
|
|
|
type appServerExecutor struct{}
|
|
|
|
func (appServerExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]types.AppServer, error) {
|
|
return cache.Presence.GetApplicationServers(ctx, apidefaults.Namespace)
|
|
}
|
|
|
|
func (appServerExecutor) upsert(ctx context.Context, cache *Cache, resource types.AppServer) error {
|
|
_, err := cache.presenceCache.UpsertApplicationServer(ctx, resource)
|
|
return trace.Wrap(err)
|
|
}
|
|
|
|
func (appServerExecutor) deleteAll(ctx context.Context, cache *Cache) error {
|
|
return cache.presenceCache.DeleteAllApplicationServers(ctx, apidefaults.Namespace)
|
|
}
|
|
|
|
func (appServerExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error {
|
|
return cache.presenceCache.DeleteApplicationServer(ctx,
|
|
resource.GetMetadata().Namespace,
|
|
resource.GetMetadata().Description, // Cache passes host ID via description field.
|
|
resource.GetName())
|
|
}
|
|
|
|
func (appServerExecutor) isSingleton() bool { return false }
|
|
|
|
var _ executor[types.AppServer] = appServerExecutor{}
|
|
|
|
type appSessionExecutor struct{}
|
|
|
|
func (appSessionExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]types.WebSession, error) {
|
|
var (
|
|
startKey string
|
|
sessions []types.WebSession
|
|
)
|
|
for {
|
|
webSessions, nextKey, err := cache.AppSession.ListAppSessions(ctx, 0, startKey, "")
|
|
if err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
|
|
sessions = append(sessions, webSessions...)
|
|
|
|
if nextKey == "" {
|
|
break
|
|
}
|
|
startKey = nextKey
|
|
}
|
|
return sessions, nil
|
|
}
|
|
|
|
func (appSessionExecutor) upsert(ctx context.Context, cache *Cache, resource types.WebSession) error {
|
|
return cache.appSessionCache.UpsertAppSession(ctx, resource)
|
|
}
|
|
|
|
func (appSessionExecutor) deleteAll(ctx context.Context, cache *Cache) error {
|
|
return cache.appSessionCache.DeleteAllAppSessions(ctx)
|
|
}
|
|
|
|
func (appSessionExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error {
|
|
return cache.appSessionCache.DeleteAppSession(ctx, types.DeleteAppSessionRequest{
|
|
SessionID: resource.GetName(),
|
|
})
|
|
}
|
|
|
|
func (appSessionExecutor) isSingleton() bool { return false }
|
|
|
|
var _ executor[types.WebSession] = appSessionExecutor{}
|
|
|
|
type snowflakeSessionExecutor struct{}
|
|
|
|
func (snowflakeSessionExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]types.WebSession, error) {
|
|
return cache.SnowflakeSession.GetSnowflakeSessions(ctx)
|
|
}
|
|
|
|
func (snowflakeSessionExecutor) upsert(ctx context.Context, cache *Cache, resource types.WebSession) error {
|
|
return cache.snowflakeSessionCache.UpsertSnowflakeSession(ctx, resource)
|
|
}
|
|
|
|
func (snowflakeSessionExecutor) deleteAll(ctx context.Context, cache *Cache) error {
|
|
return cache.snowflakeSessionCache.DeleteAllSnowflakeSessions(ctx)
|
|
}
|
|
|
|
func (snowflakeSessionExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error {
|
|
return cache.snowflakeSessionCache.DeleteSnowflakeSession(ctx, types.DeleteSnowflakeSessionRequest{
|
|
SessionID: resource.GetName(),
|
|
})
|
|
}
|
|
|
|
func (snowflakeSessionExecutor) isSingleton() bool { return false }
|
|
|
|
var _ executor[types.WebSession] = snowflakeSessionExecutor{}
|
|
|
|
//nolint:revive // Because we want this to be IdP.
|
|
type samlIdPSessionExecutor struct{}
|
|
|
|
func (samlIdPSessionExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]types.WebSession, error) {
|
|
var (
|
|
startKey string
|
|
sessions []types.WebSession
|
|
)
|
|
for {
|
|
webSessions, nextKey, err := cache.SAMLIdPSession.ListSAMLIdPSessions(ctx, 0, startKey, "")
|
|
if err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
|
|
sessions = append(sessions, webSessions...)
|
|
|
|
if nextKey == "" {
|
|
break
|
|
}
|
|
startKey = nextKey
|
|
}
|
|
return sessions, nil
|
|
}
|
|
|
|
func (samlIdPSessionExecutor) upsert(ctx context.Context, cache *Cache, resource types.WebSession) error {
|
|
return cache.samlIdPSessionCache.UpsertSAMLIdPSession(ctx, resource)
|
|
}
|
|
|
|
func (samlIdPSessionExecutor) deleteAll(ctx context.Context, cache *Cache) error {
|
|
return cache.samlIdPSessionCache.DeleteAllSAMLIdPSessions(ctx)
|
|
}
|
|
|
|
func (samlIdPSessionExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error {
|
|
return cache.samlIdPSessionCache.DeleteSAMLIdPSession(ctx, types.DeleteSAMLIdPSessionRequest{
|
|
SessionID: resource.GetName(),
|
|
})
|
|
}
|
|
|
|
func (samlIdPSessionExecutor) isSingleton() bool { return false }
|
|
|
|
var _ executor[types.WebSession] = samlIdPSessionExecutor{}
|
|
|
|
type webSessionExecutor struct{}
|
|
|
|
func (webSessionExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]types.WebSession, error) {
|
|
return cache.WebSession.List(ctx)
|
|
}
|
|
|
|
func (webSessionExecutor) upsert(ctx context.Context, cache *Cache, resource types.WebSession) error {
|
|
return cache.webSessionCache.Upsert(ctx, resource)
|
|
}
|
|
|
|
func (webSessionExecutor) deleteAll(ctx context.Context, cache *Cache) error {
|
|
return cache.webSessionCache.DeleteAll(ctx)
|
|
}
|
|
|
|
func (webSessionExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error {
|
|
return cache.webSessionCache.Delete(ctx, types.DeleteWebSessionRequest{
|
|
SessionID: resource.GetName(),
|
|
})
|
|
}
|
|
|
|
func (webSessionExecutor) isSingleton() bool { return false }
|
|
|
|
var _ executor[types.WebSession] = webSessionExecutor{}
|
|
|
|
type webTokenExecutor struct{}
|
|
|
|
func (webTokenExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]types.WebToken, error) {
|
|
return cache.WebToken.List(ctx)
|
|
}
|
|
|
|
func (webTokenExecutor) upsert(ctx context.Context, cache *Cache, resource types.WebToken) error {
|
|
return cache.webTokenCache.Upsert(ctx, resource)
|
|
}
|
|
|
|
func (webTokenExecutor) deleteAll(ctx context.Context, cache *Cache) error {
|
|
return cache.webTokenCache.DeleteAll(ctx)
|
|
}
|
|
|
|
func (webTokenExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error {
|
|
return cache.webTokenCache.Delete(ctx, types.DeleteWebTokenRequest{
|
|
Token: resource.GetName(),
|
|
})
|
|
}
|
|
|
|
func (webTokenExecutor) isSingleton() bool { return false }
|
|
|
|
var _ executor[types.WebToken] = webTokenExecutor{}
|
|
|
|
type kubeServerExecutor struct{}
|
|
|
|
func (kubeServerExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]types.KubeServer, error) {
|
|
return cache.Presence.GetKubernetesServers(ctx)
|
|
}
|
|
|
|
func (kubeServerExecutor) upsert(ctx context.Context, cache *Cache, resource types.KubeServer) error {
|
|
_, err := cache.presenceCache.UpsertKubernetesServer(ctx, resource)
|
|
return trace.Wrap(err)
|
|
}
|
|
|
|
func (kubeServerExecutor) deleteAll(ctx context.Context, cache *Cache) error {
|
|
return cache.presenceCache.DeleteAllKubernetesServers(ctx)
|
|
}
|
|
|
|
func (kubeServerExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error {
|
|
return cache.presenceCache.DeleteKubernetesServer(
|
|
ctx,
|
|
resource.GetMetadata().Description, // Cache passes host ID via description field.
|
|
resource.GetName(),
|
|
)
|
|
}
|
|
|
|
func (kubeServerExecutor) isSingleton() bool { return false }
|
|
|
|
var _ executor[types.KubeServer] = kubeServerExecutor{}
|
|
|
|
type authPreferenceExecutor struct{}
|
|
|
|
func (authPreferenceExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]types.AuthPreference, error) {
|
|
authPref, err := cache.ClusterConfig.GetAuthPreference(ctx)
|
|
if err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
return []types.AuthPreference{authPref}, nil
|
|
}
|
|
|
|
func (authPreferenceExecutor) upsert(ctx context.Context, cache *Cache, resource types.AuthPreference) error {
|
|
return cache.clusterConfigCache.SetAuthPreference(ctx, resource)
|
|
}
|
|
|
|
func (authPreferenceExecutor) deleteAll(ctx context.Context, cache *Cache) error {
|
|
return cache.clusterConfigCache.DeleteAuthPreference(ctx)
|
|
}
|
|
|
|
func (authPreferenceExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error {
|
|
return cache.clusterConfigCache.DeleteAuthPreference(ctx)
|
|
}
|
|
|
|
func (authPreferenceExecutor) isSingleton() bool { return true }
|
|
|
|
var _ executor[types.AuthPreference] = authPreferenceExecutor{}
|
|
|
|
type clusterAuditConfigExecutor struct{}
|
|
|
|
func (clusterAuditConfigExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]types.ClusterAuditConfig, error) {
|
|
auditConfig, err := cache.ClusterConfig.GetClusterAuditConfig(ctx)
|
|
if err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
return []types.ClusterAuditConfig{auditConfig}, nil
|
|
}
|
|
|
|
func (clusterAuditConfigExecutor) upsert(ctx context.Context, cache *Cache, resource types.ClusterAuditConfig) error {
|
|
return cache.clusterConfigCache.SetClusterAuditConfig(ctx, resource)
|
|
}
|
|
|
|
func (clusterAuditConfigExecutor) deleteAll(ctx context.Context, cache *Cache) error {
|
|
return cache.clusterConfigCache.DeleteClusterAuditConfig(ctx)
|
|
}
|
|
|
|
func (clusterAuditConfigExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error {
|
|
return cache.clusterConfigCache.DeleteClusterAuditConfig(ctx)
|
|
}
|
|
|
|
func (clusterAuditConfigExecutor) isSingleton() bool { return true }
|
|
|
|
var _ executor[types.ClusterAuditConfig] = clusterAuditConfigExecutor{}
|
|
|
|
type clusterNetworkingConfigExecutor struct{}
|
|
|
|
func (clusterNetworkingConfigExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]types.ClusterNetworkingConfig, error) {
|
|
networkingConfig, err := cache.ClusterConfig.GetClusterNetworkingConfig(ctx)
|
|
if err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
return []types.ClusterNetworkingConfig{networkingConfig}, nil
|
|
}
|
|
|
|
func (clusterNetworkingConfigExecutor) upsert(ctx context.Context, cache *Cache, resource types.ClusterNetworkingConfig) error {
|
|
return cache.clusterConfigCache.SetClusterNetworkingConfig(ctx, resource)
|
|
}
|
|
|
|
func (clusterNetworkingConfigExecutor) deleteAll(ctx context.Context, cache *Cache) error {
|
|
return cache.clusterConfigCache.DeleteClusterNetworkingConfig(ctx)
|
|
}
|
|
|
|
func (clusterNetworkingConfigExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error {
|
|
return cache.clusterConfigCache.DeleteClusterNetworkingConfig(ctx)
|
|
}
|
|
|
|
func (clusterNetworkingConfigExecutor) isSingleton() bool { return true }
|
|
|
|
var _ executor[types.ClusterNetworkingConfig] = clusterNetworkingConfigExecutor{}
|
|
|
|
type uiConfigExecutor struct{}
|
|
|
|
func (uiConfigExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]types.UIConfig, error) {
|
|
uiConfig, err := cache.ClusterConfig.GetUIConfig(ctx)
|
|
if err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
return []types.UIConfig{uiConfig}, nil
|
|
}
|
|
|
|
func (uiConfigExecutor) upsert(ctx context.Context, cache *Cache, resource types.UIConfig) error {
|
|
return cache.clusterConfigCache.SetUIConfig(ctx, resource)
|
|
}
|
|
|
|
func (uiConfigExecutor) deleteAll(ctx context.Context, cache *Cache) error {
|
|
return cache.clusterConfigCache.DeleteUIConfig(ctx)
|
|
}
|
|
|
|
func (uiConfigExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error {
|
|
return cache.clusterConfigCache.DeleteUIConfig(ctx)
|
|
}
|
|
|
|
func (uiConfigExecutor) isSingleton() bool { return true }
|
|
|
|
var _ executor[types.UIConfig] = uiConfigExecutor{}
|
|
|
|
type sessionRecordingConfigExecutor struct{}
|
|
|
|
func (sessionRecordingConfigExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]types.SessionRecordingConfig, error) {
|
|
sessionRecordingConfig, err := cache.ClusterConfig.GetSessionRecordingConfig(ctx)
|
|
if err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
return []types.SessionRecordingConfig{sessionRecordingConfig}, nil
|
|
}
|
|
|
|
func (sessionRecordingConfigExecutor) upsert(ctx context.Context, cache *Cache, resource types.SessionRecordingConfig) error {
|
|
return cache.clusterConfigCache.SetSessionRecordingConfig(ctx, resource)
|
|
}
|
|
|
|
func (sessionRecordingConfigExecutor) deleteAll(ctx context.Context, cache *Cache) error {
|
|
return cache.clusterConfigCache.DeleteSessionRecordingConfig(ctx)
|
|
}
|
|
|
|
func (sessionRecordingConfigExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error {
|
|
return cache.clusterConfigCache.DeleteSessionRecordingConfig(ctx)
|
|
}
|
|
|
|
func (sessionRecordingConfigExecutor) isSingleton() bool { return true }
|
|
|
|
var _ executor[types.SessionRecordingConfig] = sessionRecordingConfigExecutor{}
|
|
|
|
type installerConfigExecutor struct{}
|
|
|
|
func (installerConfigExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]types.Installer, error) {
|
|
return cache.ClusterConfig.GetInstallers(ctx)
|
|
}
|
|
|
|
func (installerConfigExecutor) upsert(ctx context.Context, cache *Cache, resource types.Installer) error {
|
|
return cache.clusterConfigCache.SetInstaller(ctx, resource)
|
|
}
|
|
|
|
func (installerConfigExecutor) deleteAll(ctx context.Context, cache *Cache) error {
|
|
return cache.clusterConfigCache.DeleteAllInstallers(ctx)
|
|
}
|
|
|
|
func (installerConfigExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error {
|
|
return cache.clusterConfigCache.DeleteInstaller(ctx, resource.GetName())
|
|
}
|
|
|
|
func (installerConfigExecutor) isSingleton() bool { return false }
|
|
|
|
var _ executor[types.Installer] = installerConfigExecutor{}
|
|
|
|
type networkRestrictionsExecutor struct{}
|
|
|
|
func (networkRestrictionsExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]types.NetworkRestrictions, error) {
|
|
restrictions, err := cache.Restrictions.GetNetworkRestrictions(ctx)
|
|
if err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
return []types.NetworkRestrictions{restrictions}, nil
|
|
}
|
|
|
|
func (networkRestrictionsExecutor) upsert(ctx context.Context, cache *Cache, resource types.NetworkRestrictions) error {
|
|
return cache.restrictionsCache.SetNetworkRestrictions(ctx, resource)
|
|
}
|
|
|
|
func (networkRestrictionsExecutor) deleteAll(ctx context.Context, cache *Cache) error {
|
|
return cache.restrictionsCache.DeleteNetworkRestrictions(ctx)
|
|
}
|
|
|
|
func (networkRestrictionsExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error {
|
|
return cache.restrictionsCache.DeleteNetworkRestrictions(ctx)
|
|
}
|
|
|
|
func (networkRestrictionsExecutor) isSingleton() bool { return true }
|
|
|
|
var _ executor[types.NetworkRestrictions] = networkRestrictionsExecutor{}
|
|
|
|
type lockExecutor struct{}
|
|
|
|
func (lockExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]types.Lock, error) {
|
|
return cache.Access.GetLocks(ctx, false)
|
|
}
|
|
|
|
func (lockExecutor) upsert(ctx context.Context, cache *Cache, resource types.Lock) error {
|
|
return cache.accessCache.UpsertLock(ctx, resource)
|
|
}
|
|
|
|
func (lockExecutor) deleteAll(ctx context.Context, cache *Cache) error {
|
|
return cache.accessCache.DeleteAllLocks(ctx)
|
|
}
|
|
|
|
func (lockExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error {
|
|
return cache.accessCache.DeleteLock(ctx, resource.GetName())
|
|
}
|
|
|
|
func (lockExecutor) isSingleton() bool { return false }
|
|
|
|
var _ executor[types.Lock] = lockExecutor{}
|
|
|
|
type windowsDesktopServicesExecutor struct{}
|
|
|
|
func (windowsDesktopServicesExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]types.WindowsDesktopService, error) {
|
|
return cache.Presence.GetWindowsDesktopServices(ctx)
|
|
}
|
|
|
|
func (windowsDesktopServicesExecutor) upsert(ctx context.Context, cache *Cache, resource types.WindowsDesktopService) error {
|
|
_, err := cache.presenceCache.UpsertWindowsDesktopService(ctx, resource)
|
|
return trace.Wrap(err)
|
|
}
|
|
|
|
func (windowsDesktopServicesExecutor) deleteAll(ctx context.Context, cache *Cache) error {
|
|
return cache.presenceCache.DeleteAllWindowsDesktopServices(ctx)
|
|
}
|
|
|
|
func (windowsDesktopServicesExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error {
|
|
return cache.presenceCache.DeleteWindowsDesktopService(ctx, resource.GetName())
|
|
}
|
|
|
|
func (windowsDesktopServicesExecutor) isSingleton() bool { return false }
|
|
|
|
var _ executor[types.WindowsDesktopService] = windowsDesktopServicesExecutor{}
|
|
|
|
type windowsDesktopsExecutor struct{}
|
|
|
|
func (windowsDesktopsExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]types.WindowsDesktop, error) {
|
|
return cache.WindowsDesktops.GetWindowsDesktops(ctx, types.WindowsDesktopFilter{})
|
|
}
|
|
|
|
func (windowsDesktopsExecutor) upsert(ctx context.Context, cache *Cache, resource types.WindowsDesktop) error {
|
|
return cache.windowsDesktopsCache.UpsertWindowsDesktop(ctx, resource)
|
|
}
|
|
|
|
func (windowsDesktopsExecutor) deleteAll(ctx context.Context, cache *Cache) error {
|
|
return cache.windowsDesktopsCache.DeleteAllWindowsDesktops(ctx)
|
|
}
|
|
|
|
func (windowsDesktopsExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error {
|
|
return cache.windowsDesktopsCache.DeleteWindowsDesktop(ctx,
|
|
resource.GetMetadata().Description, // Cache passes host ID via description field.
|
|
resource.GetName(),
|
|
)
|
|
}
|
|
|
|
func (windowsDesktopsExecutor) isSingleton() bool { return false }
|
|
|
|
var _ executor[types.WindowsDesktop] = windowsDesktopsExecutor{}
|
|
|
|
type kubeClusterExecutor struct{}
|
|
|
|
func (kubeClusterExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]types.KubeCluster, error) {
|
|
return cache.Kubernetes.GetKubernetesClusters(ctx)
|
|
}
|
|
|
|
func (kubeClusterExecutor) upsert(ctx context.Context, cache *Cache, resource types.KubeCluster) error {
|
|
if err := cache.kubernetesCache.CreateKubernetesCluster(ctx, resource); err != nil {
|
|
if !trace.IsAlreadyExists(err) {
|
|
return trace.Wrap(err)
|
|
}
|
|
return trace.Wrap(cache.kubernetesCache.UpdateKubernetesCluster(ctx, resource))
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (kubeClusterExecutor) deleteAll(ctx context.Context, cache *Cache) error {
|
|
return cache.kubernetesCache.DeleteAllKubernetesClusters(ctx)
|
|
}
|
|
|
|
func (kubeClusterExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error {
|
|
return cache.kubernetesCache.DeleteKubernetesCluster(ctx, resource.GetName())
|
|
}
|
|
|
|
func (kubeClusterExecutor) isSingleton() bool { return false }
|
|
|
|
var _ executor[types.KubeCluster] = kubeClusterExecutor{}
|
|
|
|
//nolint:revive // Because we want this to be IdP.
|
|
type samlIdPServiceProvidersExecutor struct{}
|
|
|
|
func (samlIdPServiceProvidersExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]types.SAMLIdPServiceProvider, error) {
|
|
var (
|
|
startKey string
|
|
sps []types.SAMLIdPServiceProvider
|
|
)
|
|
for {
|
|
var samlProviders []types.SAMLIdPServiceProvider
|
|
var err error
|
|
samlProviders, startKey, err = cache.SAMLIdPServiceProviders.ListSAMLIdPServiceProviders(ctx, 0, startKey)
|
|
if err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
|
|
sps = append(sps, samlProviders...)
|
|
|
|
if startKey == "" {
|
|
break
|
|
}
|
|
}
|
|
|
|
return sps, nil
|
|
}
|
|
|
|
func (samlIdPServiceProvidersExecutor) upsert(ctx context.Context, cache *Cache, resource types.SAMLIdPServiceProvider) error {
|
|
err := cache.samlIdPServiceProvidersCache.CreateSAMLIdPServiceProvider(ctx, resource)
|
|
if trace.IsAlreadyExists(err) {
|
|
err = cache.samlIdPServiceProvidersCache.UpdateSAMLIdPServiceProvider(ctx, resource)
|
|
}
|
|
return trace.Wrap(err)
|
|
}
|
|
|
|
func (samlIdPServiceProvidersExecutor) deleteAll(ctx context.Context, cache *Cache) error {
|
|
return cache.samlIdPServiceProvidersCache.DeleteAllSAMLIdPServiceProviders(ctx)
|
|
}
|
|
|
|
func (samlIdPServiceProvidersExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error {
|
|
return cache.samlIdPServiceProvidersCache.DeleteSAMLIdPServiceProvider(ctx, resource.GetName())
|
|
}
|
|
|
|
func (samlIdPServiceProvidersExecutor) isSingleton() bool { return false }
|
|
|
|
var _ executor[types.SAMLIdPServiceProvider] = samlIdPServiceProvidersExecutor{}
|
|
|
|
type userGroupsExecutor struct{}
|
|
|
|
func (userGroupsExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]types.UserGroup, error) {
|
|
var (
|
|
startKey string
|
|
resources []types.UserGroup
|
|
)
|
|
for {
|
|
var userGroups []types.UserGroup
|
|
var err error
|
|
userGroups, startKey, err = cache.UserGroups.ListUserGroups(ctx, 0, startKey)
|
|
if err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
|
|
resources = append(resources, userGroups...)
|
|
|
|
if startKey == "" {
|
|
break
|
|
}
|
|
}
|
|
|
|
return resources, nil
|
|
}
|
|
|
|
func (userGroupsExecutor) upsert(ctx context.Context, cache *Cache, resource types.UserGroup) error {
|
|
err := cache.userGroupsCache.CreateUserGroup(ctx, resource)
|
|
if trace.IsAlreadyExists(err) {
|
|
err = cache.userGroupsCache.UpdateUserGroup(ctx, resource)
|
|
}
|
|
return trace.Wrap(err)
|
|
}
|
|
|
|
func (userGroupsExecutor) deleteAll(ctx context.Context, cache *Cache) error {
|
|
return cache.userGroupsCache.DeleteAllUserGroups(ctx)
|
|
}
|
|
|
|
func (userGroupsExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error {
|
|
return cache.userGroupsCache.DeleteUserGroup(ctx, resource.GetName())
|
|
}
|
|
|
|
func (userGroupsExecutor) isSingleton() bool { return false }
|
|
|
|
var _ executor[types.UserGroup] = userGroupsExecutor{}
|