Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions api/types/installer.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import (
"time"

"github.com/gravitational/trace"

"github.com/gravitational/teleport/api/utils"
)

// Installer is an installer script resource
Expand All @@ -32,6 +34,9 @@ type Installer interface {
SetScript(string)

String() string

// Clone returns a copy of the installer.
Clone() Installer
}

// NewInstallerV1 returns a new installer resource
Expand Down Expand Up @@ -61,6 +66,11 @@ func MustNewInstallerV1(name, script string) *InstallerV1 {
return inst
}

// Clone returns a copy of the installer.
func (c *InstallerV1) Clone() Installer {
return utils.CloneProtoMsg(c)
}

// CheckAndSetDefaults implements Installer
func (c *InstallerV1) CheckAndSetDefaults() error {
c.setStaticFields()
Expand Down
8 changes: 8 additions & 0 deletions api/types/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -522,10 +522,18 @@ type WebToken interface {
SetUser(user string)
// String returns the text representation of this token
String() string
// Clone returns a copy of the token.
Clone() WebToken
}

var _ WebToken = &WebTokenV3{}

// Clone returns a copy of the token.
// GetMetadata returns the token metadata
Comment thread
rosstimothy marked this conversation as resolved.
func (r *WebTokenV3) Clone() WebToken {
return utils.CloneProtoMsg(r)
}

// GetMetadata returns the token metadata
func (r *WebTokenV3) GetMetadata() Metadata {
return r.Metadata
Expand Down
8 changes: 8 additions & 0 deletions api/types/ui_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"github.com/gravitational/trace"

"github.com/gravitational/teleport/api/constants"
"github.com/gravitational/teleport/api/utils"
)

// UIConfig defines configuration for the web UI served
Expand All @@ -37,6 +38,8 @@ type UIConfig interface {
SetScrollbackLines(int32)

String() string
// Clone returns a copy of the config.
Clone() UIConfig
}

func NewUIConfigV1() (*UIConfigV1, error) {
Expand Down Expand Up @@ -70,6 +73,11 @@ func (c *UIConfigV1) CheckAndSetDefaults() error {
return nil
}

// Clone returns a copy of the config.
func (c *UIConfigV1) Clone() UIConfig {
return utils.CloneProtoMsg(c)
}

// GetVersion returns resource version.
func (c *UIConfigV1) GetVersion() string {
return c.Version
Expand Down
59 changes: 0 additions & 59 deletions lib/cache/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,6 @@ type Cache struct {
presenceCache services.Presence
restrictionsCache services.Restrictions
databaseObjectsCache *local.DatabaseObjectService
webTokenCache types.WebTokenInterface
dynamicWindowsDesktopsCache services.DynamicWindowsDesktops
userGroupsCache services.UserGroups
userTasksCache services.UserTasks
Expand Down Expand Up @@ -1017,7 +1016,6 @@ func New(config Config) (*Cache, error) {
dynamicAccessCache: local.NewDynamicAccessService(config.Backend),
presenceCache: local.NewPresenceService(config.Backend),
restrictionsCache: local.NewRestrictionsService(config.Backend),
webTokenCache: identityService.WebTokens(),
dynamicWindowsDesktopsCache: dynamicDesktopsService,
userGroupsCache: userGroupsCache,
userTasksCache: userTasksCache,
Expand Down Expand Up @@ -1786,50 +1784,6 @@ func (c *Cache) processEvent(ctx context.Context, event types.Event) error {
return nil
}

func (c *Cache) GetUIConfig(ctx context.Context) (types.UIConfig, error) {
ctx, span := c.Tracer.Start(ctx, "cache/GetUIConfig")
defer span.End()

rg, err := readLegacyCollectionCache(c, c.legacyCacheCollections.uiConfigs)
if err != nil {
return nil, trace.Wrap(err)
}
defer rg.Release()

uiconfig, err := rg.reader.GetUIConfig(ctx)
return uiconfig, trace.Wrap(err)
}

// GetInstaller gets the installer script resource for the cluster
func (c *Cache) GetInstaller(ctx context.Context, name string) (types.Installer, error) {
ctx, span := c.Tracer.Start(ctx, "cache/GetInstaller")
defer span.End()

rg, err := readLegacyCollectionCache(c, c.legacyCacheCollections.installers)
if err != nil {
return nil, trace.Wrap(err)
}
defer rg.Release()

inst, err := rg.reader.GetInstaller(ctx, name)
return inst, trace.Wrap(err)
}

// GetInstallers gets all the installer script resources for the cluster
func (c *Cache) GetInstallers(ctx context.Context) ([]types.Installer, error) {
ctx, span := c.Tracer.Start(ctx, "cache/GetInstallers")
defer span.End()

rg, err := readLegacyCollectionCache(c, c.legacyCacheCollections.installers)
if err != nil {
return nil, trace.Wrap(err)
}
defer rg.Release()

inst, err := rg.reader.GetInstallers(ctx)
return inst, trace.Wrap(err)
}

type remoteClustersCacheKey struct {
name string
}
Expand Down Expand Up @@ -2016,19 +1970,6 @@ func (c *Cache) ListDatabaseObjects(ctx context.Context, size int, pageToken str
return rg.reader.ListDatabaseObjects(ctx, size, pageToken)
}

// GetWebToken gets a web token.
func (c *Cache) GetWebToken(ctx context.Context, req types.GetWebTokenRequest) (types.WebToken, error) {
ctx, span := c.Tracer.Start(ctx, "cache/GetWebToken")
defer span.End()

rg, err := readLegacyCollectionCache(c, c.legacyCacheCollections.webTokens)
if err != nil {
return nil, trace.Wrap(err)
}
defer rg.Release()
return rg.reader.Get(ctx, req)
}

// GetNetworkRestrictions gets the network restrictions.
func (c *Cache) GetNetworkRestrictions(ctx context.Context) (types.NetworkRestrictions, error) {
ctx, span := c.Tracer.Start(ctx, "cache/GetNetworkRestrictions")
Expand Down
1 change: 0 additions & 1 deletion lib/cache/cert_authority_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ func TestNodeCAFiltering(t *testing.T) {
DynamicAccess: p.cache.dynamicAccessCache,
Presence: p.cache.presenceCache,
Restrictions: p.cache.restrictionsCache,
WebToken: p.cache.webTokenCache,
DynamicWindowsDesktops: p.cache.dynamicWindowsDesktopsCache,
SAMLIdPServiceProviders: p.samlIDPServiceProviders,
UserGroups: p.userGroups,
Expand Down
27 changes: 27 additions & 0 deletions lib/cache/collections.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@ type collections struct {
integrations *collection[types.Integration, integrationIndex]
pluginStaticCredentials *collection[types.PluginStaticCredentials, pluginStaticCredentialsIndex]
accessMonitoringRules *collection[*accessmonitoringrulesv1.AccessMonitoringRule, accessMonitoringRuleIndex]
webTokens *collection[types.WebToken, webTokenIndex]
uiConfigs *collection[types.UIConfig, webUIConfigIndex]
installers *collection[types.Installer, installerIndex]
}

// setupCollections ensures that the appropriate [collection] is
Expand Down Expand Up @@ -516,6 +519,30 @@ func setupCollections(c Config) (*collections, error) {

out.accessMonitoringRules = collect
out.byKind[resourceKind] = out.accessMonitoringRules
case types.KindUIConfig:
collect, err := newWebUIConfigCollection(c.ClusterConfig, watch)
if err != nil {
return nil, trace.Wrap(err)
}

out.uiConfigs = collect
out.byKind[resourceKind] = out.uiConfigs
case types.KindWebToken:
collect, err := newWebTokenCollection(c.WebToken, watch)
if err != nil {
return nil, trace.Wrap(err)
}

out.webTokens = collect
out.byKind[resourceKind] = out.webTokens
case types.KindInstaller:
collect, err := newInstallerCollection(c.ClusterConfig, watch)
if err != nil {
return nil, trace.Wrap(err)
}

out.installers = collect
out.byKind[resourceKind] = out.installers
}
}

Expand Down
96 changes: 96 additions & 0 deletions lib/cache/installer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// Teleport
// Copyright (C) 2025 Gravitational, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

package cache

import (
"context"

"github.com/gravitational/trace"

"github.com/gravitational/teleport/api/types"
"github.com/gravitational/teleport/lib/services"
)

type installerIndex string

const installerNameIndex installerIndex = "name"

func newInstallerCollection(upstream services.ClusterConfiguration, w types.WatchKind) (*collection[types.Installer, installerIndex], error) {
if upstream == nil {
return nil, trace.BadParameter("missing parameter ClusterConfiguration")
}

return &collection[types.Installer, installerIndex]{
store: newStore(map[installerIndex]func(types.Installer) string{
installerNameIndex: types.Installer.GetName,
}),
fetcher: func(ctx context.Context, loadSecrets bool) ([]types.Installer, error) {
installers, err := upstream.GetInstallers(ctx)
return installers, trace.Wrap(err)
},
headerTransform: func(hdr *types.ResourceHeader) types.Installer {
return &types.InstallerV1{
Kind: hdr.Kind,
Version: hdr.Version,
Metadata: types.Metadata{
Name: hdr.Metadata.Name,
},
}
},
watch: w,
}, nil
}

// GetInstaller gets the installer script resource for the cluster
func (c *Cache) GetInstaller(ctx context.Context, name string) (types.Installer, error) {
ctx, span := c.Tracer.Start(ctx, "cache/GetInstaller")
defer span.End()

getter := genericGetter[types.Installer, installerIndex]{
cache: c,
collection: c.collections.installers,
index: installerNameIndex,
upstreamGet: c.Config.ClusterConfig.GetInstaller,
clone: types.Installer.Clone,
}
out, err := getter.get(ctx, name)
return out, trace.Wrap(err)
}

// GetInstallers gets all the installer script resources for the cluster
func (c *Cache) GetInstallers(ctx context.Context) ([]types.Installer, error) {
ctx, span := c.Tracer.Start(ctx, "cache/GetInstallers")
defer span.End()

rg, err := acquireReadGuard(c, c.collections.installers)
if err != nil {
return nil, trace.Wrap(err)
}
defer rg.Release()

if !rg.ReadCache() {
users, err := c.Config.ClusterConfig.GetInstallers(ctx)
return users, trace.Wrap(err)
}

installers := make([]types.Installer, 0, rg.store.len())
for i := range rg.store.resources(installerNameIndex, "", "") {
installers = append(installers, i.Clone())
}

return installers, nil
}
47 changes: 47 additions & 0 deletions lib/cache/installer_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Teleport
// Copyright (C) 2025 Gravitational, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

package cache

import (
"context"
"testing"

"github.com/gravitational/teleport/api/types"
)

func TestInstallers(t *testing.T) {
t.Parallel()

p := newTestPack(t, ForProxy)
t.Cleanup(p.Close)

testResources(t, p, testFuncs[types.Installer]{
newResource: func(name string) (types.Installer, error) {
return types.NewInstallerV1("test", "test.sh")
},
create: p.clusterConfigS.SetInstaller,
list: func(ctx context.Context) ([]types.Installer, error) {
return p.clusterConfigS.GetInstallers(ctx)
},
cacheList: func(ctx context.Context) ([]types.Installer, error) {
return p.cache.GetInstallers(ctx)
},
deleteAll: func(ctx context.Context) error {
return p.clusterConfigS.DeleteAllInstallers(ctx)
},
})
}
Loading
Loading