Allow to use user/group targets from the policy contract #1095

Merged
fyrchik merged 5 commits from fyrchik/frostfs-node:policy-user into master 2024-04-16 11:03:54 +00:00
15 changed files with 631 additions and 563 deletions

View file

@ -16,6 +16,8 @@ import (
const (
namespaceTarget = "namespace"
containerTarget = "container"
userTarget = "user"
groupTarget = "group"
jsonFlag = "json"
jsonFlagDesc = "Output rule chains in JSON format"
chainIDFlag = "chain-id"

View file

@ -53,6 +53,10 @@ func parseTargetType(cmd *cobra.Command) (policyengine.TargetType, error) {
return policyengine.Namespace, nil
case containerTarget:
return policyengine.Container, nil
case userTarget:
return policyengine.User, nil
case groupTarget:
return policyengine.Group, nil
}
return -1, errUnknownTargetType
}

View file

@ -27,6 +27,8 @@ const (
defaultNamespace = "root"
namespaceTarget = "namespace"
containerTarget = "container"
userTarget = "user"
groupTarget = "group"
)
const (
@ -66,6 +68,16 @@ func parseTarget(cmd *cobra.Command) *control.ChainTarget {
Name: name,
Type: control.ChainTarget_CONTAINER,
}
case userTarget:
Review
That's nice. But could you also, please, add this for `frostfs-adm`: https://git.frostfs.info/TrueCloudLab/frostfs-node/src/branch/master/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go#L38-L47
Review

Fixed

Fixed
return &control.ChainTarget{
Name: name,
Type: control.ChainTarget_USER,
}
case groupTarget:
return &control.ChainTarget{
Name: name,
Type: control.ChainTarget_GROUP,
}
default:
commonCmd.ExitOnErr(cmd, "read target type error: %w", errUnknownTargetType)
}

2
go.mod
View file

@ -9,7 +9,7 @@ require (
git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65
git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240329104804-ec0cb2169f92
git.frostfs.info/TrueCloudLab/hrw v1.2.1
git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240410114823-1f190e1668ec
git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240412130734-0e69e485115a
git.frostfs.info/TrueCloudLab/tzhash v1.8.0
git.frostfs.info/TrueCloudLab/zapjournald v0.0.0-20240124114243-cb2e66427d02
github.com/cheggaaa/pb v1.0.29

4
go.sum
View file

@ -12,8 +12,8 @@ git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240329104804-ec0cb2169f92
git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240329104804-ec0cb2169f92/go.mod h1:i0RKqiF4z3UOxLSNwhHw+cUz/JyYWuTRpnn9ere4Y3w=
git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc=
git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM=
git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240410114823-1f190e1668ec h1:OG8tBs5CN2HKp10sAWdtiFaX8qSGFyLGWfQmf4FQ6bE=
git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240410114823-1f190e1668ec/go.mod h1:H/AW85RtYxVTbcgwHW76DqXeKlsiCIOeNXHPqyDBrfQ=
git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240412130734-0e69e485115a h1:wbndKvHbwDQiSMQWL75RxiTZCeUyCi7NUj1lsfdAGkc=
git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240412130734-0e69e485115a/go.mod h1:H/AW85RtYxVTbcgwHW76DqXeKlsiCIOeNXHPqyDBrfQ=
git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 h1:M2KR3iBj7WpY3hP10IevfIB9MURr4O9mwVfJ+SjT3HA=
git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0/go.mod h1:okpbKfVYf/BpejtfFTfhZqFP+sZ8rsHrP8Rr/jYPNRc=
git.frostfs.info/TrueCloudLab/tzhash v1.8.0 h1:UFMnUIk0Zh17m8rjGHJMqku2hCgaXDqjqZzS4gsb4UA=

View file

@ -157,9 +157,12 @@ func (ac *apeChecker) List(ctx context.Context, req *container.ListRequest) (*co
reqProps,
)
s, found, err := ac.router.IsAllowed(apechain.Ingress,
policyengine.NewRequestTargetWithNamespace(namespace),
request)
rt := policyengine.NewRequestTargetWithNamespace(namespace)
rt.User = &policyengine.Target{
Type: policyengine.User,
Name: fmt.Sprintf("%s:%s", namespace, pk.Address()),
}
s, found, err := ac.router.IsAllowed(apechain.Ingress, rt, request)
if err != nil {
return nil, err
}
@ -202,9 +205,12 @@ func (ac *apeChecker) Put(ctx context.Context, req *container.PutRequest) (*cont
reqProps,
)
s, found, err := ac.router.IsAllowed(apechain.Ingress,
policyengine.NewRequestTargetWithNamespace(namespace),
request)
rt := policyengine.NewRequestTargetWithNamespace(namespace)
rt.User = &policyengine.Target{
Type: policyengine.User,
Name: fmt.Sprintf("%s:%s", namespace, pk.Address()),
}
s, found, err := ac.router.IsAllowed(apechain.Ingress, rt, request)
if err != nil {
return nil, err
}
@ -277,7 +283,7 @@ func (ac *apeChecker) validateContainerBoundedOperation(containerID *refs.Contai
return err
}
reqProps, err := ac.getRequestProps(mh, vh, cont, id)
reqProps, pk, err := ac.getRequestProps(mh, vh, cont, id)
if err != nil {
return err
}
@ -298,7 +304,7 @@ func (ac *apeChecker) validateContainerBoundedOperation(containerID *refs.Contai
)
s, found, err := ac.router.IsAllowed(apechain.Ingress,
policyengine.NewRequestTarget(namespace, id.EncodeToString()),
policyengine.NewRequestTargetExtended(namespace, id.EncodeToString(), fmt.Sprintf("%s:%s", namespace, pk.Address()), nil),
request)
if err != nil {
return err
@ -350,19 +356,19 @@ func (ac *apeChecker) getContainerProps(c *containercore.Container) map[string]s
func (ac *apeChecker) getRequestProps(mh *session.RequestMetaHeader, vh *session.RequestVerificationHeader,
cont *containercore.Container, cnrID cid.ID,
) (map[string]string, error) {
) (map[string]string, *keys.PublicKey, error) {
actor, pk, err := ac.getActorAndPublicKey(mh, vh, cnrID)
if err != nil {
return nil, err
return nil, nil, err
}
role, err := ac.getRole(actor, pk, cont, cnrID)
if err != nil {
return nil, err
return nil, nil, err
}
return map[string]string{
nativeschema.PropertyKeyActorPublicKey: hex.EncodeToString(pk.Bytes()),
nativeschema.PropertyKeyActorRole: role,
}, nil
}, pk, nil
}
func (ac *apeChecker) getRole(actor *user.ID, pk *keys.PublicKey, cont *containercore.Container, cnrID cid.ID) (string, error) {

View file

@ -19,6 +19,10 @@ func apeTarget(chainTarget *control.ChainTarget) (engine.Target, error) {
return engine.ContainerTarget(chainTarget.GetName()), nil
case control.ChainTarget_NAMESPACE:
return engine.NamespaceTarget(chainTarget.GetName()), nil
case control.ChainTarget_USER:
return engine.UserTarget(chainTarget.GetName()), nil
case control.ChainTarget_GROUP:
return engine.GroupTarget(chainTarget.GetName()), nil
default:
}
return engine.Target{}, status.Error(codes.InvalidArgument,
@ -42,6 +46,16 @@ func controlTarget(chainTarget *engine.Target) (control.ChainTarget, error) {
Name: nm,
Type: control.ChainTarget_NAMESPACE,
}, nil
case engine.User:
return control.ChainTarget{
Name: chainTarget.Name,
Type: control.ChainTarget_USER,
}, nil
case engine.Group:
return control.ChainTarget{
Name: chainTarget.Name,
Type: control.ChainTarget_GROUP,
}, nil
default:
}
return control.ChainTarget{}, status.Error(codes.InvalidArgument,

View file

@ -3188,7 +3188,8 @@ type FlushCacheRequest_Body struct {
// ID of the shard.
Shard_ID [][]byte `protobuf:"bytes,1,rep,name=shard_ID,json=shardID,proto3" json:"shard_ID,omitempty"`
// If true, then writecache will be left in read-only mode after flush completed.
// If true, then writecache will be left in read-only mode after flush
// completed.
Seal bool `protobuf:"varint,2,opt,name=seal,proto3" json:"seal,omitempty"`
}
@ -3525,7 +3526,8 @@ type GetShardEvacuationStatusResponse_Body struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// Total objects to evacuate count. The value is approximate, so evacuated + failed + skipped == total is not guaranteed after completion.
// Total objects to evacuate count. The value is approximate, so evacuated +
// failed + skipped == total is not guaranteed after completion.
TotalObjects uint64 `protobuf:"varint,1,opt,name=total_objects,json=totalObjects,proto3" json:"total_objects,omitempty"`
// Evacuated objects count.
EvacuatedObjects uint64 `protobuf:"varint,2,opt,name=evacuated_objects,json=evacuatedObjects,proto3" json:"evacuated_objects,omitempty"`

View file

@ -6,65 +6,82 @@ import "pkg/services/control/types.proto";
option go_package = "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control";
// `ControlService` provides an interface for internal work with the storage node.
// `ControlService` provides an interface for internal work with the storage
// node.
service ControlService {
// Performs health check of the storage node.
rpc HealthCheck (HealthCheckRequest) returns (HealthCheckResponse);
rpc HealthCheck(HealthCheckRequest) returns (HealthCheckResponse);
// Sets status of the storage node in FrostFS network map.
rpc SetNetmapStatus (SetNetmapStatusRequest) returns (SetNetmapStatusResponse);
rpc SetNetmapStatus(SetNetmapStatusRequest) returns (SetNetmapStatusResponse);
// Mark objects to be removed from node's local object storage.
rpc DropObjects (DropObjectsRequest) returns (DropObjectsResponse);
rpc DropObjects(DropObjectsRequest) returns (DropObjectsResponse);
// Returns list that contains information about all shards of a node.
rpc ListShards (ListShardsRequest) returns (ListShardsResponse);
rpc ListShards(ListShardsRequest) returns (ListShardsResponse);
// Sets mode of the shard.
rpc SetShardMode (SetShardModeRequest) returns (SetShardModeResponse);
rpc SetShardMode(SetShardModeRequest) returns (SetShardModeResponse);
// Synchronizes all log operations for the specified tree.
rpc SynchronizeTree (SynchronizeTreeRequest) returns (SynchronizeTreeResponse);
rpc SynchronizeTree(SynchronizeTreeRequest) returns (SynchronizeTreeResponse);
// EvacuateShard moves all data from one shard to the others.
// Deprecated: Use StartShardEvacuation/GetShardEvacuationStatus/StopShardEvacuation
rpc EvacuateShard (EvacuateShardRequest) returns (EvacuateShardResponse);
// Deprecated: Use
// StartShardEvacuation/GetShardEvacuationStatus/StopShardEvacuation
rpc EvacuateShard(EvacuateShardRequest) returns (EvacuateShardResponse);
// StartShardEvacuation starts moving all data from one shard to the others.
rpc StartShardEvacuation (StartShardEvacuationRequest) returns (StartShardEvacuationResponse);
rpc StartShardEvacuation(StartShardEvacuationRequest)
returns (StartShardEvacuationResponse);
// GetShardEvacuationStatus returns evacuation status.
rpc GetShardEvacuationStatus (GetShardEvacuationStatusRequest) returns (GetShardEvacuationStatusResponse);
rpc GetShardEvacuationStatus(GetShardEvacuationStatusRequest)
returns (GetShardEvacuationStatusResponse);
// ResetShardEvacuationStatus resets evacuation status if there is no running evacuation process.
rpc ResetShardEvacuationStatus (ResetShardEvacuationStatusRequest) returns (ResetShardEvacuationStatusResponse);
// ResetShardEvacuationStatus resets evacuation status if there is no running
// evacuation process.
rpc ResetShardEvacuationStatus(ResetShardEvacuationStatusRequest)
returns (ResetShardEvacuationStatusResponse);
// StopShardEvacuation stops moving all data from one shard to the others.
rpc StopShardEvacuation (StopShardEvacuationRequest) returns (StopShardEvacuationResponse);
rpc StopShardEvacuation(StopShardEvacuationRequest)
returns (StopShardEvacuationResponse);
// FlushCache moves all data from one shard to the others.
rpc FlushCache (FlushCacheRequest) returns (FlushCacheResponse);
rpc FlushCache(FlushCacheRequest) returns (FlushCacheResponse);
// Doctor performs storage restructuring operations on engine.
rpc Doctor (DoctorRequest) returns (DoctorResponse);
rpc Doctor(DoctorRequest) returns (DoctorResponse);
// Add local access policy engine overrides to a node.
rpc AddChainLocalOverride (AddChainLocalOverrideRequest) returns (AddChainLocalOverrideResponse);
rpc AddChainLocalOverride(AddChainLocalOverrideRequest)
returns (AddChainLocalOverrideResponse);
// Get local access policy engine overrides stored in the node by chain id.
rpc GetChainLocalOverride (GetChainLocalOverrideRequest) returns (GetChainLocalOverrideResponse);
rpc GetChainLocalOverride(GetChainLocalOverrideRequest)
returns (GetChainLocalOverrideResponse);
// List local access policy engine overrides stored in the node by container id.
rpc ListChainLocalOverrides (ListChainLocalOverridesRequest) returns (ListChainLocalOverridesResponse);
// List local access policy engine overrides stored in the node by container
// id.
rpc ListChainLocalOverrides(ListChainLocalOverridesRequest)
returns (ListChainLocalOverridesResponse);
// Remove local access policy engine overrides stored in the node by chaind id.
rpc RemoveChainLocalOverride (RemoveChainLocalOverrideRequest) returns (RemoveChainLocalOverrideResponse);
// Remove local access policy engine overrides stored in the node by chaind
// id.
rpc RemoveChainLocalOverride(RemoveChainLocalOverrideRequest)
returns (RemoveChainLocalOverrideResponse);
// Remove local access policy engine overrides stored in the node by chaind id.
rpc RemoveChainLocalOverridesByTarget (RemoveChainLocalOverridesByTargetRequest) returns (RemoveChainLocalOverridesByTargetResponse);
// Remove local access policy engine overrides stored in the node by chaind
// id.
rpc RemoveChainLocalOverridesByTarget(
RemoveChainLocalOverridesByTargetRequest)
returns (RemoveChainLocalOverridesByTargetResponse);
// List targets of the local APE overrides stored in the node.
rpc ListTargetsLocalOverrides (ListTargetsLocalOverridesRequest) returns (ListTargetsLocalOverridesResponse);
rpc ListTargetsLocalOverrides(ListTargetsLocalOverridesRequest)
returns (ListTargetsLocalOverridesResponse);
// Flush objects from write-cache and move it to degraded read only mode.
rpc SealWriteCache(SealWriteCacheRequest) returns (SealWriteCacheResponse);
@ -76,8 +93,7 @@ service ControlService {
// Health check request.
message HealthCheckRequest {
// Health check request body.
message Body {
}
message Body {}
// Body of health check request message.
Body body = 1;
@ -131,8 +147,7 @@ message SetNetmapStatusRequest {
// Set netmap status response.
message SetNetmapStatusResponse {
// Set netmap status response body
message Body {
}
message Body {}
// Body of set netmap status response message.
Body body = 1;
@ -160,8 +175,7 @@ message DropObjectsRequest {
// Response to request to drop the objects.
message DropObjectsResponse {
// Response body structure.
message Body {
}
message Body {}
// Body of the response message.
Body body = 1;
@ -173,8 +187,7 @@ message DropObjectsResponse {
// Request to list all shards of the node.
message ListShardsRequest {
// Request body structure.
message Body {
}
message Body {}
// Body of the request message.
Body body = 1;
@ -222,8 +235,7 @@ message SetShardModeRequest {
// SetShardMode response.
message SetShardModeResponse {
// Response body structure.
message Body {
}
message Body {}
// Body of set shard mode response message.
Body body = 1;
@ -252,8 +264,7 @@ message SynchronizeTreeRequest {
// SynchronizeTree response.
message SynchronizeTreeResponse {
// Response body structure.
message Body {
}
message Body {}
// Body of restore shard response message.
Body body = 1;
@ -262,7 +273,6 @@ message SynchronizeTreeResponse {
Signature signature = 2;
}
// EvacuateShard request.
message EvacuateShardRequest {
// Request body structure.
@ -281,9 +291,7 @@ message EvacuateShardRequest {
// EvacuateShard response.
message EvacuateShardResponse {
// Response body structure.
message Body {
uint32 count = 1;
}
message Body { uint32 count = 1; }
Body body = 1;
Signature signature = 2;
@ -295,7 +303,8 @@ message FlushCacheRequest {
message Body {
// ID of the shard.
repeated bytes shard_ID = 1;
// If true, then writecache will be left in read-only mode after flush completed.
// If true, then writecache will be left in read-only mode after flush
// completed.
bool seal = 2;
}
@ -306,14 +315,12 @@ message FlushCacheRequest {
// FlushCache response.
message FlushCacheResponse {
// Response body structure.
message Body {
}
message Body {}
Body body = 1;
Signature signature = 2;
}
// Doctor request.
message DoctorRequest {
// Request body structure.
@ -331,8 +338,7 @@ message DoctorRequest {
// Doctor response.
message DoctorResponse {
// Response body structure.
message Body {
}
message Body {}
Body body = 1;
Signature signature = 2;
@ -390,16 +396,13 @@ message GetShardEvacuationStatusResponse {
}
// Unix timestamp value.
message UnixTimestamp {
int64 value = 1;
}
message UnixTimestamp { int64 value = 1; }
// Duration in seconds.
message Duration {
int64 seconds = 1;
}
message Duration { int64 seconds = 1; }
// Total objects to evacuate count. The value is approximate, so evacuated + failed + skipped == total is not guaranteed after completion.
// Total objects to evacuate count. The value is approximate, so evacuated +
// failed + skipped == total is not guaranteed after completion.
uint64 total_objects = 1;
// Evacuated objects count.
uint64 evacuated_objects = 2;
@ -587,8 +590,7 @@ message RemoveChainLocalOverrideRequest {
}
message RemoveChainLocalOverrideResponse {
message Body {
}
message Body {}
Body body = 1;
@ -607,8 +609,7 @@ message RemoveChainLocalOverridesByTargetRequest {
}
message RemoveChainLocalOverridesByTargetResponse {
message Body {
}
message Body {}
Body body = 1;
@ -645,17 +646,14 @@ message SealWriteCacheResponse {
}
message DetachShardsRequest {
message Body {
repeated bytes shard_ID = 1;
}
message Body { repeated bytes shard_ID = 1; }
Body body = 1;
Signature signature = 2;
}
message DetachShardsResponse {
message Body {
}
message Body {}
Body body = 1;

View file

@ -59,13 +59,15 @@ type ControlServiceClient interface {
// Synchronizes all log operations for the specified tree.
SynchronizeTree(ctx context.Context, in *SynchronizeTreeRequest, opts ...grpc.CallOption) (*SynchronizeTreeResponse, error)
// EvacuateShard moves all data from one shard to the others.
// Deprecated: Use StartShardEvacuation/GetShardEvacuationStatus/StopShardEvacuation
// Deprecated: Use
// StartShardEvacuation/GetShardEvacuationStatus/StopShardEvacuation
EvacuateShard(ctx context.Context, in *EvacuateShardRequest, opts ...grpc.CallOption) (*EvacuateShardResponse, error)
// StartShardEvacuation starts moving all data from one shard to the others.
StartShardEvacuation(ctx context.Context, in *StartShardEvacuationRequest, opts ...grpc.CallOption) (*StartShardEvacuationResponse, error)
// GetShardEvacuationStatus returns evacuation status.
GetShardEvacuationStatus(ctx context.Context, in *GetShardEvacuationStatusRequest, opts ...grpc.CallOption) (*GetShardEvacuationStatusResponse, error)
// ResetShardEvacuationStatus resets evacuation status if there is no running evacuation process.
// ResetShardEvacuationStatus resets evacuation status if there is no running
// evacuation process.
ResetShardEvacuationStatus(ctx context.Context, in *ResetShardEvacuationStatusRequest, opts ...grpc.CallOption) (*ResetShardEvacuationStatusResponse, error)
// StopShardEvacuation stops moving all data from one shard to the others.
StopShardEvacuation(ctx context.Context, in *StopShardEvacuationRequest, opts ...grpc.CallOption) (*StopShardEvacuationResponse, error)
@ -77,11 +79,14 @@ type ControlServiceClient interface {
AddChainLocalOverride(ctx context.Context, in *AddChainLocalOverrideRequest, opts ...grpc.CallOption) (*AddChainLocalOverrideResponse, error)
// Get local access policy engine overrides stored in the node by chain id.
GetChainLocalOverride(ctx context.Context, in *GetChainLocalOverrideRequest, opts ...grpc.CallOption) (*GetChainLocalOverrideResponse, error)
// List local access policy engine overrides stored in the node by container id.
// List local access policy engine overrides stored in the node by container
// id.
ListChainLocalOverrides(ctx context.Context, in *ListChainLocalOverridesRequest, opts ...grpc.CallOption) (*ListChainLocalOverridesResponse, error)
// Remove local access policy engine overrides stored in the node by chaind id.
// Remove local access policy engine overrides stored in the node by chaind
// id.
RemoveChainLocalOverride(ctx context.Context, in *RemoveChainLocalOverrideRequest, opts ...grpc.CallOption) (*RemoveChainLocalOverrideResponse, error)
// Remove local access policy engine overrides stored in the node by chaind id.
// Remove local access policy engine overrides stored in the node by chaind
// id.
RemoveChainLocalOverridesByTarget(ctx context.Context, in *RemoveChainLocalOverridesByTargetRequest, opts ...grpc.CallOption) (*RemoveChainLocalOverridesByTargetResponse, error)
// List targets of the local APE overrides stored in the node.
ListTargetsLocalOverrides(ctx context.Context, in *ListTargetsLocalOverridesRequest, opts ...grpc.CallOption) (*ListTargetsLocalOverridesResponse, error)
@ -305,13 +310,15 @@ type ControlServiceServer interface {
// Synchronizes all log operations for the specified tree.
SynchronizeTree(context.Context, *SynchronizeTreeRequest) (*SynchronizeTreeResponse, error)
// EvacuateShard moves all data from one shard to the others.
// Deprecated: Use StartShardEvacuation/GetShardEvacuationStatus/StopShardEvacuation
// Deprecated: Use
// StartShardEvacuation/GetShardEvacuationStatus/StopShardEvacuation
EvacuateShard(context.Context, *EvacuateShardRequest) (*EvacuateShardResponse, error)
// StartShardEvacuation starts moving all data from one shard to the others.
StartShardEvacuation(context.Context, *StartShardEvacuationRequest) (*StartShardEvacuationResponse, error)
// GetShardEvacuationStatus returns evacuation status.
GetShardEvacuationStatus(context.Context, *GetShardEvacuationStatusRequest) (*GetShardEvacuationStatusResponse, error)
// ResetShardEvacuationStatus resets evacuation status if there is no running evacuation process.
// ResetShardEvacuationStatus resets evacuation status if there is no running
// evacuation process.
ResetShardEvacuationStatus(context.Context, *ResetShardEvacuationStatusRequest) (*ResetShardEvacuationStatusResponse, error)
// StopShardEvacuation stops moving all data from one shard to the others.
StopShardEvacuation(context.Context, *StopShardEvacuationRequest) (*StopShardEvacuationResponse, error)
@ -323,11 +330,14 @@ type ControlServiceServer interface {
AddChainLocalOverride(context.Context, *AddChainLocalOverrideRequest) (*AddChainLocalOverrideResponse, error)
// Get local access policy engine overrides stored in the node by chain id.
GetChainLocalOverride(context.Context, *GetChainLocalOverrideRequest) (*GetChainLocalOverrideResponse, error)
// List local access policy engine overrides stored in the node by container id.
// List local access policy engine overrides stored in the node by container
// id.
ListChainLocalOverrides(context.Context, *ListChainLocalOverridesRequest) (*ListChainLocalOverridesResponse, error)
// Remove local access policy engine overrides stored in the node by chaind id.
// Remove local access policy engine overrides stored in the node by chaind
// id.
RemoveChainLocalOverride(context.Context, *RemoveChainLocalOverrideRequest) (*RemoveChainLocalOverrideResponse, error)
// Remove local access policy engine overrides stored in the node by chaind id.
// Remove local access policy engine overrides stored in the node by chaind
// id.
RemoveChainLocalOverridesByTarget(context.Context, *RemoveChainLocalOverridesByTargetRequest) (*RemoveChainLocalOverridesByTargetResponse, error)
// List targets of the local APE overrides stored in the node.
ListTargetsLocalOverrides(context.Context, *ListTargetsLocalOverridesRequest) (*ListTargetsLocalOverridesResponse, error)

View file

@ -205,6 +205,8 @@ const (
ChainTarget_UNDEFINED ChainTarget_TargetType = 0
ChainTarget_NAMESPACE ChainTarget_TargetType = 1
ChainTarget_CONTAINER ChainTarget_TargetType = 2
ChainTarget_USER ChainTarget_TargetType = 3
ChainTarget_GROUP ChainTarget_TargetType = 4
)
// Enum value maps for ChainTarget_TargetType.
@ -213,11 +215,15 @@ var (
0: "UNDEFINED",
1: "NAMESPACE",
2: "CONTAINER",
3: "USER",
4: "GROUP",
}
ChainTarget_TargetType_value = map[string]int32{
"UNDEFINED": 0,
"NAMESPACE": 1,
"CONTAINER": 2,
"USER": 3,
"GROUP": 4,
}
)
@ -814,40 +820,41 @@ var file_pkg_services_control_types_proto_rawDesc = []byte{
0x6d, 0x61, 0x50, 0x61, 0x74, 0x68, 0x22, 0x36, 0x0a, 0x0c, 0x42, 0x6c, 0x6f, 0x62, 0x73, 0x74,
0x6f, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79,
0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0x91,
0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0xa6,
0x01, 0x0a, 0x0b, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x33,
0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1f, 0x2e, 0x63,
0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67,
0x65, 0x74, 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74,
0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x39, 0x0a, 0x0a, 0x54, 0x61, 0x72, 0x67, 0x65,
0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x4e, 0x0a, 0x0a, 0x54, 0x61, 0x72, 0x67, 0x65,
0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0d, 0x0a, 0x09, 0x55, 0x4e, 0x44, 0x45, 0x46, 0x49, 0x4e,
0x45, 0x44, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x4e, 0x41, 0x4d, 0x45, 0x53, 0x50, 0x41, 0x43,
0x45, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x4e, 0x54, 0x41, 0x49, 0x4e, 0x45, 0x52,
0x10, 0x02, 0x2a, 0x4e, 0x0a, 0x0c, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74,
0x75, 0x73, 0x12, 0x14, 0x0a, 0x10, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x44,
0x45, 0x46, 0x49, 0x4e, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x4f, 0x4e, 0x4c, 0x49,
0x4e, 0x45, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x4f, 0x46, 0x46, 0x4c, 0x49, 0x4e, 0x45, 0x10,
0x02, 0x12, 0x0f, 0x0a, 0x0b, 0x4d, 0x41, 0x49, 0x4e, 0x54, 0x45, 0x4e, 0x41, 0x4e, 0x43, 0x45,
0x10, 0x03, 0x2a, 0x6a, 0x0a, 0x0c, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x53, 0x74, 0x61, 0x74,
0x75, 0x73, 0x12, 0x1b, 0x0a, 0x17, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x5f, 0x53, 0x54, 0x41,
0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x44, 0x45, 0x46, 0x49, 0x4e, 0x45, 0x44, 0x10, 0x00, 0x12,
0x0c, 0x0a, 0x08, 0x53, 0x54, 0x41, 0x52, 0x54, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x09, 0x0a,
0x05, 0x52, 0x45, 0x41, 0x44, 0x59, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d, 0x53, 0x48, 0x55, 0x54,
0x54, 0x49, 0x4e, 0x47, 0x5f, 0x44, 0x4f, 0x57, 0x4e, 0x10, 0x03, 0x12, 0x11, 0x0a, 0x0d, 0x52,
0x45, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x55, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x04, 0x2a, 0x6a,
0x0a, 0x09, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x14, 0x53,
0x48, 0x41, 0x52, 0x44, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x44, 0x45, 0x46, 0x49,
0x4e, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x52, 0x45, 0x41, 0x44, 0x5f, 0x57, 0x52,
0x49, 0x54, 0x45, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x52, 0x45, 0x41, 0x44, 0x5f, 0x4f, 0x4e,
0x4c, 0x59, 0x10, 0x02, 0x12, 0x0c, 0x0a, 0x08, 0x44, 0x45, 0x47, 0x52, 0x41, 0x44, 0x45, 0x44,
0x10, 0x03, 0x12, 0x16, 0x0a, 0x12, 0x44, 0x45, 0x47, 0x52, 0x41, 0x44, 0x45, 0x44, 0x5f, 0x52,
0x45, 0x41, 0x44, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x04, 0x42, 0x41, 0x5a, 0x3f, 0x67, 0x69,
0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54,
0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73,
0x74, 0x66, 0x73, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72,
0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x62, 0x06, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x33,
0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x55, 0x53, 0x45, 0x52, 0x10, 0x03, 0x12, 0x09, 0x0a, 0x05,
0x47, 0x52, 0x4f, 0x55, 0x50, 0x10, 0x04, 0x2a, 0x4e, 0x0a, 0x0c, 0x4e, 0x65, 0x74, 0x6d, 0x61,
0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x14, 0x0a, 0x10, 0x53, 0x54, 0x41, 0x54, 0x55,
0x53, 0x5f, 0x55, 0x4e, 0x44, 0x45, 0x46, 0x49, 0x4e, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0a, 0x0a,
0x06, 0x4f, 0x4e, 0x4c, 0x49, 0x4e, 0x45, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x4f, 0x46, 0x46,
0x4c, 0x49, 0x4e, 0x45, 0x10, 0x02, 0x12, 0x0f, 0x0a, 0x0b, 0x4d, 0x41, 0x49, 0x4e, 0x54, 0x45,
0x4e, 0x41, 0x4e, 0x43, 0x45, 0x10, 0x03, 0x2a, 0x6a, 0x0a, 0x0c, 0x48, 0x65, 0x61, 0x6c, 0x74,
0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1b, 0x0a, 0x17, 0x48, 0x45, 0x41, 0x4c, 0x54,
0x48, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x44, 0x45, 0x46, 0x49, 0x4e,
0x45, 0x44, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x53, 0x54, 0x41, 0x52, 0x54, 0x49, 0x4e, 0x47,
0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x52, 0x45, 0x41, 0x44, 0x59, 0x10, 0x02, 0x12, 0x11, 0x0a,
0x0d, 0x53, 0x48, 0x55, 0x54, 0x54, 0x49, 0x4e, 0x47, 0x5f, 0x44, 0x4f, 0x57, 0x4e, 0x10, 0x03,
0x12, 0x11, 0x0a, 0x0d, 0x52, 0x45, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x55, 0x52, 0x49, 0x4e,
0x47, 0x10, 0x04, 0x2a, 0x6a, 0x0a, 0x09, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65,
0x12, 0x18, 0x0a, 0x14, 0x53, 0x48, 0x41, 0x52, 0x44, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x55,
0x4e, 0x44, 0x45, 0x46, 0x49, 0x4e, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x52, 0x45,
0x41, 0x44, 0x5f, 0x57, 0x52, 0x49, 0x54, 0x45, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x52, 0x45,
0x41, 0x44, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x02, 0x12, 0x0c, 0x0a, 0x08, 0x44, 0x45, 0x47,
0x52, 0x41, 0x44, 0x45, 0x44, 0x10, 0x03, 0x12, 0x16, 0x0a, 0x12, 0x44, 0x45, 0x47, 0x52, 0x41,
0x44, 0x45, 0x44, 0x5f, 0x52, 0x45, 0x41, 0x44, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x04, 0x42,
0x41, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69,
0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62,
0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x70, 0x6b,
0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72,
0x6f, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (

View file

@ -7,10 +7,10 @@ option go_package = "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/con
// Signature of some message.
message Signature {
// Public key used for signing.
bytes key = 1 [json_name = "key"];
bytes key = 1 [ json_name = "key" ];
// Binary signature.
bytes sign = 2 [json_name = "signature"];
bytes sign = 2 [ json_name = "signature" ];
}
// Status of the storage node in the FrostFS network map.
@ -31,10 +31,10 @@ enum NetmapStatus {
// FrostFS node description.
message NodeInfo {
// Public key of the FrostFS node in a binary format.
bytes public_key = 1 [json_name = "publicKey"];
bytes public_key = 1 [ json_name = "publicKey" ];
// Ways to connect to a node.
repeated string addresses = 2 [json_name = "addresses"];
repeated string addresses = 2 [ json_name = "addresses" ];
// Administrator-defined Attributes of the FrostFS Storage Node.
//
@ -74,32 +74,32 @@ message NodeInfo {
// corresponding section in FrostFS Technical specification.
message Attribute {
// Key of the node attribute.
string key = 1 [json_name = "key"];
string key = 1 [ json_name = "key" ];
// Value of the node attribute.
string value = 2 [json_name = "value"];
string value = 2 [ json_name = "value" ];
// Parent keys, if any. For example for `City` it could be `Region` and
// `Country`.
repeated string parents = 3 [json_name = "parents"];
repeated string parents = 3 [ json_name = "parents" ];
}
// Carries list of the FrostFS node attributes in a key-value form. Key name
// must be a node-unique valid UTF-8 string. Value can't be empty. NodeInfo
// structures with duplicated attribute names or attributes with empty values
// will be considered invalid.
repeated Attribute attributes = 3 [json_name = "attributes"];
repeated Attribute attributes = 3 [ json_name = "attributes" ];
// Carries state of the FrostFS node.
NetmapStatus state = 4 [json_name = "state"];
NetmapStatus state = 4 [ json_name = "state" ];
}
// Network map structure.
message Netmap {
// Network map revision number.
uint64 epoch = 1 [json_name = "epoch"];
uint64 epoch = 1 [ json_name = "epoch" ];
// Nodes presented in network.
repeated NodeInfo nodes = 2 [json_name = "nodes"];
repeated NodeInfo nodes = 2 [ json_name = "nodes" ];
}
// Health status of the storage node application.
@ -123,16 +123,16 @@ enum HealthStatus {
// Shard description.
message ShardInfo {
// ID of the shard.
bytes shard_ID = 1 [json_name = "shardID"];
bytes shard_ID = 1 [ json_name = "shardID" ];
// Path to shard's metabase.
string metabase_path = 2 [json_name = "metabasePath"];
string metabase_path = 2 [ json_name = "metabasePath" ];
// Shard's blobstor info.
repeated BlobstorInfo blobstor = 3 [json_name = "blobstor"];
repeated BlobstorInfo blobstor = 3 [ json_name = "blobstor" ];
// Path to shard's write-cache, empty if disabled.
string writecache_path = 4 [json_name = "writecachePath"];
string writecache_path = 4 [ json_name = "writecachePath" ];
// Work mode of the shard.
ShardMode mode = 5;
@ -141,15 +141,15 @@ message ShardInfo {
uint32 errorCount = 6;
// Path to shard's pilorama storage.
string pilorama_path = 7 [json_name = "piloramaPath"];
string pilorama_path = 7 [ json_name = "piloramaPath" ];
}
// Blobstor component description.
message BlobstorInfo {
// Path to the root.
string path = 1 [json_name = "path"];
string path = 1 [ json_name = "path" ];
// Component type.
string type = 2 [json_name = "type"];
string type = 2 [ json_name = "type" ];
}
// Work mode of the shard.
@ -170,7 +170,6 @@ enum ShardMode {
DEGRADED_READ_ONLY = 4;
}
// ChainTarget is an object to which local overrides
// are applied.
message ChainTarget {
@ -180,6 +179,10 @@ message ChainTarget {
NAMESPACE = 1;
CONTAINER = 2;
USER = 3;
GROUP = 4;
}
TargetType type = 1;

View file

@ -12,6 +12,7 @@ import (
apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine"
nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
)
type checkerImpl struct {
@ -84,8 +85,13 @@ func (c *checkerImpl) CheckAPE(ctx context.Context, prm Prm) error {
return fmt.Errorf("failed to create ape request: %w", err)
}
status, ruleFound, err := c.chainRouter.IsAllowed(apechain.Ingress,
policyengine.NewRequestTarget(prm.Namespace, prm.Container.EncodeToString()), r)
pub, err := keys.NewPublicKeyFromString(prm.SenderKey)
if err != nil {
return err
}
rt := policyengine.NewRequestTargetExtended(prm.Namespace, prm.Container.EncodeToString(), fmt.Sprintf("%s:%s", prm.Namespace, pub.Address()), nil)
status, ruleFound, err := c.chainRouter.IsAllowed(apechain.Ingress, rt, r)
if err != nil {
return err
}

View file

@ -16,6 +16,7 @@ import (
policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine"
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine/inmemory"
nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/stretchr/testify/require"
)
@ -147,7 +148,9 @@ var (
role = "Container"
senderKey = hex.EncodeToString([]byte{1, 0, 0, 1})
senderPrivateKey, _ = keys.NewPrivateKey()
senderKey = hex.EncodeToString(senderPrivateKey.PublicKey().Bytes())
)
func TestAPECheck(t *testing.T) {

View file

@ -51,7 +51,8 @@ func (s *Service) checkAPE(container *core.Container, cid cid.ID, operation acl.
reqProps,
)
status, found, err := s.router.IsAllowed(apechain.Ingress, engine.NewRequestTarget(namespace, cid.EncodeToString()), request)
rt := engine.NewRequestTargetExtended(namespace, cid.EncodeToString(), fmt.Sprintf("%s:%s", namespace, publicKey.Address()), nil)
status, found, err := s.router.IsAllowed(apechain.Ingress, rt, request)
if err != nil {
return apeErr(err)
}