[#1189] cli: Make util subcommand convert eACL to APE chains
Build / Build Components (1.21) (pull_request) Successful in 3m15s Details
DCO action / DCO (pull_request) Successful in 3m8s Details
Build / Build Components (1.22) (pull_request) Successful in 5m0s Details
Vulncheck / Vulncheck (pull_request) Successful in 4m17s Details
Tests and linters / gopls check (pull_request) Successful in 5m50s Details
Tests and linters / Lint (pull_request) Successful in 7m12s Details
Tests and linters / Staticcheck (pull_request) Successful in 7m20s Details
Pre-commit hooks / Pre-commit (pull_request) Successful in 9m13s Details
Tests and linters / Tests (1.21) (pull_request) Successful in 10m8s Details
Tests and linters / Tests with -race (pull_request) Successful in 10m18s Details
Tests and linters / Tests (1.22) (pull_request) Successful in 11m1s Details

Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
Airat Arifullin 2024-06-18 18:29:56 +03:00
parent 5b100699d7
commit 69bb1ed36d
3 changed files with 76 additions and 25 deletions

View File

@ -6,9 +6,17 @@ import (
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
apeutil "git.frostfs.info/TrueCloudLab/frostfs-node/internal/ape"
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
const (
fromFlagStr = "from"
toFlagStr = "to"
apeFlagStr = "ape"
)
var convertEACLCmd = &cobra.Command{ var convertEACLCmd = &cobra.Command{
Use: "eacl", Use: "eacl",
Short: "Convert representation of extended ACL table", Short: "Convert representation of extended ACL table",
@ -18,24 +26,35 @@ var convertEACLCmd = &cobra.Command{
func initConvertEACLCmd() { func initConvertEACLCmd() {
flags := convertEACLCmd.Flags() flags := convertEACLCmd.Flags()
flags.String("from", "", "File with JSON or binary encoded extended ACL table") flags.String(fromFlagStr, "", "File with JSON or binary encoded extended ACL table")
_ = convertEACLCmd.MarkFlagFilename("from") _ = convertEACLCmd.MarkFlagFilename(fromFlagStr)
_ = convertEACLCmd.MarkFlagRequired("from") _ = convertEACLCmd.MarkFlagRequired(fromFlagStr)
flags.String("to", "", "File to dump extended ACL table (default: binary encoded)") flags.String(toFlagStr, "", "File to dump extended ACL table (default: binary encoded)")
flags.Bool(commonflags.JSON, false, "Dump extended ACL table in JSON encoding") flags.Bool(commonflags.JSON, false, "Dump extended ACL table in JSON encoding")
flags.Bool(apeFlagStr, false, "Dump converted eACL table to APE chain format")
convertEACLCmd.MarkFlagsMutuallyExclusive(apeFlagStr, commonflags.JSON)
} }
func convertEACLTable(cmd *cobra.Command, _ []string) { func convertEACLTable(cmd *cobra.Command, _ []string) {
pathFrom := cmd.Flag("from").Value.String() pathFrom := cmd.Flag(fromFlagStr).Value.String()
to := cmd.Flag("to").Value.String() to := cmd.Flag(toFlagStr).Value.String()
jsonFlag, _ := cmd.Flags().GetBool(commonflags.JSON) jsonFlag, _ := cmd.Flags().GetBool(commonflags.JSON)
apeFlag, _ := cmd.Flags().GetBool(apeFlagStr)
table := common.ReadEACL(cmd, pathFrom) table := common.ReadEACL(cmd, pathFrom)
var data []byte var data []byte
var err error var err error
if jsonFlag || len(to) == 0 {
if apeFlag {
var ch *chain.Chain
ch, err = apeutil.ConvertEACLToAPE(table)
commonCmd.ExitOnErr(cmd, "convert eACL table to APE chain error: %w", err)
data = ch.Bytes()
} else if jsonFlag || len(to) == 0 {
data, err = table.MarshalJSON() data, err = table.MarshalJSON()
commonCmd.ExitOnErr(cmd, "can't JSON encode extended ACL table: %w", err) commonCmd.ExitOnErr(cmd, "can't JSON encode extended ACL table: %w", err)
} else { } else {

View File

@ -69,6 +69,50 @@ func ConvertEACLToAPE(eaclTable *eacl.Table) (*apechain.Chain, error) {
return res, nil return res, nil
} }
func apeRoleConds(role eacl.Role) (res []apechain.Condition) {
switch role {
case eacl.RoleSystem:
res = append(res,
apechain.Condition{
Op: apechain.CondStringEquals,
Kind: apechain.KindRequest,
Key: nativeschema.PropertyKeyActorRole,
Value: nativeschema.PropertyValueContainerRoleContainer,
},
)
res = append(res,
apechain.Condition{
Op: apechain.CondStringEquals,
Kind: apechain.KindRequest,
Key: nativeschema.PropertyKeyActorRole,
Value: nativeschema.PropertyValueContainerRoleIR,
},
)
case eacl.RoleOthers:
res = append(res,
apechain.Condition{
Op: apechain.CondStringEquals,
Kind: apechain.KindRequest,
Key: nativeschema.PropertyKeyActorRole,
Value: nativeschema.PropertyValueContainerRoleOthers,
},
)
case eacl.RoleUser:
res = append(res,
apechain.Condition{
Op: apechain.CondStringEquals,
Kind: apechain.KindRequest,
Key: nativeschema.PropertyKeyActorRole,
Value: nativeschema.PropertyValueContainerRoleOwner,
},
)
case eacl.RoleUnknown:
// such condition has no effect
default:
}
return
}
func appendTargetsOnly(source []apechain.Rule, st apechain.Status, act apechain.Actions, res apechain.Resources, targets []eacl.Target) []apechain.Rule { func appendTargetsOnly(source []apechain.Rule, st apechain.Status, act apechain.Actions, res apechain.Resources, targets []eacl.Target) []apechain.Rule {
// see https://git.frostfs.info/TrueCloudLab/frostfs-sdk-go/src/commit/ab75edd70939564421936d207ef80d6c1398b51b/eacl/validator.go#L101 // see https://git.frostfs.info/TrueCloudLab/frostfs-sdk-go/src/commit/ab75edd70939564421936d207ef80d6c1398b51b/eacl/validator.go#L101
// role OR public key must be equal // role OR public key must be equal
@ -79,13 +123,7 @@ func appendTargetsOnly(source []apechain.Rule, st apechain.Status, act apechain.
Any: true, Any: true,
} }
for _, target := range targets { for _, target := range targets {
var roleCondition apechain.Condition rule.Condition = append(rule.Condition, apeRoleConds(target.Role())...)
roleCondition.Kind = apechain.KindRequest
roleCondition.Key = nativeschema.PropertyKeyActorRole
roleCondition.Value = target.Role().String()
roleCondition.Op = apechain.CondStringEquals
rule.Condition = append(rule.Condition, roleCondition)
for _, binKey := range target.BinaryKeys() { for _, binKey := range target.BinaryKeys() {
var pubKeyCondition apechain.Condition var pubKeyCondition apechain.Condition
pubKeyCondition.Kind = apechain.KindRequest pubKeyCondition.Kind = apechain.KindRequest
@ -111,13 +149,7 @@ func appendTargetsAndFilters(source []apechain.Rule, st apechain.Status, act ape
Actions: act, Actions: act,
Resources: res, Resources: res,
} }
var roleCondition apechain.Condition rule.Condition = append(rule.Condition, apeRoleConds(target.Role())...)
roleCondition.Kind = apechain.KindRequest
roleCondition.Key = nativeschema.PropertyKeyActorRole
roleCondition.Value = target.Role().String()
roleCondition.Op = apechain.CondStringEquals
rule.Condition = append(rule.Condition, roleCondition)
rule.Condition, err = appendFilters(rule.Condition, filters) rule.Condition, err = appendFilters(rule.Condition, filters)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -105,7 +105,7 @@ func TestNoFilters(t *testing.T) {
req := &testRequest{ req := &testRequest{
props: map[string]string{ props: map[string]string{
nativeschema.PropertyKeyActorRole: eacl.RoleOthers.String(), nativeschema.PropertyKeyActorRole: nativeschema.PropertyValueContainerRoleOthers,
}, },
res: &testResource{name: fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cnrID.EncodeToString())}, res: &testResource{name: fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cnrID.EncodeToString())},
} }
@ -150,7 +150,7 @@ func TestNoFilters(t *testing.T) {
req := &testRequest{ req := &testRequest{
props: map[string]string{ props: map[string]string{
nativeschema.PropertyKeyActorRole: eacl.RoleOthers.String(), nativeschema.PropertyKeyActorRole: nativeschema.PropertyValueContainerRoleOthers,
nativeschema.PropertyKeyActorPublicKey: string(p2.PublicKey().Bytes()), nativeschema.PropertyKeyActorPublicKey: string(p2.PublicKey().Bytes()),
}, },
res: &testResource{name: fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cnrID.EncodeToString())}, res: &testResource{name: fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cnrID.EncodeToString())},
@ -283,7 +283,7 @@ func TestWithFilters(t *testing.T) {
req := &testRequest{ req := &testRequest{
props: map[string]string{ props: map[string]string{
nativeschema.PropertyKeyActorRole: eacl.RoleOthers.String(), nativeschema.PropertyKeyActorRole: nativeschema.PropertyValueContainerRoleOthers,
}, },
res: &testResource{ res: &testResource{
name: fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cnrID.EncodeToString()), name: fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cnrID.EncodeToString()),
@ -335,7 +335,7 @@ func TestWithFilters(t *testing.T) {
req := &testRequest{ req := &testRequest{
props: map[string]string{ props: map[string]string{
nativeschema.PropertyKeyActorRole: eacl.RoleOthers.String(), nativeschema.PropertyKeyActorRole: nativeschema.PropertyValueContainerRoleOthers,
attrKey: attrValue, attrKey: attrValue,
}, },
res: &testResource{ res: &testResource{