[#989] cli: Read and parse chains from file

* Introduce path flag to make add-rule command read and parse
  chain from file. File is binary/JSON-encoded chain.

Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
This commit is contained in:
Airat Arifullin 2024-02-16 12:36:42 +03:00 committed by aarifullin
parent 13d5cd3e21
commit b2491881bd
2 changed files with 45 additions and 10 deletions

View file

@ -2,6 +2,7 @@ package control
import ( import (
"encoding/hex" "encoding/hex"
"errors"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
@ -14,6 +15,7 @@ import (
const ( const (
ruleFlag = "rule" ruleFlag = "rule"
pathFlag = "path"
) )
var addRuleCmd = &cobra.Command{ var addRuleCmd = &cobra.Command{
@ -23,15 +25,13 @@ var addRuleCmd = &cobra.Command{
Example: `control add-rule --endpoint ... -w ... --address ... --chain-id ChainID --cid ... --rule "allow Object.Get *" Example: `control add-rule --endpoint ... -w ... --address ... --chain-id ChainID --cid ... --rule "allow Object.Get *"
--rule "deny Object.Get EbxzAdz5LB4uqxuz6crWKAumBNtZyK2rKsqQP7TdZvwr/*" --rule "deny Object.Get EbxzAdz5LB4uqxuz6crWKAumBNtZyK2rKsqQP7TdZvwr/*"
--rule "deny:QuotaLimitReached Object.Put Object.Resource:Department=HR *" --rule "deny:QuotaLimitReached Object.Put Object.Resource:Department=HR *"
control add-rule --endpoint ... -w ... --address ... --chain-id ChainID --cid ... --path some_chain.json
`, `,
Run: addRule, Run: addRule,
} }
func addRule(cmd *cobra.Command, _ []string) { func parseChain(cmd *cobra.Command) *apechain.Chain {
pk := key.Get(cmd)
target := parseTarget(cmd)
chainID, _ := cmd.Flags().GetString(chainIDFlag) chainID, _ := cmd.Flags().GetString(chainIDFlag)
hexEncoded, _ := cmd.Flags().GetBool(chainIDHexFlag) hexEncoded, _ := cmd.Flags().GetBool(chainIDHexFlag)
@ -43,20 +43,34 @@ func addRule(cmd *cobra.Command, _ []string) {
commonCmd.ExitOnErr(cmd, "can't decode chain ID as hex: %w", err) commonCmd.ExitOnErr(cmd, "can't decode chain ID as hex: %w", err)
} }
rule, _ := cmd.Flags().GetStringArray(ruleFlag)
chain := new(apechain.Chain) chain := new(apechain.Chain)
commonCmd.ExitOnErr(cmd, "parser error: %w", util.ParseAPEChain(chain, rule))
chain.ID = apechain.ID(chainIDRaw) chain.ID = apechain.ID(chainIDRaw)
serializedChain := chain.Bytes()
if rules, _ := cmd.Flags().GetStringArray(ruleFlag); len(rules) > 0 {
commonCmd.ExitOnErr(cmd, "parser error: %w", util.ParseAPEChain(chain, rules))
} else if encPath, _ := cmd.Flags().GetString(pathFlag); encPath != "" {
commonCmd.ExitOnErr(cmd, "decode binary or json error: %w", util.ParseAPEChainBinaryOrJSON(chain, encPath))
} else {
commonCmd.ExitOnErr(cmd, "parser error", errors.New("rule is not passed"))
}
cmd.Println("Parsed chain:") cmd.Println("Parsed chain:")
util.PrintHumanReadableAPEChain(cmd, chain) util.PrintHumanReadableAPEChain(cmd, chain)
return chain
}
func addRule(cmd *cobra.Command, _ []string) {
pk := key.Get(cmd)
target := parseTarget(cmd)
parsed := parseChain(cmd)
req := &control.AddChainLocalOverrideRequest{ req := &control.AddChainLocalOverrideRequest{
Body: &control.AddChainLocalOverrideRequest_Body{ Body: &control.AddChainLocalOverrideRequest_Body{
Target: target, Target: target,
Chain: serializedChain, Chain: parsed.Bytes(),
}, },
} }
@ -81,9 +95,12 @@ func initControlAddRuleCmd() {
ff := addRuleCmd.Flags() ff := addRuleCmd.Flags()
ff.StringArray(ruleFlag, []string{}, "Rule statement") ff.StringArray(ruleFlag, []string{}, "Rule statement")
ff.String(pathFlag, "", "Path to encoded chain in JSON or binary format")
ff.String(chainIDFlag, "", "Assign ID to the parsed chain") ff.String(chainIDFlag, "", "Assign ID to the parsed chain")
ff.String(targetNameFlag, "", targetNameDesc) ff.String(targetNameFlag, "", targetNameDesc)
ff.String(targetTypeFlag, "", targetTypeDesc) ff.String(targetTypeFlag, "", targetTypeDesc)
_ = addRuleCmd.MarkFlagRequired(targetTypeFlag) _ = addRuleCmd.MarkFlagRequired(targetTypeFlag)
ff.Bool(chainIDHexFlag, false, "Flag to parse chain ID as hex") ff.Bool(chainIDHexFlag, false, "Flag to parse chain ID as hex")
addRuleCmd.MarkFlagsMutuallyExclusive(pathFlag, ruleFlag)
} }

View file

@ -3,6 +3,7 @@ package util
import ( import (
"errors" "errors"
"fmt" "fmt"
"os"
"strconv" "strconv"
"strings" "strings"
@ -57,6 +58,23 @@ func PrintHumanReadableAPEChain(cmd *cobra.Command, chain *apechain.Chain) {
} }
} }
func ParseAPEChainBinaryOrJSON(chain *apechain.Chain, path string) error {
data, err := os.ReadFile(path)
if err != nil {
return fmt.Errorf("read file <%s>: %w", path, err)
}
err = chain.UnmarshalBinary(data)
if err != nil {
err = chain.UnmarshalJSON(data)
if err != nil {
return fmt.Errorf("invalid format: %w", err)
}
}
return nil
}
// ParseAPEChain parses APE chain rules. // ParseAPEChain parses APE chain rules.
func ParseAPEChain(chain *apechain.Chain, rules []string) error { func ParseAPEChain(chain *apechain.Chain, rules []string) error {
if len(rules) == 0 { if len(rules) == 0 {