Introduce APEOverride
for Bearer
-token #225
12 changed files with 245 additions and 70 deletions
|
@ -1,10 +1,10 @@
|
||||||
package apemanager
|
package ape
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
apemanager_v2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager"
|
apeV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/ape"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -27,11 +27,11 @@ type Chain struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToV2 converts Chain to v2.
|
// ToV2 converts Chain to v2.
|
||||||
func (c *Chain) ToV2() *apemanager_v2.Chain {
|
func (c *Chain) ToV2() *apeV2.Chain {
|
||||||
v2ct := new(apemanager_v2.Chain)
|
v2ct := new(apeV2.Chain)
|
||||||
|
|
||||||
if c.Raw != nil {
|
if c.Raw != nil {
|
||||||
v2Raw := new(apemanager_v2.ChainRaw)
|
v2Raw := new(apeV2.ChainRaw)
|
||||||
v2Raw.SetRaw(c.Raw)
|
v2Raw.SetRaw(c.Raw)
|
||||||
v2ct.SetKind(v2Raw)
|
v2ct.SetKind(v2Raw)
|
||||||
}
|
}
|
||||||
|
@ -40,11 +40,11 @@ func (c *Chain) ToV2() *apemanager_v2.Chain {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadFromV2 fills Chain from v2.
|
// ReadFromV2 fills Chain from v2.
|
||||||
func (c *Chain) ReadFromV2(v2ct *apemanager_v2.Chain) error {
|
func (c *Chain) ReadFromV2(v2ct *apeV2.Chain) error {
|
||||||
switch v := v2ct.GetKind().(type) {
|
switch v := v2ct.GetKind().(type) {
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unsupported chain kind: %T", v)
|
return fmt.Errorf("unsupported chain kind: %T", v)
|
||||||
case *apemanager_v2.ChainRaw:
|
case *apeV2.ChainRaw:
|
||||||
raw := v.GetRaw()
|
raw := v.GetRaw()
|
||||||
c.Raw = raw
|
c.Raw = raw
|
||||||
}
|
}
|
|
@ -1,11 +1,11 @@
|
||||||
package apemanager
|
package ape
|
||||||
|
|
||||||
import (
|
import (
|
||||||
apemanager_v2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager"
|
apeV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/ape"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TargetType is an SDK representation for v2's TargetType.
|
// TargetType is an SDK representation for v2's TargetType.
|
||||||
type TargetType apemanager_v2.TargetType
|
type TargetType apeV2.TargetType
|
||||||
|
|
||||||
const (
|
const (
|
||||||
TargetTypeUndefined TargetType = iota
|
TargetTypeUndefined TargetType = iota
|
||||||
|
@ -16,12 +16,12 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
// ToV2 converts TargetType to v2.
|
// ToV2 converts TargetType to v2.
|
||||||
func (targetType TargetType) ToV2() apemanager_v2.TargetType {
|
func (targetType TargetType) ToV2() apeV2.TargetType {
|
||||||
return apemanager_v2.TargetType(targetType)
|
return apeV2.TargetType(targetType)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FromV2 reads TargetType to v2.
|
// FromV2 reads TargetType to v2.
|
||||||
func (targetType *TargetType) FromV2(v2targetType apemanager_v2.TargetType) {
|
func (targetType *TargetType) FromV2(v2targetType apeV2.TargetType) {
|
||||||
*targetType = TargetType(v2targetType)
|
*targetType = TargetType(v2targetType)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,8 +37,8 @@ type ChainTarget struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToV2 converts ChainTarget to v2.
|
// ToV2 converts ChainTarget to v2.
|
||||||
func (ct *ChainTarget) ToV2() *apemanager_v2.ChainTarget {
|
func (ct *ChainTarget) ToV2() *apeV2.ChainTarget {
|
||||||
v2ct := new(apemanager_v2.ChainTarget)
|
v2ct := new(apeV2.ChainTarget)
|
||||||
|
|
||||||
v2ct.SetTargetType(ct.TargetType.ToV2())
|
v2ct.SetTargetType(ct.TargetType.ToV2())
|
||||||
v2ct.SetName(ct.Name)
|
v2ct.SetName(ct.Name)
|
||||||
|
@ -47,7 +47,7 @@ func (ct *ChainTarget) ToV2() *apemanager_v2.ChainTarget {
|
||||||
}
|
}
|
||||||
|
|
||||||
// FromV2 reads ChainTarget frpm v2.
|
// FromV2 reads ChainTarget frpm v2.
|
||||||
func (ct *ChainTarget) FromV2(v2ct *apemanager_v2.ChainTarget) {
|
func (ct *ChainTarget) FromV2(v2ct *apeV2.ChainTarget) {
|
||||||
ct.TargetType.FromV2(v2ct.GetTargetType())
|
ct.TargetType.FromV2(v2ct.GetTargetType())
|
||||||
ct.Name = v2ct.GetName()
|
ct.Name = v2ct.GetName()
|
||||||
}
|
}
|
|
@ -1,21 +1,21 @@
|
||||||
package apemanager_test
|
package ape_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apemanager"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
apemanager_v2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager"
|
apeV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/ape"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
m = map[apemanager.TargetType]apemanager_v2.TargetType{
|
m = map[ape.TargetType]apeV2.TargetType{
|
||||||
apemanager.TargetTypeUndefined: apemanager_v2.TargetTypeUndefined,
|
ape.TargetTypeUndefined: apeV2.TargetTypeUndefined,
|
||||||
apemanager.TargetTypeNamespace: apemanager_v2.TargetTypeNamespace,
|
ape.TargetTypeNamespace: apeV2.TargetTypeNamespace,
|
||||||
apemanager.TargetTypeContainer: apemanager_v2.TargetTypeContainer,
|
ape.TargetTypeContainer: apeV2.TargetTypeContainer,
|
||||||
apemanager.TargetTypeUser: apemanager_v2.TargetTypeUser,
|
ape.TargetTypeUser: apeV2.TargetTypeUser,
|
||||||
apemanager.TargetTypeGroup: apemanager_v2.TargetTypeGroup,
|
ape.TargetTypeGroup: apeV2.TargetTypeGroup,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ func TestTargetType(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("from v2 to sdk "+typev2.String(), func(t *testing.T) {
|
t.Run("from v2 to sdk "+typev2.String(), func(t *testing.T) {
|
||||||
var typ apemanager.TargetType
|
var typ ape.TargetType
|
||||||
typ.FromV2(typev2)
|
typ.FromV2(typev2)
|
||||||
require.Equal(t, typesdk, typ)
|
require.Equal(t, typesdk, typ)
|
||||||
})
|
})
|
||||||
|
@ -36,12 +36,12 @@ func TestTargetType(t *testing.T) {
|
||||||
|
|
||||||
func TestChainTarget(t *testing.T) {
|
func TestChainTarget(t *testing.T) {
|
||||||
var (
|
var (
|
||||||
typ = apemanager.TargetTypeNamespace
|
typ = ape.TargetTypeNamespace
|
||||||
name = "namespaceXXYYZZ"
|
name = "namespaceXXYYZZ"
|
||||||
)
|
)
|
||||||
|
|
||||||
t.Run("from sdk to v2", func(t *testing.T) {
|
t.Run("from sdk to v2", func(t *testing.T) {
|
||||||
ct := apemanager.ChainTarget{
|
ct := ape.ChainTarget{
|
||||||
TargetType: typ,
|
TargetType: typ,
|
||||||
Name: name,
|
Name: name,
|
||||||
}
|
}
|
||||||
|
@ -52,11 +52,11 @@ func TestChainTarget(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("from v2 to sdk", func(t *testing.T) {
|
t.Run("from v2 to sdk", func(t *testing.T) {
|
||||||
v2 := &apemanager_v2.ChainTarget{}
|
v2 := &apeV2.ChainTarget{}
|
||||||
v2.SetTargetType(m[typ])
|
v2.SetTargetType(m[typ])
|
||||||
v2.SetName(name)
|
v2.SetName(name)
|
||||||
|
|
||||||
var ct apemanager.ChainTarget
|
var ct ape.ChainTarget
|
||||||
ct.FromV2(v2)
|
ct.FromV2(v2)
|
||||||
|
|
||||||
require.Equal(t, typ, ct.TargetType)
|
require.Equal(t, typ, ct.TargetType)
|
|
@ -1,12 +1,12 @@
|
||||||
package apemanager_test
|
package ape_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apemanager"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
apemanager_v2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager"
|
apeV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/ape"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -15,12 +15,12 @@ const (
|
||||||
|
|
||||||
func TestChainData(t *testing.T) {
|
func TestChainData(t *testing.T) {
|
||||||
t.Run("raw chain", func(t *testing.T) {
|
t.Run("raw chain", func(t *testing.T) {
|
||||||
var c apemanager.Chain
|
var c ape.Chain
|
||||||
|
|
||||||
b := []byte(encoded)
|
b := []byte(encoded)
|
||||||
c.Raw = b
|
c.Raw = b
|
||||||
|
|
||||||
v2, ok := c.ToV2().GetKind().(*apemanager_v2.ChainRaw)
|
v2, ok := c.ToV2().GetKind().(*apeV2.ChainRaw)
|
||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
require.Equal(t, b, v2.Raw)
|
require.Equal(t, b, v2.Raw)
|
||||||
})
|
})
|
||||||
|
@ -29,13 +29,13 @@ func TestChainData(t *testing.T) {
|
||||||
func TestChainMessageV2(t *testing.T) {
|
func TestChainMessageV2(t *testing.T) {
|
||||||
b := []byte(encoded)
|
b := []byte(encoded)
|
||||||
|
|
||||||
v2Raw := &apemanager_v2.ChainRaw{}
|
v2Raw := &apeV2.ChainRaw{}
|
||||||
v2Raw.SetRaw(b)
|
v2Raw.SetRaw(b)
|
||||||
|
|
||||||
v2 := &apemanager_v2.Chain{}
|
v2 := &apeV2.Chain{}
|
||||||
v2.SetKind(v2Raw)
|
v2.SetKind(v2Raw)
|
||||||
|
|
||||||
var c apemanager.Chain
|
var c ape.Chain
|
||||||
c.ReadFromV2(v2)
|
c.ReadFromV2(v2)
|
||||||
|
|
||||||
require.NotNil(t, c.Raw)
|
require.NotNil(t, c.Raw)
|
114
bearer/bearer.go
114
bearer/bearer.go
|
@ -6,7 +6,9 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl"
|
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl"
|
||||||
|
apeV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/ape"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||||
|
apeSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape"
|
||||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||||
frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto"
|
frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto"
|
||||||
frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa"
|
frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa"
|
||||||
|
@ -33,9 +35,85 @@ type Token struct {
|
||||||
sigSet bool
|
sigSet bool
|
||||||
sig refs.Signature
|
sig refs.Signature
|
||||||
|
|
||||||
|
apeOverrideSet bool
|
||||||
|
apeOverride APEOverride
|
||||||
|
|
||||||
impersonate bool
|
impersonate bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// APEOverride is the list of APE chains defined for a target.
|
||||||
|
// These chains are meant to serve as overrides to the already defined (or even undefined)
|
||||||
|
// APE chains for the target (see contract `Policy`).
|
||||||
|
//
|
||||||
|
// The server-side processing of the bearer token with set APE overrides must verify if a client is permitted
|
||||||
|
// to override chains for the target, preventing unauthorized access through the APE mechanism.
|
||||||
|
type APEOverride struct {
|
||||||
|
// Target for which chains are applied.
|
||||||
|
Target apeSDK.ChainTarget
|
||||||
|
|
||||||
|
// The list of APE chains.
|
||||||
|
Chains []apeSDK.Chain
|
||||||
|
}
|
||||||
|
|
||||||
|
// Marshal marshals APEOverride into a protobuf binary form.
|
||||||
|
func (c *APEOverride) Marshal() ([]byte, error) {
|
||||||
|
return c.ToV2().StableMarshal(nil), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unmarshal unmarshals protobuf binary representation of APEOverride.
|
||||||
|
func (c *APEOverride) Unmarshal(data []byte) error {
|
||||||
|
overrideV2 := new(acl.APEOverride)
|
||||||
|
if err := overrideV2.Unmarshal(data); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.FromV2(overrideV2)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalJSON encodes APEOverride to protobuf JSON format.
|
||||||
|
func (c *APEOverride) MarshalJSON() ([]byte, error) {
|
||||||
|
return c.ToV2().MarshalJSON()
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON decodes APEOverride from protobuf JSON format.
|
||||||
|
func (c *APEOverride) UnmarshalJSON(data []byte) error {
|
||||||
|
overrideV2 := new(acl.APEOverride)
|
||||||
|
if err := overrideV2.UnmarshalJSON(data); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.FromV2(overrideV2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *APEOverride) FromV2(tokenAPEChains *acl.APEOverride) error {
|
||||||
|
c.Target.FromV2(tokenAPEChains.GetTarget())
|
||||||
|
if chains := tokenAPEChains.GetChains(); len(chains) > 0 {
|
||||||
|
c.Chains = make([]apeSDK.Chain, len(chains))
|
||||||
|
for i := range chains {
|
||||||
|
if err := c.Chains[i].ReadFromV2(chains[i]); err != nil {
|
||||||
|
return fmt.Errorf("invalid APE chain: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *APEOverride) ToV2() *acl.APEOverride {
|
||||||
|
if c == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
apeOverride := new(acl.APEOverride)
|
||||||
|
apeOverride.SetTarget(c.Target.ToV2())
|
||||||
|
chains := make([]*apeV2.Chain, len(c.Chains))
|
||||||
|
for i := range c.Chains {
|
||||||
|
chains[i] = c.Chains[i].ToV2()
|
||||||
|
}
|
||||||
|
apeOverride.SetChains(chains)
|
||||||
|
|
||||||
|
return apeOverride
|
||||||
|
}
|
||||||
|
|
||||||
// reads Token from the acl.BearerToken message. If checkFieldPresence is set,
|
// reads Token from the acl.BearerToken message. If checkFieldPresence is set,
|
||||||
// returns an error on absence of any protocol-required field.
|
// returns an error on absence of any protocol-required field.
|
||||||
func (b *Token) readFromV2(m acl.BearerToken, checkFieldPresence bool) error {
|
func (b *Token) readFromV2(m acl.BearerToken, checkFieldPresence bool) error {
|
||||||
|
@ -48,10 +126,11 @@ func (b *Token) readFromV2(m acl.BearerToken, checkFieldPresence bool) error {
|
||||||
|
|
||||||
b.impersonate = body.GetImpersonate()
|
b.impersonate = body.GetImpersonate()
|
||||||
|
|
||||||
|
apeOverrides := body.GetAPEOverride()
|
||||||
eaclTable := body.GetEACL()
|
eaclTable := body.GetEACL()
|
||||||
if b.eaclTableSet = eaclTable != nil; b.eaclTableSet {
|
if b.eaclTableSet = eaclTable != nil; b.eaclTableSet {
|
||||||
b.eaclTable = *eacl.NewTableFromV2(eaclTable)
|
b.eaclTable = *eacl.NewTableFromV2(eaclTable)
|
||||||
} else if checkFieldPresence && !b.impersonate {
|
} else if checkFieldPresence && !b.impersonate && apeOverrides == nil {
|
||||||
return errors.New("missing eACL table")
|
return errors.New("missing eACL table")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,6 +151,14 @@ func (b *Token) readFromV2(m acl.BearerToken, checkFieldPresence bool) error {
|
||||||
return errors.New("missing token lifetime")
|
return errors.New("missing token lifetime")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if b.apeOverrideSet = apeOverrides != nil; b.apeOverrideSet {
|
||||||
|
if err = b.apeOverride.FromV2(apeOverrides); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else if checkFieldPresence && !b.impersonate && !b.eaclTableSet {
|
||||||
|
return errors.New("missing APE override")
|
||||||
|
}
|
||||||
|
|
||||||
sig := m.GetSignature()
|
sig := m.GetSignature()
|
||||||
if b.sigSet = sig != nil; sig != nil {
|
if b.sigSet = sig != nil; sig != nil {
|
||||||
b.sig = *sig
|
b.sig = *sig
|
||||||
|
@ -90,7 +177,7 @@ func (b *Token) ReadFromV2(m acl.BearerToken) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b Token) fillBody() *acl.BearerTokenBody {
|
func (b Token) fillBody() *acl.BearerTokenBody {
|
||||||
if !b.eaclTableSet && !b.targetUserSet && !b.lifetimeSet && !b.impersonate {
|
if !b.eaclTableSet && !b.targetUserSet && !b.lifetimeSet && !b.impersonate && !b.apeOverrideSet {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,6 +203,10 @@ func (b Token) fillBody() *acl.BearerTokenBody {
|
||||||
body.SetLifetime(&lifetime)
|
body.SetLifetime(&lifetime)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if b.apeOverrideSet {
|
||||||
|
body.SetAPEOverride(b.apeOverride.ToV2())
|
||||||
|
}
|
||||||
|
|
||||||
body.SetImpersonate(b.impersonate)
|
body.SetImpersonate(b.impersonate)
|
||||||
|
|
||||||
return &body
|
return &body
|
||||||
|
@ -214,6 +305,25 @@ func (b Token) EACLTable() eacl.Table {
|
||||||
return eacl.Table{}
|
return eacl.Table{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetAPEOverride sets APE override to the bearer token.
|
||||||
|
//
|
||||||
|
// See also: APEOverride.
|
||||||
|
func (b *Token) SetAPEOverride(v APEOverride) {
|
||||||
|
b.apeOverride = v
|
||||||
|
b.apeOverrideSet = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// APEOverride returns APE override set by SetAPEOverride.
|
||||||
|
//
|
||||||
|
// Zero Token has zero APEOverride.
|
||||||
|
func (b *Token) APEOverride() APEOverride {
|
||||||
|
if b.apeOverrideSet {
|
||||||
|
return b.apeOverride
|
||||||
|
}
|
||||||
|
|
||||||
|
return APEOverride{}
|
||||||
|
}
|
||||||
|
|
||||||
// SetImpersonate mark token as impersonate to consider token signer as request owner.
|
// SetImpersonate mark token as impersonate to consider token signer as request owner.
|
||||||
// If this field is true extended EACLTable in token body isn't processed.
|
// If this field is true extended EACLTable in token body isn't processed.
|
||||||
func (b *Token) SetImpersonate(v bool) {
|
func (b *Token) SetImpersonate(v bool) {
|
||||||
|
|
|
@ -3,6 +3,7 @@ package bearer_test
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl"
|
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl"
|
||||||
|
@ -81,6 +82,58 @@ func TestToken_SetEACLTable(t *testing.T) {
|
||||||
require.True(t, isEqualEACLTables(eaclTable, val.EACLTable()))
|
require.True(t, isEqualEACLTables(eaclTable, val.EACLTable()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestToken_SetAPEOverrides(t *testing.T) {
|
||||||
|
var val bearer.Token
|
||||||
|
var m acl.BearerToken
|
||||||
|
filled := bearertest.Token()
|
||||||
|
|
||||||
|
val.WriteToV2(&m)
|
||||||
|
require.Zero(t, m.GetBody())
|
||||||
|
|
||||||
|
val2 := filled
|
||||||
|
|
||||||
|
require.NoError(t, val2.Unmarshal(val.Marshal()))
|
||||||
|
require.Zero(t, val2.APEOverride())
|
||||||
|
|
||||||
|
val2 = filled
|
||||||
|
|
||||||
|
jd, err := val.MarshalJSON()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
require.NoError(t, val2.UnmarshalJSON(jd))
|
||||||
|
require.Zero(t, val2.APEOverride())
|
||||||
|
|
||||||
|
// set value
|
||||||
|
|
||||||
|
tApe := bearertest.APEOverride()
|
||||||
|
|
||||||
|
val.SetAPEOverride(tApe)
|
||||||
|
require.Equal(t, tApe, val.APEOverride())
|
||||||
|
|
||||||
|
val.WriteToV2(&m)
|
||||||
|
require.NotNil(t, m.GetBody().GetAPEOverride())
|
||||||
|
require.True(t, tokenAPEOverridesEqual(tApe.ToV2(), m.GetBody().GetAPEOverride()))
|
||||||
|
|
||||||
|
val2 = filled
|
||||||
|
|
||||||
|
require.NoError(t, val2.Unmarshal(val.Marshal()))
|
||||||
|
apeOverride := val2.APEOverride()
|
||||||
|
require.True(t, tokenAPEOverridesEqual(tApe.ToV2(), apeOverride.ToV2()))
|
||||||
|
|
||||||
|
val2 = filled
|
||||||
|
|
||||||
|
jd, err = val.MarshalJSON()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
require.NoError(t, val2.UnmarshalJSON(jd))
|
||||||
|
apeOverride = val.APEOverride()
|
||||||
|
require.True(t, tokenAPEOverridesEqual(tApe.ToV2(), apeOverride.ToV2()))
|
||||||
|
}
|
||||||
|
|
||||||
|
func tokenAPEOverridesEqual(lhs, rhs *acl.APEOverride) bool {
|
||||||
|
return reflect.DeepEqual(lhs, rhs)
|
||||||
|
}
|
||||||
|
|
||||||
func TestToken_ForUser(t *testing.T) {
|
func TestToken_ForUser(t *testing.T) {
|
||||||
var val bearer.Token
|
var val bearer.Token
|
||||||
var m acl.BearerToken
|
var m acl.BearerToken
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package bearertest
|
package bearertest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
|
||||||
eacltest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl/test"
|
eacltest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl/test"
|
||||||
usertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user/test"
|
usertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user/test"
|
||||||
|
@ -15,6 +16,17 @@ func Token() (t bearer.Token) {
|
||||||
t.SetIat(1)
|
t.SetIat(1)
|
||||||
t.ForUser(usertest.ID())
|
t.ForUser(usertest.ID())
|
||||||
t.SetEACLTable(*eacltest.Table())
|
t.SetEACLTable(*eacltest.Table())
|
||||||
|
t.SetAPEOverride(APEOverride())
|
||||||
|
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func APEOverride() bearer.APEOverride {
|
||||||
|
return bearer.APEOverride{
|
||||||
|
Target: ape.ChainTarget{
|
||||||
|
TargetType: ape.TargetTypeContainer,
|
||||||
|
Name: "F8JsMnChywiPvbDvpxMbjTjx5KhWHHp6gCDt8BhzL9kF",
|
||||||
|
},
|
||||||
|
Chains: []ape.Chain{{Raw: []byte("{}")}},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -4,12 +4,12 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
apemanager_v2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager"
|
apemanagerV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager"
|
||||||
rpcapi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc"
|
rpcapi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
|
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
|
||||||
session_v2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
|
sessionV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature"
|
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature"
|
||||||
apemanager_sdk "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apemanager"
|
apeSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape"
|
||||||
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
|
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -17,25 +17,25 @@ import (
|
||||||
type PrmAPEManagerAddChain struct {
|
type PrmAPEManagerAddChain struct {
|
||||||
XHeaders []string
|
XHeaders []string
|
||||||
|
|
||||||
ChainTarget apemanager_sdk.ChainTarget
|
ChainTarget apeSDK.ChainTarget
|
||||||
|
|
||||||
Chain apemanager_sdk.Chain
|
Chain apeSDK.Chain
|
||||||
}
|
}
|
||||||
|
|
||||||
func (prm *PrmAPEManagerAddChain) buildRequest(c *Client) (*apemanager_v2.AddChainRequest, error) {
|
func (prm *PrmAPEManagerAddChain) buildRequest(c *Client) (*apemanagerV2.AddChainRequest, error) {
|
||||||
if len(prm.XHeaders)%2 != 0 {
|
if len(prm.XHeaders)%2 != 0 {
|
||||||
return nil, errorInvalidXHeaders
|
return nil, errorInvalidXHeaders
|
||||||
}
|
}
|
||||||
|
|
||||||
req := new(apemanager_v2.AddChainRequest)
|
req := new(apemanagerV2.AddChainRequest)
|
||||||
reqBody := new(apemanager_v2.AddChainRequestBody)
|
reqBody := new(apemanagerV2.AddChainRequestBody)
|
||||||
|
|
||||||
reqBody.SetTarget(prm.ChainTarget.ToV2())
|
reqBody.SetTarget(prm.ChainTarget.ToV2())
|
||||||
reqBody.SetChain(prm.Chain.ToV2())
|
reqBody.SetChain(prm.Chain.ToV2())
|
||||||
|
|
||||||
req.SetBody(reqBody)
|
req.SetBody(reqBody)
|
||||||
|
|
||||||
var meta session_v2.RequestMetaHeader
|
var meta sessionV2.RequestMetaHeader
|
||||||
writeXHeadersToMeta(prm.XHeaders, &meta)
|
writeXHeadersToMeta(prm.XHeaders, &meta)
|
||||||
|
|
||||||
c.prepareRequest(req, &meta)
|
c.prepareRequest(req, &meta)
|
||||||
|
@ -48,7 +48,7 @@ type ResAPEManagerAddChain struct {
|
||||||
|
|
||||||
// ChainID of set Chain. If Chain does not contain chainID before request, then
|
// ChainID of set Chain. If Chain does not contain chainID before request, then
|
||||||
// ChainID is generated.
|
// ChainID is generated.
|
||||||
ChainID apemanager_sdk.ChainID
|
ChainID apeSDK.ChainID
|
||||||
}
|
}
|
||||||
|
|
||||||
// APEManagerAddChain sets Chain for ChainTarget.
|
// APEManagerAddChain sets Chain for ChainTarget.
|
||||||
|
|
|
@ -4,12 +4,12 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
apemanager_v2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager"
|
apemanagerV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager"
|
||||||
rpcapi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc"
|
rpcapi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
|
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
|
||||||
session_v2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
|
sessionV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature"
|
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature"
|
||||||
apemanager_sdk "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apemanager"
|
apeSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape"
|
||||||
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
|
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -17,22 +17,22 @@ import (
|
||||||
type PrmAPEManagerListChains struct {
|
type PrmAPEManagerListChains struct {
|
||||||
XHeaders []string
|
XHeaders []string
|
||||||
|
|
||||||
ChainTarget apemanager_sdk.ChainTarget
|
ChainTarget apeSDK.ChainTarget
|
||||||
}
|
}
|
||||||
|
|
||||||
func (prm *PrmAPEManagerListChains) buildRequest(c *Client) (*apemanager_v2.ListChainsRequest, error) {
|
func (prm *PrmAPEManagerListChains) buildRequest(c *Client) (*apemanagerV2.ListChainsRequest, error) {
|
||||||
if len(prm.XHeaders)%2 != 0 {
|
if len(prm.XHeaders)%2 != 0 {
|
||||||
return nil, errorInvalidXHeaders
|
return nil, errorInvalidXHeaders
|
||||||
}
|
}
|
||||||
|
|
||||||
req := new(apemanager_v2.ListChainsRequest)
|
req := new(apemanagerV2.ListChainsRequest)
|
||||||
reqBody := new(apemanager_v2.ListChainsRequestBody)
|
reqBody := new(apemanagerV2.ListChainsRequestBody)
|
||||||
|
|
||||||
reqBody.SetTarget(prm.ChainTarget.ToV2())
|
reqBody.SetTarget(prm.ChainTarget.ToV2())
|
||||||
|
|
||||||
req.SetBody(reqBody)
|
req.SetBody(reqBody)
|
||||||
|
|
||||||
var meta session_v2.RequestMetaHeader
|
var meta sessionV2.RequestMetaHeader
|
||||||
writeXHeadersToMeta(prm.XHeaders, &meta)
|
writeXHeadersToMeta(prm.XHeaders, &meta)
|
||||||
|
|
||||||
c.prepareRequest(req, &meta)
|
c.prepareRequest(req, &meta)
|
||||||
|
@ -43,7 +43,7 @@ func (prm *PrmAPEManagerListChains) buildRequest(c *Client) (*apemanager_v2.List
|
||||||
type ResAPEManagerListChains struct {
|
type ResAPEManagerListChains struct {
|
||||||
statusRes
|
statusRes
|
||||||
|
|
||||||
Chains []apemanager_sdk.Chain
|
Chains []apeSDK.Chain
|
||||||
}
|
}
|
||||||
|
|
||||||
// APEManagerListChains lists Chains for ChainTarget.
|
// APEManagerListChains lists Chains for ChainTarget.
|
||||||
|
@ -69,7 +69,7 @@ func (c *Client) APEManagerListChains(ctx context.Context, prm PrmAPEManagerList
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, ch := range resp.GetBody().GetChains() {
|
for _, ch := range resp.GetBody().GetChains() {
|
||||||
var chSDK apemanager_sdk.Chain
|
var chSDK apeSDK.Chain
|
||||||
if err := chSDK.ReadFromV2(ch); err != nil {
|
if err := chSDK.ReadFromV2(ch); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,12 +4,12 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
apemanager_v2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager"
|
apemanagerV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager"
|
||||||
rpcapi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc"
|
rpcapi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
|
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
|
||||||
session_v2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
|
sessionV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature"
|
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature"
|
||||||
apemanager_sdk "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apemanager"
|
apeSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape"
|
||||||
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
|
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -17,25 +17,25 @@ import (
|
||||||
type PrmAPEManagerRemoveChain struct {
|
type PrmAPEManagerRemoveChain struct {
|
||||||
XHeaders []string
|
XHeaders []string
|
||||||
|
|
||||||
ChainTarget apemanager_sdk.ChainTarget
|
ChainTarget apeSDK.ChainTarget
|
||||||
|
|
||||||
ChainID apemanager_sdk.ChainID
|
ChainID apeSDK.ChainID
|
||||||
}
|
}
|
||||||
|
|
||||||
func (prm *PrmAPEManagerRemoveChain) buildRequest(c *Client) (*apemanager_v2.RemoveChainRequest, error) {
|
func (prm *PrmAPEManagerRemoveChain) buildRequest(c *Client) (*apemanagerV2.RemoveChainRequest, error) {
|
||||||
if len(prm.XHeaders)%2 != 0 {
|
if len(prm.XHeaders)%2 != 0 {
|
||||||
return nil, errorInvalidXHeaders
|
return nil, errorInvalidXHeaders
|
||||||
}
|
}
|
||||||
|
|
||||||
req := new(apemanager_v2.RemoveChainRequest)
|
req := new(apemanagerV2.RemoveChainRequest)
|
||||||
reqBody := new(apemanager_v2.RemoveChainRequestBody)
|
reqBody := new(apemanagerV2.RemoveChainRequestBody)
|
||||||
|
|
||||||
reqBody.SetTarget(prm.ChainTarget.ToV2())
|
reqBody.SetTarget(prm.ChainTarget.ToV2())
|
||||||
reqBody.SetChainID(prm.ChainID)
|
reqBody.SetChainID(prm.ChainID)
|
||||||
|
|
||||||
req.SetBody(reqBody)
|
req.SetBody(reqBody)
|
||||||
|
|
||||||
var meta session_v2.RequestMetaHeader
|
var meta sessionV2.RequestMetaHeader
|
||||||
writeXHeadersToMeta(prm.XHeaders, &meta)
|
writeXHeadersToMeta(prm.XHeaders, &meta)
|
||||||
|
|
||||||
c.prepareRequest(req, &meta)
|
c.prepareRequest(req, &meta)
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -3,7 +3,7 @@ module git.frostfs.info/TrueCloudLab/frostfs-sdk-go
|
||||||
go 1.20
|
go 1.20
|
||||||
|
|
||||||
require (
|
require (
|
||||||
git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240516133103-0803bc6ded00
|
git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240529164544-9e825239ac5f
|
||||||
git.frostfs.info/TrueCloudLab/frostfs-contract v0.0.0-20230307110621-19a8ef2d02fb
|
git.frostfs.info/TrueCloudLab/frostfs-contract v0.0.0-20230307110621-19a8ef2d02fb
|
||||||
git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0
|
git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0
|
||||||
git.frostfs.info/TrueCloudLab/hrw v1.2.1
|
git.frostfs.info/TrueCloudLab/hrw v1.2.1
|
||||||
|
|
BIN
go.sum
BIN
go.sum
Binary file not shown.
Loading…
Reference in a new issue