package apemanager import ( "encoding/hex" "errors" internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" apeSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape" client_sdk "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" "github.com/spf13/cobra" ) const ( chainIDFlag = "chain-id" chainIDHexFlag = "chain-id-hex" ruleFlag = "rule" pathFlag = "path" ) const ( targetNameFlag = "target-name" targetNameDesc = "Resource name in APE resource name format" targetTypeFlag = "target-type" targetTypeDesc = "Resource type(container/namespace)" ) const ( namespaceTarget = "namespace" containerTarget = "container" userTarget = "user" groupTarget = "group" ) var errUnknownTargetType = errors.New("unknown target type") var addCmd = &cobra.Command{ Use: "add", Short: "Add rule chain for a target", Run: add, PersistentPreRun: func(cmd *cobra.Command, _ []string) { commonflags.Bind(cmd) }, } func parseTarget(cmd *cobra.Command) (ct apeSDK.ChainTarget) { typ, _ := cmd.Flags().GetString(targetTypeFlag) name, _ := cmd.Flags().GetString(targetNameFlag) ct.Name = name switch typ { case namespaceTarget: ct.TargetType = apeSDK.TargetTypeNamespace case containerTarget: var cnr cid.ID commonCmd.ExitOnErr(cmd, "can't decode container ID: %w", cnr.DecodeString(name)) ct.TargetType = apeSDK.TargetTypeContainer case userTarget: ct.TargetType = apeSDK.TargetTypeUser case groupTarget: ct.TargetType = apeSDK.TargetTypeGroup default: commonCmd.ExitOnErr(cmd, "read target type error: %w", errUnknownTargetType) } return ct } func parseChain(cmd *cobra.Command) apeSDK.Chain { chainID, _ := cmd.Flags().GetString(chainIDFlag) hexEncoded, _ := cmd.Flags().GetBool(chainIDHexFlag) chainIDRaw := []byte(chainID) if hexEncoded { var err error chainIDRaw, err = hex.DecodeString(chainID) commonCmd.ExitOnErr(cmd, "can't decode chain ID as hex: %w", err) } chain := new(apechain.Chain) chain.ID = apechain.ID(chainIDRaw) 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: %w", errors.New("rule is not passed")) } cmd.Println("Parsed chain:") util.PrintHumanReadableAPEChain(cmd, chain) serialized := chain.Bytes() return apeSDK.Chain{ Raw: serialized, } } func add(cmd *cobra.Command, _ []string) { c := parseChain(cmd) target := parseTarget(cmd) key := key.Get(cmd) cli := internalclient.GetSDKClientByFlag(cmd, key, commonflags.RPC) res, err := cli.APEManagerAddChain(cmd.Context(), client_sdk.PrmAPEManagerAddChain{ ChainTarget: target, Chain: c, }) commonCmd.ExitOnErr(cmd, "add chain error: %w", err) cmd.Println("Rule has been added.") cmd.Println("Chain ID: ", string(res.ChainID)) } func initAddCmd() { commonflags.Init(addCmd) ff := addCmd.Flags() 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(targetNameFlag, "", targetNameDesc) ff.String(targetTypeFlag, "", targetTypeDesc) _ = addCmd.MarkFlagRequired(targetTypeFlag) ff.Bool(chainIDHexFlag, false, "Flag to parse chain ID as hex") addCmd.MarkFlagsMutuallyExclusive(pathFlag, ruleFlag) }