Forbid custom namespaces in various resources (#49830)

* Forbid Database and App updates with custom namespaces

* Forbid custom namespaces on api/types.KeepAlive

* Forbid custom namespaces in api/types.Metadata

* Forbid custom namespaces in api/types.RoleV6

* Use a share validation helper, improve error message
This commit is contained in:
Alan Parra
2024-12-05 19:21:24 +00:00
committed by GitHub
parent d9c4906bcc
commit 8e723cc7ff
9 changed files with 70 additions and 13 deletions
+1 -1
View File
@@ -30,7 +30,7 @@ func TestKubeClustersSorter(t *testing.T) {
servers := make([]KubeCluster, len(testVals))
for i := 0; i < len(testVals); i++ {
var err error
servers[i], err = NewKubernetesClusterV3FromLegacyCluster("_", &KubernetesCluster{
servers[i], err = NewKubernetesClusterV3FromLegacyCluster("", &KubernetesCluster{
Name: testVals[i],
})
require.NoError(t, err)
+14
View File
@@ -143,3 +143,17 @@ func IsValidNamespace(s string) bool {
}
var validNamespace = regexp.MustCompile(`^[A-Za-z0-9]+$`)
// ValidateNamespaceDefault ensures that the namespace is the "default"
// namespace.
// This is a precursor to a hard-removal of namespaces.
func ValidateNamespaceDefault(ns string) error {
if ns == defaults.Namespace {
return nil
}
const message = "" +
"namespace %q invalid, custom namespaces are deprecated; " +
"the namespace field should be omitted or set to %q"
return trace.BadParameter(message, ns, defaults.Namespace)
}
+4
View File
@@ -67,9 +67,13 @@ func (s *KeepAlive) CheckAndSetDefaults() error {
if s.IsEmpty() {
return trace.BadParameter("missing resource name")
}
if s.Namespace == "" {
s.Namespace = defaults.Namespace
}
if err := ValidateNamespaceDefault(s.Namespace); err != nil {
return trace.Wrap(err)
}
return nil
}
+4
View File
@@ -478,9 +478,13 @@ func (m *Metadata) CheckAndSetDefaults() error {
if m.Name == "" {
return trace.BadParameter("missing parameter Name")
}
if m.Namespace == "" {
m.Namespace = defaults.Namespace
}
if err := ValidateNamespaceDefault(m.Namespace); err != nil {
return trace.Wrap(err)
}
// adjust expires time to UTC if it's set
if m.Expires != nil {
+1 -1
View File
@@ -266,7 +266,7 @@ func TestMatchSearch_ResourceSpecific(t *testing.T) {
name: "kube cluster",
matchingSearchVals: []string{"foo", "prod", "env"},
newResource: func(t *testing.T) ResourceWithLabels {
kc, err := NewKubernetesClusterV3FromLegacyCluster("_", &KubernetesCluster{
kc, err := NewKubernetesClusterV3FromLegacyCluster("", &KubernetesCluster{
Name: "foo",
StaticLabels: labels,
})
+27 -4
View File
@@ -1071,8 +1071,9 @@ func (r *RoleV6) CheckAndSetDefaults() error {
if len(r.Spec.Options.BPF) == 0 {
r.Spec.Options.BPF = defaults.EnhancedEvents()
}
if r.Spec.Allow.Namespaces == nil {
r.Spec.Allow.Namespaces = []string{defaults.Namespace}
if err := checkAndSetRoleConditionNamespaces(&r.Spec.Allow.Namespaces); err != nil {
// Using trace.BadParameter instead of trace.Wrap for a better error message.
return trace.BadParameter("allow: %s", err)
}
if r.Spec.Options.RecordSession == nil {
r.Spec.Options.RecordSession = &RecordSession{
@@ -1175,8 +1176,9 @@ func (r *RoleV6) CheckAndSetDefaults() error {
return trace.BadParameter("unrecognized role version: %v", r.Version)
}
if r.Spec.Deny.Namespaces == nil {
r.Spec.Deny.Namespaces = []string{defaults.Namespace}
if err := checkAndSetRoleConditionNamespaces(&r.Spec.Deny.Namespaces); err != nil {
// Using trace.BadParameter instead of trace.Wrap for a better error message.
return trace.BadParameter("deny: %s", err)
}
// Validate request.kubernetes_resources fields are all valid.
@@ -1322,6 +1324,27 @@ func (r *RoleV6) CheckAndSetDefaults() error {
return nil
}
func checkAndSetRoleConditionNamespaces(namespaces *[]string) error {
// If nil use the default.
// This distinguishes between nil and empty (in accordance to legacy code).
if *namespaces == nil {
*namespaces = []string{defaults.Namespace}
return nil
}
for i, ns := range *namespaces {
if ns == Wildcard {
continue // OK, wildcard is accepted.
}
if err := ValidateNamespaceDefault(ns); err != nil {
// Using trace.BadParameter instead of trace.Wrap for a better error message.
return trace.BadParameter("namespaces[%d]: %s", i, err)
}
}
return nil
}
// String returns the human readable representation of a role.
func (r *RoleV6) String() string {
options, _ := json.Marshal(r.Spec.Options)
+4
View File
@@ -44,6 +44,10 @@ func (s *DatabaseServicesService) UpsertDatabaseService(ctx context.Context, ser
if err := services.CheckAndSetDefaults(service); err != nil {
return nil, trace.Wrap(err)
}
if err := types.ValidateNamespaceDefault(service.GetNamespace()); err != nil {
return nil, trace.Wrap(err)
}
rev := service.GetRevision()
value, err := services.MarshalDatabaseService(service)
if err != nil {
+14 -6
View File
@@ -345,10 +345,10 @@ func (s *PresenceService) UpsertNode(ctx context.Context, server types.Server) (
if server.GetNamespace() == "" {
server.SetNamespace(apidefaults.Namespace)
}
if n := server.GetNamespace(); n != apidefaults.Namespace {
return nil, trace.BadParameter("cannot place node in namespace %q, custom namespaces are deprecated", n)
if err := types.ValidateNamespaceDefault(server.GetNamespace()); err != nil {
return nil, trace.Wrap(err)
}
rev := server.GetRevision()
value, err := services.MarshalServer(server)
if err != nil {
@@ -377,10 +377,10 @@ func (s *PresenceService) UpdateNode(ctx context.Context, server types.Server) (
if server.GetNamespace() == "" {
server.SetNamespace(apidefaults.Namespace)
}
if n := server.GetNamespace(); n != apidefaults.Namespace {
return nil, trace.BadParameter("cannot place node in namespace %q, custom namespaces are deprecated", n)
if err := types.ValidateNamespaceDefault(server.GetNamespace()); err != nil {
return nil, trace.Wrap(err)
}
rev := server.GetRevision()
value, err := services.MarshalServer(server)
if err != nil {
@@ -1003,6 +1003,10 @@ func (s *PresenceService) UpsertDatabaseServer(ctx context.Context, server types
if err := services.CheckAndSetDefaults(server); err != nil {
return nil, trace.Wrap(err)
}
if err := types.ValidateNamespaceDefault(server.GetNamespace()); err != nil {
return nil, trace.Wrap(err)
}
rev := server.GetRevision()
value, err := services.MarshalDatabaseServer(server)
if err != nil {
@@ -1096,6 +1100,10 @@ func (s *PresenceService) UpsertApplicationServer(ctx context.Context, server ty
if err := services.CheckAndSetDefaults(server); err != nil {
return nil, trace.Wrap(err)
}
if err := types.ValidateNamespaceDefault(server.GetNamespace()); err != nil {
return nil, trace.Wrap(err)
}
rev := server.GetRevision()
value, err := services.MarshalAppServer(server)
if err != nil {
+1 -1
View File
@@ -499,7 +499,7 @@ func TestMatchResourceByFilters(t *testing.T) {
{
name: "kube cluster",
resource: func() types.ResourceWithLabels {
cluster, err := types.NewKubernetesClusterV3FromLegacyCluster("_", &types.KubernetesCluster{
cluster, err := types.NewKubernetesClusterV3FromLegacyCluster("", &types.KubernetesCluster{
Name: "foo",
})
require.NoError(t, err)