Files
teleport/lib/cache/collections.go
T
rosstimothy b0dc78610e Migrate upserting CAs to gRPC (#23140)
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
2023-03-16 14:46:43 +00:00

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{}