forked from TrueCloudLab/frostfs-s3-gw
[#292] authmate: Support custom attributes
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
This commit is contained in:
parent
c32220762f
commit
eae49908da
8 changed files with 109 additions and 35 deletions
|
@ -23,6 +23,7 @@ This document outlines major changes between releases.
|
||||||
- Support policy-engine (#257)
|
- Support policy-engine (#257)
|
||||||
- Support `policy` contract (#259)
|
- Support `policy` contract (#259)
|
||||||
- Support `proxy` contract (#287)
|
- Support `proxy` contract (#287)
|
||||||
|
- Authmate: support custom attributes (#292)
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- Generalise config param `use_default_xmlns_for_complete_multipart` to `use_default_xmlns` so that use default xmlns for all requests (#221)
|
- Generalise config param `use_default_xmlns_for_complete_multipart` to `use_default_xmlns` so that use default xmlns for all requests (#221)
|
||||||
|
|
|
@ -11,9 +11,7 @@ import (
|
||||||
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
|
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
|
||||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
|
||||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -42,11 +40,11 @@ func (m credentialsMock) GetBox(_ context.Context, addr oid.Address) (*accessbox
|
||||||
return box, nil
|
return box, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m credentialsMock) Put(context.Context, cid.ID, user.ID, *accessbox.AccessBox, uint64, ...*keys.PublicKey) (oid.Address, error) {
|
func (m credentialsMock) Put(context.Context, cid.ID, tokens.CredentialsParam) (oid.Address, error) {
|
||||||
return oid.Address{}, nil
|
return oid.Address{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m credentialsMock) Update(context.Context, oid.Address, user.ID, *accessbox.AccessBox, uint64, ...*keys.PublicKey) (oid.Address, error) {
|
func (m credentialsMock) Update(context.Context, oid.Address, tokens.CredentialsParam) (oid.Address, error) {
|
||||||
return oid.Address{}, nil
|
return oid.Address{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ import (
|
||||||
frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa"
|
frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
||||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
||||||
|
@ -113,6 +114,7 @@ type (
|
||||||
Lifetime time.Duration
|
Lifetime time.Duration
|
||||||
AwsCliCredentialsFile string
|
AwsCliCredentialsFile string
|
||||||
ContainerPolicies ContainerPolicies
|
ContainerPolicies ContainerPolicies
|
||||||
|
CustomAttributes []object.Attribute
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateSecretOptions contains options for passing to Agent.UpdateSecret method.
|
// UpdateSecretOptions contains options for passing to Agent.UpdateSecret method.
|
||||||
|
@ -121,6 +123,7 @@ type (
|
||||||
GatesPublicKeys []*keys.PublicKey
|
GatesPublicKeys []*keys.PublicKey
|
||||||
Address oid.Address
|
Address oid.Address
|
||||||
GatePrivateKey *keys.PrivateKey
|
GatePrivateKey *keys.PrivateKey
|
||||||
|
CustomAttributes []object.Attribute
|
||||||
}
|
}
|
||||||
|
|
||||||
tokenUpdateOptions struct {
|
tokenUpdateOptions struct {
|
||||||
|
@ -278,7 +281,15 @@ func (a *Agent) IssueSecret(ctx context.Context, w io.Writer, options *IssueSecr
|
||||||
|
|
||||||
creds := tokens.New(a.frostFS, secrets.EphemeralKey, cache.DefaultAccessBoxConfig(a.log))
|
creds := tokens.New(a.frostFS, secrets.EphemeralKey, cache.DefaultAccessBoxConfig(a.log))
|
||||||
|
|
||||||
addr, err := creds.Put(ctx, id, idOwner, box, lifetime.Exp, options.GatesPublicKeys...)
|
prm := tokens.CredentialsParam{
|
||||||
|
OwnerID: idOwner,
|
||||||
|
AccessBox: box,
|
||||||
|
Expiration: lifetime.Exp,
|
||||||
|
Keys: options.GatesPublicKeys,
|
||||||
|
CustomAttributes: options.CustomAttributes,
|
||||||
|
}
|
||||||
|
|
||||||
|
addr, err := creds.Put(ctx, id, prm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to put creds: %w", err)
|
return fmt.Errorf("failed to put creds: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -354,8 +365,16 @@ func (a *Agent) UpdateSecret(ctx context.Context, w io.Writer, options *UpdateSe
|
||||||
a.log.Info(logs.UpdateAccessCredObjectIntoFrostFS,
|
a.log.Info(logs.UpdateAccessCredObjectIntoFrostFS,
|
||||||
zap.Stringer("owner_tkn", idOwner))
|
zap.Stringer("owner_tkn", idOwner))
|
||||||
|
|
||||||
|
prm := tokens.CredentialsParam{
|
||||||
|
OwnerID: idOwner,
|
||||||
|
AccessBox: updatedBox,
|
||||||
|
Expiration: lifetime.Exp,
|
||||||
|
Keys: options.GatesPublicKeys,
|
||||||
|
CustomAttributes: options.CustomAttributes,
|
||||||
|
}
|
||||||
|
|
||||||
oldAddr := options.Address
|
oldAddr := options.Address
|
||||||
addr, err := creds.Update(ctx, oldAddr, idOwner, updatedBox, lifetime.Exp, options.GatesPublicKeys...)
|
addr, err := creds.Update(ctx, oldAddr, prm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to update creds: %w", err)
|
return fmt.Errorf("failed to update creds: %w", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,8 @@ var issueSecretCmd = &cobra.Command{
|
||||||
Use: "issue-secret",
|
Use: "issue-secret",
|
||||||
Short: "Issue a secret in FrostFS network",
|
Short: "Issue a secret in FrostFS network",
|
||||||
Long: "Creates new s3 credentials to use with frostfs-s3-gw",
|
Long: "Creates new s3 credentials to use with frostfs-s3-gw",
|
||||||
Example: `frostfs-s3-authmate issue-secret --wallet wallet.json --peer s01.frostfs.devenv:8080 --gate-public-key 031a6c6fbbdf02ca351745fa86b9ba5a9452d785ac4f7fc2b7548ca2a46c4fcf4a`,
|
Example: `frostfs-s3-authmate issue-secret --wallet wallet.json --peer s01.frostfs.devenv:8080 --gate-public-key 031a6c6fbbdf02ca351745fa86b9ba5a9452d785ac4f7fc2b7548ca2a46c4fcf4a
|
||||||
|
frostfs-s3-authmate issue-secret --wallet wallet.json --peer s01.frostfs.devenv:8080 --gate-public-key 031a6c6fbbdf02ca351745fa86b9ba5a9452d785ac4f7fc2b7548ca2a46c4fcf4a --attributes LOGIN=NUUb82KR2JrVByHs2YSKgtK29gKnF5q6Vt`,
|
||||||
RunE: runIssueSecretCmd,
|
RunE: runIssueSecretCmd,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,6 +43,7 @@ const (
|
||||||
frostfsIDProxyFlag = "frostfsid-proxy"
|
frostfsIDProxyFlag = "frostfsid-proxy"
|
||||||
frostfsIDNamespaceFlag = "frostfsid-namespace"
|
frostfsIDNamespaceFlag = "frostfsid-namespace"
|
||||||
rpcEndpointFlag = "rpc-endpoint"
|
rpcEndpointFlag = "rpc-endpoint"
|
||||||
|
attributesFlag = "attributes"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -86,6 +88,7 @@ func initIssueSecretCmd() {
|
||||||
issueSecretCmd.Flags().String(frostfsIDProxyFlag, "", "Proxy contract hash (LE) or name in NNS to use when interact with frostfsid contract")
|
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(frostfsIDNamespaceFlag, "", "Namespace to register public key in frostfsid contract")
|
||||||
issueSecretCmd.Flags().String(rpcEndpointFlag, "", "NEO node RPC address")
|
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)
|
_ = issueSecretCmd.MarkFlagRequired(walletFlag)
|
||||||
_ = issueSecretCmd.MarkFlagRequired(peerFlag)
|
_ = issueSecretCmd.MarkFlagRequired(peerFlag)
|
||||||
|
@ -184,6 +187,11 @@ func runIssueSecretCmd(cmd *cobra.Command, _ []string) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
customAttrs, err := parseObjectAttrs(viper.GetString(attributesFlag))
|
||||||
|
if err != nil {
|
||||||
|
return wrapPreparationError(fmt.Errorf("failed to parse attributes: %s", err))
|
||||||
|
}
|
||||||
|
|
||||||
issueSecretOptions := &authmate.IssueSecretOptions{
|
issueSecretOptions := &authmate.IssueSecretOptions{
|
||||||
Container: authmate.ContainerOptions{
|
Container: authmate.ContainerOptions{
|
||||||
ID: cnrID,
|
ID: cnrID,
|
||||||
|
@ -199,6 +207,7 @@ func runIssueSecretCmd(cmd *cobra.Command, _ []string) error {
|
||||||
ContainerPolicies: policies,
|
ContainerPolicies: policies,
|
||||||
Lifetime: lifetime,
|
Lifetime: lifetime,
|
||||||
AwsCliCredentialsFile: viper.GetString(awsCLICredentialFlag),
|
AwsCliCredentialsFile: viper.GetString(awsCLICredentialFlag),
|
||||||
|
CustomAttributes: customAttrs,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = authmate.New(log, frostFS).IssueSecret(ctx, os.Stdout, issueSecretOptions); err != nil {
|
if err = authmate.New(log, frostFS).IssueSecret(ctx, os.Stdout, issueSecretOptions); err != nil {
|
||||||
|
|
|
@ -44,6 +44,7 @@ func initUpdateSecretCmd() {
|
||||||
updateSecretCmd.Flags().String(frostfsIDProxyFlag, "", "Proxy contract hash (LE) or name in NNS to use when interact with frostfsid contract")
|
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(frostfsIDNamespaceFlag, "", "Namespace to register public key in frostfsid contract")
|
||||||
updateSecretCmd.Flags().String(rpcEndpointFlag, "", "NEO node RPC address")
|
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)
|
_ = updateSecretCmd.MarkFlagRequired(walletFlag)
|
||||||
_ = updateSecretCmd.MarkFlagRequired(peerFlag)
|
_ = updateSecretCmd.MarkFlagRequired(peerFlag)
|
||||||
|
@ -122,11 +123,17 @@ func runUpdateSecretCmd(cmd *cobra.Command, _ []string) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
customAttrs, err := parseObjectAttrs(viper.GetString(attributesFlag))
|
||||||
|
if err != nil {
|
||||||
|
return wrapPreparationError(fmt.Errorf("failed to parse attributes: %s", err))
|
||||||
|
}
|
||||||
|
|
||||||
updateSecretOptions := &authmate.UpdateSecretOptions{
|
updateSecretOptions := &authmate.UpdateSecretOptions{
|
||||||
Address: accessBoxAddress,
|
Address: accessBoxAddress,
|
||||||
FrostFSKey: key,
|
FrostFSKey: key,
|
||||||
GatesPublicKeys: gatesPublicKeys,
|
GatesPublicKeys: gatesPublicKeys,
|
||||||
GatePrivateKey: gateKey,
|
GatePrivateKey: gateKey,
|
||||||
|
CustomAttributes: customAttrs,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = authmate.New(log, frostFS).UpdateSecret(ctx, os.Stdout, updateSecretOptions); err != nil {
|
if err = authmate.New(log, frostFS).UpdateSecret(ctx, os.Stdout, updateSecretOptions); err != nil {
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api"
|
||||||
|
@ -12,6 +13,7 @@ import (
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/frostfs"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/frostfs"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/frostfs/frostfsid"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/frostfs/frostfsid"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/logs"
|
"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"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/pool"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
|
@ -153,3 +155,23 @@ func createFrostFSID(ctx context.Context, log *zap.Logger, cfg frostfsid.Config)
|
||||||
|
|
||||||
return cli, nil
|
return cli, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseObjectAttrs(attributes string) ([]object.Attribute, error) {
|
||||||
|
if len(attributes) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
rawAttrs := strings.Split(attributes, ",")
|
||||||
|
|
||||||
|
attrs := make([]object.Attribute, len(rawAttrs))
|
||||||
|
for i := range rawAttrs {
|
||||||
|
k, v, found := strings.Cut(rawAttrs[i], "=")
|
||||||
|
if !found {
|
||||||
|
return nil, fmt.Errorf("invalid attribute format: %s", rawAttrs[i])
|
||||||
|
}
|
||||||
|
attrs[i].SetKey(k)
|
||||||
|
attrs[i].SetValue(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
return attrs, nil
|
||||||
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/cache"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/cache"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/creds/accessbox"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/creds/accessbox"
|
||||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
||||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||||
|
@ -19,8 +20,16 @@ type (
|
||||||
// Credentials is a bearer token get/put interface.
|
// Credentials is a bearer token get/put interface.
|
||||||
Credentials interface {
|
Credentials interface {
|
||||||
GetBox(context.Context, oid.Address) (*accessbox.Box, error)
|
GetBox(context.Context, oid.Address) (*accessbox.Box, error)
|
||||||
Put(context.Context, cid.ID, user.ID, *accessbox.AccessBox, uint64, ...*keys.PublicKey) (oid.Address, error)
|
Put(context.Context, cid.ID, CredentialsParam) (oid.Address, error)
|
||||||
Update(context.Context, oid.Address, user.ID, *accessbox.AccessBox, uint64, ...*keys.PublicKey) (oid.Address, error)
|
Update(context.Context, oid.Address, CredentialsParam) (oid.Address, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
CredentialsParam struct {
|
||||||
|
OwnerID user.ID
|
||||||
|
AccessBox *accessbox.AccessBox
|
||||||
|
Expiration uint64
|
||||||
|
Keys keys.PublicKeys
|
||||||
|
CustomAttributes []object.Attribute
|
||||||
}
|
}
|
||||||
|
|
||||||
cred struct {
|
cred struct {
|
||||||
|
@ -50,6 +59,9 @@ type PrmObjectCreate struct {
|
||||||
|
|
||||||
// Object payload.
|
// Object payload.
|
||||||
Payload []byte
|
Payload []byte
|
||||||
|
|
||||||
|
// CustomAttributes are additional user provided attributes for box object.
|
||||||
|
CustomAttributes []object.Attribute
|
||||||
}
|
}
|
||||||
|
|
||||||
// FrostFS represents virtual connection to FrostFS network.
|
// FrostFS represents virtual connection to FrostFS network.
|
||||||
|
@ -123,33 +135,34 @@ func (c *cred) getAccessBox(ctx context.Context, addr oid.Address) (*accessbox.A
|
||||||
return &box, nil
|
return &box, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cred) Put(ctx context.Context, idCnr cid.ID, issuer user.ID, box *accessbox.AccessBox, expiration uint64, keys ...*keys.PublicKey) (oid.Address, error) {
|
func (c *cred) Put(ctx context.Context, idCnr cid.ID, prm CredentialsParam) (oid.Address, error) {
|
||||||
return c.createObject(ctx, idCnr, nil, issuer, box, expiration, keys...)
|
return c.createObject(ctx, idCnr, nil, prm)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cred) Update(ctx context.Context, addr oid.Address, issuer user.ID, box *accessbox.AccessBox, expiration uint64, keys ...*keys.PublicKey) (oid.Address, error) {
|
func (c *cred) Update(ctx context.Context, addr oid.Address, prm CredentialsParam) (oid.Address, error) {
|
||||||
objID := addr.Object()
|
objID := addr.Object()
|
||||||
return c.createObject(ctx, addr.Container(), &objID, issuer, box, expiration, keys...)
|
return c.createObject(ctx, addr.Container(), &objID, prm)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cred) createObject(ctx context.Context, cnrID cid.ID, newVersionFor *oid.ID, issuer user.ID, box *accessbox.AccessBox, expiration uint64, keys ...*keys.PublicKey) (oid.Address, error) {
|
func (c *cred) createObject(ctx context.Context, cnrID cid.ID, newVersionFor *oid.ID, prm CredentialsParam) (oid.Address, error) {
|
||||||
if len(keys) == 0 {
|
if len(prm.Keys) == 0 {
|
||||||
return oid.Address{}, ErrEmptyPublicKeys
|
return oid.Address{}, ErrEmptyPublicKeys
|
||||||
} else if box == nil {
|
} else if prm.AccessBox == nil {
|
||||||
return oid.Address{}, ErrEmptyBearerToken
|
return oid.Address{}, ErrEmptyBearerToken
|
||||||
}
|
}
|
||||||
data, err := box.Marshal()
|
data, err := prm.AccessBox.Marshal()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return oid.Address{}, fmt.Errorf("marshall box: %w", err)
|
return oid.Address{}, fmt.Errorf("marshall box: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
idObj, err := c.frostFS.CreateObject(ctx, PrmObjectCreate{
|
idObj, err := c.frostFS.CreateObject(ctx, PrmObjectCreate{
|
||||||
Creator: issuer,
|
Creator: prm.OwnerID,
|
||||||
Container: cnrID,
|
Container: cnrID,
|
||||||
Filepath: strconv.FormatInt(time.Now().Unix(), 10) + "_access.box",
|
Filepath: strconv.FormatInt(time.Now().Unix(), 10) + "_access.box",
|
||||||
ExpirationEpoch: expiration,
|
ExpirationEpoch: prm.Expiration,
|
||||||
NewVersionFor: newVersionFor,
|
NewVersionFor: newVersionFor,
|
||||||
Payload: data,
|
Payload: data,
|
||||||
|
CustomAttributes: prm.CustomAttributes,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return oid.Address{}, fmt.Errorf("create object: %w", err)
|
return oid.Address{}, fmt.Errorf("create object: %w", err)
|
||||||
|
|
|
@ -120,6 +120,11 @@ func (x *AuthmateFrostFS) CreateObject(ctx context.Context, prm tokens.PrmObject
|
||||||
attributes = append(attributes, [2]string{accessBoxCRDTNameAttr, versions.Name()})
|
attributes = append(attributes, [2]string{accessBoxCRDTNameAttr, versions.Name()})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, attr := range prm.CustomAttributes {
|
||||||
|
// we don't check attribute duplication since storage node does this
|
||||||
|
attributes = append(attributes, [2]string{attr.Key(), attr.Value()})
|
||||||
|
}
|
||||||
|
|
||||||
return x.frostFS.CreateObject(ctx, layer.PrmObjectCreate{
|
return x.frostFS.CreateObject(ctx, layer.PrmObjectCreate{
|
||||||
Container: prm.Container,
|
Container: prm.Container,
|
||||||
Filepath: prm.Filepath,
|
Filepath: prm.Filepath,
|
||||||
|
|
Loading…
Reference in a new issue