[#414] authmate: Support setting policy chain #414
12 changed files with 284 additions and 93 deletions
|
@ -16,6 +16,7 @@ This document outlines major changes between releases.
|
|||
- Support tag checks in policies (#357, #365, #392)
|
||||
- Support IAM-MFA checks (#367)
|
||||
- More docs (#334, #353)
|
||||
- Add `register-user` command to `authmate` (#414)
|
||||
|
||||
### Changed
|
||||
- Update dependencies noted by govulncheck (#368)
|
||||
|
|
|
@ -16,6 +16,10 @@ type (
|
|||
frostFSIDInitError struct {
|
||||
err error
|
||||
}
|
||||
|
||||
policyInitError struct {
|
||||
err error
|
||||
}
|
||||
)
|
||||
|
||||
func wrapPreparationError(e error) error {
|
||||
|
@ -50,6 +54,14 @@ func (e frostFSIDInitError) Error() string {
|
|||
return e.err.Error()
|
||||
}
|
||||
|
||||
func wrapPolicyInitError(e error) error {
|
||||
return policyInitError{e}
|
||||
}
|
||||
|
||||
func (e policyInitError) Error() string {
|
||||
return e.err.Error()
|
||||
}
|
||||
|
||||
// ExitCode picks corresponding error code depending on the type of error provided.
|
||||
// Returns 1 if error type is unknown.
|
||||
func ExitCode(e error) int {
|
||||
|
@ -62,6 +74,8 @@ func ExitCode(e error) int {
|
|||
return 4
|
||||
case frostFSIDInitError:
|
||||
return 4
|
||||
case policyInitError:
|
||||
return 5
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@ import (
|
|||
"time"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/authmate"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/frostfs/frostfsid/contract"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/wallet"
|
||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
|
@ -36,16 +35,10 @@ const (
|
|||
lifetimeFlag = "lifetime"
|
||||
containerPolicyFlag = "container-policy"
|
||||
awsCLICredentialFlag = "aws-cli-credentials"
|
||||
frostfsIDFlag = "frostfsid"
|
||||
frostfsIDProxyFlag = "frostfsid-proxy"
|
||||
frostfsIDNamespaceFlag = "frostfsid-namespace"
|
||||
rpcEndpointFlag = "rpc-endpoint"
|
||||
attributesFlag = "attributes"
|
||||
)
|
||||
|
||||
const (
|
||||
walletPassphraseCfg = "wallet.passphrase"
|
||||
)
|
||||
const walletPassphraseCfg = "wallet.passphrase"
|
||||
|
||||
const (
|
||||
defaultAccessBoxLifetime = 30 * 24 * time.Hour
|
||||
|
@ -79,10 +72,6 @@ func initIssueSecretCmd() {
|
|||
issueSecretCmd.Flags().Duration(poolHealthcheckTimeoutFlag, defaultPoolHealthcheckTimeout, "Timeout for request to node to decide if it is alive")
|
||||
issueSecretCmd.Flags().Duration(poolRebalanceIntervalFlag, defaultPoolRebalanceInterval, "Interval for updating nodes health status")
|
||||
issueSecretCmd.Flags().Duration(poolStreamTimeoutFlag, defaultPoolStreamTimeout, "Timeout for individual operation in streaming RPC")
|
||||
issueSecretCmd.Flags().String(frostfsIDFlag, "", "FrostfsID contract hash (LE) or name in NNS to register public key in contract (rpc-endpoint flag also must be provided)")
|
||||
issueSecretCmd.Flags().String(frostfsIDProxyFlag, "", "Proxy contract hash (LE) or name in NNS to use when interact with frostfsid contract")
|
||||
issueSecretCmd.Flags().String(frostfsIDNamespaceFlag, "", "Namespace to register public key in frostfsid contract")
|
||||
issueSecretCmd.Flags().String(rpcEndpointFlag, "", "NEO node RPC address")
|
||||
issueSecretCmd.Flags().String(attributesFlag, "", "User attributes in form of Key1=Value1,Key2=Value2 (note: you cannot override system attributes)")
|
||||
|
||||
_ = issueSecretCmd.MarkFlagRequired(walletFlag)
|
||||
|
@ -148,29 +137,6 @@ func runIssueSecretCmd(cmd *cobra.Command, _ []string) error {
|
|||
return wrapFrostFSInitError(fmt.Errorf("failed to create FrostFS component: %s", err))
|
||||
}
|
||||
|
||||
frostFSID := viper.GetString(frostfsIDFlag)
|
||||
if frostFSID != "" {
|
||||
rpcAddress := viper.GetString(rpcEndpointFlag)
|
||||
if rpcAddress == "" {
|
||||
return wrapPreparationError(fmt.Errorf("you can use '%s' flag only along with '%s'", frostfsIDFlag, rpcEndpointFlag))
|
||||
}
|
||||
cfg := contract.Config{
|
||||
RPCAddress: rpcAddress,
|
||||
Contract: frostFSID,
|
||||
ProxyContract: viper.GetString(frostfsIDProxyFlag),
|
||||
Key: key,
|
||||
}
|
||||
|
||||
frostfsIDClient, err := createFrostFSID(ctx, log, cfg)
|
||||
if err != nil {
|
||||
return wrapFrostFSIDInitError(err)
|
||||
}
|
||||
|
||||
if err = registerPublicKey(frostfsIDClient, viper.GetString(frostfsIDNamespaceFlag), key.PublicKey()); err != nil {
|
||||
return wrapBusinessLogicError(fmt.Errorf("failed to register key in frostfsid: %w", err))
|
||||
}
|
||||
}
|
||||
|
||||
customAttrs, err := parseObjectAttrs(viper.GetString(attributesFlag))
|
||||
if err != nil {
|
||||
return wrapPreparationError(fmt.Errorf("failed to parse attributes: %s", err))
|
||||
|
|
202
cmd/s3-authmate/modules/register-user.go
Normal file
202
cmd/s3-authmate/modules/register-user.go
Normal file
|
@ -0,0 +1,202 @@
|
|||
package modules
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-contract/policy"
|
||||
ffsidContract "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/frostfs/frostfsid/contract"
|
||||
policyContact "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/frostfs/policy/contract"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/logs"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/wallet"
|
||||
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
var registerUserCmd = &cobra.Command{
|
||||
Use: "register-user",
|
||||
Short: "Register user and add allowed policy to him",
|
||||
Long: "Register user in FrostFSID contract and add allowed policies. This is need to get access to s3-gw operations.",
|
||||
Example: `frostfs-s3-authmate register-user --wallet wallet.json --rpc-endpoint http://morph-chain.frostfs.devenv:30333
|
||||
frostfs-s3-authmate register-user --wallet wallet.json --contract-wallet contract-wallet.json --rpc-endpoint http://morph-chain.frostfs.devenv:30333 --namespace namespace --frostfsid-name devenv --frostfsid-contract frostfsid.frostfs --proxy-contract proxy.frostfs --policy-contract policy.frostfs`,
|
||||
RunE: runRegisterUserCmd,
|
||||
}
|
||||
|
||||
const (
|
||||
frostfsIDContractFlag = "frostfsid-contract"
|
||||
proxyContractFlag = "proxy-contract"
|
||||
usernameFlag = "username"
|
||||
namespaceFlag = "namespace"
|
||||
policyContractFlag = "policy-contract"
|
||||
contractWalletFlag = "contract-wallet"
|
||||
contractWalletAddressFlag = "contract-wallet-address"
|
||||
rpcEndpointFlag = "rpc-endpoint"
|
||||
)
|
||||
|
||||
const walletContractPassphraseCfg = "wallet.contract.passphrase"
|
||||
|
||||
func initRegisterUserCmd() {
|
||||
registerUserCmd.Flags().String(walletFlag, "", "Path to the wallet with account of the user that will be registered in FrostFS ID contract")
|
||||
registerUserCmd.Flags().String(addressFlag, "", "Address of the user wallet that will be registered in FrostFS ID contract")
|
||||
registerUserCmd.Flags().String(frostfsIDContractFlag, "frostfsid.frostfs", "FrostfsID contract hash (LE) or name in NNS to register public key in contract")
|
||||
registerUserCmd.Flags().String(proxyContractFlag, "proxy.frostfs", "Proxy contract hash (LE) or name in NNS to use when interact with frostfsid contract")
|
||||
registerUserCmd.Flags().String(namespaceFlag, "", "Namespace to register public key in frostfsid contract and add policy chains")
|
||||
registerUserCmd.Flags().String(usernameFlag, "", "Username to set for public key in frostfsid contract")
|
||||
registerUserCmd.Flags().String(contractWalletFlag, "", "Path to wallet that will be used to interact with contracts (if missing key from wallet flag be used)")
|
||||
registerUserCmd.Flags().String(contractWalletAddressFlag, "", "Address of the contract wallet account")
|
||||
registerUserCmd.Flags().String(policyContractFlag, "policy.frostfs", "Policy contract hash (LE) or name in NNS to save allowed chains for key")
|
||||
registerUserCmd.Flags().String(rpcEndpointFlag, "", "NEO node RPC address")
|
||||
|
||||
_ = registerUserCmd.MarkFlagRequired(walletFlag)
|
||||
_ = registerUserCmd.MarkFlagRequired(rpcEndpointFlag)
|
||||
}
|
||||
|
||||
func runRegisterUserCmd(cmd *cobra.Command, _ []string) error {
|
||||
ctx, cancel := context.WithTimeout(cmd.Context(), viper.GetDuration(timeoutFlag))
|
||||
defer cancel()
|
||||
|
||||
log := getLogger()
|
||||
|
||||
key, contractKey, err := parseKeys()
|
||||
if err != nil {
|
||||
return wrapPreparationError(err)
|
||||
}
|
||||
|
||||
frostfsIDClient, err := initFrostFSIDContract(ctx, log, contractKey)
|
||||
if err != nil {
|
||||
return wrapFrostFSIDInitError(err)
|
||||
}
|
||||
|
||||
if err = registerPublicKey(log, frostfsIDClient, key.PublicKey()); err != nil {
|
||||
return wrapBusinessLogicError(err)
|
||||
}
|
||||
|
||||
policyClient, err := initPolicyContract(ctx, log, contractKey)
|
||||
if err != nil {
|
||||
return wrapPolicyInitError(err)
|
||||
}
|
||||
|
||||
if err = addAllowedPolicyChains(cmd, log, policyClient, key.PublicKey()); err != nil {
|
||||
return wrapBusinessLogicError(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseKeys() (userKey *keys.PrivateKey, contractKey *keys.PrivateKey, err error) {
|
||||
password := wallet.GetPassword(viper.GetViper(), walletPassphraseCfg)
|
||||
key, err := wallet.GetKeyFromPath(viper.GetString(walletFlag), viper.GetString(addressFlag), password)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to load frostfs private key: %s", err)
|
||||
}
|
||||
|
||||
contractKey = key
|
||||
if contractWallet := viper.GetString(contractWalletFlag); contractWallet != "" {
|
||||
password = wallet.GetPassword(viper.GetViper(), walletContractPassphraseCfg)
|
||||
contractKey, err = wallet.GetKeyFromPath(contractWallet, viper.GetString(contractWalletAddressFlag), password)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to load contract private key: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
return key, contractKey, nil
|
||||
}
|
||||
|
||||
func initFrostFSIDContract(ctx context.Context, log *zap.Logger, key *keys.PrivateKey) (*ffsidContract.FrostFSID, error) {
|
||||
log.Debug(logs.PrepareFrostfsIDClient)
|
||||
|
||||
cfg := ffsidContract.Config{
|
||||
RPCAddress: viper.GetString(rpcEndpointFlag),
|
||||
Contract: viper.GetString(frostfsIDContractFlag),
|
||||
ProxyContract: viper.GetString(proxyContractFlag),
|
||||
Key: key,
|
||||
}
|
||||
|
||||
cli, err := ffsidContract.New(ctx, cfg)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create frostfsid client: %w", err)
|
||||
}
|
||||
|
||||
return cli, nil
|
||||
}
|
||||
|
||||
func registerPublicKey(log *zap.Logger, cli *ffsidContract.FrostFSID, key *keys.PublicKey) error {
|
||||
namespace := viper.GetString(namespaceFlag)
|
||||
|
||||
log.Debug(logs.CreateSubjectInFrostFSID)
|
||||
err := cli.Wait(cli.CreateSubject(namespace, key))
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "subject already exists") {
|
||||
log.Debug(logs.SubjectAlreadyExistsInFrostFSID, zap.String("address", key.Address()))
|
||||
} else {
|
||||
return fmt.Errorf("create subject in frostfsid: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
name := viper.GetString(usernameFlag)
|
||||
if name == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
log.Debug(logs.SetSubjectNameInFrostFSID)
|
||||
if err = cli.Wait(cli.SetSubjectName(key, name)); err != nil {
|
||||
return fmt.Errorf("set subject name in frostfsid: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func initPolicyContract(ctx context.Context, log *zap.Logger, key *keys.PrivateKey) (*policyContact.Client, error) {
|
||||
log.Debug(logs.PreparePolicyClient)
|
||||
|
||||
cfg := policyContact.Config{
|
||||
RPCAddress: viper.GetString(rpcEndpointFlag),
|
||||
Contract: viper.GetString(policyContractFlag),
|
||||
ProxyContract: viper.GetString(proxyContractFlag),
|
||||
Key: key,
|
||||
}
|
||||
|
||||
cli, err := policyContact.New(ctx, cfg)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create policy client: %w", err)
|
||||
}
|
||||
|
||||
return cli, nil
|
||||
}
|
||||
|
||||
func addAllowedPolicyChains(cmd *cobra.Command, log *zap.Logger, cli *policyContact.Client, key *keys.PublicKey) error {
|
||||
log.Debug(logs.AddPolicyChainRules)
|
||||
namespace := viper.GetString(namespaceFlag)
|
||||
|
||||
allowAllRule := chain.Rule{
|
||||
Status: chain.Allow,
|
||||
Actions: chain.Actions{Names: []string{"*"}},
|
||||
Resources: chain.Resources{Names: []string{"*"}},
|
||||
}
|
||||
|
||||
chains := []*chain.Chain{
|
||||
{ID: chain.ID(chain.S3 + ":authmate"), Rules: []chain.Rule{allowAllRule}},
|
||||
{ID: chain.ID(chain.Ingress + ":authmate"), Rules: []chain.Rule{allowAllRule}},
|
||||
}
|
||||
|
||||
kind := policy.Kind(policy.User)
|
||||
entity := namespace + ":" + key.Address()
|
||||
tx := cli.StartTx()
|
||||
for _, ch := range chains {
|
||||
tx.AddChain(kind, entity, ch.ID, ch.Bytes())
|
||||
}
|
||||
|
||||
if err := cli.SendTx(tx); err != nil {
|
||||
return fmt.Errorf("add policy chain: %w", err)
|
||||
}
|
||||
|
||||
cmd.Printf("Added policy rules:\nkind: '%c'\nentity: '%s'\nchains:\n", kind, entity)
|
||||
enc := json.NewEncoder(os.Stdout)
|
||||
return enc.Encode(chains)
|
||||
}
|
|
@ -65,4 +65,7 @@ GoVersion: {{ runtimeVersion }}
|
|||
|
||||
rootCmd.AddCommand(updateSecretCmd)
|
||||
initUpdateSecretCmd()
|
||||
|
||||
rootCmd.AddCommand(registerUserCmd)
|
||||
initRegisterUserCmd()
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@ import (
|
|||
"strings"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/authmate"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/frostfs/frostfsid/contract"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/wallet"
|
||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
|
@ -40,10 +39,6 @@ func initUpdateSecretCmd() {
|
|||
updateSecretCmd.Flags().Duration(poolHealthcheckTimeoutFlag, defaultPoolHealthcheckTimeout, "Timeout for request to node to decide if it is alive")
|
||||
updateSecretCmd.Flags().Duration(poolRebalanceIntervalFlag, defaultPoolRebalanceInterval, "Interval for updating nodes health status")
|
||||
updateSecretCmd.Flags().Duration(poolStreamTimeoutFlag, defaultPoolStreamTimeout, "Timeout for individual operation in streaming RPC")
|
||||
updateSecretCmd.Flags().String(frostfsIDFlag, "", "FrostfsID contract hash (LE) or name in NNS to register public key in contract (rpc-endpoint flag also must be provided)")
|
||||
updateSecretCmd.Flags().String(frostfsIDProxyFlag, "", "Proxy contract hash (LE) or name in NNS to use when interact with frostfsid contract")
|
||||
updateSecretCmd.Flags().String(frostfsIDNamespaceFlag, "", "Namespace to register public key in frostfsid contract")
|
||||
updateSecretCmd.Flags().String(rpcEndpointFlag, "", "NEO node RPC address")
|
||||
updateSecretCmd.Flags().String(attributesFlag, "", "User attributes in form of Key1=Value1,Key2=Value2 (note: you cannot override system attributes)")
|
||||
|
||||
_ = updateSecretCmd.MarkFlagRequired(walletFlag)
|
||||
|
@ -100,29 +95,6 @@ func runUpdateSecretCmd(cmd *cobra.Command, _ []string) error {
|
|||
return wrapFrostFSInitError(fmt.Errorf("failed to create FrostFS component: %s", err))
|
||||
}
|
||||
|
||||
frostFSID := viper.GetString(frostfsIDFlag)
|
||||
if frostFSID != "" {
|
||||
rpcAddress := viper.GetString(rpcEndpointFlag)
|
||||
if rpcAddress == "" {
|
||||
return wrapPreparationError(fmt.Errorf("you can use '%s' flag only along with '%s'", frostfsIDFlag, rpcEndpointFlag))
|
||||
}
|
||||
cfg := contract.Config{
|
||||
RPCAddress: rpcAddress,
|
||||
Contract: frostFSID,
|
||||
ProxyContract: viper.GetString(frostfsIDProxyFlag),
|
||||
Key: key,
|
||||
}
|
||||
|
||||
frostfsIDClient, err := createFrostFSID(ctx, log, cfg)
|
||||
if err != nil {
|
||||
return wrapFrostFSIDInitError(err)
|
||||
}
|
||||
|
||||
if err = registerPublicKey(frostfsIDClient, viper.GetString(frostfsIDNamespaceFlag), key.PublicKey()); err != nil {
|
||||
return wrapBusinessLogicError(fmt.Errorf("failed to register key in frostfsid: %w", err))
|
||||
}
|
||||
}
|
||||
|
||||
customAttrs, err := parseObjectAttrs(viper.GetString(attributesFlag))
|
||||
if err != nil {
|
||||
return wrapPreparationError(fmt.Errorf("failed to parse attributes: %s", err))
|
||||
|
|
|
@ -11,7 +11,6 @@ import (
|
|||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/authmate"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/frostfs"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/frostfs/frostfsid/contract"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/logs"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/pool"
|
||||
|
@ -145,26 +144,6 @@ func getLogger() *zap.Logger {
|
|||
return log
|
||||
}
|
||||
|
||||
func createFrostFSID(ctx context.Context, log *zap.Logger, cfg contract.Config) (*contract.FrostFSID, error) {
|
||||
log.Debug(logs.PrepareFrostfsIDClient)
|
||||
|
||||
cli, err := contract.New(ctx, cfg)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create frostfsid client: %w", err)
|
||||
}
|
||||
|
||||
return cli, nil
|
||||
}
|
||||
|
||||
func registerPublicKey(cli *contract.FrostFSID, namespace string, key *keys.PublicKey) error {
|
||||
err := cli.Wait(cli.CreateSubject(namespace, key))
|
||||
if err != nil && !strings.Contains(err.Error(), "subject already exists") {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseObjectAttrs(attributes string) ([]object.Attribute, error) {
|
||||
if len(attributes) == 0 {
|
||||
return nil, nil
|
||||
|
|
|
@ -146,12 +146,6 @@ the secret. Format of `access_key_id`: `%cid0%oid`, where 0(zero) is a delimiter
|
|||
24h). Default value is `720h` (30 days). It will be ceil rounded to the nearest amount of epoch
|
||||
* `--aws-cli-credentials` - path to the aws cli credentials file, where authmate will write `access_key_id` and
|
||||
`secret_access_key` to
|
||||
* `--access-key-id` -- credentials that you want to update (e.g. to add more gates that can use your creds)
|
||||
without changing values of `aws_access_key_id` and `aws_secret_access_key`. If you want to update credential you MUST
|
||||
provide also secret key using `AUTHMATE_SECRET_ACCESS_KEY` env variable.
|
||||
* `--frostfsid` -- FrostfsID contract hash (LE) or name in NNS to register public key in contract
|
||||
(`--rpc-endpoint` flag also must be provided).
|
||||
* `--rpc-endpoint` -- NEO node RPC address.
|
||||
|
||||
### Bearer tokens
|
||||
|
||||
|
@ -212,6 +206,57 @@ can be set via parameter `--container-policy` (json-string and file path allowed
|
|||
}
|
||||
```
|
||||
|
||||
## User registration
|
||||
|
||||
To be able to interact with FrostFS Storage using s3-gw the user (whose credential is used) must be registered in
|
||||
`frostfsid` contract and also must have allowed chain rules in `policy` contract.
|
||||
|
||||
### CLI parameters
|
||||
|
||||
**Required parameters:**
|
||||
|
||||
* `--wallet` is a path to a wallet `.json` file. You can provide a passphrase to decrypt
|
||||
a wallet via environment variable `AUTHMATE_WALLET_PASSPHRASE`, or you will be asked to enter a passphrase
|
||||
interactively. You can also specify an account address to use from a wallet using the `--address` parameter. Key from
|
||||
this wallet will be registered in `frostfsid` contract and for this key allowed rules will be added.
|
||||
* `--rpc-endpoint` -- NEO node RPC address.
|
||||
|
||||
**Optional parameters:**
|
||||
|
||||
* `--frostfsid-contract` -- FrostfsID contract hash (LE) or name in NNS to register public key in contract (
|
||||
default: `frostfsid.frostfs`).
|
||||
* `--username` -- Username to set for public key in frostfsid contract.
|
||||
* `--namespace` -- Namespace to register public key in frostfsid contract and add allowed rules (default: `""`).
|
||||
* `--contract-wallet` -- is a path to a contract wallet `.json` file. This wallet will be used to sign transactions
|
||||
(if missing key from wallet flag be used). You can provide a passphrase to decrypt
|
||||
a wallet via environment variable `AUTHMATE_WALLET_CONTRACT_PASSPHRASE`, or you will be asked to enter a passphrase
|
||||
interactively. You can also specify an account address to use from a wallet using the `--contract-wallet-address`
|
||||
parameter.
|
||||
* `--policy-contract` -- Policy contract hash (LE) or name in NNS to save allowed chains for key (
|
||||
default: `policy.frostfs`).
|
||||
* `--proxy-contract` -- Proxy contract hash (LE) or name in NNS to use when interact with frostfsid contract (
|
||||
default: `proxy.frostfs`).
|
||||
|
||||
Example command that not only create access keys for key, but also register key in frostfsid contract and
|
||||
create allowed rules in policy contract:
|
||||
|
||||
```shell
|
||||
$ frostfs-s3-authmate register-user --wallet subject-wallet.json \
|
||||
--contract-wallet wallet-registered-in-proxy-contract.json \
|
||||
--frostfsid-contract frostfsid.frostfs \
|
||||
--namespace "" \
|
||||
--usrername devenv \
|
||||
--proxy-contract proxy.frostfs \
|
||||
--policy-contract policy.frostfs \
|
||||
--rpc-endpoint http://morph-chain.frostfs.devenv:30333
|
||||
|
||||
Added policy rules:
|
||||
kind: 'u'
|
||||
entity: ':NbUgTSFvPmsRxmGeWpuuGeJUoRoi6PErcM'
|
||||
chains:
|
||||
[{"ID":"czM6YXV0aG1hdGU=","Rules":[{"Status":"Allow","Actions":{"Inverted":false,"Names":["*"]},"Resources":{"Inverted":false,"Names":["*"]},"Any":false,"Condition":null}],"MatchType":"DenyPriority"},{"ID":"aW5ncmVzczphdXRobWF0ZQ==","Rules":[{"Status":"Allow","Actions":{"Inverted":false,"Names":["*"]},"Resources":{"Inverted":false,"Names":["*"]},"Any":false,"Condition":null}],"MatchType":"DenyPriority"}]
|
||||
```
|
||||
|
||||
## Obtaining credential secrets
|
||||
|
||||
You can get a secret access key and bearer token associated with an access key ID by obtaining a
|
||||
|
|
2
go.mod
2
go.mod
|
@ -4,7 +4,7 @@ go 1.20
|
|||
|
||||
require (
|
||||
git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240530152826-2f6d3209e1d3
|
||||
git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240409115729-6eb492025bdd
|
||||
git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240417080107-db361318009c
|
||||
git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20230531082742-c97d21411eb6
|
||||
git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240531132048-ebd8fcd1685f
|
||||
git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240611102930-ac965e8d176a
|
||||
|
|
4
go.sum
4
go.sum
|
@ -38,8 +38,8 @@ cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3f
|
|||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240530152826-2f6d3209e1d3 h1:H5GvrVlowIMWfzqQkhY0p0myooJxQ1sMRVSFfXawwWg=
|
||||
git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240530152826-2f6d3209e1d3/go.mod h1:OBDSr+DqV1z4VDouoX3YMleNc4DPBVBWTG3WDT2PK1o=
|
||||
git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240409115729-6eb492025bdd h1:fujTUMMn0wnpEKNDWLejFL916EPuaYD1MdZpk1ZokU8=
|
||||
git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240409115729-6eb492025bdd/go.mod h1:F/fe1OoIDKr5Bz99q4sriuHDuf3aZefZy9ZsCqEtgxc=
|
||||
git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240417080107-db361318009c h1:V58j1eg12wxbl4fUbjWtBOexl3zFt4w0EGHpCPkWJhQ=
|
||||
git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240417080107-db361318009c/go.mod h1:F/fe1OoIDKr5Bz99q4sriuHDuf3aZefZy9ZsCqEtgxc=
|
||||
git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSVCB8JNSfPG7Uk4r2oSk=
|
||||
git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU=
|
||||
git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20230531082742-c97d21411eb6 h1:aGQ6QaAnTerQ5Dq5b2/f9DUQtSqPkZZ/bkMx/HKuLCo=
|
||||
|
|
|
@ -78,6 +78,10 @@ func (f *FrostFSID) CreateSubject(namespace string, key *keys.PublicKey) (util.U
|
|||
return f.cli.CreateSubject(namespace, key)
|
||||
}
|
||||
|
||||
func (f *FrostFSID) SetSubjectName(key *keys.PublicKey, name string) (util.Uint256, uint32, error) {
|
||||
return f.cli.SetSubjectName(key.GetScriptHash(), name)
|
||||
}
|
||||
|
||||
func (f *FrostFSID) Wait(tx util.Uint256, vub uint32, err error) error {
|
||||
_, err = f.cli.Wait(tx, vub, err)
|
||||
return err
|
||||
|
|
|
@ -51,6 +51,11 @@ const (
|
|||
AddedStoragePeer = "added storage peer" // Info in ../../cmd/s3-gw/app_settings.go
|
||||
PrepareConnectionPool = "prepare connection pool" // Debug in ../../cmd/s3-authmate/modules/utils.go
|
||||
PrepareFrostfsIDClient = "prepare frostfsid client" // Debug in ../../cmd/s3-authmate/modules/utils.go
|
||||
PreparePolicyClient = "prepare policy client" // Debug in ../../cmd/s3-authmate/modules/utils.go
|
||||
CreateSubjectInFrostFSID = "create subject in frostfsid" // Debug in ../../cmd/s3-authmate/modules/utils.go
|
||||
SubjectAlreadyExistsInFrostFSID = "subject already exists in frostfsid" // Debug in ../../cmd/s3-authmate/modules/utils.go
|
||||
SetSubjectNameInFrostFSID = "set subject name in frostfsid" // Debug in ../../cmd/s3-authmate/modules/utils.go
|
||||
AddPolicyChainRules = "add policy chain rules" // Debug in ../../cmd/s3-authmate/modules/utils.go
|
||||
InvalidCacheEntryType = "invalid cache entry type" // Warn in ../../api/cache/*
|
||||
InvalidCacheKeyType = "invalid cache key type" // Warn in ../../api/cache/objectslist.go
|
||||
ObjectIsCopied = "object is copied" // Info in ../../api/handler/copy.go
|
||||
|
|
Loading…
Reference in a new issue