diff --git a/cmd/frostfs-cli/modules/control/add_rule.go b/cmd/frostfs-cli/modules/control/add_rule.go index f57823ed3..ca9220009 100644 --- a/cmd/frostfs-cli/modules/control/add_rule.go +++ b/cmd/frostfs-cli/modules/control/add_rule.go @@ -4,6 +4,7 @@ import ( "bytes" "crypto/sha256" "encoding/json" + "fmt" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" @@ -13,6 +14,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" + nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/spf13/cobra" ) @@ -60,10 +62,15 @@ func addRule(cmd *cobra.Command, _ []string) { cmd.Println("Container ID: " + cidStr) cmd.Println("Parsed chain:\n" + prettyJSONFormat(cmd, serializedChain)) + name := fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cidStr) + req := &control.AddChainLocalOverrideRequest{ Body: &control.AddChainLocalOverrideRequest_Body{ - ContainerId: rawCID, - Chain: serializedChain, + Target: &control.ChainTarget{ + Type: control.ChainTarget_CONTAINER, + Name: name, + }, + Chain: serializedChain, }, } diff --git a/cmd/frostfs-cli/modules/control/get_rule.go b/cmd/frostfs-cli/modules/control/get_rule.go index 0c34a696e..962ef179b 100644 --- a/cmd/frostfs-cli/modules/control/get_rule.go +++ b/cmd/frostfs-cli/modules/control/get_rule.go @@ -2,6 +2,7 @@ package control import ( "crypto/sha256" + "fmt" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" @@ -10,6 +11,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" + nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/spf13/cobra" ) @@ -32,10 +34,15 @@ func getRule(cmd *cobra.Command, _ []string) { chainID, _ := cmd.Flags().GetString(chainIDFlag) + name := fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cidStr) + req := &control.GetChainLocalOverrideRequest{ Body: &control.GetChainLocalOverrideRequest_Body{ - ContainerId: rawCID, - ChainId: chainID, + Target: &control.ChainTarget{ + Name: name, + Type: control.ChainTarget_CONTAINER, + }, + ChainId: chainID, }, } diff --git a/cmd/frostfs-cli/modules/control/list_rules.go b/cmd/frostfs-cli/modules/control/list_rules.go index 6a0879d0e..c1e47f483 100644 --- a/cmd/frostfs-cli/modules/control/list_rules.go +++ b/cmd/frostfs-cli/modules/control/list_rules.go @@ -2,6 +2,7 @@ package control import ( "crypto/sha256" + "fmt" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" @@ -10,6 +11,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" + nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/spf13/cobra" ) @@ -30,9 +32,14 @@ func listRules(cmd *cobra.Command, _ []string) { rawCID := make([]byte, sha256.Size) cnr.Encode(rawCID) + name := fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cidStr) + req := &control.ListChainLocalOverridesRequest{ Body: &control.ListChainLocalOverridesRequest_Body{ - ContainerId: rawCID, + Target: &control.ChainTarget{ + Name: name, + Type: control.ChainTarget_CONTAINER, + }, }, } diff --git a/cmd/frostfs-cli/modules/control/remove_rule.go b/cmd/frostfs-cli/modules/control/remove_rule.go index de064536b..c3f4aeb0c 100644 --- a/cmd/frostfs-cli/modules/control/remove_rule.go +++ b/cmd/frostfs-cli/modules/control/remove_rule.go @@ -2,6 +2,7 @@ package control import ( "crypto/sha256" + "fmt" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" @@ -9,6 +10,7 @@ import ( commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/spf13/cobra" ) @@ -35,10 +37,15 @@ func removeRule(cmd *cobra.Command, _ []string) { chainID, _ := cmd.Flags().GetString(chainIDFlag) + name := fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cidStr) + req := &control.RemoveChainLocalOverrideRequest{ Body: &control.RemoveChainLocalOverrideRequest_Body{ - ContainerId: rawCID, - ChainId: chainID, + Target: &control.ChainTarget{ + Name: name, + Type: control.ChainTarget_CONTAINER, + }, + ChainId: chainID, }, } diff --git a/go.mod b/go.mod index aa0f689c1..43ff1648a 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231122162120-56debcfa569e git.frostfs.info/TrueCloudLab/hrw v1.2.1 - git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231128145636-a0a35bf4bf31 + git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231205092054-2d4a9fc6dcb3 git.frostfs.info/TrueCloudLab/tzhash v1.8.0 github.com/cheggaaa/pb v1.0.29 github.com/chzyer/readline v1.5.1 diff --git a/go.sum b/go.sum index 0167d4a51..bede02d05 100644 Binary files a/go.sum and b/go.sum differ diff --git a/pkg/services/control/server/policy_engine.go b/pkg/services/control/server/policy_engine.go index 8565cd9c1..cbb6ba803 100644 --- a/pkg/services/control/server/policy_engine.go +++ b/pkg/services/control/server/policy_engine.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "strings" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" @@ -14,13 +15,36 @@ import ( "google.golang.org/grpc/status" ) +// extractCID extracts CID from the schema's pattern. +// TODO (aarifullin): This is temporary solution should be replaced by +// resource name validation. +func extractCID(resource string) (cid.ID, error) { + var cidStr string + + // Sscanf requires to make tokens delimited by spaces. + pattern := strings.Replace(nativeschema.ResourceFormatRootContainerObjects, "/", " ", -1) + resource = strings.Replace(resource, "/", " ", -1) + + if _, err := fmt.Sscanf(resource, pattern, &cidStr); err != nil { + err = fmt.Errorf("could not parse the target name '%s' to CID: %w", resource, err) + return cid.ID{}, err + } + var cid cid.ID + err := cid.DecodeString(cidStr) + return cid, err +} + func (s *Server) AddChainLocalOverride(_ context.Context, req *control.AddChainLocalOverrideRequest) (*control.AddChainLocalOverrideResponse, error) { if err := s.isValidRequest(req); err != nil { return nil, status.Error(codes.PermissionDenied, err.Error()) } - var cid cid.ID - err := cid.Decode(req.GetBody().GetContainerId()) + target := req.GetBody().GetTarget() + if target.Type != control.ChainTarget_CONTAINER { + return nil, status.Error(codes.Internal, fmt.Errorf("target type is not supported: %s", target.Type.String()).Error()) + } + + cid, err := extractCID(target.GetName()) if err != nil { return nil, status.Error(codes.InvalidArgument, err.Error()) } @@ -37,10 +61,12 @@ func (s *Server) AddChainLocalOverride(_ context.Context, req *control.AddChainL s.apeChainCounter.Add(1) // TODO (aarifullin): the such chain id is not well-designed yet. - chain.ID = apechain.ID(fmt.Sprintf("%s:%d", apechain.Ingress, s.apeChainCounter.Load())) + if chain.ID == "" { + chain.ID = apechain.ID(fmt.Sprintf("%s:%d", apechain.Ingress, s.apeChainCounter.Load())) + } resource := fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cid.EncodeToString()) - if _, err = src.LocalStorage().AddOverride(apechain.Ingress, resource, &chain); err != nil { + if _, err = src.LocalStorage().AddOverride(apechain.Ingress, engine.ContainerTarget(resource), &chain); err != nil { return nil, status.Error(getCodeByLocalStorageErr(err), err.Error()) } @@ -61,8 +87,12 @@ func (s *Server) GetChainLocalOverride(_ context.Context, req *control.GetChainL return nil, status.Error(codes.PermissionDenied, err.Error()) } - var cid cid.ID - err := cid.Decode(req.GetBody().GetContainerId()) + target := req.GetBody().GetTarget() + if target.Type != control.ChainTarget_CONTAINER { + return nil, status.Error(codes.Internal, fmt.Errorf("target type is not supported: %s", target.Type.String()).Error()) + } + + cid, err := extractCID(target.GetName()) if err != nil { return nil, status.Error(codes.InvalidArgument, err.Error()) } @@ -73,7 +103,7 @@ func (s *Server) GetChainLocalOverride(_ context.Context, req *control.GetChainL } resource := fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cid.EncodeToString()) - chain, err := src.LocalStorage().GetOverride(apechain.Ingress, resource, apechain.ID(req.GetBody().GetChainId())) + chain, err := src.LocalStorage().GetOverride(apechain.Ingress, engine.ContainerTarget(resource), apechain.ID(req.GetBody().GetChainId())) if err != nil { return nil, status.Error(getCodeByLocalStorageErr(err), err.Error()) } @@ -95,8 +125,12 @@ func (s *Server) ListChainLocalOverrides(_ context.Context, req *control.ListCha return nil, status.Error(codes.PermissionDenied, err.Error()) } - var cid cid.ID - err := cid.Decode(req.GetBody().GetContainerId()) + target := req.GetBody().GetTarget() + if target.Type != control.ChainTarget_CONTAINER { + return nil, status.Error(codes.Internal, fmt.Errorf("target type is not supported: %s", target.Type.String()).Error()) + } + + cid, err := extractCID(target.GetName()) if err != nil { return nil, status.Error(codes.InvalidArgument, err.Error()) } @@ -107,7 +141,7 @@ func (s *Server) ListChainLocalOverrides(_ context.Context, req *control.ListCha } resource := fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cid.EncodeToString()) - chains, err := src.LocalStorage().ListOverrides(apechain.Ingress, resource) + chains, err := src.LocalStorage().ListOverrides(apechain.Ingress, engine.ContainerTarget(resource)) if err != nil { return nil, status.Error(getCodeByLocalStorageErr(err), err.Error()) } @@ -133,8 +167,12 @@ func (s *Server) RemoveChainLocalOverride(_ context.Context, req *control.Remove return nil, status.Error(codes.PermissionDenied, err.Error()) } - var cid cid.ID - err := cid.Decode(req.GetBody().GetContainerId()) + target := req.GetBody().GetTarget() + if target.Type != control.ChainTarget_CONTAINER { + return nil, status.Error(codes.Internal, fmt.Errorf("target type is not supported: %s", target.Type.String()).Error()) + } + + cid, err := extractCID(target.GetName()) if err != nil { return nil, status.Error(codes.InvalidArgument, err.Error()) } @@ -145,7 +183,7 @@ func (s *Server) RemoveChainLocalOverride(_ context.Context, req *control.Remove } resource := fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cid.EncodeToString()) - if err = src.LocalStorage().RemoveOverride(apechain.Ingress, resource, apechain.ID(req.GetBody().GetChainId())); err != nil { + if err = src.LocalStorage().RemoveOverride(apechain.Ingress, engine.ContainerTarget(resource), apechain.ID(req.GetBody().GetChainId())); err != nil { return nil, status.Error(getCodeByLocalStorageErr(err), err.Error()) } resp := &control.RemoveChainLocalOverrideResponse{ diff --git a/pkg/services/control/service.pb.go b/pkg/services/control/service.pb.go index 346a43664..8b8739aba 100644 Binary files a/pkg/services/control/service.pb.go and b/pkg/services/control/service.pb.go differ diff --git a/pkg/services/control/service.proto b/pkg/services/control/service.proto index e7d218f20..cbc3aaf54 100644 --- a/pkg/services/control/service.proto +++ b/pkg/services/control/service.proto @@ -421,10 +421,12 @@ message StopShardEvacuationResponse { // AddChainLocalOverride request. message AddChainLocalOverrideRequest { message Body { - // Container id for which the overrides are applied. - bytes container_id = 1; + // Target for which the overrides are applied. + ChainTarget target = 1; - // Serialized rule chain. + // Serialized rule chain. If chain ID is left empty + // in the chain, then it will be generated and returned + // in the response. bytes chain = 2; } @@ -437,6 +439,8 @@ message AddChainLocalOverrideRequest { message AddChainLocalOverrideResponse { message Body { // Chain ID assigned for the added rule chain. + // If chain ID is left empty in the request, then + // it will be generated. string chain_id = 1; } @@ -448,8 +452,8 @@ message AddChainLocalOverrideResponse { // GetChainLocalOverride request. message GetChainLocalOverrideRequest { message Body { - // Container id for which the overrides are defined. - bytes container_id = 1; + // Target for which the overrides are applied. + ChainTarget target = 1; // Chain ID assigned for the added rule chain. string chain_id = 2; @@ -475,8 +479,8 @@ message GetChainLocalOverrideResponse { // ListChainLocalOverrides request. message ListChainLocalOverridesRequest { message Body { - // Container id for which the overrides are defined. - bytes container_id = 1; + // Target for which the overrides are applied. + ChainTarget target = 1; } Body body = 1; @@ -498,8 +502,8 @@ message ListChainLocalOverridesResponse { message RemoveChainLocalOverrideRequest { message Body { - // Container id for which the overrides are defined. - bytes container_id = 1; + // Target for which the overrides are applied. + ChainTarget target = 1; // Chain ID assigned for the added rule chain. string chain_id = 2; diff --git a/pkg/services/control/service_frostfs.pb.go b/pkg/services/control/service_frostfs.pb.go index 852788a30..e163e54b7 100644 Binary files a/pkg/services/control/service_frostfs.pb.go and b/pkg/services/control/service_frostfs.pb.go differ diff --git a/pkg/services/control/types.pb.go b/pkg/services/control/types.pb.go index f031f8043..8f083d695 100644 Binary files a/pkg/services/control/types.pb.go and b/pkg/services/control/types.pb.go differ diff --git a/pkg/services/control/types.proto b/pkg/services/control/types.proto index b34988c2e..d1bc05e29 100644 --- a/pkg/services/control/types.proto +++ b/pkg/services/control/types.proto @@ -169,3 +169,20 @@ enum ShardMode { // DegradedReadOnly. DEGRADED_READ_ONLY = 4; } + + +// ChainTarget is an object to which local overrides +// are applied. +message ChainTarget { + enum TargetType { + UNDEFINED = 0; + + NAMESPACE = 1; + + CONTAINER = 2; + } + + TargetType type = 1; + + string Name = 2; +} \ No newline at end of file diff --git a/pkg/services/control/types_frostfs.pb.go b/pkg/services/control/types_frostfs.pb.go index ab246dbdc..858d85a1c 100644 Binary files a/pkg/services/control/types_frostfs.pb.go and b/pkg/services/control/types_frostfs.pb.go differ diff --git a/pkg/services/object/acl/ape.go b/pkg/services/object/acl/ape.go index 525ed5930..a48bb5c9f 100644 --- a/pkg/services/object/acl/ape.go +++ b/pkg/services/object/acl/ape.go @@ -9,6 +9,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" + policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" ) var errAPEChainNoSource = errors.New("could not get ape chain source for the container") @@ -36,7 +37,9 @@ func (c *apeCheckerImpl) CheckIfRequestPermitted(reqInfo v2.RequestInfo) error { request := new(Request) request.FromRequestInfo(reqInfo) - status, ruleFound, err := chainCache.IsAllowed(apechain.Ingress, "", request) + cnrTarget := getResource(reqInfo).Name() + + status, ruleFound, err := chainCache.IsAllowed(apechain.Ingress, policyengine.NewRequestTargetWithContainer(cnrTarget), request) if err != nil { return err }