forked from TrueCloudLab/frostfs-node
[#1157] cli: Support adding APE overrides to Bearer token
Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
This commit is contained in:
parent
4044e50d74
commit
1589b2e7bd
3 changed files with 138 additions and 2 deletions
|
@ -15,10 +15,12 @@ import (
|
|||
eaclSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
const (
|
||||
eaclFlag = "eacl"
|
||||
apeFlag = "ape"
|
||||
issuedAtFlag = "issued-at"
|
||||
notValidBeforeFlag = "not-valid-before"
|
||||
ownerFlag = "owner"
|
||||
|
@ -37,10 +39,17 @@ In this case --` + commonflags.RPC + ` flag should be specified and the epoch in
|
|||
is set to current epoch + n.
|
||||
`,
|
||||
Run: createToken,
|
||||
PersistentPreRun: func(cmd *cobra.Command, _ []string) {
|
||||
ff := cmd.Flags()
|
||||
|
||||
_ = viper.BindPFlag(commonflags.WalletPath, ff.Lookup(commonflags.WalletPath))
|
||||
_ = viper.BindPFlag(commonflags.Account, ff.Lookup(commonflags.Account))
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
createCmd.Flags().StringP(eaclFlag, "e", "", "Path to the extended ACL table (mutually exclusive with --impersonate flag)")
|
||||
createCmd.Flags().StringP(eaclFlag, "e", "", "Path to the extended ACL table (mutually exclusive with --impersonate and --ape flag)")
|
||||
createCmd.Flags().StringP(apeFlag, "a", "", "Path to the JSON-encoded APE override (mutually exclusive with --impersonate and --eacl flag)")
|
||||
createCmd.Flags().StringP(issuedAtFlag, "i", "+0", "Epoch to issue token at")
|
||||
createCmd.Flags().StringP(notValidBeforeFlag, "n", "+0", "Not valid before epoch")
|
||||
createCmd.Flags().StringP(commonflags.ExpireAt, "x", "", "The last active epoch for the token")
|
||||
|
@ -49,10 +58,13 @@ func init() {
|
|||
createCmd.Flags().Bool(jsonFlag, false, "Output token in JSON")
|
||||
createCmd.Flags().Bool(impersonateFlag, false, "Mark token as impersonate to consider the token signer as the request owner (mutually exclusive with --eacl flag)")
|
||||
createCmd.Flags().StringP(commonflags.RPC, commonflags.RPCShorthand, commonflags.RPCDefault, commonflags.RPCUsage)
|
||||
createCmd.Flags().StringP(commonflags.WalletPath, commonflags.WalletPathShorthand, commonflags.WalletPathDefault, commonflags.WalletPathUsage)
|
||||
createCmd.Flags().StringP(commonflags.Account, commonflags.AccountShorthand, commonflags.AccountDefault, commonflags.AccountUsage)
|
||||
|
||||
createCmd.MarkFlagsMutuallyExclusive(eaclFlag, impersonateFlag)
|
||||
createCmd.MarkFlagsMutuallyExclusive(eaclFlag, apeFlag, impersonateFlag)
|
||||
|
||||
_ = cobra.MarkFlagFilename(createCmd.Flags(), eaclFlag)
|
||||
_ = cobra.MarkFlagFilename(createCmd.Flags(), apeFlag)
|
||||
|
||||
_ = cobra.MarkFlagRequired(createCmd.Flags(), commonflags.ExpireAt)
|
||||
_ = cobra.MarkFlagRequired(createCmd.Flags(), ownerFlag)
|
||||
|
@ -119,6 +131,14 @@ func createToken(cmd *cobra.Command, _ []string) {
|
|||
b.SetEACLTable(*table)
|
||||
}
|
||||
|
||||
apePath, _ := cmd.Flags().GetString(apeFlag)
|
||||
if apePath != "" {
|
||||
var apeOverride bearer.APEOverride
|
||||
raw, err := os.ReadFile(apePath)
|
||||
commonCmd.ExitOnErr(cmd, "can't read APE rules: %w", err)
|
||||
commonCmd.ExitOnErr(cmd, "can't parse APE rules: %w", json.Unmarshal(raw, &apeOverride))
|
||||
b.SetAPEOverride(apeOverride)
|
||||
}
|
||||
var data []byte
|
||||
|
||||
toJSON, _ := cmd.Flags().GetBool(jsonFlag)
|
||||
|
|
115
cmd/frostfs-cli/modules/bearer/generate_override.go
Normal file
115
cmd/frostfs-cli/modules/bearer/generate_override.go
Normal file
|
@ -0,0 +1,115 @@
|
|||
package bearer
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
|
||||
parseutil "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"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
|
||||
cidSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||
apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
errChainIDCannotBeEmpty = errors.New("chain id cannot be empty")
|
||||
errRuleIsNotParsed = errors.New("rule is not passed")
|
||||
)
|
||||
|
||||
const (
|
||||
chainIDFlag = "chain-id"
|
||||
chainIDHexFlag = "chain-id-hex"
|
||||
ruleFlag = "rule"
|
||||
pathFlag = "path"
|
||||
outputFlag = "output"
|
||||
)
|
||||
|
||||
var generateAPEOverrideCmd = &cobra.Command{
|
||||
Use: "generate-ape-override",
|
||||
Short: "Generate APE override.",
|
||||
Long: `Generate APE override by target and APE chains. Util command.
|
||||
|
||||
Generated APE override can be dumped to a file in JSON format that is passed to
|
||||
"create" command.
|
||||
`,
|
||||
Run: genereateAPEOverride,
|
||||
}
|
||||
|
||||
func genereateAPEOverride(cmd *cobra.Command, _ []string) {
|
||||
c := parseChain(cmd)
|
||||
|
||||
targetCID, _ := cmd.Flags().GetString(commonflags.CIDFlag)
|
||||
var cid cidSDK.ID
|
||||
commonCmd.ExitOnErr(cmd, "invalid cid format: %w", cid.DecodeString(targetCID))
|
||||
|
||||
override := &bearer.APEOverride{
|
||||
Target: apeSDK.ChainTarget{
|
||||
TargetType: apeSDK.TargetTypeContainer,
|
||||
Name: targetCID,
|
||||
},
|
||||
Chains: []apeSDK.Chain{
|
||||
{
|
||||
Raw: c.Bytes(),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
overrideMarshalled, err := override.MarshalJSON()
|
||||
commonCmd.ExitOnErr(cmd, "failed to marshal APE override: %w", err)
|
||||
|
||||
outputPath, _ := cmd.Flags().GetString(outputFlag)
|
||||
if outputPath != "" {
|
||||
err := os.WriteFile(outputPath, []byte(overrideMarshalled), 0o644)
|
||||
commonCmd.ExitOnErr(cmd, "dump error: %w", err)
|
||||
} else {
|
||||
fmt.Print("\n")
|
||||
fmt.Println(string(overrideMarshalled))
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
ff := generateAPEOverrideCmd.Flags()
|
||||
|
||||
ff.StringP(commonflags.CIDFlag, "", "", "Target container ID.")
|
||||
_ = cobra.MarkFlagRequired(createCmd.Flags(), commonflags.CIDFlag)
|
||||
|
||||
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.Bool(chainIDHexFlag, false, "Flag to parse chain ID as hex")
|
||||
|
||||
ff.String(outputFlag, "", "Output path to dump result JSON-encoded APE override")
|
||||
_ = cobra.MarkFlagFilename(createCmd.Flags(), outputFlag)
|
||||
}
|
||||
|
||||
func parseChainID(cmd *cobra.Command) apechain.ID {
|
||||
chainID, _ := cmd.Flags().GetString(chainIDFlag)
|
||||
if chainID == "" {
|
||||
commonCmd.ExitOnErr(cmd, "read chain id error: %w",
|
||||
errChainIDCannotBeEmpty)
|
||||
}
|
||||
return apechain.ID(chainID)
|
||||
}
|
||||
|
||||
func parseChain(cmd *cobra.Command) *apechain.Chain {
|
||||
chain := new(apechain.Chain)
|
||||
|
||||
if rules, _ := cmd.Flags().GetStringArray(ruleFlag); len(rules) > 0 {
|
||||
commonCmd.ExitOnErr(cmd, "parser error: %w", parseutil.ParseAPEChain(chain, rules))
|
||||
} else if encPath, _ := cmd.Flags().GetString(pathFlag); encPath != "" {
|
||||
commonCmd.ExitOnErr(cmd, "decode binary or json error: %w", parseutil.ParseAPEChainBinaryOrJSON(chain, encPath))
|
||||
} else {
|
||||
commonCmd.ExitOnErr(cmd, "parser error: %w", errRuleIsNotParsed)
|
||||
}
|
||||
|
||||
chain.ID = parseChainID(cmd)
|
||||
|
||||
cmd.Println("Parsed chain:")
|
||||
parseutil.PrintHumanReadableAPEChain(cmd, chain)
|
||||
|
||||
return chain
|
||||
}
|
|
@ -11,4 +11,5 @@ var Cmd = &cobra.Command{
|
|||
|
||||
func init() {
|
||||
Cmd.AddCommand(createCmd)
|
||||
Cmd.AddCommand(generateAPEOverrideCmd)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue