Andrey Smirnov c2c2d65bc9
refactor: use COSI access filter for resource access
This replaces old resource API filter the new one based on new COSI
feature to filter access to the resources.

There should be no functional changes.

Signed-off-by: Andrey Smirnov <andrey.smirnov@talos-systems.com>
2022-08-08 17:25:09 +04:00

65 lines
2.0 KiB
Go

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package resources
import (
"context"
"fmt"
"strings"
"github.com/cosi-project/runtime/pkg/resource"
"github.com/cosi-project/runtime/pkg/resource/meta"
"github.com/cosi-project/runtime/pkg/safe"
"github.com/cosi-project/runtime/pkg/state"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"github.com/talos-systems/talos/pkg/grpc/middleware/authz"
"github.com/talos-systems/talos/pkg/machinery/role"
)
// AccessPolicy defines the access policy for resources accessed via the API.
func AccessPolicy(st state.State) state.FilteringRule {
return func(ctx context.Context, access state.Access) error {
if !access.Verb.Readonly() {
return status.Error(codes.PermissionDenied, "write access is not allowed")
}
rd, err := safe.StateGet[*meta.ResourceDefinition](ctx, st, resource.NewMetadata(meta.NamespaceName, meta.ResourceDefinitionType, strings.ToLower(access.ResourceType), resource.VersionUndefined))
if err != nil {
if state.IsNotFoundError(err) {
return status.Error(codes.PermissionDenied, fmt.Sprintf("resource type %q is not supported", access.ResourceType))
}
return err
}
roles := authz.GetRoles(ctx)
spec := rd.TypedSpec()
switch spec.Sensitivity {
case meta.Sensitive:
if !roles.Includes(role.Admin) {
return authz.ErrNotAuthorized
}
case meta.NonSensitive:
// nothing
default:
return fmt.Errorf("unexpected sensitivity %q", spec.Sensitivity)
}
_, err = safe.StateGet[*meta.Namespace](ctx, st, resource.NewMetadata(meta.NamespaceName, meta.NamespaceType, access.ResourceNamespace, resource.VersionUndefined))
if err != nil {
if state.IsNotFoundError(err) {
return status.Error(codes.PermissionDenied, fmt.Sprintf("namespace %q is not supported", access.ResourceNamespace))
}
return err
}
return nil
}
}