Skip to content

Commit 2ea940c

Browse files
committed
Convert network restrictions to new cache mechanism
Moves networking restrictins to the new cache collection scheme that was introduced in #52210. No additional functionality changes have been made here. This should be a purely mechanical translation to the new internal caching machinery.
1 parent 1bc5c32 commit 2ea940c

8 files changed

+149
-70
lines changed

api/types/restrictions.go

+9
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ import (
2020
"time"
2121

2222
"github.com/gravitational/trace"
23+
24+
"github.com/gravitational/teleport/api/utils"
2325
)
2426

2527
// NetworkRestrictions defines network restrictions applied to SSH session.
@@ -33,6 +35,8 @@ type NetworkRestrictions interface {
3335
GetDeny() []AddressCondition
3436
// SetDeny sets a list of denied network addresses (overrides Allow list)
3537
SetDeny(deny []AddressCondition)
38+
// Clone returns a copy of the network restrictions.
39+
Clone() NetworkRestrictions
3640
}
3741

3842
// NewNetworkRestrictions creates a new NetworkRestrictions with the given name.
@@ -46,6 +50,11 @@ func NewNetworkRestrictions() NetworkRestrictions {
4650
}
4751
}
4852

53+
// Clone returns a copy of the network restrictions.
54+
func (r *NetworkRestrictionsV4) Clone() NetworkRestrictions {
55+
return utils.CloneProtoMsg(r)
56+
}
57+
4958
func (r *NetworkRestrictionsV4) setStaticFields() {
5059
if r.Version == "" {
5160
r.Version = V4

lib/cache/cache.go

-16
Original file line numberDiff line numberDiff line change
@@ -509,7 +509,6 @@ type Cache struct {
509509
accessCache services.Access
510510
dynamicAccessCache services.DynamicAccessExt
511511
presenceCache services.Presence
512-
restrictionsCache services.Restrictions
513512
crownJewelsCache services.CrownJewels
514513
databaseObjectsCache *local.DatabaseObjectService
515514
webTokenCache types.WebTokenInterface
@@ -1042,7 +1041,6 @@ func New(config Config) (*Cache, error) {
10421041
accessCache: local.NewAccessService(config.Backend),
10431042
dynamicAccessCache: local.NewDynamicAccessService(config.Backend),
10441043
presenceCache: local.NewPresenceService(config.Backend),
1045-
restrictionsCache: local.NewRestrictionsService(config.Backend),
10461044
crownJewelsCache: crownJewelCache,
10471045
webTokenCache: identityService.WebTokens(),
10481046
dynamicWindowsDesktopsCache: dynamicDesktopsService,
@@ -1926,20 +1924,6 @@ func (c *Cache) GetWebToken(ctx context.Context, req types.GetWebTokenRequest) (
19261924
return rg.reader.Get(ctx, req)
19271925
}
19281926

1929-
// GetNetworkRestrictions gets the network restrictions.
1930-
func (c *Cache) GetNetworkRestrictions(ctx context.Context) (types.NetworkRestrictions, error) {
1931-
ctx, span := c.Tracer.Start(ctx, "cache/GetNetworkRestrictions")
1932-
defer span.End()
1933-
1934-
rg, err := readLegacyCollectionCache(c, c.legacyCacheCollections.networkRestrictions)
1935-
if err != nil {
1936-
return nil, trace.Wrap(err)
1937-
}
1938-
defer rg.Release()
1939-
1940-
return rg.reader.GetNetworkRestrictions(ctx)
1941-
}
1942-
19431927
// GetDynamicWindowsDesktop returns registered dynamic Windows desktop by name.
19441928
func (c *Cache) GetDynamicWindowsDesktop(ctx context.Context, name string) (types.DynamicWindowsDesktop, error) {
19451929
ctx, span := c.Tracer.Start(ctx, "cache/GetDynamicWindowsDesktop")

lib/cache/cert_authority_test.go

-1
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ func TestNodeCAFiltering(t *testing.T) {
9393
Access: p.cache.accessCache,
9494
DynamicAccess: p.cache.dynamicAccessCache,
9595
Presence: p.cache.presenceCache,
96-
Restrictions: p.cache.restrictionsCache,
9796
WebToken: p.cache.webTokenCache,
9897
DynamicWindowsDesktops: p.cache.dynamicWindowsDesktopsCache,
9998
SAMLIdPServiceProviders: p.samlIDPServiceProviders,

lib/cache/collections.go

+9
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ type collections struct {
100100
tunnelConnections *collection[types.TunnelConnection, tunnelConnectionIndex]
101101
remoteClusters *collection[types.RemoteCluster, remoteClusterIndex]
102102
staticHostUsers *collection[*userprovisioningv2.StaticHostUser, staticHostUserIndex]
103+
networkRestrictions *collection[types.NetworkRestrictions, networkingRestrictionIndex]
103104
}
104105

105106
// setupCollections ensures that the appropriate [collection] is
@@ -477,6 +478,14 @@ func setupCollections(c Config) (*collections, error) {
477478

478479
out.staticHostUsers = collect
479480
out.byKind[resourceKind] = out.staticHostUsers
481+
case types.KindNetworkRestrictions:
482+
collect, err := newNetworkingRestrictionCollection(c.Restrictions, watch)
483+
if err != nil {
484+
return nil, trace.Wrap(err)
485+
}
486+
487+
out.networkRestrictions = collect
488+
out.byKind[resourceKind] = out.networkRestrictions
480489
}
481490
}
482491

lib/cache/legacy_collections.go

-47
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,6 @@ type legacyCollections struct {
117117
userTasks collectionReader[userTasksGetter]
118118
crownJewels collectionReader[crownjewelsGetter]
119119
kubeWaitingContainers collectionReader[kubernetesWaitingContainerGetter]
120-
networkRestrictions collectionReader[networkRestrictionGetter]
121120
proxies collectionReader[services.ProxyGetter]
122121
uiConfigs collectionReader[uiConfigGetter]
123122
userLoginStates collectionReader[services.UserLoginStatesGetter]
@@ -190,15 +189,6 @@ func setupLegacyCollections(c *Cache, watches []types.WatchKind) (*legacyCollect
190189
watch: watch,
191190
}
192191
collections.byKind[resourceKind] = collections.crownJewels
193-
case types.KindNetworkRestrictions:
194-
if c.Restrictions == nil {
195-
return nil, trace.BadParameter("missing parameter Restrictions")
196-
}
197-
collections.networkRestrictions = &genericCollection[types.NetworkRestrictions, networkRestrictionGetter, networkRestrictionsExecutor]{
198-
cache: c,
199-
watch: watch,
200-
}
201-
collections.byKind[resourceKind] = collections.networkRestrictions
202192
case types.KindDynamicWindowsDesktop:
203193
if c.WindowsDesktops == nil {
204194
return nil, trace.BadParameter("missing parameter DynamicWindowsDesktops")
@@ -615,43 +605,6 @@ type installerGetter interface {
615605

616606
var _ executor[types.Installer, installerGetter] = installerConfigExecutor{}
617607

618-
type networkRestrictionsExecutor struct{}
619-
620-
func (networkRestrictionsExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]types.NetworkRestrictions, error) {
621-
restrictions, err := cache.Restrictions.GetNetworkRestrictions(ctx)
622-
if err != nil {
623-
return nil, trace.Wrap(err)
624-
}
625-
return []types.NetworkRestrictions{restrictions}, nil
626-
}
627-
628-
func (networkRestrictionsExecutor) upsert(ctx context.Context, cache *Cache, resource types.NetworkRestrictions) error {
629-
return cache.restrictionsCache.SetNetworkRestrictions(ctx, resource)
630-
}
631-
632-
func (networkRestrictionsExecutor) deleteAll(ctx context.Context, cache *Cache) error {
633-
return cache.restrictionsCache.DeleteNetworkRestrictions(ctx)
634-
}
635-
636-
func (networkRestrictionsExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error {
637-
return cache.restrictionsCache.DeleteNetworkRestrictions(ctx)
638-
}
639-
640-
func (networkRestrictionsExecutor) isSingleton() bool { return true }
641-
642-
func (networkRestrictionsExecutor) getReader(cache *Cache, cacheOK bool) networkRestrictionGetter {
643-
if cacheOK {
644-
return cache.restrictionsCache
645-
}
646-
return cache.Config.Restrictions
647-
}
648-
649-
type networkRestrictionGetter interface {
650-
GetNetworkRestrictions(context.Context) (types.NetworkRestrictions, error)
651-
}
652-
653-
var _ executor[types.NetworkRestrictions, networkRestrictionGetter] = networkRestrictionsExecutor{}
654-
655608
type dynamicWindowsDesktopsExecutor struct{}
656609

657610
func (dynamicWindowsDesktopsExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]types.DynamicWindowsDesktop, error) {

lib/cache/network_restrictions.go

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// Teleport
2+
// Copyright (C) 2025 Gravitational, Inc.
3+
//
4+
// This program is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU Affero General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// This program is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU Affero General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU Affero General Public License
15+
// along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
17+
package cache
18+
19+
import (
20+
"context"
21+
22+
"github.com/gravitational/trace"
23+
24+
"github.com/gravitational/teleport/api/types"
25+
"github.com/gravitational/teleport/lib/services"
26+
)
27+
28+
type networkingRestrictionIndex string
29+
30+
const networkingRestrictionNameIndex networkingRestrictionIndex = "name"
31+
32+
func newNetworkingRestrictionCollection(upstream services.Restrictions, w types.WatchKind) (*collection[types.NetworkRestrictions, networkingRestrictionIndex], error) {
33+
if upstream == nil {
34+
return nil, trace.BadParameter("missing parameter Restrictions")
35+
}
36+
37+
return &collection[types.NetworkRestrictions, networkingRestrictionIndex]{
38+
store: newStore(map[networkingRestrictionIndex]func(types.NetworkRestrictions) string{
39+
networkingRestrictionNameIndex: types.NetworkRestrictions.GetName,
40+
}),
41+
fetcher: func(ctx context.Context, loadSecrets bool) ([]types.NetworkRestrictions, error) {
42+
restrictions, err := upstream.GetNetworkRestrictions(ctx)
43+
if err != nil {
44+
return nil, trace.Wrap(err)
45+
}
46+
return []types.NetworkRestrictions{restrictions}, nil
47+
},
48+
headerTransform: func(hdr *types.ResourceHeader) types.NetworkRestrictions {
49+
return &types.NetworkRestrictionsV4{
50+
Kind: hdr.Kind,
51+
Version: hdr.Version,
52+
Metadata: types.Metadata{
53+
Name: hdr.Metadata.Name,
54+
},
55+
}
56+
},
57+
watch: w,
58+
}, nil
59+
}
60+
61+
// GetNetworkRestrictions gets the network restrictions.
62+
func (c *Cache) GetNetworkRestrictions(ctx context.Context) (types.NetworkRestrictions, error) {
63+
ctx, span := c.Tracer.Start(ctx, "cache/GetNetworkRestrictions")
64+
defer span.End()
65+
66+
getter := genericGetter[types.NetworkRestrictions, networkingRestrictionIndex]{
67+
cache: c,
68+
collection: c.collections.networkRestrictions,
69+
index: networkingRestrictionNameIndex,
70+
upstreamGet: func(ctx context.Context, s string) (types.NetworkRestrictions, error) {
71+
restriction, err := c.Config.Restrictions.GetNetworkRestrictions(ctx)
72+
return restriction, trace.Wrap(err)
73+
},
74+
clone: types.NetworkRestrictions.Clone,
75+
}
76+
out, err := getter.get(ctx, types.MetaNameNetworkRestrictions)
77+
return out, trace.Wrap(err)
78+
}
+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Teleport
2+
// Copyright (C) 2025 Gravitational, Inc.
3+
//
4+
// This program is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU Affero General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// This program is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU Affero General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU Affero General Public License
15+
// along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
17+
package cache
18+
19+
import (
20+
"context"
21+
"testing"
22+
23+
"github.com/gravitational/trace"
24+
25+
"github.com/gravitational/teleport/api/types"
26+
)
27+
28+
func TestNetworkRestrictions(t *testing.T) {
29+
t.Parallel()
30+
31+
p := newTestPack(t, ForAuth)
32+
t.Cleanup(p.Close)
33+
34+
testResources(t, p, testFuncs[types.NetworkRestrictions]{
35+
newResource: func(name string) (types.NetworkRestrictions, error) {
36+
return types.NewNetworkRestrictions(), nil
37+
},
38+
create: p.restrictions.SetNetworkRestrictions,
39+
list: func(ctx context.Context) ([]types.NetworkRestrictions, error) {
40+
restrictions, err := p.restrictions.GetNetworkRestrictions(ctx)
41+
return []types.NetworkRestrictions{restrictions}, trace.Wrap(err)
42+
},
43+
cacheList: func(ctx context.Context) ([]types.NetworkRestrictions, error) {
44+
restrictions, err := p.cache.GetNetworkRestrictions(ctx)
45+
if trace.IsNotFound(err) {
46+
return nil, nil
47+
}
48+
return []types.NetworkRestrictions{restrictions}, trace.Wrap(err)
49+
},
50+
deleteAll: p.restrictions.DeleteNetworkRestrictions,
51+
})
52+
}

lib/services/local/events.go

+1-6
Original file line numberDiff line numberDiff line change
@@ -1842,16 +1842,11 @@ func (p *networkRestrictionsParser) match(key backend.Key) bool {
18421842
func (p *networkRestrictionsParser) parse(event backend.Event) (types.Resource, error) {
18431843
switch event.Type {
18441844
case types.OpDelete:
1845-
name := event.Item.Key.TrimPrefix(backend.NewKey(restrictionsPrefix, network)).String()
1846-
if name == "" {
1847-
return nil, trace.NotFound("failed parsing %v", event.Item.Key.String())
1848-
}
1849-
18501845
return &types.ResourceHeader{
18511846
Kind: types.KindNetworkRestrictions,
18521847
Version: types.V1,
18531848
Metadata: types.Metadata{
1854-
Name: strings.TrimPrefix(name, backend.SeparatorString),
1849+
Name: types.MetaNameNetworkRestrictions,
18551850
Namespace: apidefaults.Namespace,
18561851
},
18571852
}, nil

0 commit comments

Comments
 (0)