mirror of
https://github.com/gravitational/teleport
synced 2024-10-21 01:34:01 +00:00
Dont allow cloud tenants to update certain cluster networking config fields (#28634)
* Dont allow cloud tenants to update certain cluster networking fields * resolve comments * remove fmt.Sprintf
This commit is contained in:
parent
732ad92d5f
commit
3fff0bdbbf
|
@ -4111,7 +4111,47 @@ func (a *ServerWithRoles) SetClusterNetworkingConfig(ctx context.Context, newNet
|
|||
return trace.AccessDenied("proxy peering is an enterprise-only feature")
|
||||
}
|
||||
|
||||
oldNetConf, err := a.authServer.GetClusterNetworkingConfig(ctx)
|
||||
if err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
|
||||
if err := a.validateCloudNetworkConfigUpdate(newNetConfig, oldNetConf); err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
|
||||
return a.authServer.SetClusterNetworkingConfig(ctx, newNetConfig)
|
||||
|
||||
}
|
||||
func (a *ServerWithRoles) validateCloudNetworkConfigUpdate(newConfig, oldConfig types.ClusterNetworkingConfig) error {
|
||||
if a.hasBuiltinRole(types.RoleAdmin) {
|
||||
return nil
|
||||
}
|
||||
|
||||
if !modules.GetModules().Features().Cloud {
|
||||
return nil
|
||||
}
|
||||
|
||||
const cloudUpdateFailureMsg = "cloud tenants cannot update %q"
|
||||
|
||||
if newConfig.GetProxyListenerMode() != oldConfig.GetProxyListenerMode() {
|
||||
return trace.BadParameter(cloudUpdateFailureMsg, "proxy_listener_mode")
|
||||
}
|
||||
newtst, _ := newConfig.GetTunnelStrategyType()
|
||||
oldtst, _ := oldConfig.GetTunnelStrategyType()
|
||||
if newtst != oldtst {
|
||||
return trace.BadParameter(cloudUpdateFailureMsg, "tunnel_strategy")
|
||||
}
|
||||
|
||||
if newConfig.GetKeepAliveInterval() != oldConfig.GetKeepAliveInterval() {
|
||||
return trace.BadParameter(cloudUpdateFailureMsg, "keep_alive_interval")
|
||||
}
|
||||
|
||||
if newConfig.GetKeepAliveCountMax() != oldConfig.GetKeepAliveCountMax() {
|
||||
return trace.BadParameter(cloudUpdateFailureMsg, "keep_alive_count_max")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ResetClusterNetworkingConfig resets cluster networking configuration to defaults.
|
||||
|
@ -4129,6 +4169,14 @@ func (a *ServerWithRoles) ResetClusterNetworkingConfig(ctx context.Context) erro
|
|||
return trace.Wrap(err)
|
||||
}
|
||||
}
|
||||
oldNetConf, err := a.authServer.GetClusterNetworkingConfig(ctx)
|
||||
if err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
|
||||
if err := a.validateCloudNetworkConfigUpdate(types.DefaultClusterNetworkingConfig(), oldNetConf); err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
|
||||
return a.authServer.SetClusterNetworkingConfig(ctx, types.DefaultClusterNetworkingConfig())
|
||||
}
|
||||
|
|
|
@ -53,6 +53,7 @@ import (
|
|||
libdefaults "github.com/gravitational/teleport/lib/defaults"
|
||||
"github.com/gravitational/teleport/lib/events"
|
||||
"github.com/gravitational/teleport/lib/events/eventstest"
|
||||
"github.com/gravitational/teleport/lib/modules"
|
||||
"github.com/gravitational/teleport/lib/services"
|
||||
"github.com/gravitational/teleport/lib/session"
|
||||
"github.com/gravitational/teleport/lib/tlsca"
|
||||
|
@ -1137,6 +1138,136 @@ func TestAuthPreferenceRBAC(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func TestClusterNetworkingCloudUpdates(t *testing.T) {
|
||||
srv := newTestTLSServer(t)
|
||||
ctx := context.Background()
|
||||
err := srv.Auth().SetClusterNetworkingConfig(ctx, types.DefaultClusterNetworkingConfig())
|
||||
require.NoError(t, err)
|
||||
|
||||
user, _, err := CreateUserAndRole(srv.Auth(), "username", []string{}, []types.Rule{
|
||||
{
|
||||
Resources: []string{
|
||||
types.KindClusterNetworkingConfig,
|
||||
},
|
||||
Verbs: services.RW(),
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
for _, tc := range []struct {
|
||||
cloud bool
|
||||
identity TestIdentity
|
||||
expectSetErr string
|
||||
clusterNetworkingConfig types.ClusterNetworkingConfig
|
||||
name string
|
||||
}{
|
||||
{
|
||||
name: "non admin user can set existing values to the same value",
|
||||
cloud: true,
|
||||
identity: TestUser(user.GetName()),
|
||||
clusterNetworkingConfig: types.DefaultClusterNetworkingConfig(),
|
||||
},
|
||||
{
|
||||
name: "non admin user cannot set keep_alive_interval",
|
||||
cloud: true,
|
||||
identity: TestUser(user.GetName()),
|
||||
expectSetErr: "keep_alive_interval",
|
||||
clusterNetworkingConfig: newClusterNetworkingConf(t, types.ClusterNetworkingConfigSpecV2{
|
||||
KeepAliveInterval: types.Duration(time.Second * 20),
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "non admin user cannot set tunnel_strategy",
|
||||
cloud: true,
|
||||
identity: TestUser(user.GetName()),
|
||||
expectSetErr: "tunnel_strategy",
|
||||
clusterNetworkingConfig: newClusterNetworkingConf(t, types.ClusterNetworkingConfigSpecV2{
|
||||
TunnelStrategy: &types.TunnelStrategyV1{
|
||||
Strategy: &types.TunnelStrategyV1_ProxyPeering{
|
||||
ProxyPeering: types.DefaultProxyPeeringTunnelStrategy(),
|
||||
},
|
||||
},
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "non admin user cannot set proxy_listener_mode",
|
||||
cloud: true,
|
||||
identity: TestUser(user.GetName()),
|
||||
expectSetErr: "proxy_listener_mode",
|
||||
clusterNetworkingConfig: newClusterNetworkingConf(t, types.ClusterNetworkingConfigSpecV2{
|
||||
ProxyListenerMode: types.ProxyListenerMode_Multiplex,
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "non admin user cannot set keep_alive_count_max",
|
||||
cloud: true,
|
||||
identity: TestUser(user.GetName()),
|
||||
expectSetErr: "keep_alive_count_max",
|
||||
clusterNetworkingConfig: newClusterNetworkingConf(t, types.ClusterNetworkingConfigSpecV2{
|
||||
KeepAliveCountMax: 55,
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "non admin user can set client_idle_timeout",
|
||||
cloud: true,
|
||||
identity: TestUser(user.GetName()),
|
||||
clusterNetworkingConfig: newClusterNetworkingConf(t, types.ClusterNetworkingConfigSpecV2{
|
||||
ClientIdleTimeout: types.Duration(time.Second * 67),
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "admin user can set keep_alive_interval",
|
||||
cloud: true,
|
||||
identity: TestAdmin(),
|
||||
clusterNetworkingConfig: newClusterNetworkingConf(t, types.ClusterNetworkingConfigSpecV2{
|
||||
KeepAliveInterval: types.Duration(time.Second * 67),
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "non admin user can set keep_alive_interval on non cloud cluster",
|
||||
cloud: false,
|
||||
identity: TestUser(user.GetName()),
|
||||
clusterNetworkingConfig: newClusterNetworkingConf(t, types.ClusterNetworkingConfigSpecV2{
|
||||
KeepAliveInterval: types.Duration(time.Second * 67),
|
||||
}),
|
||||
},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
modules.SetTestModules(t, &modules.TestModules{
|
||||
TestBuildType: modules.BuildEnterprise,
|
||||
TestFeatures: modules.Features{
|
||||
Cloud: tc.cloud,
|
||||
},
|
||||
})
|
||||
|
||||
client, err := srv.NewClient(tc.identity)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = client.SetClusterNetworkingConfig(ctx, tc.clusterNetworkingConfig)
|
||||
if err != nil {
|
||||
require.NotEmpty(t, tc.expectSetErr)
|
||||
require.ErrorContains(t, err, tc.expectSetErr)
|
||||
} else {
|
||||
require.Empty(t, tc.expectSetErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func newClusterNetworkingConf(t *testing.T, spec types.ClusterNetworkingConfigSpecV2) types.ClusterNetworkingConfig {
|
||||
c := &types.ClusterNetworkingConfigV2{
|
||||
Metadata: types.Metadata{
|
||||
Labels: map[string]string{
|
||||
types.OriginLabel: types.OriginDynamic,
|
||||
},
|
||||
},
|
||||
Spec: spec,
|
||||
}
|
||||
err := c.CheckAndSetDefaults()
|
||||
require.NoError(t, err)
|
||||
return c
|
||||
}
|
||||
|
||||
func TestClusterNetworkingConfigRBAC(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx := context.Background()
|
||||
|
|
Loading…
Reference in a new issue