forked from TrueCloudLab/frostfs-s3-gw
Compare commits
25 commits
master
...
feature/96
Author | SHA1 | Date | |
---|---|---|---|
10bc3884af | |||
dea79631bb | |||
618ea318ba | |||
7ae4323116 | |||
c0f959ece7 | |||
0cf19d24ee | |||
188e0cfd01 | |||
50aeba6a4e | |||
c6d0e5fc44 | |||
377fa127b5 | |||
f02bad65a8 | |||
13d00dd7ce | |||
02122892ca | |||
272e3a0f03 | |||
65a8e2dadc | |||
b7e15402a1 | |||
0cc6b41b2d | |||
51be9d9778 | |||
1cad101609 | |||
d631ee55c9 | |||
85c8210ffd | |||
bcfbcdc82f | |||
fd310f5e9f | |||
1f5f2bd3d5 | |||
a32b41716f |
55 changed files with 1885 additions and 805 deletions
29
CHANGELOG.md
29
CHANGELOG.md
|
@ -4,13 +4,18 @@ This document outlines major changes between releases.
|
|||
|
||||
## [Unreleased]
|
||||
|
||||
## [0.29.0] - Zemu - 2024-05-27
|
||||
|
||||
### Fixed
|
||||
- Fix marshaling errors in `DeleteObjects` method (#222)
|
||||
- Fix status code in GET/HEAD delete marker (#226)
|
||||
- Fix `NextVersionIDMarker` in `list-object-versions` (#248)
|
||||
- Fix possibility of panic during SIGHUP (#288)
|
||||
- Fix flaky `TestErrorTimeoutChecking` (`make test` sometimes failed) (#290)
|
||||
- Fix user owner ID in billing metrics (#321)
|
||||
- Fix log-level change on SIGHUP (#313)
|
||||
- Fix anonymous put request (#311)
|
||||
- Fix routine leak from nns resolver (#324)
|
||||
- Fix svace errors (#325, #328)
|
||||
|
||||
### Added
|
||||
- Add new `frostfs.buffer_max_size_for_put` config param and sync TZ hash for PUT operations (#197)
|
||||
|
@ -22,10 +27,10 @@ This document outlines major changes between releases.
|
|||
- Support per namespace placement policies configuration (see `namespaces.config` config param) (#266)
|
||||
- Support control api to manage policies. See `control` config section (#258)
|
||||
- Add `namespace` label to billing metrics (#271)
|
||||
- Support policy-engine (#257)
|
||||
- Support `policy` contract (#259)
|
||||
- Support policy-engine (#257, #259, #282, #283, #302, #307, #345, #351, #358, #360, #362, #383, #354)
|
||||
- Support `proxy` contract (#287)
|
||||
- Authmate: support custom attributes (#292)
|
||||
- Add FrostfsID cache (#269)
|
||||
|
||||
### Changed
|
||||
- Generalise config param `use_default_xmlns_for_complete_multipart` to `use_default_xmlns` so that use default xmlns for all requests (#221)
|
||||
|
@ -34,9 +39,23 @@ This document outlines major changes between releases.
|
|||
- Use tombstone when delete multipart upload (#275)
|
||||
- Support new parameter `cache.accessbox.removing_check_interval` (#305)
|
||||
- Use APE rules instead of eACL in container creation (#306)
|
||||
- Rework bucket policy with policy-engine (#261)
|
||||
- Improved object listing speed (#165, #347)
|
||||
- Logging improvement (#300, #318)
|
||||
|
||||
### Removed
|
||||
- Drop sending whitespace characters during complete multipart upload and related config param `kludge.complete_multipart_keepalive` (#227)
|
||||
- Unused legacy minio related code (#299)
|
||||
- Redundant output with journald logging (#298)
|
||||
|
||||
## [0.28.2] - 2024-05-27
|
||||
|
||||
### Fixed
|
||||
- `anon` user in billing metrics (#321)
|
||||
- Parts are not removed when multipart object removed (#370)
|
||||
|
||||
### Added
|
||||
- Put request in duration metrics (#280)
|
||||
|
||||
## [0.28.1] - 2024-01-24
|
||||
|
||||
|
@ -154,4 +173,6 @@ To see CHANGELOG for older versions, refer to https://github.com/nspcc-dev/neofs
|
|||
[0.27.0]: https://git.frostfs.info/TrueCloudLab/frostfs-s3-gw/compare/b2148cc3...v0.27.0
|
||||
[0.28.0]: https://git.frostfs.info/TrueCloudLab/frostfs-s3-gw/compare/v0.27.0...v0.28.0
|
||||
[0.28.1]: https://git.frostfs.info/TrueCloudLab/frostfs-s3-gw/compare/v0.28.0...v0.28.1
|
||||
[Unreleased]: https://git.frostfs.info/TrueCloudLab/frostfs-s3-gw/compare/v0.28.1...master
|
||||
[0.28.2]: https://git.frostfs.info/TrueCloudLab/frostfs-s3-gw/compare/v0.28.1...v0.28.2
|
||||
[0.29.0]: https://git.frostfs.info/TrueCloudLab/frostfs-s3-gw/compare/v0.28.2...v0.29.0
|
||||
[Unreleased]: https://git.frostfs.info/TrueCloudLab/frostfs-s3-gw/compare/v0.29.0...master
|
||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
v0.28.1
|
||||
v0.29.0
|
||||
|
|
41
api/cache/cache_test.go
vendored
41
api/cache/cache_test.go
vendored
|
@ -3,10 +3,13 @@ package cache
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/creds/accessbox"
|
||||
cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test"
|
||||
oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zaptest/observer"
|
||||
|
@ -194,6 +197,44 @@ func TestNotificationConfigurationCacheType(t *testing.T) {
|
|||
assertInvalidCacheEntry(t, cache.GetNotificationConfiguration(key), observedLog)
|
||||
}
|
||||
|
||||
func TestFrostFSIDSubjectCacheType(t *testing.T) {
|
||||
logger, observedLog := getObservedLogger()
|
||||
cache := NewFrostfsIDCache(DefaultFrostfsIDConfig(logger))
|
||||
|
||||
key, err := util.Uint160DecodeStringLE("4ea976429703418ef00fc4912a409b6a0b973034")
|
||||
require.NoError(t, err)
|
||||
value := &client.SubjectExtended{}
|
||||
|
||||
err = cache.PutSubject(key, value)
|
||||
require.NoError(t, err)
|
||||
val := cache.GetSubject(key)
|
||||
require.Equal(t, value, val)
|
||||
require.Equal(t, 0, observedLog.Len())
|
||||
|
||||
err = cache.cache.Set(key, "tmp")
|
||||
require.NoError(t, err)
|
||||
assertInvalidCacheEntry(t, cache.GetSubject(key), observedLog)
|
||||
}
|
||||
|
||||
func TestFrostFSIDUserKeyCacheType(t *testing.T) {
|
||||
logger, observedLog := getObservedLogger()
|
||||
cache := NewFrostfsIDCache(DefaultFrostfsIDConfig(logger))
|
||||
|
||||
ns, name := "ns", "name"
|
||||
value, err := keys.NewPrivateKey()
|
||||
require.NoError(t, err)
|
||||
|
||||
err = cache.PutUserKey(ns, name, value.PublicKey())
|
||||
require.NoError(t, err)
|
||||
val := cache.GetUserKey(ns, name)
|
||||
require.Equal(t, value.PublicKey(), val)
|
||||
require.Equal(t, 0, observedLog.Len())
|
||||
|
||||
err = cache.cache.Set(ns+"/"+name, "tmp")
|
||||
require.NoError(t, err)
|
||||
assertInvalidCacheEntry(t, cache.GetUserKey(ns, name), observedLog)
|
||||
}
|
||||
|
||||
func assertInvalidCacheEntry(t *testing.T, val interface{}, observedLog *observer.ObservedLogs) {
|
||||
require.Nil(t, val)
|
||||
require.Equal(t, 1, observedLog.Len())
|
||||
|
|
77
api/cache/frostfsid.go
vendored
Normal file
77
api/cache/frostfsid.go
vendored
Normal file
|
@ -0,0 +1,77 @@
|
|||
package cache
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/logs"
|
||||
"github.com/bluele/gcache"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// FrostfsIDCache provides lru cache for frostfsid contract.
|
||||
type FrostfsIDCache struct {
|
||||
cache gcache.Cache
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
const (
|
||||
// DefaultFrostfsIDCacheSize is a default maximum number of entries in cache.
|
||||
DefaultFrostfsIDCacheSize = 1e4
|
||||
// DefaultFrostfsIDCacheLifetime is a default lifetime of entries in cache.
|
||||
DefaultFrostfsIDCacheLifetime = time.Minute
|
||||
)
|
||||
|
||||
// DefaultFrostfsIDConfig returns new default cache expiration values.
|
||||
func DefaultFrostfsIDConfig(logger *zap.Logger) *Config {
|
||||
return &Config{
|
||||
Size: DefaultFrostfsIDCacheSize,
|
||||
Lifetime: DefaultFrostfsIDCacheLifetime,
|
||||
Logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
// NewFrostfsIDCache creates an object of FrostfsIDCache.
|
||||
func NewFrostfsIDCache(config *Config) *FrostfsIDCache {
|
||||
gc := gcache.New(config.Size).LRU().Expiration(config.Lifetime).Build()
|
||||
return &FrostfsIDCache{cache: gc, logger: config.Logger}
|
||||
}
|
||||
|
||||
// GetSubject returns a cached client.SubjectExtended. Returns nil if value is missing.
|
||||
func (c *FrostfsIDCache) GetSubject(key util.Uint160) *client.SubjectExtended {
|
||||
return get[client.SubjectExtended](c, key)
|
||||
}
|
||||
|
||||
// PutSubject puts a client.SubjectExtended to cache.
|
||||
func (c *FrostfsIDCache) PutSubject(key util.Uint160, subject *client.SubjectExtended) error {
|
||||
return c.cache.Set(key, subject)
|
||||
}
|
||||
|
||||
// GetUserKey returns a cached *keys.PublicKey. Returns nil if value is missing.
|
||||
func (c *FrostfsIDCache) GetUserKey(ns, name string) *keys.PublicKey {
|
||||
return get[keys.PublicKey](c, ns+"/"+name)
|
||||
}
|
||||
|
||||
// PutUserKey puts a client.SubjectExtended to cache.
|
||||
func (c *FrostfsIDCache) PutUserKey(ns, name string, userKey *keys.PublicKey) error {
|
||||
return c.cache.Set(ns+"/"+name, userKey)
|
||||
}
|
||||
|
||||
func get[T any](c *FrostfsIDCache, key any) *T {
|
||||
entry, err := c.cache.Get(key)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
result, ok := entry.(*T)
|
||||
if !ok {
|
||||
c.logger.Warn(logs.InvalidCacheEntryType, zap.String("actual", fmt.Sprintf("%T", entry)),
|
||||
zap.String("expected", fmt.Sprintf("%T", result)))
|
||||
return nil
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
|
@ -284,6 +284,32 @@ func (h *handler) GetBucketACLHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
func (h *handler) encodeBucketCannedACL(ctx context.Context, bktInfo *data.BucketInfo, settings *data.BucketSettings) *AccessControlPolicy {
|
||||
res := h.encodePrivateCannedACL(ctx, bktInfo, settings)
|
||||
|
||||
switch settings.CannedACL {
|
||||
case basicACLPublic:
|
||||
grantee := NewGrantee(acpGroup)
|
||||
grantee.URI = allUsersGroup
|
||||
|
||||
res.AccessControlList = append(res.AccessControlList, &Grant{
|
||||
Grantee: grantee,
|
||||
Permission: aclWrite,
|
||||
})
|
||||
fallthrough
|
||||
case basicACLReadOnly:
|
||||
grantee := NewGrantee(acpGroup)
|
||||
grantee.URI = allUsersGroup
|
||||
|
||||
res.AccessControlList = append(res.AccessControlList, &Grant{
|
||||
Grantee: grantee,
|
||||
Permission: aclRead,
|
||||
})
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func (h *handler) encodePrivateCannedACL(ctx context.Context, bktInfo *data.BucketInfo, settings *data.BucketSettings) *AccessControlPolicy {
|
||||
ownerDisplayName := bktInfo.Owner.EncodeToString()
|
||||
ownerEncodedID := ownerDisplayName
|
||||
|
||||
|
@ -308,26 +334,6 @@ func (h *handler) encodeBucketCannedACL(ctx context.Context, bktInfo *data.Bucke
|
|||
Permission: aclFullControl,
|
||||
}}
|
||||
|
||||
switch settings.CannedACL {
|
||||
case basicACLPublic:
|
||||
grantee := NewGrantee(acpGroup)
|
||||
grantee.URI = allUsersGroup
|
||||
|
||||
res.AccessControlList = append(res.AccessControlList, &Grant{
|
||||
Grantee: grantee,
|
||||
Permission: aclWrite,
|
||||
})
|
||||
fallthrough
|
||||
case basicACLReadOnly:
|
||||
grantee := NewGrantee(acpGroup)
|
||||
grantee.URI = allUsersGroup
|
||||
|
||||
res.AccessControlList = append(res.AccessControlList, &Grant{
|
||||
Grantee: grantee,
|
||||
Permission: aclRead,
|
||||
})
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
|
@ -444,7 +450,7 @@ func (h *handler) putBucketACLAPEHandler(w http.ResponseWriter, r *http.Request,
|
|||
}
|
||||
|
||||
chainRules := bucketCannedACLToAPERules(cannedACL, reqInfo, key, bktInfo.CID)
|
||||
if err = h.ape.SaveACLChains(reqInfo.Namespace, chainRules); err != nil {
|
||||
if err = h.ape.SaveACLChains(bktInfo.CID.EncodeToString(), chainRules); err != nil {
|
||||
h.logAndSendError(w, "failed to add morph rule chains", reqInfo, err)
|
||||
return
|
||||
}
|
||||
|
@ -513,19 +519,17 @@ func (h *handler) GetObjectACLHandler(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
apeEnabled := bktInfo.APEEnabled
|
||||
|
||||
if !apeEnabled {
|
||||
settings, err := h.obj.GetBucketSettings(r.Context(), bktInfo)
|
||||
if err != nil {
|
||||
h.logAndSendError(w, "couldn't get bucket settings", reqInfo, err)
|
||||
return
|
||||
}
|
||||
apeEnabled = len(settings.CannedACL) != 0
|
||||
settings, err := h.obj.GetBucketSettings(r.Context(), bktInfo)
|
||||
if err != nil {
|
||||
h.logAndSendError(w, "couldn't get bucket settings", reqInfo, err)
|
||||
return
|
||||
}
|
||||
|
||||
if apeEnabled {
|
||||
h.logAndSendError(w, "acl not supported for this bucket", reqInfo, errors.GetAPIError(errors.ErrAccessControlListNotSupported))
|
||||
if bktInfo.APEEnabled || len(settings.CannedACL) != 0 {
|
||||
if err = middleware.EncodeToResponse(w, h.encodePrivateCannedACL(ctx, bktInfo, settings)); err != nil {
|
||||
h.logAndSendError(w, "something went wrong", reqInfo, err)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -543,7 +547,7 @@ func (h *handler) GetObjectACLHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
objInfo, err := h.obj.GetObjectInfo(ctx, prm)
|
||||
if err != nil {
|
||||
h.logAndSendError(w, "could not object info", reqInfo, err)
|
||||
h.logAndSendError(w, "could not get object info", reqInfo, err)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -681,7 +685,8 @@ func (h *handler) DeleteBucketPolicyHandler(w http.ResponseWriter, r *http.Reque
|
|||
return
|
||||
}
|
||||
|
||||
if err = h.ape.DeleteBucketPolicy(reqInfo.Namespace, bktInfo.CID, getBucketChainID(chain.S3, bktInfo)); err != nil {
|
||||
chainIDs := []chain.ID{getBucketChainID(chain.S3, bktInfo), getBucketChainID(chain.Ingress, bktInfo)}
|
||||
if err = h.ape.DeleteBucketPolicy(reqInfo.Namespace, bktInfo.CID, chainIDs); err != nil {
|
||||
h.logAndSendError(w, "failed to delete policy from storage", reqInfo, err)
|
||||
return
|
||||
}
|
||||
|
@ -735,13 +740,6 @@ func (h *handler) PutBucketPolicyHandler(w http.ResponseWriter, r *http.Request)
|
|||
}
|
||||
}
|
||||
|
||||
nativeChain, err := engineiam.ConvertToNativeChain(bktPolicy, h.nativeResolver(reqInfo.Namespace, bktInfo))
|
||||
if err != nil {
|
||||
h.logAndSendError(w, "could not convert s3 policy to native chain policy", reqInfo, err)
|
||||
return
|
||||
}
|
||||
nativeChain.ID = getBucketChainID(chain.Ingress, bktInfo)
|
||||
|
||||
s3Chain, err := engineiam.ConvertToS3Chain(bktPolicy, h.frostfsid)
|
||||
if err != nil {
|
||||
h.logAndSendError(w, "could not convert s3 policy to chain policy", reqInfo, err)
|
||||
|
@ -749,7 +747,22 @@ func (h *handler) PutBucketPolicyHandler(w http.ResponseWriter, r *http.Request)
|
|||
}
|
||||
s3Chain.ID = getBucketChainID(chain.S3, bktInfo)
|
||||
|
||||
if err = h.ape.PutBucketPolicy(reqInfo.Namespace, bktInfo.CID, jsonPolicy, []*chain.Chain{s3Chain, nativeChain}); err != nil {
|
||||
nativeChain, err := engineiam.ConvertToNativeChain(bktPolicy, h.nativeResolver(reqInfo.Namespace, bktInfo))
|
||||
if err == nil {
|
||||
nativeChain.ID = getBucketChainID(chain.Ingress, bktInfo)
|
||||
} else if !stderrors.Is(err, engineiam.ErrActionsNotApplicable) {
|
||||
h.logAndSendError(w, "could not convert s3 policy to native chain policy", reqInfo, err)
|
||||
return
|
||||
} else {
|
||||
h.reqLogger(r.Context()).Warn(logs.PolicyCouldntBeConvertedToNativeRules)
|
||||
}
|
||||
|
||||
chainsToSave := []*chain.Chain{s3Chain}
|
||||
if nativeChain != nil {
|
||||
chainsToSave = append(chainsToSave, nativeChain)
|
||||
}
|
||||
|
||||
if err = h.ape.PutBucketPolicy(reqInfo.Namespace, bktInfo.CID, jsonPolicy, chainsToSave); err != nil {
|
||||
h.logAndSendError(w, "failed to update policy in contract", reqInfo, err)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -1324,60 +1324,101 @@ func TestPutBucketAPE(t *testing.T) {
|
|||
_, err := hc.tp.ContainerEACL(hc.Context(), layer.PrmContainerEACL{ContainerID: info.BktInfo.CID})
|
||||
require.ErrorContains(t, err, "not found")
|
||||
|
||||
chains, err := hc.h.ape.(*apeMock).ListChains(engine.NamespaceTarget(""))
|
||||
chains, err := hc.h.ape.(*apeMock).ListChains(engine.ContainerTarget(info.BktInfo.CID.EncodeToString()))
|
||||
require.NoError(t, err)
|
||||
require.Len(t, chains, 2)
|
||||
}
|
||||
|
||||
func TestPutBucketObjectACLErrorAPE(t *testing.T) {
|
||||
func TestPutObjectACLErrorAPE(t *testing.T) {
|
||||
hc := prepareHandlerContext(t)
|
||||
bktName, objName := "bucket-for-acl-ape", "object"
|
||||
|
||||
info := createBucket(hc, bktName)
|
||||
putObject(hc, bktName, objName)
|
||||
|
||||
putObjectWithHeadersAssertS3Error(hc, bktName, objName, map[string]string{api.AmzACL: basicACLPublic}, s3errors.ErrAccessControlListNotSupported)
|
||||
putObjectWithHeaders(hc, bktName, objName, map[string]string{api.AmzACL: basicACLPrivate}) // only `private` canned acl is allowed, that is actually ignored
|
||||
putObjectWithHeaders(hc, bktName, objName, nil)
|
||||
|
||||
aclBody := &AccessControlPolicy{}
|
||||
putBucketACLAssertS3Error(hc, bktName, info.Box, nil, aclBody, s3errors.ErrAccessControlListNotSupported)
|
||||
|
||||
putObjectACLAssertS3Error(hc, bktName, objName, info.Box, nil, aclBody, s3errors.ErrAccessControlListNotSupported)
|
||||
getObjectACLAssertS3Error(hc, bktName, objName, s3errors.ErrAccessControlListNotSupported)
|
||||
|
||||
aclRes := getObjectACL(hc, bktName, objName)
|
||||
checkPrivateACL(t, aclRes, info.Key.PublicKey())
|
||||
}
|
||||
|
||||
func TestGetBucketACLAPE(t *testing.T) {
|
||||
func TestCreateObjectACLErrorAPE(t *testing.T) {
|
||||
hc := prepareHandlerContext(t)
|
||||
bktName, objName, objNameCopy := "bucket-for-acl-ape", "object", "copy"
|
||||
|
||||
createBucket(hc, bktName)
|
||||
|
||||
putObject(hc, bktName, objName)
|
||||
copyObject(hc, bktName, objName, objNameCopy, CopyMeta{Headers: map[string]string{api.AmzACL: basicACLPublic}}, http.StatusBadRequest)
|
||||
copyObject(hc, bktName, objName, objNameCopy, CopyMeta{Headers: map[string]string{api.AmzACL: basicACLPrivate}}, http.StatusOK)
|
||||
|
||||
createMultipartUploadAssertS3Error(hc, bktName, objName, map[string]string{api.AmzACL: basicACLPublic}, s3errors.ErrAccessControlListNotSupported)
|
||||
createMultipartUpload(hc, bktName, objName, map[string]string{api.AmzACL: basicACLPrivate})
|
||||
}
|
||||
|
||||
func TestPutObjectACLBackwardCompatibility(t *testing.T) {
|
||||
hc := prepareHandlerContext(t)
|
||||
hc.config.aclEnabled = true
|
||||
bktName, objName := "bucket-for-acl-ape", "object"
|
||||
|
||||
info := createBucket(hc, bktName)
|
||||
|
||||
putObjectWithHeadersBase(hc, bktName, objName, map[string]string{api.AmzACL: basicACLPrivate}, info.Box, nil)
|
||||
putObjectWithHeadersBase(hc, bktName, objName, map[string]string{api.AmzACL: basicACLPublic}, info.Box, nil)
|
||||
|
||||
aclRes := getObjectACL(hc, bktName, objName)
|
||||
require.Len(t, aclRes.AccessControlList, 2)
|
||||
require.Equal(t, hex.EncodeToString(info.Key.PublicKey().Bytes()), aclRes.AccessControlList[0].Grantee.ID)
|
||||
require.Equal(t, aclFullControl, aclRes.AccessControlList[0].Permission)
|
||||
require.Equal(t, allUsersGroup, aclRes.AccessControlList[1].Grantee.URI)
|
||||
require.Equal(t, aclFullControl, aclRes.AccessControlList[1].Permission)
|
||||
|
||||
aclBody := &AccessControlPolicy{}
|
||||
putObjectACLBase(hc, bktName, objName, info.Box, nil, aclBody)
|
||||
}
|
||||
|
||||
func TestBucketACLAPE(t *testing.T) {
|
||||
hc := prepareHandlerContext(t)
|
||||
bktName := "bucket-for-acl-ape"
|
||||
|
||||
info := createBucket(hc, bktName)
|
||||
|
||||
aclBody := &AccessControlPolicy{}
|
||||
putBucketACLAssertS3Error(hc, bktName, info.Box, nil, aclBody, s3errors.ErrAccessControlListNotSupported)
|
||||
|
||||
aclRes := getBucketACL(hc, bktName)
|
||||
checkPrivateBucketACL(t, aclRes, info.Key.PublicKey())
|
||||
checkPrivateACL(t, aclRes, info.Key.PublicKey())
|
||||
|
||||
putBucketACL(hc, bktName, info.Box, map[string]string{api.AmzACL: basicACLPrivate})
|
||||
aclRes = getBucketACL(hc, bktName)
|
||||
checkPrivateBucketACL(t, aclRes, info.Key.PublicKey())
|
||||
checkPrivateACL(t, aclRes, info.Key.PublicKey())
|
||||
|
||||
putBucketACL(hc, bktName, info.Box, map[string]string{api.AmzACL: basicACLReadOnly})
|
||||
aclRes = getBucketACL(hc, bktName)
|
||||
checkPublicReadBucketACL(t, aclRes, info.Key.PublicKey())
|
||||
checkPublicReadACL(t, aclRes, info.Key.PublicKey())
|
||||
|
||||
putBucketACL(hc, bktName, info.Box, map[string]string{api.AmzACL: basicACLPublic})
|
||||
aclRes = getBucketACL(hc, bktName)
|
||||
checkPublicReadWriteBucketACL(t, aclRes, info.Key.PublicKey())
|
||||
checkPublicReadWriteACL(t, aclRes, info.Key.PublicKey())
|
||||
}
|
||||
|
||||
func checkPrivateBucketACL(t *testing.T, aclRes *AccessControlPolicy, ownerKey *keys.PublicKey) {
|
||||
checkBucketACLOwner(t, aclRes, ownerKey, 1)
|
||||
func checkPrivateACL(t *testing.T, aclRes *AccessControlPolicy, ownerKey *keys.PublicKey) {
|
||||
checkACLOwner(t, aclRes, ownerKey, 1)
|
||||
}
|
||||
|
||||
func checkPublicReadBucketACL(t *testing.T, aclRes *AccessControlPolicy, ownerKey *keys.PublicKey) {
|
||||
checkBucketACLOwner(t, aclRes, ownerKey, 2)
|
||||
func checkPublicReadACL(t *testing.T, aclRes *AccessControlPolicy, ownerKey *keys.PublicKey) {
|
||||
checkACLOwner(t, aclRes, ownerKey, 2)
|
||||
|
||||
require.Equal(t, allUsersGroup, aclRes.AccessControlList[1].Grantee.URI)
|
||||
require.Equal(t, aclRead, aclRes.AccessControlList[1].Permission)
|
||||
}
|
||||
|
||||
func checkPublicReadWriteBucketACL(t *testing.T, aclRes *AccessControlPolicy, ownerKey *keys.PublicKey) {
|
||||
checkBucketACLOwner(t, aclRes, ownerKey, 3)
|
||||
func checkPublicReadWriteACL(t *testing.T, aclRes *AccessControlPolicy, ownerKey *keys.PublicKey) {
|
||||
checkACLOwner(t, aclRes, ownerKey, 3)
|
||||
|
||||
require.Equal(t, allUsersGroup, aclRes.AccessControlList[1].Grantee.URI)
|
||||
require.Equal(t, aclWrite, aclRes.AccessControlList[1].Permission)
|
||||
|
@ -1386,7 +1427,7 @@ func checkPublicReadWriteBucketACL(t *testing.T, aclRes *AccessControlPolicy, ow
|
|||
require.Equal(t, aclRead, aclRes.AccessControlList[2].Permission)
|
||||
}
|
||||
|
||||
func checkBucketACLOwner(t *testing.T, aclRes *AccessControlPolicy, ownerKey *keys.PublicKey, ln int) {
|
||||
func checkACLOwner(t *testing.T, aclRes *AccessControlPolicy, ownerKey *keys.PublicKey, ln int) {
|
||||
ownerIDStr := hex.EncodeToString(ownerKey.Bytes())
|
||||
ownerNameStr := ownerKey.Address()
|
||||
|
||||
|
@ -1409,6 +1450,7 @@ func TestBucketPolicy(t *testing.T) {
|
|||
getBucketPolicy(hc, bktName, s3errors.ErrNoSuchBucketPolicy)
|
||||
|
||||
newPolicy := engineiam.Policy{
|
||||
Version: "2012-10-17",
|
||||
Statement: []engineiam.Statement{{
|
||||
Principal: map[engineiam.PrincipalType][]string{engineiam.Wildcard: {}},
|
||||
Effect: engineiam.DenyEffect,
|
||||
|
@ -1426,6 +1468,35 @@ func TestBucketPolicy(t *testing.T) {
|
|||
require.Equal(t, newPolicy, bktPolicy)
|
||||
}
|
||||
|
||||
func TestDeleteBucketWithPolicy(t *testing.T) {
|
||||
hc := prepareHandlerContext(t)
|
||||
|
||||
bktName := "bucket-for-policy"
|
||||
bi := createTestBucket(hc, bktName)
|
||||
|
||||
newPolicy := engineiam.Policy{
|
||||
Version: "2012-10-17",
|
||||
Statement: []engineiam.Statement{{
|
||||
Principal: map[engineiam.PrincipalType][]string{engineiam.Wildcard: {}},
|
||||
Effect: engineiam.AllowEffect,
|
||||
Action: engineiam.Action{"s3:PutObject"},
|
||||
Resource: engineiam.Resource{"arn:aws:s3:::bucket-for-policy/*"},
|
||||
}},
|
||||
}
|
||||
|
||||
putBucketPolicy(hc, bktName, newPolicy)
|
||||
|
||||
require.Len(t, hc.h.ape.(*apeMock).policyMap, 1)
|
||||
require.Len(t, hc.h.ape.(*apeMock).chainMap[engine.ContainerTarget(bi.CID.EncodeToString())], 4)
|
||||
|
||||
deleteBucket(t, hc, bktName, http.StatusNoContent)
|
||||
|
||||
require.Empty(t, hc.h.ape.(*apeMock).policyMap)
|
||||
chains, err := hc.h.ape.(*apeMock).ListChains(engine.ContainerTarget(bi.CID.EncodeToString()))
|
||||
require.NoError(t, err)
|
||||
require.Empty(t, chains)
|
||||
}
|
||||
|
||||
func TestBucketPolicyUnmarshal(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
|
@ -1661,9 +1732,12 @@ func putObjectACLBase(hc *handlerContext, bktName, objName string, box *accessbo
|
|||
return w
|
||||
}
|
||||
|
||||
func getObjectACLAssertS3Error(hc *handlerContext, bktName, objName string, code s3errors.ErrorCode) {
|
||||
func getObjectACL(hc *handlerContext, bktName, objName string) *AccessControlPolicy {
|
||||
w := getObjectACLBase(hc, bktName, objName)
|
||||
assertS3Error(hc.t, w, s3errors.GetAPIError(code))
|
||||
assertStatus(hc.t, w, http.StatusOK)
|
||||
res := &AccessControlPolicy{}
|
||||
parseTestResponse(hc.t, w, res)
|
||||
return res
|
||||
}
|
||||
|
||||
func getObjectACLBase(hc *handlerContext, bktName, objName string) *httptest.ResponseRecorder {
|
||||
|
@ -1671,3 +1745,29 @@ func getObjectACLBase(hc *handlerContext, bktName, objName string) *httptest.Res
|
|||
hc.Handler().GetObjectACLHandler(w, r)
|
||||
return w
|
||||
}
|
||||
|
||||
func putObjectWithHeaders(hc *handlerContext, bktName, objName string, headers map[string]string) http.Header {
|
||||
w := putObjectWithHeadersBase(hc, bktName, objName, headers, nil, nil)
|
||||
assertStatus(hc.t, w, http.StatusOK)
|
||||
return w.Header()
|
||||
}
|
||||
|
||||
func putObjectWithHeadersAssertS3Error(hc *handlerContext, bktName, objName string, headers map[string]string, code s3errors.ErrorCode) {
|
||||
w := putObjectWithHeadersBase(hc, bktName, objName, headers, nil, nil)
|
||||
assertS3Error(hc.t, w, s3errors.GetAPIError(code))
|
||||
}
|
||||
|
||||
func putObjectWithHeadersBase(hc *handlerContext, bktName, objName string, headers map[string]string, box *accessbox.Box, data []byte) *httptest.ResponseRecorder {
|
||||
body := bytes.NewReader(data)
|
||||
w, r := prepareTestPayloadRequest(hc, bktName, objName, body)
|
||||
|
||||
for k, v := range headers {
|
||||
r.Header.Set(k, v)
|
||||
}
|
||||
|
||||
ctx := middleware.SetBoxData(r.Context(), box)
|
||||
r = r.WithContext(ctx)
|
||||
|
||||
hc.Handler().PutObjectHandler(w, r)
|
||||
return w
|
||||
}
|
||||
|
|
|
@ -57,9 +57,9 @@ type (
|
|||
// APE is Access Policy Engine that needs to save policy and acl info to different places.
|
||||
APE interface {
|
||||
PutBucketPolicy(ns string, cnrID cid.ID, policy []byte, chains []*chain.Chain) error
|
||||
DeleteBucketPolicy(ns string, cnrID cid.ID, chainID chain.ID) error
|
||||
DeleteBucketPolicy(ns string, cnrID cid.ID, chainIDs []chain.ID) error
|
||||
GetBucketPolicy(ns string, cnrID cid.ID) ([]byte, error)
|
||||
SaveACLChains(ns string, chains []*chain.Chain) error
|
||||
SaveACLChains(cid string, chains []*chain.Chain) error
|
||||
}
|
||||
)
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ func (h *handler) CopyObjectHandler(w http.ResponseWriter, r *http.Request) {
|
|||
ctx = r.Context()
|
||||
reqInfo = middleware.GetReqInfo(ctx)
|
||||
|
||||
containsACL = containsACLHeaders(r)
|
||||
cannedACLStatus = aclHeadersStatus(r)
|
||||
)
|
||||
|
||||
src := r.Header.Get(api.AmzCopySource)
|
||||
|
@ -93,7 +93,14 @@ func (h *handler) CopyObjectHandler(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
if containsACL {
|
||||
apeEnabled := dstBktInfo.APEEnabled || settings.CannedACL != ""
|
||||
if apeEnabled && cannedACLStatus == aclStatusYes {
|
||||
h.logAndSendError(w, "acl not supported for this bucket", reqInfo, errors.GetAPIError(errors.ErrAccessControlListNotSupported))
|
||||
return
|
||||
}
|
||||
|
||||
needUpdateEACLTable := !(apeEnabled || cannedACLStatus == aclStatusNo)
|
||||
if needUpdateEACLTable {
|
||||
if sessionTokenEACL, err = getSessionTokenSetEACL(ctx); err != nil {
|
||||
h.logAndSendError(w, "could not get eacl session token from a box", reqInfo, err)
|
||||
return
|
||||
|
@ -232,7 +239,7 @@ func (h *handler) CopyObjectHandler(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
if containsACL {
|
||||
if needUpdateEACLTable {
|
||||
newEaclTable, err := h.getNewEAclTable(r, dstBktInfo, dstObjInfo)
|
||||
if err != nil {
|
||||
h.logAndSendError(w, "could not get new eacl table", reqInfo, err)
|
||||
|
|
|
@ -22,6 +22,7 @@ type CopyMeta struct {
|
|||
Tags map[string]string
|
||||
MetadataDirective string
|
||||
Metadata map[string]string
|
||||
Headers map[string]string
|
||||
}
|
||||
|
||||
func TestCopyWithTaggingDirective(t *testing.T) {
|
||||
|
@ -279,6 +280,10 @@ func copyObject(hc *handlerContext, bktName, fromObject, toObject string, copyMe
|
|||
}
|
||||
r.Header.Set(api.AmzTagging, tagsQuery.Encode())
|
||||
|
||||
for key, val := range copyMeta.Headers {
|
||||
r.Header.Set(key, val)
|
||||
}
|
||||
|
||||
hc.Handler().CopyObjectHandler(w, r)
|
||||
assertStatus(hc.t, w, statusCode)
|
||||
}
|
||||
|
|
|
@ -66,7 +66,10 @@ func (h *handler) PutBucketCorsHandler(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
middleware.WriteSuccessResponseHeadersOnly(w)
|
||||
if err = middleware.WriteSuccessResponseHeadersOnly(w); err != nil {
|
||||
h.logAndSendError(w, "write response", reqInfo, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) DeleteBucketCorsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
@ -200,7 +203,10 @@ func (h *handler) Preflight(w http.ResponseWriter, r *http.Request) {
|
|||
if o != wildcard {
|
||||
w.Header().Set(api.AccessControlAllowCredentials, "true")
|
||||
}
|
||||
middleware.WriteSuccessResponseHeadersOnly(w)
|
||||
if err = middleware.WriteSuccessResponseHeadersOnly(w); err != nil {
|
||||
h.logAndSendError(w, "write response", reqInfo, err)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import (
|
|||
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
|
||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session"
|
||||
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
|
@ -276,6 +277,19 @@ func (h *handler) DeleteBucketHandler(w http.ResponseWriter, r *http.Request) {
|
|||
SessionToken: sessionToken,
|
||||
}); err != nil {
|
||||
h.logAndSendError(w, "couldn't delete bucket", reqInfo, err)
|
||||
return
|
||||
}
|
||||
|
||||
chainIDs := []chain.ID{
|
||||
getBucketChainID(chain.S3, bktInfo),
|
||||
getBucketChainID(chain.Ingress, bktInfo),
|
||||
getBucketCannedChainID(chain.S3, bktInfo.CID),
|
||||
getBucketCannedChainID(chain.Ingress, bktInfo.CID),
|
||||
}
|
||||
if err = h.ape.DeleteBucketPolicy(reqInfo.Namespace, bktInfo.CID, chainIDs); err != nil {
|
||||
h.logAndSendError(w, "failed to delete policy from storage", reqInfo, err)
|
||||
return
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
@ -234,24 +235,33 @@ func multipartUpload(hc *handlerContext, bktName, objName string, headers map[st
|
|||
}
|
||||
|
||||
func createMultipartUploadEncrypted(hc *handlerContext, bktName, objName string, headers map[string]string) *InitiateMultipartUploadResponse {
|
||||
return createMultipartUploadBase(hc, bktName, objName, true, headers)
|
||||
return createMultipartUploadOkBase(hc, bktName, objName, true, headers)
|
||||
}
|
||||
|
||||
func createMultipartUpload(hc *handlerContext, bktName, objName string, headers map[string]string) *InitiateMultipartUploadResponse {
|
||||
return createMultipartUploadBase(hc, bktName, objName, false, headers)
|
||||
return createMultipartUploadOkBase(hc, bktName, objName, false, headers)
|
||||
}
|
||||
|
||||
func createMultipartUploadBase(hc *handlerContext, bktName, objName string, encrypted bool, headers map[string]string) *InitiateMultipartUploadResponse {
|
||||
func createMultipartUploadOkBase(hc *handlerContext, bktName, objName string, encrypted bool, headers map[string]string) *InitiateMultipartUploadResponse {
|
||||
w := createMultipartUploadBase(hc, bktName, objName, encrypted, headers)
|
||||
multipartInitInfo := &InitiateMultipartUploadResponse{}
|
||||
readResponse(hc.t, w, http.StatusOK, multipartInitInfo)
|
||||
return multipartInitInfo
|
||||
}
|
||||
|
||||
func createMultipartUploadAssertS3Error(hc *handlerContext, bktName, objName string, headers map[string]string, code errors.ErrorCode) {
|
||||
w := createMultipartUploadBase(hc, bktName, objName, false, headers)
|
||||
assertS3Error(hc.t, w, errors.GetAPIError(code))
|
||||
}
|
||||
|
||||
func createMultipartUploadBase(hc *handlerContext, bktName, objName string, encrypted bool, headers map[string]string) *httptest.ResponseRecorder {
|
||||
w, r := prepareTestRequest(hc, bktName, objName, nil)
|
||||
if encrypted {
|
||||
setEncryptHeaders(r)
|
||||
}
|
||||
setHeaders(r, headers)
|
||||
hc.Handler().CreateMultipartUploadHandler(w, r)
|
||||
multipartInitInfo := &InitiateMultipartUploadResponse{}
|
||||
readResponse(hc.t, w, http.StatusOK, multipartInitInfo)
|
||||
|
||||
return multipartInitInfo
|
||||
return w
|
||||
}
|
||||
|
||||
func completeMultipartUpload(hc *handlerContext, bktName, objName, uploadID string, partsETags []string) {
|
||||
|
|
|
@ -267,7 +267,7 @@ func (a *apeMock) PutBucketPolicy(ns string, cnrID cid.ID, policy []byte, chain
|
|||
}
|
||||
|
||||
for i := range chain {
|
||||
if err := a.AddChain(engine.NamespaceTarget(ns), chain[i]); err != nil {
|
||||
if err := a.AddChain(engine.ContainerTarget(cnrID.EncodeToString()), chain[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -275,11 +275,17 @@ func (a *apeMock) PutBucketPolicy(ns string, cnrID cid.ID, policy []byte, chain
|
|||
return nil
|
||||
}
|
||||
|
||||
func (a *apeMock) DeleteBucketPolicy(ns string, cnrID cid.ID, chainID chain.ID) error {
|
||||
func (a *apeMock) DeleteBucketPolicy(ns string, cnrID cid.ID, chainIDs []chain.ID) error {
|
||||
if err := a.DeletePolicy(ns, cnrID); err != nil {
|
||||
return err
|
||||
}
|
||||
return a.RemoveChain(engine.NamespaceTarget(ns), chainID)
|
||||
for i := range chainIDs {
|
||||
if err := a.RemoveChain(engine.ContainerTarget(cnrID.EncodeToString()), chainIDs[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *apeMock) GetBucketPolicy(ns string, cnrID cid.ID) ([]byte, error) {
|
||||
|
@ -291,9 +297,9 @@ func (a *apeMock) GetBucketPolicy(ns string, cnrID cid.ID) ([]byte, error) {
|
|||
return policy, nil
|
||||
}
|
||||
|
||||
func (a *apeMock) SaveACLChains(ns string, chains []*chain.Chain) error {
|
||||
func (a *apeMock) SaveACLChains(cid string, chains []*chain.Chain) error {
|
||||
for i := range chains {
|
||||
if err := a.AddChain(engine.NamespaceTarget(ns), chains[i]); err != nil {
|
||||
if err := a.AddChain(engine.ContainerTarget(cid), chains[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
|
|
@ -140,7 +140,10 @@ func (h *handler) HeadBucketHandler(w http.ResponseWriter, r *http.Request) {
|
|||
w.Header().Set(api.ContainerZone, bktInfo.Zone)
|
||||
}
|
||||
|
||||
middleware.WriteResponse(w, http.StatusOK, nil, middleware.MimeNone)
|
||||
if err = middleware.WriteResponse(w, http.StatusOK, nil, middleware.MimeNone); err != nil {
|
||||
h.logAndSendError(w, "write response", reqInfo, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) setLockingHeaders(bktInfo *data.BucketInfo, lockInfo data.LockInfo, header http.Header) error {
|
||||
|
|
|
@ -103,6 +103,9 @@ const (
|
|||
|
||||
func (h *handler) CreateMultipartUploadHandler(w http.ResponseWriter, r *http.Request) {
|
||||
reqInfo := middleware.GetReqInfo(r.Context())
|
||||
uploadID := uuid.New()
|
||||
cannedACLStatus := aclHeadersStatus(r)
|
||||
additional := []zap.Field{zap.String("uploadID", uploadID.String())}
|
||||
|
||||
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
||||
if err != nil {
|
||||
|
@ -110,8 +113,17 @@ func (h *handler) CreateMultipartUploadHandler(w http.ResponseWriter, r *http.Re
|
|||
return
|
||||
}
|
||||
|
||||
uploadID := uuid.New()
|
||||
additional := []zap.Field{zap.String("uploadID", uploadID.String())}
|
||||
settings, err := h.obj.GetBucketSettings(r.Context(), bktInfo)
|
||||
if err != nil {
|
||||
h.logAndSendError(w, "couldn't get bucket settings", reqInfo, err)
|
||||
return
|
||||
}
|
||||
|
||||
apeEnabled := bktInfo.APEEnabled || settings.CannedACL != ""
|
||||
if apeEnabled && cannedACLStatus == aclStatusYes {
|
||||
h.logAndSendError(w, "acl not supported for this bucket", reqInfo, errors.GetAPIError(errors.ErrAccessControlListNotSupported))
|
||||
return
|
||||
}
|
||||
|
||||
p := &layer.CreateMultipartParams{
|
||||
Info: &layer.UploadInfoParams{
|
||||
|
@ -122,7 +134,8 @@ func (h *handler) CreateMultipartUploadHandler(w http.ResponseWriter, r *http.Re
|
|||
Data: &layer.UploadData{},
|
||||
}
|
||||
|
||||
if containsACLHeaders(r) {
|
||||
needUpdateEACLTable := !(apeEnabled || cannedACLStatus == aclStatusNo)
|
||||
if needUpdateEACLTable {
|
||||
key, err := h.bearerTokenIssuerKey(r.Context())
|
||||
if err != nil {
|
||||
h.logAndSendError(w, "couldn't get gate key", reqInfo, err, additional...)
|
||||
|
@ -266,7 +279,10 @@ func (h *handler) UploadPartHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
w.Header().Set(api.ETag, data.Quote(hash))
|
||||
middleware.WriteSuccessResponseHeadersOnly(w)
|
||||
if err = middleware.WriteSuccessResponseHeadersOnly(w); err != nil {
|
||||
h.logAndSendError(w, "write response", reqInfo, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) UploadPartCopy(w http.ResponseWriter, r *http.Request) {
|
||||
|
|
|
@ -38,6 +38,36 @@ func TestMultipartUploadInvalidPart(t *testing.T) {
|
|||
assertS3Error(hc.t, w, s3Errors.GetAPIError(s3Errors.ErrEntityTooSmall))
|
||||
}
|
||||
|
||||
func TestDeleteMultipartAllParts(t *testing.T) {
|
||||
hc := prepareHandlerContext(t)
|
||||
|
||||
partSize := layer.UploadMinSize
|
||||
objLen := 6 * partSize
|
||||
|
||||
bktName, bktName2, objName := "bucket", "bucket2", "object"
|
||||
|
||||
// unversioned bucket
|
||||
createTestBucket(hc, bktName)
|
||||
multipartUpload(hc, bktName, objName, nil, objLen, partSize)
|
||||
deleteObject(t, hc, bktName, objName, emptyVersion)
|
||||
require.Empty(t, hc.tp.Objects())
|
||||
|
||||
// encrypted multipart
|
||||
multipartUploadEncrypted(hc, bktName, objName, nil, objLen, partSize)
|
||||
deleteObject(t, hc, bktName, objName, emptyVersion)
|
||||
require.Empty(t, hc.tp.Objects())
|
||||
|
||||
// versions bucket
|
||||
createTestBucket(hc, bktName2)
|
||||
putBucketVersioning(t, hc, bktName2, true)
|
||||
multipartUpload(hc, bktName2, objName, nil, objLen, partSize)
|
||||
_, hdr := getObject(hc, bktName2, objName)
|
||||
versionID := hdr.Get("X-Amz-Version-Id")
|
||||
deleteObject(t, hc, bktName2, objName, emptyVersion)
|
||||
deleteObject(t, hc, bktName2, objName, versionID)
|
||||
require.Empty(t, hc.tp.Objects())
|
||||
}
|
||||
|
||||
func TestMultipartReUploadPart(t *testing.T) {
|
||||
hc := prepareHandlerContext(t)
|
||||
|
||||
|
|
|
@ -186,12 +186,31 @@ func (h *handler) PutObjectHandler(w http.ResponseWriter, r *http.Request) {
|
|||
err error
|
||||
newEaclTable *eacl.Table
|
||||
sessionTokenEACL *session.Container
|
||||
containsACL = containsACLHeaders(r)
|
||||
cannedACLStatus = aclHeadersStatus(r)
|
||||
ctx = r.Context()
|
||||
reqInfo = middleware.GetReqInfo(ctx)
|
||||
)
|
||||
|
||||
if containsACL {
|
||||
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
||||
if err != nil {
|
||||
h.logAndSendError(w, "could not get bucket objInfo", reqInfo, err)
|
||||
return
|
||||
}
|
||||
|
||||
settings, err := h.obj.GetBucketSettings(ctx, bktInfo)
|
||||
if err != nil {
|
||||
h.logAndSendError(w, "could not get bucket settings", reqInfo, err)
|
||||
return
|
||||
}
|
||||
|
||||
apeEnabled := bktInfo.APEEnabled || settings.CannedACL != ""
|
||||
if apeEnabled && cannedACLStatus == aclStatusYes {
|
||||
h.logAndSendError(w, "acl not supported for this bucket", reqInfo, errors.GetAPIError(errors.ErrAccessControlListNotSupported))
|
||||
return
|
||||
}
|
||||
|
||||
needUpdateEACLTable := !(apeEnabled || cannedACLStatus == aclStatusNo)
|
||||
if needUpdateEACLTable {
|
||||
if sessionTokenEACL, err = getSessionTokenSetEACL(r.Context()); err != nil {
|
||||
h.logAndSendError(w, "could not get eacl session token from a box", reqInfo, err)
|
||||
return
|
||||
|
@ -204,12 +223,6 @@ func (h *handler) PutObjectHandler(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
||||
if err != nil {
|
||||
h.logAndSendError(w, "could not get bucket objInfo", reqInfo, err)
|
||||
return
|
||||
}
|
||||
|
||||
metadata := parseMetadata(r)
|
||||
if contentType := r.Header.Get(api.ContentType); len(contentType) > 0 {
|
||||
metadata[api.ContentType] = contentType
|
||||
|
@ -261,12 +274,6 @@ func (h *handler) PutObjectHandler(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
settings, err := h.obj.GetBucketSettings(ctx, bktInfo)
|
||||
if err != nil {
|
||||
h.logAndSendError(w, "could not get bucket settings", reqInfo, err)
|
||||
return
|
||||
}
|
||||
|
||||
params.Lock, err = formObjectLock(ctx, bktInfo, settings.LockConfiguration, r.Header)
|
||||
if err != nil {
|
||||
h.logAndSendError(w, "could not form object lock", reqInfo, err)
|
||||
|
@ -292,7 +299,7 @@ func (h *handler) PutObjectHandler(w http.ResponseWriter, r *http.Request) {
|
|||
h.reqLogger(ctx).Error(logs.CouldntSendNotification, zap.Error(err))
|
||||
}
|
||||
|
||||
if containsACL {
|
||||
if needUpdateEACLTable {
|
||||
if newEaclTable, err = h.getNewEAclTable(r, bktInfo, objInfo); err != nil {
|
||||
h.logAndSendError(w, "could not get new eacl table", reqInfo, err)
|
||||
return
|
||||
|
@ -337,7 +344,10 @@ func (h *handler) PutObjectHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
w.Header().Set(api.ETag, data.Quote(objInfo.ETag(h.cfg.MD5Enabled())))
|
||||
|
||||
middleware.WriteSuccessResponseHeadersOnly(w)
|
||||
if err = middleware.WriteSuccessResponseHeadersOnly(w); err != nil {
|
||||
h.logAndSendError(w, "write response", reqInfo, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) getBodyReader(r *http.Request) (io.ReadCloser, error) {
|
||||
|
@ -462,7 +472,7 @@ func (h *handler) PostObject(w http.ResponseWriter, r *http.Request) {
|
|||
ctx = r.Context()
|
||||
reqInfo = middleware.GetReqInfo(ctx)
|
||||
metadata = make(map[string]string)
|
||||
containsACL = containsACLHeaders(r)
|
||||
cannedACLStatus = aclHeadersStatus(r)
|
||||
)
|
||||
|
||||
policy, err := checkPostPolicy(r, reqInfo, metadata)
|
||||
|
@ -480,7 +490,26 @@ func (h *handler) PostObject(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
}
|
||||
|
||||
if containsACL {
|
||||
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
|
||||
if err != nil {
|
||||
h.logAndSendError(w, "could not get bucket objInfo", reqInfo, err)
|
||||
return
|
||||
}
|
||||
|
||||
settings, err := h.obj.GetBucketSettings(ctx, bktInfo)
|
||||
if err != nil {
|
||||
h.logAndSendError(w, "could not get bucket settings", reqInfo, err)
|
||||
return
|
||||
}
|
||||
|
||||
apeEnabled := bktInfo.APEEnabled || settings.CannedACL != ""
|
||||
if apeEnabled && cannedACLStatus == aclStatusYes {
|
||||
h.logAndSendError(w, "acl not supported for this bucket", reqInfo, errors.GetAPIError(errors.ErrAccessControlListNotSupported))
|
||||
return
|
||||
}
|
||||
|
||||
needUpdateEACLTable := !(apeEnabled || cannedACLStatus == aclStatusNo)
|
||||
if needUpdateEACLTable {
|
||||
if sessionTokenEACL, err = getSessionTokenSetEACL(ctx); err != nil {
|
||||
h.logAndSendError(w, "could not get eacl session token from a box", reqInfo, err)
|
||||
return
|
||||
|
@ -507,12 +536,6 @@ func (h *handler) PostObject(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
bktInfo, err := h.obj.GetBucketInfo(ctx, reqInfo.BucketName)
|
||||
if err != nil {
|
||||
h.logAndSendError(w, "could not get bucket info", reqInfo, err)
|
||||
return
|
||||
}
|
||||
|
||||
params := &layer.PutObjectParams{
|
||||
BktInfo: bktInfo,
|
||||
Object: reqInfo.ObjectName,
|
||||
|
@ -579,9 +602,7 @@ func (h *handler) PostObject(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
}
|
||||
|
||||
if settings, err := h.obj.GetBucketSettings(ctx, bktInfo); err != nil {
|
||||
h.reqLogger(ctx).Warn(logs.CouldntGetBucketVersioning, zap.String("bucket name", reqInfo.BucketName), zap.Error(err))
|
||||
} else if settings.VersioningEnabled() {
|
||||
if settings.VersioningEnabled() {
|
||||
w.Header().Set(api.AmzVersionID, objInfo.VersionID())
|
||||
}
|
||||
|
||||
|
@ -602,7 +623,11 @@ func (h *handler) PostObject(w http.ResponseWriter, r *http.Request) {
|
|||
ETag: data.Quote(objInfo.ETag(h.cfg.MD5Enabled())),
|
||||
}
|
||||
w.WriteHeader(status)
|
||||
if _, err = w.Write(middleware.EncodeResponse(resp)); err != nil {
|
||||
respData, err := middleware.EncodeResponse(resp)
|
||||
if err != nil {
|
||||
h.logAndSendError(w, "encode response", reqInfo, err)
|
||||
}
|
||||
if _, err = w.Write(respData); err != nil {
|
||||
h.logAndSendError(w, "something went wrong", reqInfo, err)
|
||||
}
|
||||
return
|
||||
|
@ -673,9 +698,33 @@ func checkPostPolicy(r *http.Request, reqInfo *middleware.ReqInfo, metadata map[
|
|||
return policy, nil
|
||||
}
|
||||
|
||||
func containsACLHeaders(r *http.Request) bool {
|
||||
return r.Header.Get(api.AmzACL) != "" || r.Header.Get(api.AmzGrantRead) != "" ||
|
||||
r.Header.Get(api.AmzGrantFullControl) != "" || r.Header.Get(api.AmzGrantWrite) != ""
|
||||
type aclStatus int
|
||||
|
||||
const (
|
||||
// aclStatusNo means no acl headers at all.
|
||||
aclStatusNo aclStatus = iota
|
||||
// aclStatusYesAPECompatible means that only X-Amz-Acl present and equals to private.
|
||||
aclStatusYesAPECompatible
|
||||
// aclStatusYes means any other acl headers configuration.
|
||||
aclStatusYes
|
||||
)
|
||||
|
||||
func aclHeadersStatus(r *http.Request) aclStatus {
|
||||
if r.Header.Get(api.AmzGrantRead) != "" ||
|
||||
r.Header.Get(api.AmzGrantFullControl) != "" ||
|
||||
r.Header.Get(api.AmzGrantWrite) != "" {
|
||||
return aclStatusYes
|
||||
}
|
||||
|
||||
cannedACL := r.Header.Get(api.AmzACL)
|
||||
if cannedACL != "" {
|
||||
if cannedACL == basicACLPrivate {
|
||||
return aclStatusYesAPECompatible
|
||||
}
|
||||
return aclStatusYes
|
||||
}
|
||||
|
||||
return aclStatusNo
|
||||
}
|
||||
|
||||
func (h *handler) getNewEAclTable(r *http.Request, bktInfo *data.BucketInfo, objInfo *data.ObjectInfo) (*eacl.Table, error) {
|
||||
|
@ -849,7 +898,7 @@ func (h *handler) createBucketHandlerPolicy(w http.ResponseWriter, r *http.Reque
|
|||
h.reqLogger(ctx).Info(logs.BucketIsCreated, zap.Stringer("container_id", bktInfo.CID))
|
||||
|
||||
chains := bucketCannedACLToAPERules(cannedACL, reqInfo, key, bktInfo.CID)
|
||||
if err = h.ape.SaveACLChains(reqInfo.Namespace, chains); err != nil {
|
||||
if err = h.ape.SaveACLChains(bktInfo.CID.EncodeToString(), chains); err != nil {
|
||||
h.logAndSendError(w, "failed to add morph rule chain", reqInfo, err)
|
||||
return
|
||||
}
|
||||
|
@ -873,7 +922,10 @@ func (h *handler) createBucketHandlerPolicy(w http.ResponseWriter, r *http.Reque
|
|||
return
|
||||
}
|
||||
|
||||
middleware.WriteSuccessResponseHeadersOnly(w)
|
||||
if err = middleware.WriteSuccessResponseHeadersOnly(w); err != nil {
|
||||
h.logAndSendError(w, "write response", reqInfo, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) createBucketHandlerACL(w http.ResponseWriter, r *http.Request) {
|
||||
|
@ -942,7 +994,10 @@ func (h *handler) createBucketHandlerACL(w http.ResponseWriter, r *http.Request)
|
|||
return
|
||||
}
|
||||
|
||||
middleware.WriteSuccessResponseHeadersOnly(w)
|
||||
if err = middleware.WriteSuccessResponseHeadersOnly(w); err != nil {
|
||||
h.logAndSendError(w, "write response", reqInfo, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
const s3ActionPrefix = "s3:"
|
||||
|
|
|
@ -31,9 +31,12 @@ func (h *handler) reqLogger(ctx context.Context) *zap.Logger {
|
|||
|
||||
func (h *handler) logAndSendError(w http.ResponseWriter, logText string, reqInfo *middleware.ReqInfo, err error, additional ...zap.Field) {
|
||||
err = handleDeleteMarker(w, err)
|
||||
code := middleware.WriteErrorResponse(w, reqInfo, transformToS3Error(err))
|
||||
if code, wrErr := middleware.WriteErrorResponse(w, reqInfo, transformToS3Error(err)); wrErr != nil {
|
||||
additional = append(additional, zap.NamedError("write_response_error", wrErr))
|
||||
} else {
|
||||
additional = append(additional, zap.Int("status", code))
|
||||
}
|
||||
fields := []zap.Field{
|
||||
zap.Int("status", code),
|
||||
zap.String("request_id", reqInfo.RequestID),
|
||||
zap.String("method", reqInfo.API),
|
||||
zap.String("bucket", reqInfo.BucketName),
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"io"
|
||||
"time"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl"
|
||||
v2container "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container"
|
||||
objectv2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware"
|
||||
|
@ -220,7 +221,7 @@ func (t *TestFrostFS) ReadObject(ctx context.Context, prm PrmObjectRead) (*Objec
|
|||
|
||||
if obj, ok := t.objects[sAddr]; ok {
|
||||
owner := getBearerOwner(ctx)
|
||||
if !t.checkAccess(prm.Container, owner, eacl.OperationGet) {
|
||||
if !t.checkAccess(prm.Container, owner, eacl.OperationGet, obj) {
|
||||
return nil, ErrAccessDenied
|
||||
}
|
||||
|
||||
|
@ -322,9 +323,9 @@ func (t *TestFrostFS) DeleteObject(ctx context.Context, prm PrmObjectDelete) err
|
|||
return err
|
||||
}
|
||||
|
||||
if _, ok := t.objects[addr.EncodeToString()]; ok {
|
||||
if obj, ok := t.objects[addr.EncodeToString()]; ok {
|
||||
owner := getBearerOwner(ctx)
|
||||
if !t.checkAccess(prm.Container, owner, eacl.OperationDelete) {
|
||||
if !t.checkAccess(prm.Container, owner, eacl.OperationDelete, obj) {
|
||||
return ErrAccessDenied
|
||||
}
|
||||
|
||||
|
@ -376,7 +377,7 @@ func (t *TestFrostFS) ContainerEACL(_ context.Context, prm PrmContainerEACL) (*e
|
|||
return table, nil
|
||||
}
|
||||
|
||||
func (t *TestFrostFS) checkAccess(cnrID cid.ID, owner user.ID, op eacl.Operation) bool {
|
||||
func (t *TestFrostFS) checkAccess(cnrID cid.ID, owner user.ID, op eacl.Operation, obj *object.Object) bool {
|
||||
cnr, ok := t.containers[cnrID.EncodeToString()]
|
||||
if !ok {
|
||||
return false
|
||||
|
@ -392,22 +393,51 @@ func (t *TestFrostFS) checkAccess(cnrID cid.ID, owner user.ID, op eacl.Operation
|
|||
}
|
||||
|
||||
for _, rec := range table.Records() {
|
||||
if rec.Operation() == op && len(rec.Filters()) == 0 {
|
||||
for _, trgt := range rec.Targets() {
|
||||
if trgt.Role() == eacl.RoleOthers {
|
||||
return rec.Action() == eacl.ActionAllow
|
||||
}
|
||||
var targetOwner user.ID
|
||||
for _, pk := range eacl.TargetECDSAKeys(&trgt) {
|
||||
user.IDFromKey(&targetOwner, *pk)
|
||||
if targetOwner.Equals(owner) {
|
||||
return rec.Action() == eacl.ActionAllow
|
||||
}
|
||||
}
|
||||
if rec.Operation() != op {
|
||||
continue
|
||||
}
|
||||
|
||||
if !matchTarget(rec, owner) {
|
||||
continue
|
||||
}
|
||||
|
||||
if matchFilter(rec.Filters(), obj) {
|
||||
return rec.Action() == eacl.ActionAllow
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func matchTarget(rec eacl.Record, owner user.ID) bool {
|
||||
for _, trgt := range rec.Targets() {
|
||||
if trgt.Role() == eacl.RoleOthers {
|
||||
return true
|
||||
}
|
||||
var targetOwner user.ID
|
||||
for _, pk := range eacl.TargetECDSAKeys(&trgt) {
|
||||
user.IDFromKey(&targetOwner, *pk)
|
||||
if targetOwner.Equals(owner) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func matchFilter(filters []eacl.Filter, obj *object.Object) bool {
|
||||
objID, _ := obj.ID()
|
||||
for _, f := range filters {
|
||||
fv2 := f.ToV2()
|
||||
if fv2.GetMatchType() != acl.MatchTypeStringEqual ||
|
||||
fv2.GetHeaderType() != acl.HeaderTypeObject ||
|
||||
fv2.GetKey() != acl.FilterObjectID ||
|
||||
fv2.GetValue() != objID.EncodeToString() {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"context"
|
||||
"crypto/ecdsa"
|
||||
"crypto/rand"
|
||||
"encoding/json"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"io"
|
||||
|
@ -791,9 +792,40 @@ func (n *layer) removeOldVersion(ctx context.Context, bkt *data.BucketInfo, node
|
|||
return obj.VersionID, nil
|
||||
}
|
||||
|
||||
if nodeVersion.IsCombined {
|
||||
return "", n.removeCombinedObject(ctx, bkt, nodeVersion)
|
||||
}
|
||||
|
||||
return "", n.objectDelete(ctx, bkt, nodeVersion.OID)
|
||||
}
|
||||
|
||||
func (n *layer) removeCombinedObject(ctx context.Context, bkt *data.BucketInfo, nodeVersion *data.NodeVersion) error {
|
||||
combinedObj, err := n.objectGet(ctx, bkt, nodeVersion.OID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("get combined object '%s': %w", nodeVersion.OID.EncodeToString(), err)
|
||||
}
|
||||
|
||||
var parts []*data.PartInfo
|
||||
if err = json.Unmarshal(combinedObj.Payload(), &parts); err != nil {
|
||||
return fmt.Errorf("unmarshal combined object parts: %w", err)
|
||||
}
|
||||
|
||||
for _, part := range parts {
|
||||
if err = n.objectDelete(ctx, bkt, part.OID); err == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if !client.IsErrObjectAlreadyRemoved(err) && !client.IsErrObjectNotFound(err) {
|
||||
return fmt.Errorf("couldn't delete part '%s': %w", part.OID.EncodeToString(), err)
|
||||
}
|
||||
|
||||
n.reqLogger(ctx).Warn(logs.CouldntDeletePart, zap.String("cid", bkt.CID.EncodeToString()),
|
||||
zap.String("oid", part.OID.EncodeToString()), zap.Int("part number", part.Number), zap.Error(err))
|
||||
}
|
||||
|
||||
return n.objectDelete(ctx, bkt, nodeVersion.OID)
|
||||
}
|
||||
|
||||
// DeleteObjects from the storage.
|
||||
func (n *layer) DeleteObjects(ctx context.Context, p *DeleteObjectParams) []*VersionedObject {
|
||||
for i, obj := range p.Objects {
|
||||
|
|
|
@ -384,7 +384,7 @@ func (n *layer) headLastVersionIfNotDeleted(ctx context.Context, bkt *data.Bucke
|
|||
meta, err := n.objectHead(ctx, bkt, node.OID)
|
||||
if err != nil {
|
||||
if client.IsErrObjectNotFound(err) {
|
||||
return nil, fmt.Errorf("%w: %s", apiErrors.GetAPIError(apiErrors.ErrNoSuchKey), err.Error())
|
||||
return nil, fmt.Errorf("%w: %s; %s", apiErrors.GetAPIError(apiErrors.ErrNoSuchKey), err.Error(), node.OID.EncodeToString())
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -59,7 +59,9 @@ func Auth(center Center, log *zap.Logger) Func {
|
|||
if _, ok := err.(apiErrors.Error); !ok {
|
||||
err = apiErrors.GetAPIError(apiErrors.ErrAccessDenied)
|
||||
}
|
||||
WriteErrorResponse(w, GetReqInfo(r.Context()), err)
|
||||
if _, wrErr := WriteErrorResponse(w, GetReqInfo(r.Context()), err); wrErr != nil {
|
||||
reqLogOrDefault(ctx, log).Error(logs.FailedToWriteResponse, zap.Error(wrErr))
|
||||
}
|
||||
return
|
||||
}
|
||||
} else {
|
||||
|
@ -97,7 +99,9 @@ func FrostfsIDValidation(frostfsID FrostFSIDValidator, log *zap.Logger) Func {
|
|||
|
||||
if err = validateBearerToken(frostfsID, bd.Gate.BearerToken); err != nil {
|
||||
reqLogOrDefault(ctx, log).Error(logs.FrostfsIDValidationFailed, zap.Error(err))
|
||||
WriteErrorResponse(w, GetReqInfo(r.Context()), err)
|
||||
if _, wrErr := WriteErrorResponse(w, GetReqInfo(r.Context()), err); wrErr != nil {
|
||||
reqLogOrDefault(ctx, log).Error(logs.FailedToWriteResponse, zap.Error(wrErr))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
|
60
api/middleware/log_http.go
Normal file
60
api/middleware/log_http.go
Normal file
|
@ -0,0 +1,60 @@
|
|||
package middleware
|
||||
|
||||
import (
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/logs"
|
||||
"go.uber.org/zap"
|
||||
"io"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type HttpLogSettings interface {
|
||||
GetHttpLogEnabled() bool
|
||||
GetMaxLogBody() int64
|
||||
}
|
||||
|
||||
// LogHttp logs http parameters from s3 request
|
||||
func LogHttp(l *zap.Logger, settings HttpLogSettings) Func {
|
||||
return func(h http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if !settings.GetHttpLogEnabled() {
|
||||
h.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
var httplog = l.With(
|
||||
zap.String("from", r.RemoteAddr),
|
||||
zap.String("URI", r.RequestURI),
|
||||
zap.String("method", r.Method),
|
||||
)
|
||||
|
||||
httplog = withFieldIfExist(httplog, "query", r.URL.Query())
|
||||
httplog = withFieldIfExist(httplog, "headers", r.Header)
|
||||
if r.ContentLength != 0 && r.ContentLength <= settings.GetMaxLogBody() {
|
||||
var err error
|
||||
httplog, err = withBody(httplog, r)
|
||||
if err != nil {
|
||||
l.Error("read body error")
|
||||
}
|
||||
}
|
||||
httplog.Info(logs.RequestHTTP)
|
||||
h.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func withBody(httplog *zap.Logger, r *http.Request) (*zap.Logger, error) {
|
||||
var body = make([]byte, r.ContentLength)
|
||||
_, err := r.Body.Read(body)
|
||||
if err != nil && err != io.EOF {
|
||||
return nil, err
|
||||
}
|
||||
httplog = httplog.With(zap.String("body", string(body)))
|
||||
|
||||
return httplog, nil
|
||||
}
|
||||
|
||||
func withFieldIfExist(log *zap.Logger, label string, data map[string][]string) *zap.Logger {
|
||||
if len(data) != 0 {
|
||||
log = log.With(zap.Any(label, data))
|
||||
}
|
||||
return log
|
||||
}
|
|
@ -47,7 +47,9 @@ func PolicyCheck(cfg PolicyConfig) Func {
|
|||
ctx := r.Context()
|
||||
if err := policyCheck(r, cfg); err != nil {
|
||||
reqLogOrDefault(ctx, cfg.Log).Error(logs.PolicyValidationFailed, zap.Error(err))
|
||||
WriteErrorResponse(w, GetReqInfo(ctx), err)
|
||||
if _, wrErr := WriteErrorResponse(w, GetReqInfo(ctx), err); wrErr != nil {
|
||||
reqLogOrDefault(ctx, cfg.Log).Error(logs.FailedToWriteResponse, zap.Error(wrErr))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -58,13 +60,39 @@ func PolicyCheck(cfg PolicyConfig) Func {
|
|||
|
||||
func policyCheck(r *http.Request, cfg PolicyConfig) error {
|
||||
reqType, bktName, objName := getBucketObject(r, cfg.Domains)
|
||||
req, err := getPolicyRequest(r, cfg.FrostfsID, reqType, bktName, objName, cfg.Log)
|
||||
req, userKey, userGroups, err := getPolicyRequest(r, cfg.FrostfsID, reqType, bktName, objName, cfg.Log)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var bktInfo *data.BucketInfo
|
||||
if reqType != noneType && !strings.HasSuffix(req.Operation(), CreateBucketOperation) {
|
||||
bktInfo, err = cfg.BucketResolver(r.Context(), bktName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
reqInfo := GetReqInfo(r.Context())
|
||||
target := engine.NewRequestTargetWithNamespace(reqInfo.Namespace)
|
||||
if bktInfo != nil {
|
||||
cnrTarget := engine.ContainerTarget(bktInfo.CID.EncodeToString())
|
||||
target.Container = &cnrTarget
|
||||
}
|
||||
|
||||
if userKey != nil {
|
||||
entityName := fmt.Sprintf("%s:%s", reqInfo.Namespace, userKey.Address())
|
||||
uTarget := engine.UserTarget(entityName)
|
||||
target.User = &uTarget
|
||||
}
|
||||
|
||||
gts := make([]engine.Target, len(userGroups))
|
||||
for i, group := range userGroups {
|
||||
entityName := fmt.Sprintf("%s:%s", reqInfo.Namespace, group)
|
||||
gts[i] = engine.GroupTarget(entityName)
|
||||
}
|
||||
target.Groups = gts
|
||||
|
||||
st, found, err := cfg.Storage.IsAllowed(chain.S3, target, req)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -81,9 +109,9 @@ func policyCheck(r *http.Request, cfg PolicyConfig) error {
|
|||
return apiErr.GetAPIErrorWithError(apiErr.ErrAccessDenied, fmt.Errorf("policy check: %s", st.String()))
|
||||
}
|
||||
|
||||
isAPE, err := isAPEBehavior(r.Context(), req, cfg, reqType, bktName)
|
||||
if err != nil {
|
||||
return err
|
||||
isAPE := !cfg.Settings.ACLEnabled()
|
||||
if bktInfo != nil {
|
||||
isAPE = bktInfo.APEEnabled
|
||||
}
|
||||
|
||||
if isAPE && cfg.Settings.PolicyDenyByDefault() {
|
||||
|
@ -93,38 +121,25 @@ func policyCheck(r *http.Request, cfg PolicyConfig) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func isAPEBehavior(ctx context.Context, req *testutil.Request, cfg PolicyConfig, reqType ReqType, bktName string) (bool, error) {
|
||||
if reqType == noneType ||
|
||||
strings.HasSuffix(req.Operation(), CreateBucketOperation) {
|
||||
return !cfg.Settings.ACLEnabled(), nil
|
||||
}
|
||||
|
||||
bktInfo, err := cfg.BucketResolver(ctx, bktName) // we cannot use reqInfo.BucketName because it hasn't been set yet
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return bktInfo.APEEnabled, nil
|
||||
}
|
||||
|
||||
func getPolicyRequest(r *http.Request, frostfsid FrostFSIDInformer, reqType ReqType, bktName string, objName string, log *zap.Logger) (*testutil.Request, error) {
|
||||
func getPolicyRequest(r *http.Request, frostfsid FrostFSIDInformer, reqType ReqType, bktName string, objName string, log *zap.Logger) (*testutil.Request, *keys.PublicKey, []string, error) {
|
||||
var (
|
||||
owner string
|
||||
groups []string
|
||||
pk *keys.PublicKey
|
||||
)
|
||||
|
||||
ctx := r.Context()
|
||||
bd, err := GetBoxData(ctx)
|
||||
if err == nil && bd.Gate.BearerToken != nil {
|
||||
pk, err := keys.NewPublicKeyFromBytes(bd.Gate.BearerToken.SigningKeyBytes(), elliptic.P256())
|
||||
pk, err = keys.NewPublicKeyFromBytes(bd.Gate.BearerToken.SigningKeyBytes(), elliptic.P256())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parse pubclic key from btoken: %w", err)
|
||||
return nil, nil, nil, fmt.Errorf("parse pubclic key from btoken: %w", err)
|
||||
}
|
||||
owner = pk.Address()
|
||||
|
||||
groups, err = frostfsid.GetUserGroupIDs(pk.GetScriptHash())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("get group ids: %w", err)
|
||||
return nil, nil, nil, fmt.Errorf("get group ids: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -145,7 +160,7 @@ func getPolicyRequest(r *http.Request, frostfsid FrostFSIDInformer, reqType ReqT
|
|||
s3.PropertyKeyOwner: owner,
|
||||
common.PropertyKeyFrostFSIDGroupID: chain.FormCondSliceContainsValue(groups),
|
||||
},
|
||||
), nil
|
||||
), pk, groups, nil
|
||||
}
|
||||
|
||||
type ReqType int
|
||||
|
@ -176,11 +191,11 @@ func getBucketObject(r *http.Request, domains []string) (reqType ReqType, bktNam
|
|||
return noneType, "", ""
|
||||
}
|
||||
|
||||
if ind := strings.IndexByte(bktObj, '/'); ind != -1 {
|
||||
if ind := strings.IndexByte(bktObj, '/'); ind != -1 && bktObj[ind+1:] != "" {
|
||||
return objectType, bktObj[:ind], bktObj[ind+1:]
|
||||
}
|
||||
|
||||
return bucketType, bktObj, ""
|
||||
return bucketType, strings.TrimSuffix(bktObj, "/"), ""
|
||||
}
|
||||
|
||||
func determineOperation(r *http.Request, reqType ReqType) (operation string) {
|
||||
|
|
82
api/middleware/policy_test.go
Normal file
82
api/middleware/policy_test.go
Normal file
|
@ -0,0 +1,82 @@
|
|||
package middleware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestReqTypeDetermination(t *testing.T) {
|
||||
bkt, obj, domain := "test-bucket", "test-object", "domain"
|
||||
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
target string
|
||||
host string
|
||||
domains []string
|
||||
expectedType ReqType
|
||||
expectedBktName string
|
||||
expectedObjName string
|
||||
}{
|
||||
{
|
||||
name: "bucket request, path-style",
|
||||
target: "/" + bkt,
|
||||
expectedType: bucketType,
|
||||
expectedBktName: bkt,
|
||||
},
|
||||
{
|
||||
name: "bucket request with slash, path-style",
|
||||
target: "/" + bkt + "/",
|
||||
expectedType: bucketType,
|
||||
expectedBktName: bkt,
|
||||
},
|
||||
{
|
||||
name: "object request, path-style",
|
||||
target: "/" + bkt + "/" + obj,
|
||||
expectedType: objectType,
|
||||
expectedBktName: bkt,
|
||||
expectedObjName: obj,
|
||||
},
|
||||
{
|
||||
name: "object request with slash, path-style",
|
||||
target: "/" + bkt + "/" + obj + "/",
|
||||
expectedType: objectType,
|
||||
expectedBktName: bkt,
|
||||
expectedObjName: obj + "/",
|
||||
},
|
||||
{
|
||||
name: "none type request",
|
||||
target: "/",
|
||||
expectedType: noneType,
|
||||
},
|
||||
{
|
||||
name: "bucket request, virtual-hosted style",
|
||||
target: "/",
|
||||
host: bkt + "." + domain,
|
||||
domains: []string{"some-domain", domain},
|
||||
expectedType: bucketType,
|
||||
expectedBktName: bkt,
|
||||
},
|
||||
{
|
||||
name: "object request, virtual-hosted style",
|
||||
target: "/" + obj,
|
||||
host: bkt + "." + domain,
|
||||
domains: []string{"some-domain", domain},
|
||||
expectedType: objectType,
|
||||
expectedBktName: bkt,
|
||||
expectedObjName: obj,
|
||||
},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
r := httptest.NewRequest(http.MethodPut, tc.target, nil)
|
||||
r.Host = tc.host
|
||||
|
||||
reqType, bktName, objName := getBucketObject(r, tc.domains)
|
||||
require.Equal(t, tc.expectedType, reqType)
|
||||
require.Equal(t, tc.expectedBktName, bktName)
|
||||
require.Equal(t, tc.expectedObjName, objName)
|
||||
})
|
||||
}
|
||||
}
|
|
@ -118,7 +118,8 @@ var s3ErrorResponseMap = map[string]string{
|
|||
}
|
||||
|
||||
// WriteErrorResponse writes error headers.
|
||||
func WriteErrorResponse(w http.ResponseWriter, reqInfo *ReqInfo, err error) int {
|
||||
// returns http error code and error in case of failure of response writing.
|
||||
func WriteErrorResponse(w http.ResponseWriter, reqInfo *ReqInfo, err error) (int, error) {
|
||||
code := http.StatusInternalServerError
|
||||
|
||||
if e, ok := err.(errors.Error); ok {
|
||||
|
@ -134,9 +135,14 @@ func WriteErrorResponse(w http.ResponseWriter, reqInfo *ReqInfo, err error) int
|
|||
|
||||
// Generates error response.
|
||||
errorResponse := getAPIErrorResponse(reqInfo, err)
|
||||
encodedErrorResponse := EncodeResponse(errorResponse)
|
||||
WriteResponse(w, code, encodedErrorResponse, MimeXML)
|
||||
return code
|
||||
encodedErrorResponse, err := EncodeResponse(errorResponse)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("encode response: %w", err)
|
||||
}
|
||||
if err = WriteResponse(w, code, encodedErrorResponse, MimeXML); err != nil {
|
||||
return 0, fmt.Errorf("write response: %w", err)
|
||||
}
|
||||
return code, nil
|
||||
}
|
||||
|
||||
// Write http common headers.
|
||||
|
@ -157,7 +163,7 @@ func removeSensitiveHeaders(h http.Header) {
|
|||
}
|
||||
|
||||
// WriteResponse writes given statusCode and response into w (with mType header if set).
|
||||
func WriteResponse(w http.ResponseWriter, statusCode int, response []byte, mType mimeType) {
|
||||
func WriteResponse(w http.ResponseWriter, statusCode int, response []byte, mType mimeType) error {
|
||||
setCommonHeaders(w)
|
||||
if mType != MimeNone {
|
||||
w.Header().Set(hdrContentType, string(mType))
|
||||
|
@ -165,37 +171,46 @@ func WriteResponse(w http.ResponseWriter, statusCode int, response []byte, mType
|
|||
w.Header().Set(hdrContentLength, strconv.Itoa(len(response)))
|
||||
w.WriteHeader(statusCode)
|
||||
if response == nil {
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
WriteResponseBody(w, response)
|
||||
return WriteResponseBody(w, response)
|
||||
}
|
||||
|
||||
// WriteResponseBody writes response into w.
|
||||
func WriteResponseBody(w http.ResponseWriter, response []byte) {
|
||||
_, _ = w.Write(response)
|
||||
func WriteResponseBody(w http.ResponseWriter, response []byte) error {
|
||||
if _, err := w.Write(response); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if flusher, ok := w.(http.Flusher); ok {
|
||||
flusher.Flush()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// EncodeResponse encodes the response headers into XML format.
|
||||
func EncodeResponse(response interface{}) []byte {
|
||||
func EncodeResponse(response interface{}) ([]byte, error) {
|
||||
var bytesBuffer bytes.Buffer
|
||||
bytesBuffer.WriteString(xml.Header)
|
||||
_ = xml.
|
||||
NewEncoder(&bytesBuffer).
|
||||
Encode(response)
|
||||
return bytesBuffer.Bytes()
|
||||
if err := xml.NewEncoder(&bytesBuffer).Encode(response); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return bytesBuffer.Bytes(), nil
|
||||
}
|
||||
|
||||
// EncodeResponseNoHeader encodes response without setting xml.Header.
|
||||
// Should be used with periodicXMLWriter which sends xml.Header to the client
|
||||
// with whitespaces to keep connection alive.
|
||||
func EncodeResponseNoHeader(response interface{}) []byte {
|
||||
func EncodeResponseNoHeader(response interface{}) ([]byte, error) {
|
||||
var bytesBuffer bytes.Buffer
|
||||
_ = xml.NewEncoder(&bytesBuffer).Encode(response)
|
||||
return bytesBuffer.Bytes()
|
||||
if err := xml.NewEncoder(&bytesBuffer).Encode(response); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return bytesBuffer.Bytes(), nil
|
||||
}
|
||||
|
||||
// EncodeToResponse encodes the response into ResponseWriter.
|
||||
|
@ -227,8 +242,8 @@ func EncodeToResponseNoHeader(w http.ResponseWriter, response interface{}) error
|
|||
|
||||
// WriteSuccessResponseHeadersOnly writes HTTP (200) OK response with no data
|
||||
// to the client.
|
||||
func WriteSuccessResponseHeadersOnly(w http.ResponseWriter) {
|
||||
WriteResponse(w, http.StatusOK, nil, MimeNone)
|
||||
func WriteSuccessResponseHeadersOnly(w http.ResponseWriter) error {
|
||||
return WriteResponse(w, http.StatusOK, nil, MimeNone)
|
||||
}
|
||||
|
||||
// Error -- Returns S3 error string.
|
||||
|
|
|
@ -96,6 +96,7 @@ type Settings interface {
|
|||
s3middleware.RequestSettings
|
||||
s3middleware.PolicySettings
|
||||
s3middleware.MetricsSettings
|
||||
s3middleware.HttpLogSettings
|
||||
}
|
||||
|
||||
type FrostFSID interface {
|
||||
|
@ -115,8 +116,7 @@ type Config struct {
|
|||
// Domains optional. If empty no virtual hosted domains will be attached.
|
||||
Domains []string
|
||||
|
||||
FrostfsID FrostFSID
|
||||
|
||||
FrostfsID FrostFSID
|
||||
FrostFSIDValidation bool
|
||||
|
||||
PolicyChecker engine.ChainRouter
|
||||
|
@ -125,6 +125,7 @@ type Config struct {
|
|||
func NewRouter(cfg Config) *chi.Mux {
|
||||
api := chi.NewRouter()
|
||||
api.Use(
|
||||
s3middleware.LogHttp(cfg.Log, cfg.MiddlewareSettings),
|
||||
s3middleware.Request(cfg.Log, cfg.MiddlewareSettings),
|
||||
middleware.ThrottleWithOpts(cfg.Throttle),
|
||||
middleware.Recoverer,
|
||||
|
@ -178,14 +179,24 @@ func errorResponseHandler(w http.ResponseWriter, r *http.Request) {
|
|||
reqInfo := s3middleware.GetReqInfo(ctx)
|
||||
|
||||
desc := fmt.Sprintf("Unknown API request at %s", r.URL.Path)
|
||||
s3middleware.WriteErrorResponse(w, reqInfo, errors.Error{
|
||||
_, wrErr := s3middleware.WriteErrorResponse(w, reqInfo, errors.Error{
|
||||
Code: "UnknownAPIRequest",
|
||||
Description: desc,
|
||||
HTTPStatusCode: http.StatusBadRequest,
|
||||
})
|
||||
|
||||
if log := s3middleware.GetReqLog(ctx); log != nil {
|
||||
log.Error(logs.RequestUnmatched, zap.String("method", reqInfo.API), zap.String("http method", r.Method), zap.String("url", r.RequestURI))
|
||||
fields := []zap.Field{
|
||||
zap.String("method", reqInfo.API),
|
||||
zap.String("http method", r.Method),
|
||||
zap.String("url", r.RequestURI),
|
||||
}
|
||||
|
||||
if wrErr != nil {
|
||||
fields = append(fields, zap.NamedError("write_response_error", wrErr))
|
||||
}
|
||||
|
||||
log.Error(logs.RequestUnmatched, fields...)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -196,8 +196,10 @@ func TestPolicyChecker(t *testing.T) {
|
|||
func TestPolicyCheckerReqTypeDetermination(t *testing.T) {
|
||||
chiRouter := prepareRouter(t)
|
||||
bktName, objName := "bucket", "object"
|
||||
createBucket(chiRouter, "", bktName)
|
||||
|
||||
policy := engineiam.Policy{
|
||||
Version: "2012-10-17",
|
||||
Statement: []engineiam.Statement{{
|
||||
Principal: map[engineiam.PrincipalType][]string{engineiam.Wildcard: {}},
|
||||
Effect: engineiam.AllowEffect,
|
||||
|
@ -269,7 +271,7 @@ func TestACLAPE(t *testing.T) {
|
|||
listBucketsErr(router, ns, apiErrors.ErrAccessDenied)
|
||||
|
||||
// Allow operations and check
|
||||
allowOperations(router, ns, []string{"s3:CreateBucket", "s3:ListBuckets"})
|
||||
allowOperations(router, ns, []string{"s3:CreateBucket", "s3:ListAllMyBuckets"})
|
||||
createBucket(router, ns, bktName)
|
||||
listBuckets(router, ns)
|
||||
})
|
||||
|
@ -295,7 +297,7 @@ func TestACLAPE(t *testing.T) {
|
|||
listBuckets(router, ns)
|
||||
|
||||
// Deny operations and check
|
||||
denyOperations(router, ns, []string{"s3:CreateBucket", "s3:ListBuckets"})
|
||||
denyOperations(router, ns, []string{"s3:CreateBucket", "s3:ListAllMyBuckets"})
|
||||
createBucketErr(router, ns, bktName, apiErrors.ErrAccessDenied)
|
||||
listBucketsErr(router, ns, apiErrors.ErrAccessDenied)
|
||||
})
|
||||
|
@ -353,6 +355,7 @@ func denyOperations(router *routerMock, ns string, operations []string) {
|
|||
|
||||
func addPolicy(router *routerMock, ns string, id string, effect engineiam.Effect, operations []string) {
|
||||
policy := engineiam.Policy{
|
||||
Version: "2012-10-17",
|
||||
Statement: []engineiam.Statement{{
|
||||
Principal: map[engineiam.PrincipalType][]string{engineiam.Wildcard: {}},
|
||||
Effect: effect,
|
||||
|
|
|
@ -82,11 +82,6 @@ type FrostFS interface {
|
|||
TimeToEpoch(context.Context, time.Time) (uint64, uint64, error)
|
||||
}
|
||||
|
||||
// FrostFSID represents interface to interact with frostfsid contract.
|
||||
type FrostFSID interface {
|
||||
RegisterPublicKey(ns string, key *keys.PublicKey) error
|
||||
}
|
||||
|
||||
// Agent contains client communicating with FrostFS and logger.
|
||||
type Agent struct {
|
||||
frostFS FrostFS
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
"time"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/authmate"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/frostfs/frostfsid"
|
||||
"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"
|
||||
|
@ -170,7 +170,7 @@ func runIssueSecretCmd(cmd *cobra.Command, _ []string) error {
|
|||
if rpcAddress == "" {
|
||||
return wrapPreparationError(fmt.Errorf("you can use '%s' flag only along with '%s'", frostfsIDFlag, rpcEndpointFlag))
|
||||
}
|
||||
cfg := frostfsid.Config{
|
||||
cfg := contract.Config{
|
||||
RPCAddress: rpcAddress,
|
||||
Contract: frostFSID,
|
||||
ProxyContract: viper.GetString(frostfsIDProxyFlag),
|
||||
|
@ -182,7 +182,7 @@ func runIssueSecretCmd(cmd *cobra.Command, _ []string) error {
|
|||
return wrapFrostFSIDInitError(err)
|
||||
}
|
||||
|
||||
if err = frostfsIDClient.RegisterPublicKey(viper.GetString(frostfsIDNamespaceFlag), key.PublicKey()); err != nil {
|
||||
if err = registerPublicKey(frostfsIDClient, viper.GetString(frostfsIDNamespaceFlag), key.PublicKey()); err != nil {
|
||||
return wrapBusinessLogicError(fmt.Errorf("failed to register key in frostfsid: %w", err))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/authmate"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/frostfs/frostfsid"
|
||||
"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"
|
||||
|
@ -106,7 +106,7 @@ func runUpdateSecretCmd(cmd *cobra.Command, _ []string) error {
|
|||
if rpcAddress == "" {
|
||||
return wrapPreparationError(fmt.Errorf("you can use '%s' flag only along with '%s'", frostfsIDFlag, rpcEndpointFlag))
|
||||
}
|
||||
cfg := frostfsid.Config{
|
||||
cfg := contract.Config{
|
||||
RPCAddress: rpcAddress,
|
||||
Contract: frostFSID,
|
||||
ProxyContract: viper.GetString(frostfsIDProxyFlag),
|
||||
|
@ -118,7 +118,7 @@ func runUpdateSecretCmd(cmd *cobra.Command, _ []string) error {
|
|||
return wrapFrostFSIDInitError(err)
|
||||
}
|
||||
|
||||
if err = frostfsIDClient.RegisterPublicKey(viper.GetString(frostfsIDNamespaceFlag), key.PublicKey()); err != nil {
|
||||
if err = registerPublicKey(frostfsIDClient, viper.GetString(frostfsIDNamespaceFlag), key.PublicKey()); err != nil {
|
||||
return wrapBusinessLogicError(fmt.Errorf("failed to register key in frostfsid: %w", err))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ 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"
|
||||
"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,10 +145,10 @@ func getLogger() *zap.Logger {
|
|||
return log
|
||||
}
|
||||
|
||||
func createFrostFSID(ctx context.Context, log *zap.Logger, cfg frostfsid.Config) (authmate.FrostFSID, error) {
|
||||
func createFrostFSID(ctx context.Context, log *zap.Logger, cfg contract.Config) (*contract.FrostFSID, error) {
|
||||
log.Debug(logs.PrepareFrostfsIDClient)
|
||||
|
||||
cli, err := frostfsid.New(ctx, cfg)
|
||||
cli, err := contract.New(ctx, cfg)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create frostfsid client: %w", err)
|
||||
}
|
||||
|
@ -156,6 +156,15 @@ func createFrostFSID(ctx context.Context, log *zap.Logger, cfg frostfsid.Config)
|
|||
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
|
||||
|
|
|
@ -30,6 +30,7 @@ import (
|
|||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/creds/tokens"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/frostfs"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/frostfs/frostfsid"
|
||||
ffidcontract "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/frostfs/frostfsid/contract"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/frostfs/policy"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/frostfs/policy/contract"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/frostfs/services"
|
||||
|
@ -86,6 +87,8 @@ type (
|
|||
|
||||
appSettings struct {
|
||||
logLevel zap.AtomicLevel
|
||||
httpLoggingEnabled bool
|
||||
maxHttpLogBody int64
|
||||
maxClient maxClientsConfig
|
||||
defaultMaxAge int
|
||||
notificatorEnabled bool
|
||||
|
@ -207,6 +210,8 @@ func newAppSettings(log *Logger, v *viper.Viper, key *keys.PrivateKey) *appSetti
|
|||
defaultMaxAge: fetchDefaultMaxAge(v, log.logger),
|
||||
notificatorEnabled: v.GetBool(cfgEnableNATS),
|
||||
frostfsidValidation: v.GetBool(cfgFrostfsIDValidationEnabled),
|
||||
httpLoggingEnabled: v.GetBool(cfgLoggerRequestEnabled),
|
||||
maxHttpLogBody: v.GetInt64(cfgLoggerRequestMaxBody),
|
||||
}
|
||||
|
||||
settings.resolveZoneList = v.GetStringSlice(cfgResolveBucketAllow)
|
||||
|
@ -424,6 +429,18 @@ func (s *appSettings) setPolicyDenyByDefault(policyDenyByDefault bool) {
|
|||
s.mu.Unlock()
|
||||
}
|
||||
|
||||
func (s *appSettings) GetMaxLogBody() int64 {
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
return s.maxHttpLogBody
|
||||
}
|
||||
|
||||
func (s *appSettings) GetHttpLogEnabled() bool {
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
return s.httpLoggingEnabled
|
||||
}
|
||||
|
||||
func (a *App) initAPI(ctx context.Context) {
|
||||
a.initLayer(ctx)
|
||||
a.initHandler()
|
||||
|
@ -453,8 +470,7 @@ func (a *App) initMetrics() {
|
|||
}
|
||||
|
||||
func (a *App) initFrostfsID(ctx context.Context) {
|
||||
var err error
|
||||
a.frostfsid, err = frostfsid.New(ctx, frostfsid.Config{
|
||||
cli, err := ffidcontract.New(ctx, ffidcontract.Config{
|
||||
RPCAddress: a.cfg.GetString(cfgRPCEndpoint),
|
||||
Contract: a.cfg.GetString(cfgFrostfsIDContract),
|
||||
ProxyContract: a.cfg.GetString(cfgProxyContract),
|
||||
|
@ -463,6 +479,15 @@ func (a *App) initFrostfsID(ctx context.Context) {
|
|||
if err != nil {
|
||||
a.log.Fatal(logs.InitFrostfsIDContractFailed, zap.Error(err))
|
||||
}
|
||||
|
||||
a.frostfsid, err = frostfsid.NewFrostFSID(frostfsid.Config{
|
||||
Cache: cache.NewFrostfsIDCache(getFrostfsIDCacheConfig(a.cfg, a.log)),
|
||||
FrostFSID: cli,
|
||||
Logger: a.log,
|
||||
})
|
||||
if err != nil {
|
||||
a.log.Fatal(logs.InitFrostfsIDContractFailed, zap.Error(err))
|
||||
}
|
||||
}
|
||||
|
||||
func (a *App) initPolicyStorage(ctx context.Context) {
|
||||
|
@ -950,6 +975,15 @@ func getMorphPolicyCacheConfig(v *viper.Viper, l *zap.Logger) *cache.Config {
|
|||
return cacheCfg
|
||||
}
|
||||
|
||||
func getFrostfsIDCacheConfig(v *viper.Viper, l *zap.Logger) *cache.Config {
|
||||
cacheCfg := cache.DefaultFrostfsIDConfig(l)
|
||||
|
||||
cacheCfg.Lifetime = fetchCacheLifetime(v, l, cfgFrostfsIDCacheLifetime, cacheCfg.Lifetime)
|
||||
cacheCfg.Size = fetchCacheSize(v, l, cfgFrostfsIDCacheSize, cacheCfg.Size)
|
||||
|
||||
return cacheCfg
|
||||
}
|
||||
|
||||
func (a *App) initHandler() {
|
||||
var err error
|
||||
|
||||
|
|
|
@ -68,8 +68,10 @@ var (
|
|||
|
||||
const ( // Settings.
|
||||
// Logger.
|
||||
cfgLoggerLevel = "logger.level"
|
||||
cfgLoggerDestination = "logger.destination"
|
||||
cfgLoggerLevel = "logger.level"
|
||||
cfgLoggerDestination = "logger.destination"
|
||||
cfgLoggerRequestEnabled = "http_logging.enabled"
|
||||
cfgLoggerRequestMaxBody = "http_logging.max_body"
|
||||
|
||||
// Wallet.
|
||||
cfgWalletPath = "wallet.path"
|
||||
|
@ -114,6 +116,8 @@ const ( // Settings.
|
|||
cfgAccessControlCacheSize = "cache.accesscontrol.size"
|
||||
cfgMorphPolicyCacheLifetime = "cache.morph_policy.lifetime"
|
||||
cfgMorphPolicyCacheSize = "cache.morph_policy.size"
|
||||
cfgFrostfsIDCacheLifetime = "cache.frostfsid.lifetime"
|
||||
cfgFrostfsIDCacheSize = "cache.frostfsid.size"
|
||||
|
||||
cfgAccessBoxCacheRemovingCheckInterval = "cache.accessbox.removing_check_interval"
|
||||
|
||||
|
@ -700,6 +704,8 @@ func newSettings() *viper.Viper {
|
|||
// logger:
|
||||
v.SetDefault(cfgLoggerLevel, "debug")
|
||||
v.SetDefault(cfgLoggerDestination, "stdout")
|
||||
v.SetDefault(cfgLoggerRequestEnabled, false)
|
||||
v.SetDefault(cfgLoggerRequestMaxBody, 1024)
|
||||
|
||||
// pool:
|
||||
v.SetDefault(cfgPoolErrorThreshold, defaultPoolErrorThreshold)
|
||||
|
|
|
@ -104,6 +104,9 @@ S3_GW_CACHE_ACCESSCONTROL_SIZE=100000
|
|||
# Cache which stores list of policy chains
|
||||
S3_GW_CACHE_MORPH_POLICY_LIFETIME=1m
|
||||
S3_GW_CACHE_MORPH_POLICY_SIZE=10000
|
||||
# Cache which stores frostfsid subject info
|
||||
S3_GW_CACHE_FROSTFSID_LIFETIME=1m
|
||||
S3_GW_CACHE_FROSTFSID_SIZE=10000
|
||||
|
||||
# NATS
|
||||
S3_GW_NATS_ENABLED=true
|
||||
|
|
|
@ -54,6 +54,12 @@ logger:
|
|||
level: debug
|
||||
destination: stdout
|
||||
|
||||
# log http request data (URI, headers, query, etc)
|
||||
http_logging:
|
||||
enabled: false
|
||||
# max body size to log
|
||||
max_body: 1024
|
||||
|
||||
# RPC endpoint and order of resolving of bucket names
|
||||
rpc_endpoint: http://morph-chain.frostfs.devenv:30333
|
||||
resolve_order:
|
||||
|
@ -129,6 +135,10 @@ cache:
|
|||
morph_policy:
|
||||
lifetime: 1m
|
||||
size: 10000
|
||||
# Cache which stores frostfsid subject info
|
||||
frostfsid:
|
||||
lifetime: 1m
|
||||
size: 10000
|
||||
|
||||
nats:
|
||||
enabled: true
|
||||
|
|
|
@ -1,73 +1,58 @@
|
|||
# S3 API support
|
||||
|
||||
Reference:
|
||||
|
||||
* [AWS S3 API Reference](https://docs.aws.amazon.com/AmazonS3/latest/API/s3-api.pdf)
|
||||
|
||||
| | Legend |
|
||||
|----|-------------------------------------------|
|
||||
| 🟢 | Supported |
|
||||
| 🟡 | Partially supported |
|
||||
| 🔵 | Not supported yet, but will be in future |
|
||||
| 🔴 | Not applicable or will never be supported |
|
||||
| | Legend |
|
||||
|-----|-------------------------------------------|
|
||||
| 🟢 | Supported |
|
||||
| 🟡 | Partially supported |
|
||||
| 🔵 | Not supported yet, but will be in future |
|
||||
| 🔴 | Not applicable or will never be supported |
|
||||
|
||||
## Object
|
||||
|
||||
| | Method | Comments |
|
||||
|----|------------------------|-----------------------------------------|
|
||||
| 🟢 | CopyObject | Done on gateway side |
|
||||
| 🟢 | DeleteObject | |
|
||||
| 🟢 | DeleteObjects | aka DeleteMultipleObjects |
|
||||
| 🟢 | GetObject | |
|
||||
| 🔴 | GetObjectTorrent | We don't plan implementing BT gateway |
|
||||
| 🟢 | HeadObject | |
|
||||
| 🟢 | ListParts | Parts loaded with MultipartUpload |
|
||||
| 🟢 | ListObjects | |
|
||||
| 🟢 | ListObjectsV2 | |
|
||||
| 🟢 | PutObject | Content-MD5 header deprecated |
|
||||
| 🔵 | SelectObjectContent | Need to have some Lambda to execute SQL |
|
||||
| 🔵 | WriteGetObjectResponse | Waiting for Lambda to be developed |
|
||||
| 🟢 | GetObjectAttributes | |
|
||||
| | Method | Comments |
|
||||
|-----|------------------------|-----------------------------------------|
|
||||
| 🟢 | CopyObject | Done on gateway side |
|
||||
| 🟢 | DeleteObject | |
|
||||
| 🟢 | DeleteObjects | aka DeleteMultipleObjects |
|
||||
| 🟢 | GetObject | |
|
||||
| 🔴 | GetObjectTorrent | We don't plan implementing BT gateway |
|
||||
| 🟢 | HeadObject | |
|
||||
| 🟢 | ListParts | Parts loaded with MultipartUpload |
|
||||
| 🟢 | ListObjects | |
|
||||
| 🟢 | ListObjectsV2 | |
|
||||
| 🟢 | PutObject | Content-MD5 header deprecated |
|
||||
| 🔵 | SelectObjectContent | Need to have some Lambda to execute SQL |
|
||||
| 🔵 | WriteGetObjectResponse | Waiting for Lambda to be developed |
|
||||
| 🟢 | GetObjectAttributes | |
|
||||
|
||||
## ACL
|
||||
|
||||
For now there are some limitations:
|
||||
* [Bucket policy](https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucket-policies.html) supports only one `Principal` per `Statement`.
|
||||
Principal must be `"AWS": "*"` (to refer all users) or `"CanonicalUser": "0313b1ac3a8076e155a7e797b24f0b650cccad5941ea59d7cfd51a024a8b2a06bf"` (hex encoded public key of desired user).
|
||||
* Resource in bucket policy is an array. Each item MUST contain bucket name, CAN contain object name (wildcards are not supported):
|
||||
```json
|
||||
{
|
||||
"Statement": [
|
||||
{
|
||||
"Resource": [
|
||||
"arn:aws:s3:::bucket",
|
||||
"arn:aws:s3:::bucket/some/object"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
* AWS conditions and wildcard are not supported in [resources](https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-arn-format.html)
|
||||
* Only `CanonicalUser` (with hex encoded public key) and `All Users Group` are supported in [ACL](https://docs.aws.amazon.com/AmazonS3/latest/userguide/acl-overview.html)
|
||||
|
||||
| | Method | Comments |
|
||||
|----|--------------|-----------------|
|
||||
| 🟡 | GetObjectAcl | See Limitations |
|
||||
| 🟡 | PutObjectAcl | See Limitations |
|
||||
| | Method | Comments |
|
||||
|-----|--------------|-----------------------------------|
|
||||
| 🟢 | GetObjectAcl | Objects can have only private acl |
|
||||
| 🔴 | PutObjectAcl | Use PutBucketPolicy instead |
|
||||
|
||||
## Locking
|
||||
|
||||
For now there are some limitations:
|
||||
|
||||
* Retention period can't be shortened, only extended.
|
||||
* You can't delete locks or object with unexpired lock.
|
||||
|
||||
| | Method | Comments |
|
||||
|-----|----------------------------|---------------------------|
|
||||
| 🟡 | GetObjectLegalHold | |
|
||||
| 🟢 | GetObjectLockConfiguration | GetBucketObjectLockConfig |
|
||||
| 🟡 | GetObjectRetention | |
|
||||
| 🟡 | PutObjectLegalHold | |
|
||||
| 🟢 | PutObjectLockConfiguration | PutBucketObjectLockConfig |
|
||||
| 🟡 | PutObjectRetention | |
|
||||
| | Method | Comments |
|
||||
|-----|----------------------------|-------------------------------|
|
||||
| 🟡 | GetObjectLegalHold | |
|
||||
| 🟢 | GetObjectLockConfiguration | aka GetBucketObjectLockConfig |
|
||||
| 🟡 | GetObjectRetention | |
|
||||
| 🟡 | PutObjectLegalHold | |
|
||||
| 🟢 | PutObjectLockConfiguration | aka PutBucketObjectLockConfig |
|
||||
| 🟡 | PutObjectRetention | |
|
||||
|
||||
## Multipart
|
||||
|
||||
|
@ -75,185 +60,185 @@ CompleteMultipartUpload operations may take long time to complete. Gateway
|
|||
sends whitespace characters to keep connection with the client alive. In this
|
||||
case, gateway is unable to set proper HTTP headers like `X-Amz-Version-Id`.
|
||||
|
||||
| | Method | Comments |
|
||||
|----|-------------------------|----------|
|
||||
| 🟢 | AbortMultipartUpload | |
|
||||
| 🟢 | CompleteMultipartUpload | |
|
||||
| 🟢 | CreateMultipartUpload | |
|
||||
| 🟢 | ListMultipartUploads | |
|
||||
| 🟢 | ListParts | |
|
||||
| 🟢 | UploadPart | |
|
||||
| 🟢 | UploadPartCopy | |
|
||||
| | Method | Comments |
|
||||
|-----|-------------------------|----------|
|
||||
| 🟢 | AbortMultipartUpload | |
|
||||
| 🟢 | CompleteMultipartUpload | |
|
||||
| 🟢 | CreateMultipartUpload | |
|
||||
| 🟢 | ListMultipartUploads | |
|
||||
| 🟢 | ListParts | |
|
||||
| 🟢 | UploadPart | |
|
||||
| 🟢 | UploadPartCopy | |
|
||||
|
||||
## Tagging
|
||||
|
||||
| | Method | Comments |
|
||||
|----|---------------------|----------|
|
||||
| 🟢 | DeleteObjectTagging | |
|
||||
| 🟢 | GetObjectTagging | |
|
||||
| 🟢 | PutObjectTagging | |
|
||||
| | Method | Comments |
|
||||
|-----|---------------------|----------|
|
||||
| 🟢 | DeleteObjectTagging | |
|
||||
| 🟢 | GetObjectTagging | |
|
||||
| 🟢 | PutObjectTagging | |
|
||||
|
||||
## Versioning
|
||||
|
||||
See also `GetObject` and other method parameters.
|
||||
|
||||
| | Method | Comments |
|
||||
|----|--------------------|--------------------------|
|
||||
| 🟢 | ListObjectVersions | ListBucketObjectVersions |
|
||||
| 🔵 | RestoreObject | |
|
||||
| | Method | Comments |
|
||||
|-----|--------------------|--------------------------|
|
||||
| 🟢 | ListObjectVersions | ListBucketObjectVersions |
|
||||
| 🔵 | RestoreObject | |
|
||||
|
||||
## Bucket
|
||||
|
||||
| | Method | Comments |
|
||||
|----|----------------------|-----------|
|
||||
| 🟢 | CreateBucket | PutBucket |
|
||||
| 🟢 | DeleteBucket | |
|
||||
| 🟢 | GetBucketLocation | |
|
||||
| 🟢 | HeadBucket | |
|
||||
| 🟢 | ListBuckets | |
|
||||
| 🔵 | PutPublicAccessBlock | |
|
||||
| | Method | Comments |
|
||||
|-----|----------------------|-----------|
|
||||
| 🟢 | CreateBucket | PutBucket |
|
||||
| 🟢 | DeleteBucket | |
|
||||
| 🟢 | GetBucketLocation | |
|
||||
| 🟢 | HeadBucket | |
|
||||
| 🟢 | ListBuckets | |
|
||||
| 🔵 | PutPublicAccessBlock | |
|
||||
|
||||
## Acceleration
|
||||
|
||||
| | Method | Comments |
|
||||
|----|----------------------------------|---------------------|
|
||||
| 🔴 | GetBucketAccelerateConfiguration | GetBucketAccelerate |
|
||||
| 🔴 | PutBucketAccelerateConfiguration | |
|
||||
| | Method | Comments |
|
||||
|-----|----------------------------------|---------------------|
|
||||
| 🔴 | GetBucketAccelerateConfiguration | GetBucketAccelerate |
|
||||
| 🔴 | PutBucketAccelerateConfiguration | |
|
||||
|
||||
## ACL
|
||||
|
||||
| | Method | Comments |
|
||||
|----|--------------|---------------------|
|
||||
| 🟡 | GetBucketAcl | See ACL limitations |
|
||||
| 🟡 | PutBucketAcl | See ACL Limitations |
|
||||
| | Method | Comments |
|
||||
|-----|--------------|------------------------------|
|
||||
| 🟡 | GetBucketAcl | Only canned acl is supported |
|
||||
| 🟡 | PutBucketAcl | Only canned acl is supported |
|
||||
|
||||
## Analytics
|
||||
|
||||
| | Method | Comments |
|
||||
|----|------------------------------------|----------|
|
||||
| 🔵 | DeleteBucketAnalyticsConfiguration | |
|
||||
| 🔵 | GetBucketAnalyticsConfiguration | |
|
||||
| 🔵 | ListBucketAnalyticsConfigurations | |
|
||||
| 🔵 | PutBucketAnalyticsConfiguration | |
|
||||
| | Method | Comments |
|
||||
|-----|------------------------------------|----------|
|
||||
| 🔵 | DeleteBucketAnalyticsConfiguration | |
|
||||
| 🔵 | GetBucketAnalyticsConfiguration | |
|
||||
| 🔵 | ListBucketAnalyticsConfigurations | |
|
||||
| 🔵 | PutBucketAnalyticsConfiguration | |
|
||||
|
||||
## CORS
|
||||
|
||||
| | Method | Comments |
|
||||
|----|------------------|----------|
|
||||
| 🟢 | DeleteBucketCors | |
|
||||
| 🟢 | GetBucketCors | |
|
||||
| 🟢 | PutBucketCors | |
|
||||
| | Method | Comments |
|
||||
|-----|------------------|----------|
|
||||
| 🟢 | DeleteBucketCors | |
|
||||
| 🟢 | GetBucketCors | |
|
||||
| 🟢 | PutBucketCors | |
|
||||
|
||||
## Encryption
|
||||
|
||||
| | Method | Comments |
|
||||
|----|------------------------|----------|
|
||||
| 🔵 | DeleteBucketEncryption | |
|
||||
| 🔵 | GetBucketEncryption | |
|
||||
| 🔵 | PutBucketEncryption | |
|
||||
| | Method | Comments |
|
||||
|-----|------------------------|----------|
|
||||
| 🔵 | DeleteBucketEncryption | |
|
||||
| 🔵 | GetBucketEncryption | |
|
||||
| 🔵 | PutBucketEncryption | |
|
||||
|
||||
## Inventory
|
||||
|
||||
| | Method | Comments |
|
||||
|----|------------------------------------|----------|
|
||||
| 🔵 | DeleteBucketInventoryConfiguration | |
|
||||
| 🔵 | GetBucketInventoryConfiguration | |
|
||||
| 🔵 | ListBucketInventoryConfigurations | |
|
||||
| 🔵 | PutBucketInventoryConfiguration | |
|
||||
| | Method | Comments |
|
||||
|-----|------------------------------------|----------|
|
||||
| 🔵 | DeleteBucketInventoryConfiguration | |
|
||||
| 🔵 | GetBucketInventoryConfiguration | |
|
||||
| 🔵 | ListBucketInventoryConfigurations | |
|
||||
| 🔵 | PutBucketInventoryConfiguration | |
|
||||
|
||||
## Lifecycle
|
||||
|
||||
| | Method | Comments |
|
||||
|----|---------------------------------|----------|
|
||||
| 🔵 | DeleteBucketLifecycle | |
|
||||
| 🔵 | GetBucketLifecycle | |
|
||||
| 🔵 | GetBucketLifecycleConfiguration | |
|
||||
| 🔵 | PutBucketLifecycle | |
|
||||
| 🔵 | PutBucketLifecycleConfiguration | |
|
||||
| | Method | Comments |
|
||||
|-----|---------------------------------|----------|
|
||||
| 🔵 | DeleteBucketLifecycle | |
|
||||
| 🔵 | GetBucketLifecycle | |
|
||||
| 🔵 | GetBucketLifecycleConfiguration | |
|
||||
| 🔵 | PutBucketLifecycle | |
|
||||
| 🔵 | PutBucketLifecycleConfiguration | |
|
||||
|
||||
## Logging
|
||||
|
||||
| | Method | Comments |
|
||||
|----|------------------|----------|
|
||||
| 🔵 | GetBucketLogging | |
|
||||
| 🔵 | PutBucketLogging | |
|
||||
| | Method | Comments |
|
||||
|-----|------------------|----------|
|
||||
| 🔵 | GetBucketLogging | |
|
||||
| 🔵 | PutBucketLogging | |
|
||||
|
||||
## Metrics
|
||||
|
||||
| | Method | Comments |
|
||||
|----|----------------------------------|----------|
|
||||
| 🔵 | DeleteBucketMetricsConfiguration | |
|
||||
| 🔵 | GetBucketMetricsConfiguration | |
|
||||
| 🔵 | ListBucketMetricsConfigurations | |
|
||||
| 🔵 | PutBucketMetricsConfiguration | |
|
||||
| | Method | Comments |
|
||||
|-----|----------------------------------|----------|
|
||||
| 🔵 | DeleteBucketMetricsConfiguration | |
|
||||
| 🔵 | GetBucketMetricsConfiguration | |
|
||||
| 🔵 | ListBucketMetricsConfigurations | |
|
||||
| 🔵 | PutBucketMetricsConfiguration | |
|
||||
|
||||
## Notifications
|
||||
|
||||
| | Method | Comments |
|
||||
|----|------------------------------------|---------------|
|
||||
| 🔵 | GetBucketNotification | |
|
||||
| 🔵 | GetBucketNotificationConfiguration | |
|
||||
| 🔵 | ListenBucketNotification | non-standard? |
|
||||
| 🔵 | PutBucketNotification | |
|
||||
| 🔵 | PutBucketNotificationConfiguration | |
|
||||
| | Method | Comments |
|
||||
|-----|------------------------------------|---------------|
|
||||
| 🔵 | GetBucketNotification | |
|
||||
| 🔵 | GetBucketNotificationConfiguration | |
|
||||
| 🔵 | ListenBucketNotification | non-standard? |
|
||||
| 🔵 | PutBucketNotification | |
|
||||
| 🔵 | PutBucketNotificationConfiguration | |
|
||||
|
||||
## Ownership controls
|
||||
|
||||
| | Method | Comments |
|
||||
|----|-------------------------------|----------|
|
||||
| 🔵 | DeleteBucketOwnershipControls | |
|
||||
| 🔵 | GetBucketOwnershipControls | |
|
||||
| 🔵 | PutBucketOwnershipControls | |
|
||||
| | Method | Comments |
|
||||
|-----|-------------------------------|----------|
|
||||
| 🔵 | DeleteBucketOwnershipControls | |
|
||||
| 🔵 | GetBucketOwnershipControls | |
|
||||
| 🔵 | PutBucketOwnershipControls | |
|
||||
|
||||
## Policy and replication
|
||||
|
||||
| | Method | Comments |
|
||||
|----|-------------------------|-----------------------------|
|
||||
| 🔵 | DeleteBucketPolicy | |
|
||||
| 🔵 | DeleteBucketReplication | |
|
||||
| 🔵 | DeletePublicAccessBlock | |
|
||||
| 🟡 | GetBucketPolicy | See ACL limitations |
|
||||
| 🔵 | GetBucketPolicyStatus | |
|
||||
| 🔵 | GetBucketReplication | |
|
||||
| 🟢 | PostPolicyBucket | Upload file using POST form |
|
||||
| 🟡 | PutBucketPolicy | See ACL limitations |
|
||||
| 🔵 | PutBucketReplication | |
|
||||
| | Method | Comments |
|
||||
|-----|-------------------------|------------------------------|
|
||||
| 🟢 | DeleteBucketPolicy | |
|
||||
| 🔵 | DeleteBucketReplication | |
|
||||
| 🔵 | DeletePublicAccessBlock | |
|
||||
| 🟢 | GetBucketPolicy | |
|
||||
| 🔵 | GetBucketPolicyStatus | |
|
||||
| 🔵 | GetBucketReplication | |
|
||||
| 🟢 | PostPolicyBucket | Upload file using POST form |
|
||||
| 🟡 | PutBucketPolicy | Conditions are not supported |
|
||||
| 🔵 | PutBucketReplication | |
|
||||
|
||||
## Request payment
|
||||
|
||||
| | Method | Comments |
|
||||
|----|-------------------------|----------|
|
||||
| 🔴 | GetBucketRequestPayment | |
|
||||
| 🔴 | PutBucketRequestPayment | |
|
||||
| | Method | Comments |
|
||||
|-----|-------------------------|----------|
|
||||
| 🔴 | GetBucketRequestPayment | |
|
||||
| 🔴 | PutBucketRequestPayment | |
|
||||
|
||||
## Tagging
|
||||
|
||||
| | Method | Comments |
|
||||
|----|---------------------|----------|
|
||||
| 🟢 | DeleteBucketTagging | |
|
||||
| 🟢 | GetBucketTagging | |
|
||||
| 🟢 | PutBucketTagging | |
|
||||
| | Method | Comments |
|
||||
|-----|---------------------|----------|
|
||||
| 🟢 | DeleteBucketTagging | |
|
||||
| 🟢 | GetBucketTagging | |
|
||||
| 🟢 | PutBucketTagging | |
|
||||
|
||||
## Tiering
|
||||
|
||||
| | Method | Comments |
|
||||
|----|---------------------------------------------|----------|
|
||||
| 🔵 | DeleteBucketIntelligentTieringConfiguration | |
|
||||
| 🔵 | GetBucketIntelligentTieringConfiguration | |
|
||||
| 🔵 | ListBucketIntelligentTieringConfigurations | |
|
||||
| 🔵 | PutBucketIntelligentTieringConfiguration | |
|
||||
| | Method | Comments |
|
||||
|-----|---------------------------------------------|----------|
|
||||
| 🔵 | DeleteBucketIntelligentTieringConfiguration | |
|
||||
| 🔵 | GetBucketIntelligentTieringConfiguration | |
|
||||
| 🔵 | ListBucketIntelligentTieringConfigurations | |
|
||||
| 🔵 | PutBucketIntelligentTieringConfiguration | |
|
||||
|
||||
## Versioning
|
||||
|
||||
| | Method | Comments |
|
||||
|----|---------------------|----------|
|
||||
| 🟢 | GetBucketVersioning | |
|
||||
| 🟢 | PutBucketVersioning | |
|
||||
| | Method | Comments |
|
||||
|-----|---------------------|----------|
|
||||
| 🟢 | GetBucketVersioning | |
|
||||
| 🟢 | PutBucketVersioning | |
|
||||
|
||||
## Website
|
||||
|
||||
| | Method | Comments |
|
||||
|----|---------------------|----------|
|
||||
| 🔵 | DeleteBucketWebsite | |
|
||||
| 🔵 | GetBucketWebsite | |
|
||||
| 🔵 | PutBucketWebsite | |
|
||||
| | Method | Comments |
|
||||
|-----|---------------------|----------|
|
||||
| 🔵 | DeleteBucketWebsite | |
|
||||
| 🔵 | GetBucketWebsite | |
|
||||
| 🔵 | PutBucketWebsite | |
|
||||
|
|
|
@ -418,6 +418,9 @@ cache:
|
|||
morph_policy:
|
||||
lifetime: 30s
|
||||
size: 10000
|
||||
frostfsid:
|
||||
lifetime: 1m
|
||||
size: 10000
|
||||
```
|
||||
|
||||
| Parameter | Type | Default value | Description |
|
||||
|
@ -431,6 +434,7 @@ cache:
|
|||
| `accessbox` | [Accessbox cache config](#accessbox-subsection) | `lifetime: 10m`<br>`size: 100` | Cache which stores access box with tokens by its address. |
|
||||
| `accesscontrol` | [Cache config](#cache-subsection) | `lifetime: 1m`<br>`size: 100000` | Cache which stores owner to cache operation mapping. |
|
||||
| `morph_policy` | [Cache config](#cache-subsection) | `lifetime: 1m`<br>`size: 10000` | Cache which stores list of policy chains. |
|
||||
| `frostfsid` | [Cache config](#cache-subsection) | `lifetime: 1m`<br>`size: 10000` | Cache which stores FrostfsID subject info. |
|
||||
|
||||
#### `cache` subsection
|
||||
|
||||
|
|
23
go.mod
23
go.mod
|
@ -3,11 +3,11 @@ module git.frostfs.info/TrueCloudLab/frostfs-s3-gw
|
|||
go 1.20
|
||||
|
||||
require (
|
||||
git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240215114728-2a124b95bc02
|
||||
git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.1-0.20231218084346-bce7ef18c83b
|
||||
git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240306101814-c1c7b344b9c0
|
||||
git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240409115729-6eb492025bdd
|
||||
git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20230531082742-c97d21411eb6
|
||||
git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240301150205-6fe4e2541d0b
|
||||
git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240226094215-c960b1b08831
|
||||
git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240402141532-e5040d35e99d
|
||||
git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240412130734-0e69e485115a
|
||||
git.frostfs.info/TrueCloudLab/zapjournald v0.0.0-20240124114243-cb2e66427d02
|
||||
github.com/aws/aws-sdk-go v1.44.6
|
||||
github.com/bluele/gcache v0.0.2
|
||||
|
@ -15,7 +15,7 @@ require (
|
|||
github.com/google/uuid v1.3.1
|
||||
github.com/minio/sio v0.3.0
|
||||
github.com/nats-io/nats.go v1.13.1-0.20220121202836-972a071d373d
|
||||
github.com/nspcc-dev/neo-go v0.104.1-0.20231206061802-441eb8aa86be
|
||||
github.com/nspcc-dev/neo-go v0.105.0
|
||||
github.com/panjf2000/ants/v2 v2.5.0
|
||||
github.com/prometheus/client_golang v1.15.1
|
||||
github.com/prometheus/client_model v0.3.0
|
||||
|
@ -28,10 +28,10 @@ require (
|
|||
go.opentelemetry.io/otel v1.16.0
|
||||
go.opentelemetry.io/otel/trace v1.16.0
|
||||
go.uber.org/zap v1.26.0
|
||||
golang.org/x/crypto v0.14.0
|
||||
golang.org/x/crypto v0.17.0
|
||||
golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63
|
||||
google.golang.org/grpc v1.59.0
|
||||
google.golang.org/protobuf v1.31.0
|
||||
google.golang.org/protobuf v1.33.0
|
||||
)
|
||||
|
||||
require (
|
||||
|
@ -50,6 +50,7 @@ require (
|
|||
github.com/go-logr/logr v1.2.4 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/golang/snappy v0.0.1 // indirect
|
||||
github.com/gorilla/websocket v1.5.0 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3 // indirect
|
||||
github.com/hashicorp/golang-lru v0.6.0 // indirect
|
||||
|
@ -78,8 +79,10 @@ require (
|
|||
github.com/spf13/cast v1.5.0 // indirect
|
||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||
github.com/subosito/gotenv v1.4.2 // indirect
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954 // indirect
|
||||
github.com/twmb/murmur3 v1.1.8 // indirect
|
||||
github.com/urfave/cli v1.22.5 // indirect
|
||||
go.etcd.io/bbolt v1.3.8 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.16.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.16.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.16.0 // indirect
|
||||
|
@ -90,9 +93,9 @@ require (
|
|||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/net v0.17.0 // indirect
|
||||
golang.org/x/sync v0.3.0 // indirect
|
||||
golang.org/x/sys v0.13.0 // indirect
|
||||
golang.org/x/term v0.13.0 // indirect
|
||||
golang.org/x/text v0.13.0 // indirect
|
||||
golang.org/x/sys v0.15.0 // indirect
|
||||
golang.org/x/term v0.15.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20231120223509-83a465c0220f // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231127180814-3a041ad873d4 // indirect
|
||||
|
|
78
go.sum
78
go.sum
|
@ -36,20 +36,20 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX
|
|||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||
cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
|
||||
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.20240215114728-2a124b95bc02 h1:SAoUNpK1KBcY9NwP3ZZwDMXB5bvGCQiHxpXCw6wdpAI=
|
||||
git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240215114728-2a124b95bc02/go.mod h1:uY0AYmCznjZdghDnAk7THFIe1Vlg531IxUcus7ZfUJI=
|
||||
git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.1-0.20231218084346-bce7ef18c83b h1:zdbOxyqkxRyOLc7/2oNFu5tBwwg0Q6+0tJM3RkAxHlE=
|
||||
git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.1-0.20231218084346-bce7ef18c83b/go.mod h1:YMFtNZy2MgeiSwt0t8lqk8dYBGzlbhmV1cbbstJJ6oY=
|
||||
git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240306101814-c1c7b344b9c0 h1:4iyAj9k7W29YpyzUTwMuMBbL3G3M96kMbX62OwGNGfE=
|
||||
git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240306101814-c1c7b344b9c0/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-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=
|
||||
git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20230531082742-c97d21411eb6/go.mod h1:W8Nn08/l6aQ7UlIbpF7FsQou7TVpcRD1ZT1KG4TrFhE=
|
||||
git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240301150205-6fe4e2541d0b h1:nLIWYXe4e1fWgpKeMfVke/CNBn388egh4fArFdvhfHw=
|
||||
git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240301150205-6fe4e2541d0b/go.mod h1:XcgrbZ88XfvhAMxmZCQJ0dv6FyRSq6Mg2J7nN8uuO0k=
|
||||
git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240402141532-e5040d35e99d h1:MYlPcYV/8j3PP0Yv0t6kJwPwOnhHNTybHi05g+ofyw0=
|
||||
git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240402141532-e5040d35e99d/go.mod h1:s2ISRBm7AjfTdfZ3aF6gQt9VXz+n8cwSZcRiaVUMVI0=
|
||||
git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc=
|
||||
git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM=
|
||||
git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240226094215-c960b1b08831 h1:yK2iGQlg5kMmU47ZHor/g52mVS1xEgJSRQ4Olp76Cg8=
|
||||
git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240226094215-c960b1b08831/go.mod h1:YVL7yFaT0QNSpA0z+RHudLvrLwT+lsFYGyBSVc1ustI=
|
||||
git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240412130734-0e69e485115a h1:wbndKvHbwDQiSMQWL75RxiTZCeUyCi7NUj1lsfdAGkc=
|
||||
git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240412130734-0e69e485115a/go.mod h1:H/AW85RtYxVTbcgwHW76DqXeKlsiCIOeNXHPqyDBrfQ=
|
||||
git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 h1:M2KR3iBj7WpY3hP10IevfIB9MURr4O9mwVfJ+SjT3HA=
|
||||
git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0/go.mod h1:okpbKfVYf/BpejtfFTfhZqFP+sZ8rsHrP8Rr/jYPNRc=
|
||||
git.frostfs.info/TrueCloudLab/tzhash v1.8.0 h1:UFMnUIk0Zh17m8rjGHJMqku2hCgaXDqjqZzS4gsb4UA=
|
||||
|
@ -66,6 +66,7 @@ github.com/aws/aws-sdk-go v1.44.6 h1:Y+uHxmZfhRTLX2X3khkdxCoTZAyGEX21aOUHe1U6geg
|
|||
github.com/aws/aws-sdk-go v1.44.6/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bits-and-blooms/bitset v1.8.0 h1:FD+XqgOZDUxxZ8hzoBFuV9+cGWY9CslN6d5MS5JVb4c=
|
||||
github.com/bluele/gcache v0.0.2 h1:WcbfdXICg7G/DGBh1PFfcirkWOQV+v077yF1pSy3DGw=
|
||||
github.com/bluele/gcache v0.0.2/go.mod h1:m15KV+ECjptwSPxKhOhQoAFQVtUFjTVkc3H8o0t/fp0=
|
||||
github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
|
||||
|
@ -87,6 +88,8 @@ github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWH
|
|||
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ=
|
||||
github.com/consensys/gnark-crypto v0.12.2-0.20231013160410-1f65e75b6dfb h1:f0BMgIjhZy4lSRHCXFbQst85f5agZAjtDMixQqBWNpc=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
|
@ -104,6 +107,8 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.m
|
|||
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/frankban/quicktest v1.14.5 h1:dfYrrRyLtiqT9GyKXgdh+k4inNeTvmGbuSgZ3lx3GhA=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
|
||||
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
|
@ -149,6 +154,7 @@ github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu
|
|||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
|
||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
|
@ -197,6 +203,8 @@ github.com/hashicorp/golang-lru/v2 v2.0.2 h1:Dwmkdr5Nc/oBiXgJS3CDHNhJtIHkuZ3DZF5
|
|||
github.com/hashicorp/golang-lru/v2 v2.0.2/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
|
||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
|
@ -228,6 +236,7 @@ github.com/minio/sio v0.3.0 h1:syEFBewzOMOYVzSTFpp1MqpSZk8rUNbz8VIIc+PNzus=
|
|||
github.com/minio/sio v0.3.0/go.mod h1:8b0yPp2avGThviy/+OCJBI6OMpvxoUuiLvE6F1lebhw=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY=
|
||||
github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o=
|
||||
github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
|
||||
github.com/nats-io/jwt/v2 v2.2.1-0.20220113022732-58e87895b296 h1:vU9tpM3apjYlLLeY23zRWJ9Zktr5jp+mloR942LEOpY=
|
||||
|
@ -241,12 +250,21 @@ github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
|
|||
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
||||
github.com/nspcc-dev/go-ordered-json v0.0.0-20231123160306-3374ff1e7a3c h1:OOQeE613BH93ICPq3eke5N78gWNeMjcBWkmD2NKyXVg=
|
||||
github.com/nspcc-dev/go-ordered-json v0.0.0-20231123160306-3374ff1e7a3c/go.mod h1:79bEUDEviBHJMFV6Iq6in57FEOCMcRhfQnfaf0ETA5U=
|
||||
github.com/nspcc-dev/neo-go v0.104.1-0.20231206061802-441eb8aa86be h1:nZ2Hi5JSXdq3JXDi/8lms1UXQDAA5LVGpOpcrf2bRVA=
|
||||
github.com/nspcc-dev/neo-go v0.104.1-0.20231206061802-441eb8aa86be/go.mod h1:dsu8+VDMgGF7QNtPFBU4seE3pxSq8fYCuk3A6he4+ZQ=
|
||||
github.com/nspcc-dev/neo-go v0.105.0 h1:vtNZYFEFySK8zRDhLzQYha849VzWrcKezlnq/oNQg/w=
|
||||
github.com/nspcc-dev/neo-go v0.105.0/go.mod h1:6pchIHg5okeZO955RxpTh5q0sUI0vtpgPM6Q+no1rlI=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231127165613-b35f351f0ba0 h1:N+dMIBmteXjJpkH6UZ7HmNftuFxkqszfGLbhsEctnv0=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231127165613-b35f351f0ba0/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=
|
||||
github.com/nspcc-dev/rfc6979 v0.2.0 h1:3e1WNxrN60/6N0DW7+UYisLeZJyfqZTNOjeV/toYvOE=
|
||||
github.com/nspcc-dev/rfc6979 v0.2.0/go.mod h1:exhIh1PdpDC5vQmyEsGvc4YDM/lyQp/452QxGq/UEso=
|
||||
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA=
|
||||
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/panjf2000/ants/v2 v2.5.0 h1:1rWGWSnxCsQBga+nQbA4/iY6VMeNoOIAM0ZWh9u3q2Q=
|
||||
github.com/panjf2000/ants/v2 v2.5.0/go.mod h1:cU93usDlihJZ5CfRGNDYsiBYvoilLvBF5Qp/BT2GNRE=
|
||||
github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU=
|
||||
|
@ -301,6 +319,7 @@ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl
|
|||
github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8=
|
||||
github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954 h1:xQdMZ1WLrgkkvOZ/LDQxjVxMLdby7osSh4ZEVa5sIjs=
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM=
|
||||
github.com/twmb/murmur3 v1.1.8 h1:8Yt9taO/WN3l08xErzjeschgZU2QSrwm1kclYq+0aRg=
|
||||
github.com/twmb/murmur3 v1.1.8/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ=
|
||||
github.com/urfave/cli v1.22.5 h1:lNq9sAHXK2qfdI8W+GRItjCEkI+2oR4d+MEHy1CKXoU=
|
||||
|
@ -314,6 +333,7 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
|
|||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
go.etcd.io/bbolt v1.3.8 h1:xs88BrvEv273UsB79e0hcVrlUWmS0a8upikMFhSyAtA=
|
||||
go.etcd.io/bbolt v1.3.8/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
|
@ -353,8 +373,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
|
|||
golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
|
||||
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
||||
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
|
||||
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
|
@ -390,8 +410,10 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
|||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
|
@ -412,9 +434,11 @@ golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/
|
|||
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
|
@ -449,6 +473,7 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ
|
|||
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
|
||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
@ -457,7 +482,10 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
@ -471,8 +499,10 @@ golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
@ -487,12 +517,12 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
|
||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
|
||||
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
|
||||
golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
|
||||
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
|
@ -501,8 +531,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
|
@ -554,10 +584,12 @@ golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4f
|
|||
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||
golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 h1:Vve/L0v7CXXuxUmaMGIEK/dEeq7uiqb5qBgQrZzIE7E=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=
|
||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
||||
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||
|
@ -663,17 +695,22 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba
|
|||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
|
||||
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
@ -689,3 +726,4 @@ honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9
|
|||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||
rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU=
|
||||
|
|
84
internal/frostfs/frostfsid/contract/frostfsid.go
Normal file
84
internal/frostfs/frostfsid/contract/frostfsid.go
Normal file
|
@ -0,0 +1,84 @@
|
|||
package contract
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client"
|
||||
frostfsutil "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/frostfs/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
||||
)
|
||||
|
||||
type FrostFSID struct {
|
||||
cli *client.Client
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
// RPCAddress is an endpoint to connect to neo rpc.
|
||||
RPCAddress string
|
||||
|
||||
// Contract is hash of contract or its name in NNS.
|
||||
Contract string
|
||||
|
||||
// ProxyContract is hash of proxy contract or its name in NNS to interact with frostfsid.
|
||||
ProxyContract string
|
||||
|
||||
// Key is used to interact with frostfsid contract.
|
||||
// If this is nil than random key will be generated.
|
||||
Key *keys.PrivateKey
|
||||
}
|
||||
|
||||
// New creates new FrostfsID contract wrapper that implements auth.FrostFSID interface.
|
||||
func New(ctx context.Context, cfg Config) (*FrostFSID, error) {
|
||||
contractHash, err := frostfsutil.ResolveContractHash(cfg.Contract, cfg.RPCAddress)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("resolve frostfs contract hash: %w", err)
|
||||
}
|
||||
|
||||
key := cfg.Key
|
||||
if key == nil {
|
||||
if key, err = keys.NewPrivateKey(); err != nil {
|
||||
return nil, fmt.Errorf("generate anon private key for frostfsid: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
rpcCli, err := rpcclient.New(ctx, cfg.RPCAddress, rpcclient.Options{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("init rpc client: %w", err)
|
||||
}
|
||||
|
||||
var opt client.Options
|
||||
opt.ProxyContract, err = frostfsutil.ResolveContractHash(cfg.ProxyContract, cfg.RPCAddress)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("resolve frostfs contract hash: %w", err)
|
||||
}
|
||||
|
||||
cli, err := client.New(rpcCli, wallet.NewAccountFromPrivateKey(key), contractHash, opt)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("init frostfsid client: %w", err)
|
||||
}
|
||||
|
||||
return &FrostFSID{
|
||||
cli: cli,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (f *FrostFSID) GetSubjectExtended(userHash util.Uint160) (*client.SubjectExtended, error) {
|
||||
return f.cli.GetSubjectExtended(userHash)
|
||||
}
|
||||
|
||||
func (f *FrostFSID) GetSubjectKeyByName(namespace, name string) (*keys.PublicKey, error) {
|
||||
return f.cli.GetSubjectKeyByName(namespace, name)
|
||||
}
|
||||
|
||||
func (f *FrostFSID) CreateSubject(namespace string, key *keys.PublicKey) (util.Uint256, uint32, error) {
|
||||
return f.cli.CreateSubject(namespace, key)
|
||||
}
|
||||
|
||||
func (f *FrostFSID) Wait(tx util.Uint256, vub uint32, err error) error {
|
||||
_, err = f.cli.Wait(tx, vub, err)
|
||||
return err
|
||||
}
|
|
@ -1,128 +1,128 @@
|
|||
package frostfsid
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"errors"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/cache"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/handler"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/authmate"
|
||||
frostfsutil "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/frostfs/util"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/frostfs/frostfsid/contract"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/logs"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type FrostFSID struct {
|
||||
cli *client.Client
|
||||
frostfsid *contract.FrostFSID
|
||||
cache *cache.FrostfsIDCache
|
||||
log *zap.Logger
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
// RPCAddress is an endpoint to connect to neo rpc.
|
||||
RPCAddress string
|
||||
|
||||
// Contract is hash of contract or its name in NNS.
|
||||
Contract string
|
||||
|
||||
// ProxyContract is hash of proxy contract or its name in NNS to interact with frostfsid.
|
||||
ProxyContract string
|
||||
|
||||
// Key is used to interact with frostfsid contract.
|
||||
// If this is nil than random key will be generated.
|
||||
Key *keys.PrivateKey
|
||||
Cache *cache.FrostfsIDCache
|
||||
FrostFSID *contract.FrostFSID
|
||||
Logger *zap.Logger
|
||||
}
|
||||
|
||||
var (
|
||||
_ api.FrostFSID = (*FrostFSID)(nil)
|
||||
_ authmate.FrostFSID = (*FrostFSID)(nil)
|
||||
_ handler.FrostFSID = (*FrostFSID)(nil)
|
||||
_ api.FrostFSID = (*FrostFSID)(nil)
|
||||
_ handler.FrostFSID = (*FrostFSID)(nil)
|
||||
)
|
||||
|
||||
// New creates new FrostfsID contract wrapper that implements auth.FrostFSID interface.
|
||||
func New(ctx context.Context, cfg Config) (*FrostFSID, error) {
|
||||
contractHash, err := frostfsutil.ResolveContractHash(cfg.Contract, cfg.RPCAddress)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("resolve frostfs contract hash: %w", err)
|
||||
}
|
||||
|
||||
key := cfg.Key
|
||||
if key == nil {
|
||||
if key, err = keys.NewPrivateKey(); err != nil {
|
||||
return nil, fmt.Errorf("generate anon private key for frostfsid: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
rpcCli, err := rpcclient.New(ctx, cfg.RPCAddress, rpcclient.Options{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("init rpc client: %w", err)
|
||||
}
|
||||
|
||||
var opt client.Options
|
||||
opt.ProxyContract, err = frostfsutil.ResolveContractHash(cfg.ProxyContract, cfg.RPCAddress)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("resolve frostfs contract hash: %w", err)
|
||||
}
|
||||
|
||||
cli, err := client.New(rpcCli, wallet.NewAccountFromPrivateKey(key), contractHash, opt)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("init frostfsid client: %w", err)
|
||||
// NewFrostFSID creates new FrostfsID wrapper.
|
||||
func NewFrostFSID(cfg Config) (*FrostFSID, error) {
|
||||
switch {
|
||||
case cfg.FrostFSID == nil:
|
||||
return nil, errors.New("missing frostfsid client")
|
||||
case cfg.Cache == nil:
|
||||
return nil, errors.New("missing frostfsid cache")
|
||||
case cfg.Logger == nil:
|
||||
return nil, errors.New("missing frostfsid logger")
|
||||
}
|
||||
|
||||
return &FrostFSID{
|
||||
cli: cli,
|
||||
frostfsid: cfg.FrostFSID,
|
||||
cache: cfg.Cache,
|
||||
log: cfg.Logger,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (f *FrostFSID) ValidatePublicKey(key *keys.PublicKey) error {
|
||||
_, err := f.cli.GetSubjectByKey(key)
|
||||
_, err := f.getSubject(key.GetScriptHash())
|
||||
return err
|
||||
}
|
||||
|
||||
func (f *FrostFSID) RegisterPublicKey(ns string, key *keys.PublicKey) error {
|
||||
_, err := f.cli.Wait(f.cli.CreateSubject(ns, key))
|
||||
if err != nil && !strings.Contains(err.Error(), "subject already exists") {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *FrostFSID) GetUserAddress(namespace, name string) (string, error) {
|
||||
key, err := f.cli.GetSubjectKeyByName(namespace, name)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return key.Address(), nil
|
||||
}
|
||||
|
||||
func (f *FrostFSID) GetUserKey(account, name string) (string, error) {
|
||||
key, err := f.cli.GetSubjectKeyByName(account, name)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return hex.EncodeToString(key.Bytes()), nil
|
||||
}
|
||||
|
||||
func (f *FrostFSID) GetUserGroupIDs(userHash util.Uint160) ([]string, error) {
|
||||
subjExt, err := f.cli.GetSubjectExtended(userHash)
|
||||
subj, err := f.getSubject(userHash)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "not found") {
|
||||
f.log.Debug(logs.UserGroupsListIsEmpty, zap.Error(err))
|
||||
return nil, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res := make([]string, len(subjExt.Groups))
|
||||
for i, group := range subjExt.Groups {
|
||||
res := make([]string, len(subj.Groups))
|
||||
for i, group := range subj.Groups {
|
||||
res[i] = strconv.FormatInt(group.ID, 10)
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (f *FrostFSID) getSubject(addr util.Uint160) (*client.SubjectExtended, error) {
|
||||
if subj := f.cache.GetSubject(addr); subj != nil {
|
||||
return subj, nil
|
||||
}
|
||||
|
||||
subj, err := f.frostfsid.GetSubjectExtended(addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = f.cache.PutSubject(addr, subj); err != nil {
|
||||
f.log.Warn(logs.CouldntCacheSubject, zap.Error(err))
|
||||
}
|
||||
|
||||
return subj, nil
|
||||
}
|
||||
|
||||
func (f *FrostFSID) GetUserAddress(namespace, name string) (string, error) {
|
||||
userKey, err := f.getUserKey(namespace, name)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return userKey.Address(), nil
|
||||
}
|
||||
|
||||
func (f *FrostFSID) GetUserKey(namespace, name string) (string, error) {
|
||||
userKey, err := f.getUserKey(namespace, name)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return hex.EncodeToString(userKey.Bytes()), nil
|
||||
}
|
||||
|
||||
func (f *FrostFSID) getUserKey(namespace, name string) (*keys.PublicKey, error) {
|
||||
if userKey := f.cache.GetUserKey(namespace, name); userKey != nil {
|
||||
return userKey, nil
|
||||
}
|
||||
|
||||
userKey, err := f.frostfsid.GetSubjectKeyByName(namespace, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = f.cache.PutUserKey(namespace, name, userKey); err != nil {
|
||||
f.log.Warn(logs.CouldntCacheUserKey, zap.Error(err))
|
||||
}
|
||||
|
||||
return userKey, nil
|
||||
}
|
||||
|
|
|
@ -41,6 +41,11 @@ type Config struct {
|
|||
Key *keys.PrivateKey
|
||||
}
|
||||
|
||||
const (
|
||||
batchSize = 100
|
||||
iteratorChainsByPrefix = "iteratorChainsByPrefix"
|
||||
)
|
||||
|
||||
var _ policy.Contract = (*Client)(nil)
|
||||
|
||||
// New creates new Policy contract wrapper.
|
||||
|
@ -114,7 +119,8 @@ func (c *Client) RemoveChain(kind policycontract.Kind, entity string, name []byt
|
|||
}
|
||||
|
||||
func (c *Client) ListChains(kind policycontract.Kind, entity string, name []byte) ([][]byte, error) {
|
||||
items, err := c.policyContract.ListChainsByPrefix(big.NewInt(int64(kind)), entity, name)
|
||||
items, err := commonclient.ReadIteratorItems(c.actor, batchSize, c.contractHash, iteratorChainsByPrefix,
|
||||
big.NewInt(int64(kind)), entity, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -9,6 +9,8 @@ import (
|
|||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
|
||||
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine"
|
||||
"github.com/google/uuid"
|
||||
"github.com/nspcc-dev/neo-go/pkg/neorpc/result"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
@ -25,7 +27,7 @@ type MorphRuleChainStorageConfig struct {
|
|||
Log *zap.Logger
|
||||
}
|
||||
|
||||
var _ engine.MorphRuleChainStorage = (*MorphRuleChainStorage)(nil)
|
||||
var _ engine.MorphRuleChainStorageReader = (*MorphRuleChainStorage)(nil)
|
||||
|
||||
const bucketPolicyPrefix = 'b'
|
||||
|
||||
|
@ -37,11 +39,11 @@ func NewMorphRuleChainStorage(config *MorphRuleChainStorageConfig) *MorphRuleCha
|
|||
}
|
||||
}
|
||||
|
||||
func (c *MorphRuleChainStorage) AddMorphRuleChain(chain.Name, engine.Target, *chain.Chain) (util.Uint256, uint32, error) {
|
||||
func (c *MorphRuleChainStorage) GetAdmin() (util.Uint160, error) {
|
||||
panic("should never be called")
|
||||
}
|
||||
|
||||
func (c *MorphRuleChainStorage) RemoveMorphRuleChain(chain.Name, engine.Target, chain.ID) (util.Uint256, uint32, error) {
|
||||
func (c *MorphRuleChainStorage) ListTargetsIterator(engine.TargetType) (uuid.UUID, result.Iterator, error) {
|
||||
panic("should never be called")
|
||||
}
|
||||
|
||||
|
@ -74,23 +76,25 @@ func (c *MorphRuleChainStorage) ListMorphRuleChains(name chain.Name, target engi
|
|||
}
|
||||
|
||||
func (c *MorphRuleChainStorage) PutBucketPolicy(ns string, cnrID cid.ID, policy []byte, chains []*chain.Chain) error {
|
||||
c.cache.Delete(cache.MorphPolicyCacheKey{Target: engine.NamespaceTarget(ns), Name: chain.S3})
|
||||
c.cache.Delete(cache.MorphPolicyCacheKey{Target: engine.ContainerTarget(cnrID.EncodeToString()), Name: chain.S3})
|
||||
|
||||
tx := c.contract.StartTx()
|
||||
tx.AddChain(policycontract.IAM, ns, getBucketPolicyName(cnrID), policy)
|
||||
|
||||
for i := range chains {
|
||||
tx.AddChain(policycontract.Namespace, ns, chains[i].ID, chains[i].Bytes())
|
||||
tx.AddChain(policycontract.Container, cnrID.EncodeToString(), chains[i].ID, chains[i].Bytes())
|
||||
}
|
||||
|
||||
return c.contract.SendTx(tx)
|
||||
}
|
||||
|
||||
func (c *MorphRuleChainStorage) DeleteBucketPolicy(ns string, cnrID cid.ID, chainID chain.ID) error {
|
||||
c.cache.Delete(cache.MorphPolicyCacheKey{Target: engine.NamespaceTarget(ns), Name: chain.S3})
|
||||
func (c *MorphRuleChainStorage) DeleteBucketPolicy(ns string, cnrID cid.ID, chainIDs []chain.ID) error {
|
||||
c.cache.Delete(cache.MorphPolicyCacheKey{Target: engine.ContainerTarget(cnrID.EncodeToString()), Name: chain.S3})
|
||||
|
||||
tx := c.contract.StartTx()
|
||||
tx.RemoveChain(policycontract.Namespace, ns, chainID)
|
||||
for _, chainID := range chainIDs {
|
||||
tx.RemoveChain(policycontract.Container, cnrID.EncodeToString(), chainID)
|
||||
}
|
||||
tx.RemoveChain(policycontract.IAM, ns, getBucketPolicyName(cnrID))
|
||||
|
||||
return c.contract.SendTx(tx)
|
||||
|
@ -100,25 +104,29 @@ func (c *MorphRuleChainStorage) GetBucketPolicy(ns string, cnrID cid.ID) ([]byte
|
|||
return c.contract.GetChain(policycontract.IAM, ns, getBucketPolicyName(cnrID))
|
||||
}
|
||||
|
||||
func (c *MorphRuleChainStorage) SaveACLChains(ns string, chains []*chain.Chain) error {
|
||||
c.cache.Delete(cache.MorphPolicyCacheKey{Target: engine.NamespaceTarget(ns), Name: chain.S3})
|
||||
c.cache.Delete(cache.MorphPolicyCacheKey{Target: engine.NamespaceTarget(ns), Name: chain.Ingress})
|
||||
func (c *MorphRuleChainStorage) SaveACLChains(cid string, chains []*chain.Chain) error {
|
||||
c.cache.Delete(cache.MorphPolicyCacheKey{Target: engine.ContainerTarget(cid), Name: chain.S3})
|
||||
c.cache.Delete(cache.MorphPolicyCacheKey{Target: engine.ContainerTarget(cid), Name: chain.Ingress})
|
||||
|
||||
tx := c.contract.StartTx()
|
||||
for i := range chains {
|
||||
tx.AddChain(policycontract.Namespace, ns, chains[i].ID, chains[i].Bytes())
|
||||
tx.AddChain(policycontract.Container, cid, chains[i].ID, chains[i].Bytes())
|
||||
}
|
||||
|
||||
return c.contract.SendTx(tx)
|
||||
}
|
||||
|
||||
func getKind(target engine.Target) policycontract.Kind {
|
||||
var kind policycontract.Kind = policycontract.Container
|
||||
if target.Type != engine.Container {
|
||||
kind = policycontract.Namespace
|
||||
switch target.Type {
|
||||
case engine.Container:
|
||||
return policycontract.Container
|
||||
case engine.User:
|
||||
return 'u'
|
||||
case engine.Group:
|
||||
return 'g'
|
||||
default:
|
||||
return policycontract.Namespace
|
||||
}
|
||||
|
||||
return kind
|
||||
}
|
||||
|
||||
func getBucketPolicyName(cnrID cid.ID) []byte {
|
||||
|
|
|
@ -70,8 +70,8 @@ func (s *Storage) PutBucketPolicy(ns string, cnrID cid.ID, policy []byte, policy
|
|||
return s.morph.PutBucketPolicy(ns, cnrID, policy, policyChains)
|
||||
}
|
||||
|
||||
func (s *Storage) DeleteBucketPolicy(ns string, cnrID cid.ID, chainID chain.ID) error {
|
||||
return s.morph.DeleteBucketPolicy(ns, cnrID, chainID)
|
||||
func (s *Storage) DeleteBucketPolicy(ns string, cnrID cid.ID, chainIDs []chain.ID) error {
|
||||
return s.morph.DeleteBucketPolicy(ns, cnrID, chainIDs)
|
||||
}
|
||||
|
||||
func (s *Storage) GetBucketPolicy(ns string, cnrID cid.ID) ([]byte, error) {
|
||||
|
|
|
@ -169,6 +169,7 @@ func (w *PoolWrapper) GetSubTreeStream(ctx context.Context, bktInfo *data.Bucket
|
|||
RootID: rootID,
|
||||
Depth: depth,
|
||||
BearerToken: getBearer(ctx, bktInfo),
|
||||
Order: treepool.AscendingOrder,
|
||||
}
|
||||
|
||||
subTreeReader, err := w.p.GetSubTree(ctx, poolPrm)
|
||||
|
|
|
@ -66,7 +66,6 @@ const (
|
|||
SomeACLNotFullyMapped = "some acl not fully mapped" // Warn in ../../api/handler/acl.go
|
||||
CouldntDeleteObject = "couldn't delete object" // Error in ../../api/layer/layer.go
|
||||
NotificatorIsDisabledS3WontProduceNotificationEvents = "notificator is disabled, s3 won't produce notification events" // Warn in ../../api/handler/api.go
|
||||
CouldntGetBucketVersioning = "couldn't get bucket versioning" // Warn in ../../api/handler/put.go
|
||||
BucketIsCreated = "bucket is created" // Info in ../../api/handler/put.go
|
||||
CouldntDeleteNotificationConfigurationObject = "couldn't delete notification configuration object" // Error in ../../api/layer/notifications.go
|
||||
CouldNotParseContainerObjectLockEnabledAttribute = "could not parse container object lock enabled attribute" // Error in ../../api/layer/container.go
|
||||
|
@ -105,31 +104,32 @@ const (
|
|||
FailedToPassAuthentication = "failed to pass authentication" // Error in ../../api/middleware/auth.go
|
||||
FailedToResolveCID = "failed to resolve CID" // Debug in ../../api/middleware/metrics.go
|
||||
RequestStart = "request start" // Info in ../../api/middleware/reqinfo.go
|
||||
FailedToUnescapeObjectName = "failed to unescape object name" // Warn in ../../api/middleware/reqinfo.go
|
||||
CouldNotHandleMessage = "could not handle message" // Error in ../../api/notifications/controller.go
|
||||
CouldNotACKMessage = "could not ACK message" // Error in ../../api/notifications/controller.go
|
||||
CouldntMarshalAnEvent = "couldn't marshal an event" // Error in ../../api/notifications/controller.go
|
||||
CouldntSendAnEventToTopic = "couldn't send an event to topic" // Error in ../../api/notifications/controller.go
|
||||
InvalidDefaultMaxAge = "invalid defaultMaxAge" // Fatal in ../../cmd/s3-gw/app_settings.go
|
||||
CantShutDownService = "can't shut down service" // Panic in ../../cmd/s3-gw/service.go
|
||||
CouldntGenerateRandomKey = "couldn't generate random key" // Fatal in ../../cmd/s3-gw/app.go
|
||||
FailedToEnableNotifications = "failed to enable notifications" // Fatal in ../../cmd/s3-gw/app.go
|
||||
CouldntInitializeLayer = "couldn't initialize layer" // Fatal in ../../cmd/s3-gw/app.go
|
||||
FailedToCreateResolver = "failed to create resolver" // Fatal in ../../cmd/s3-gw/app.go
|
||||
CouldNotLoadFrostFSPrivateKey = "could not load FrostFS private key" // Fatal in ../../cmd/s3-gw/app.go
|
||||
FailedToCreateConnectionPool = "failed to create connection pool" // Fatal in ../../cmd/s3-gw/app.go
|
||||
FailedToDialConnectionPool = "failed to dial connection pool" // Fatal in ../../cmd/s3-gw/app.go
|
||||
FailedToCreateTreePool = "failed to create tree pool" // Fatal in ../../cmd/s3-gw/app.go
|
||||
FailedToDialTreePool = "failed to dial tree pool" // Fatal in ../../cmd/s3-gw/app.go
|
||||
ListenAndServe = "listen and serve" // Fatal in ../../cmd/s3-gw/app.go
|
||||
NoHealthyServers = "no healthy servers" // Fatal in ../../cmd/s3-gw/app.go
|
||||
CouldNotInitializeAPIHandler = "could not initialize API handler" // Fatal in ../../cmd/s3-gw/app.go
|
||||
RuntimeSoftMemoryDefinedWithGOMEMLIMIT = "soft runtime memory defined with GOMEMLIMIT environment variable, config value skipped" // Warn in ../../cmd/s3-gw/app.go
|
||||
RuntimeSoftMemoryLimitUpdated = "soft runtime memory limit value updated" // Info in ../../cmd/s3-gw/app.go
|
||||
AnonRequestSkipFrostfsIDValidation = "anon request, skip FrostfsID validation" // Debug in ../../api/middleware/auth.go
|
||||
FrostfsIDValidationFailed = "FrostfsID validation failed" // Error in ../../api/middleware/auth.go
|
||||
InitFrostfsIDContractFailed = "init frostfsid contract failed" // Fatal in ../../cmd/s3-gw/app.go
|
||||
InitPolicyContractFailed = "init policy contract failed" // Fatal in ../../cmd/s3-gw/app.go
|
||||
RequestHTTP = "http request"
|
||||
FailedToUnescapeObjectName = "failed to unescape object name" // Warn in ../../api/middleware/reqinfo.go
|
||||
CouldNotHandleMessage = "could not handle message" // Error in ../../api/notifications/controller.go
|
||||
CouldNotACKMessage = "could not ACK message" // Error in ../../api/notifications/controller.go
|
||||
CouldntMarshalAnEvent = "couldn't marshal an event" // Error in ../../api/notifications/controller.go
|
||||
CouldntSendAnEventToTopic = "couldn't send an event to topic" // Error in ../../api/notifications/controller.go
|
||||
InvalidDefaultMaxAge = "invalid defaultMaxAge" // Fatal in ../../cmd/s3-gw/app_settings.go
|
||||
CantShutDownService = "can't shut down service" // Panic in ../../cmd/s3-gw/service.go
|
||||
CouldntGenerateRandomKey = "couldn't generate random key" // Fatal in ../../cmd/s3-gw/app.go
|
||||
FailedToEnableNotifications = "failed to enable notifications" // Fatal in ../../cmd/s3-gw/app.go
|
||||
CouldntInitializeLayer = "couldn't initialize layer" // Fatal in ../../cmd/s3-gw/app.go
|
||||
FailedToCreateResolver = "failed to create resolver" // Fatal in ../../cmd/s3-gw/app.go
|
||||
CouldNotLoadFrostFSPrivateKey = "could not load FrostFS private key" // Fatal in ../../cmd/s3-gw/app.go
|
||||
FailedToCreateConnectionPool = "failed to create connection pool" // Fatal in ../../cmd/s3-gw/app.go
|
||||
FailedToDialConnectionPool = "failed to dial connection pool" // Fatal in ../../cmd/s3-gw/app.go
|
||||
FailedToCreateTreePool = "failed to create tree pool" // Fatal in ../../cmd/s3-gw/app.go
|
||||
FailedToDialTreePool = "failed to dial tree pool" // Fatal in ../../cmd/s3-gw/app.go
|
||||
ListenAndServe = "listen and serve" // Fatal in ../../cmd/s3-gw/app.go
|
||||
NoHealthyServers = "no healthy servers" // Fatal in ../../cmd/s3-gw/app.go
|
||||
CouldNotInitializeAPIHandler = "could not initialize API handler" // Fatal in ../../cmd/s3-gw/app.go
|
||||
RuntimeSoftMemoryDefinedWithGOMEMLIMIT = "soft runtime memory defined with GOMEMLIMIT environment variable, config value skipped" // Warn in ../../cmd/s3-gw/app.go
|
||||
RuntimeSoftMemoryLimitUpdated = "soft runtime memory limit value updated" // Info in ../../cmd/s3-gw/app.go
|
||||
AnonRequestSkipFrostfsIDValidation = "anon request, skip FrostfsID validation" // Debug in ../../api/middleware/auth.go
|
||||
FrostfsIDValidationFailed = "FrostfsID validation failed" // Error in ../../api/middleware/auth.go
|
||||
InitFrostfsIDContractFailed = "init frostfsid contract failed" // Fatal in ../../cmd/s3-gw/app.go
|
||||
InitPolicyContractFailed = "init policy contract failed" // Fatal in ../../cmd/s3-gw/app.go
|
||||
ControlAPIHealthcheck = "healthcheck request"
|
||||
ControlAPIPutPolicies = "put policies request"
|
||||
ControlAPIRemovePolicies = "remove policies request"
|
||||
|
@ -149,4 +149,9 @@ const (
|
|||
FailedToGenerateRequestID = "failed to generate request id"
|
||||
InvalidBucketObjectLockEnabledHeader = "invalid X-Amz-Bucket-Object-Lock-Enabled header"
|
||||
InvalidTreeKV = "invalid tree service meta KV"
|
||||
FailedToWriteResponse = "failed to write response"
|
||||
PolicyCouldntBeConvertedToNativeRules = "policy couldn't be converted to native rules, only s3 rules be applied"
|
||||
CouldntCacheSubject = "couldn't cache subject info"
|
||||
UserGroupsListIsEmpty = "user groups list is empty, subject not found"
|
||||
CouldntCacheUserKey = "couldn't cache user key"
|
||||
)
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
|
||||
policycontract "git.frostfs.info/TrueCloudLab/frostfs-contract/policy"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/pkg/service/control"
|
||||
controlSvc "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/pkg/service/control/server"
|
||||
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
|
||||
|
@ -23,13 +24,30 @@ type Config struct {
|
|||
}
|
||||
|
||||
type PolicyData struct {
|
||||
Namespace string
|
||||
Chain *chain.Chain
|
||||
Kind policycontract.Kind
|
||||
Name string
|
||||
Chain *chain.Chain
|
||||
}
|
||||
|
||||
type PolicyInfo struct {
|
||||
Namespace string
|
||||
ChainID chain.ID
|
||||
Kind policycontract.Kind
|
||||
Name string
|
||||
ChainID chain.ID
|
||||
}
|
||||
|
||||
func kindToTarget(k policycontract.Kind) control.PolicyTarget {
|
||||
switch k {
|
||||
case policycontract.Container:
|
||||
return control.PolicyTarget_CONTAINER
|
||||
case policycontract.Namespace:
|
||||
return control.PolicyTarget_NAMESPACE
|
||||
case 'u':
|
||||
return control.PolicyTarget_USER
|
||||
case 'g':
|
||||
return control.PolicyTarget_GROUP
|
||||
default:
|
||||
return control.PolicyTarget_TARGET_UNDEFINED
|
||||
}
|
||||
}
|
||||
|
||||
func New(ctx context.Context, addr string, key *keys.PrivateKey) (*Client, error) {
|
||||
|
@ -70,8 +88,9 @@ func (c *Client) PutPolicies(ctx context.Context, policies []PolicyData) error {
|
|||
chainDatas := make([]*control.PutPoliciesRequest_ChainData, len(policies))
|
||||
for i := range policies {
|
||||
chainDatas[i] = &control.PutPoliciesRequest_ChainData{
|
||||
Namespace: policies[i].Namespace,
|
||||
Chain: policies[i].Chain.Bytes(),
|
||||
Target: kindToTarget(policies[i].Kind),
|
||||
Name: policies[i].Name,
|
||||
Chain: policies[i].Chain.Bytes(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -93,8 +112,9 @@ func (c *Client) RemovePolicies(ctx context.Context, policies []PolicyInfo) erro
|
|||
chainInfos := make([]*control.RemovePoliciesRequest_ChainInfo, len(policies))
|
||||
for i := range policies {
|
||||
chainInfos[i] = &control.RemovePoliciesRequest_ChainInfo{
|
||||
Namespace: policies[i].Namespace,
|
||||
ChainID: []byte(policies[i].ChainID),
|
||||
Target: kindToTarget(policies[i].Kind),
|
||||
Name: policies[i].Name,
|
||||
ChainID: []byte(policies[i].ChainID),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -112,11 +132,12 @@ func (c *Client) RemovePolicies(ctx context.Context, policies []PolicyInfo) erro
|
|||
return err
|
||||
}
|
||||
|
||||
func (c *Client) GetPolicy(ctx context.Context, namespace string, chainID chain.ID) (*chain.Chain, error) {
|
||||
func (c *Client) GetPolicy(ctx context.Context, kind policycontract.Kind, name string, chainID chain.ID) (*chain.Chain, error) {
|
||||
req := &control.GetPolicyRequest{
|
||||
Body: &control.GetPolicyRequest_Body{
|
||||
Namespace: namespace,
|
||||
ChainID: []byte(chainID),
|
||||
Target: kindToTarget(kind),
|
||||
Name: name,
|
||||
ChainID: []byte(chainID),
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -137,10 +158,11 @@ func (c *Client) GetPolicy(ctx context.Context, namespace string, chainID chain.
|
|||
return &policyChain, nil
|
||||
}
|
||||
|
||||
func (c *Client) ListPolicies(ctx context.Context, namespace string) ([]chain.ID, error) {
|
||||
func (c *Client) ListPolicies(ctx context.Context, kind policycontract.Kind, name string) ([]chain.ID, error) {
|
||||
req := &control.ListPoliciesRequest{
|
||||
Body: &control.ListPoliciesRequest_Body{
|
||||
Namespace: namespace,
|
||||
Target: kindToTarget(kind),
|
||||
Name: name,
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -140,14 +140,39 @@ func (s *Server) putPolicy(data *control.PutPoliciesRequest_ChainData) error {
|
|||
return status.Error(codes.InvalidArgument, "missing chain id")
|
||||
}
|
||||
|
||||
ns := s.settings.ResolveNamespaceAlias(data.GetNamespace())
|
||||
if _, err := s.chainStorage.AddOverride(chain.S3, engine.NamespaceTarget(ns), &overrideChain); err != nil {
|
||||
t, err := s.parseTarget(data.Target, data.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := s.chainStorage.AddOverride(chain.S3, t, &overrideChain); err != nil {
|
||||
return status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Server) parseTarget(target control.PolicyTarget, name string) (engine.Target, error) {
|
||||
var (
|
||||
t engine.Target
|
||||
err error
|
||||
)
|
||||
switch target {
|
||||
case control.PolicyTarget_NAMESPACE:
|
||||
ns := s.settings.ResolveNamespaceAlias(name)
|
||||
t = engine.NamespaceTarget(ns)
|
||||
case control.PolicyTarget_CONTAINER:
|
||||
t = engine.ContainerTarget(name)
|
||||
case control.PolicyTarget_USER:
|
||||
t = engine.UserTarget(name)
|
||||
case control.PolicyTarget_GROUP:
|
||||
t = engine.GroupTarget(name)
|
||||
default:
|
||||
err = status.Error(codes.InvalidArgument, fmt.Sprintf("invalid target: %s", target.String()))
|
||||
}
|
||||
return t, err
|
||||
}
|
||||
|
||||
// RemovePolicies removes existing policies.
|
||||
//
|
||||
// If request is unsigned or signed by disallowed key, permission error returns.
|
||||
|
@ -169,8 +194,11 @@ func (s *Server) RemovePolicies(_ context.Context, req *control.RemovePoliciesRe
|
|||
}
|
||||
|
||||
func (s *Server) removePolicy(info *control.RemovePoliciesRequest_ChainInfo) error {
|
||||
ns := s.settings.ResolveNamespaceAlias(info.GetNamespace())
|
||||
err := s.chainStorage.RemoveOverride(chain.S3, engine.NamespaceTarget(ns), chain.ID(info.GetChainID()))
|
||||
t, err := s.parseTarget(info.Target, info.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = s.chainStorage.RemoveOverride(chain.S3, t, chain.ID(info.GetChainID()))
|
||||
if err != nil {
|
||||
if isNotFoundError(err) {
|
||||
return status.Error(codes.NotFound, err.Error())
|
||||
|
@ -184,16 +212,20 @@ func (s *Server) removePolicy(info *control.RemovePoliciesRequest_ChainInfo) err
|
|||
//
|
||||
// If request is unsigned or signed by disallowed key, permission error returns.
|
||||
func (s *Server) GetPolicy(_ context.Context, req *control.GetPolicyRequest) (*control.GetPolicyResponse, error) {
|
||||
s.log.Info(logs.ControlAPIGetPolicy, zap.String("namespace", req.GetBody().GetNamespace()),
|
||||
s.log.Info(logs.ControlAPIGetPolicy, zap.Stringer("target", req.GetBody().GetTarget()), zap.String("name", req.GetBody().GetName()),
|
||||
zap.Binary("chainId", req.GetBody().GetChainID()), zap.String("key", hex.EncodeToString(req.Signature.Key)))
|
||||
|
||||
t, err := s.parseTarget(req.GetBody().GetTarget(), req.GetBody().GetName())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// verify request
|
||||
if err := s.isValidRequest(req); err != nil {
|
||||
return nil, status.Error(codes.PermissionDenied, err.Error())
|
||||
}
|
||||
|
||||
ns := s.settings.ResolveNamespaceAlias(req.GetBody().GetNamespace())
|
||||
overrideChain, err := s.chainStorage.GetOverride(chain.S3, engine.NamespaceTarget(ns), chain.ID(req.GetBody().GetChainID()))
|
||||
overrideChain, err := s.chainStorage.GetOverride(chain.S3, t, chain.ID(req.GetBody().GetChainID()))
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.InvalidArgument, err.Error())
|
||||
}
|
||||
|
@ -205,16 +237,20 @@ func (s *Server) GetPolicy(_ context.Context, req *control.GetPolicyRequest) (*c
|
|||
//
|
||||
// If request is unsigned or signed by disallowed key, permission error returns.
|
||||
func (s *Server) ListPolicies(_ context.Context, req *control.ListPoliciesRequest) (*control.ListPoliciesResponse, error) {
|
||||
s.log.Info(logs.ControlAPIListPolicies, zap.String("namespace", req.GetBody().GetNamespace()),
|
||||
s.log.Info(logs.ControlAPIListPolicies, zap.Stringer("target", req.GetBody().GetTarget()), zap.String("name", req.GetBody().GetName()),
|
||||
zap.String("key", hex.EncodeToString(req.Signature.Key)))
|
||||
|
||||
t, err := s.parseTarget(req.GetBody().GetTarget(), req.GetBody().GetName())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// verify request
|
||||
if err := s.isValidRequest(req); err != nil {
|
||||
return nil, status.Error(codes.PermissionDenied, err.Error())
|
||||
}
|
||||
|
||||
ns := s.settings.ResolveNamespaceAlias(req.GetBody().GetNamespace())
|
||||
chains, err := s.chainStorage.ListOverrides(chain.S3, engine.NamespaceTarget(ns))
|
||||
chains, err := s.chainStorage.ListOverrides(chain.S3, t)
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.InvalidArgument, err.Error())
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc v3.21.9
|
||||
// protoc-gen-go v1.30.0
|
||||
// protoc v3.21.12
|
||||
// source: pkg/service/control/service.proto
|
||||
|
||||
package control
|
||||
|
@ -77,6 +77,67 @@ func (HealthStatus) EnumDescriptor() ([]byte, []int) {
|
|||
return file_pkg_service_control_service_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
// Policy target to store chains.
|
||||
type PolicyTarget int32
|
||||
|
||||
const (
|
||||
// Undefined target, invalid to use.
|
||||
PolicyTarget_TARGET_UNDEFINED PolicyTarget = 0
|
||||
// Container target for bucket policies.
|
||||
PolicyTarget_CONTAINER PolicyTarget = 1
|
||||
// Namespace target for namespace policies.
|
||||
PolicyTarget_NAMESPACE PolicyTarget = 2
|
||||
// User target for namespace user policies.
|
||||
PolicyTarget_USER PolicyTarget = 3
|
||||
// Group target for namespace target policies.
|
||||
PolicyTarget_GROUP PolicyTarget = 4
|
||||
)
|
||||
|
||||
// Enum value maps for PolicyTarget.
|
||||
var (
|
||||
PolicyTarget_name = map[int32]string{
|
||||
0: "TARGET_UNDEFINED",
|
||||
1: "CONTAINER",
|
||||
2: "NAMESPACE",
|
||||
3: "USER",
|
||||
4: "GROUP",
|
||||
}
|
||||
PolicyTarget_value = map[string]int32{
|
||||
"TARGET_UNDEFINED": 0,
|
||||
"CONTAINER": 1,
|
||||
"NAMESPACE": 2,
|
||||
"USER": 3,
|
||||
"GROUP": 4,
|
||||
}
|
||||
)
|
||||
|
||||
func (x PolicyTarget) Enum() *PolicyTarget {
|
||||
p := new(PolicyTarget)
|
||||
*p = x
|
||||
return p
|
||||
}
|
||||
|
||||
func (x PolicyTarget) String() string {
|
||||
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
||||
}
|
||||
|
||||
func (PolicyTarget) Descriptor() protoreflect.EnumDescriptor {
|
||||
return file_pkg_service_control_service_proto_enumTypes[1].Descriptor()
|
||||
}
|
||||
|
||||
func (PolicyTarget) Type() protoreflect.EnumType {
|
||||
return &file_pkg_service_control_service_proto_enumTypes[1]
|
||||
}
|
||||
|
||||
func (x PolicyTarget) Number() protoreflect.EnumNumber {
|
||||
return protoreflect.EnumNumber(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use PolicyTarget.Descriptor instead.
|
||||
func (PolicyTarget) EnumDescriptor() ([]byte, []int) {
|
||||
return file_pkg_service_control_service_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
// Signature of some message.
|
||||
type Signature struct {
|
||||
state protoimpl.MessageState
|
||||
|
@ -794,10 +855,12 @@ type PutPoliciesRequest_ChainData struct {
|
|||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// Namespace.
|
||||
Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"`
|
||||
// Policy entity type.
|
||||
Target PolicyTarget `protobuf:"varint,1,opt,name=target,proto3,enum=s3gw.control.PolicyTarget" json:"target,omitempty"`
|
||||
// Policy name.
|
||||
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
|
||||
// Chain rules.
|
||||
Chain []byte `protobuf:"bytes,2,opt,name=chain,proto3" json:"chain,omitempty"`
|
||||
Chain []byte `protobuf:"bytes,3,opt,name=chain,proto3" json:"chain,omitempty"`
|
||||
}
|
||||
|
||||
func (x *PutPoliciesRequest_ChainData) Reset() {
|
||||
|
@ -832,9 +895,16 @@ func (*PutPoliciesRequest_ChainData) Descriptor() ([]byte, []int) {
|
|||
return file_pkg_service_control_service_proto_rawDescGZIP(), []int{3, 0}
|
||||
}
|
||||
|
||||
func (x *PutPoliciesRequest_ChainData) GetNamespace() string {
|
||||
func (x *PutPoliciesRequest_ChainData) GetTarget() PolicyTarget {
|
||||
if x != nil {
|
||||
return x.Namespace
|
||||
return x.Target
|
||||
}
|
||||
return PolicyTarget_TARGET_UNDEFINED
|
||||
}
|
||||
|
||||
func (x *PutPoliciesRequest_ChainData) GetName() string {
|
||||
if x != nil {
|
||||
return x.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
@ -936,10 +1006,12 @@ type RemovePoliciesRequest_ChainInfo struct {
|
|||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// Namespace.
|
||||
Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"`
|
||||
// Policy entity type.
|
||||
Target PolicyTarget `protobuf:"varint,1,opt,name=target,proto3,enum=s3gw.control.PolicyTarget" json:"target,omitempty"`
|
||||
// Policy name.
|
||||
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
|
||||
// Chain id to remove.
|
||||
ChainID []byte `protobuf:"bytes,2,opt,name=chainID,proto3" json:"chainID,omitempty"`
|
||||
ChainID []byte `protobuf:"bytes,3,opt,name=chainID,proto3" json:"chainID,omitempty"`
|
||||
}
|
||||
|
||||
func (x *RemovePoliciesRequest_ChainInfo) Reset() {
|
||||
|
@ -974,9 +1046,16 @@ func (*RemovePoliciesRequest_ChainInfo) Descriptor() ([]byte, []int) {
|
|||
return file_pkg_service_control_service_proto_rawDescGZIP(), []int{5, 0}
|
||||
}
|
||||
|
||||
func (x *RemovePoliciesRequest_ChainInfo) GetNamespace() string {
|
||||
func (x *RemovePoliciesRequest_ChainInfo) GetTarget() PolicyTarget {
|
||||
if x != nil {
|
||||
return x.Namespace
|
||||
return x.Target
|
||||
}
|
||||
return PolicyTarget_TARGET_UNDEFINED
|
||||
}
|
||||
|
||||
func (x *RemovePoliciesRequest_ChainInfo) GetName() string {
|
||||
if x != nil {
|
||||
return x.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
@ -1078,10 +1157,12 @@ type GetPolicyRequest_Body struct {
|
|||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// Namespace.
|
||||
Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"`
|
||||
// Chain id to remove.
|
||||
ChainID []byte `protobuf:"bytes,2,opt,name=chainID,proto3" json:"chainID,omitempty"`
|
||||
// Policy entity type.
|
||||
Target PolicyTarget `protobuf:"varint,1,opt,name=target,proto3,enum=s3gw.control.PolicyTarget" json:"target,omitempty"`
|
||||
// Policy name.
|
||||
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
|
||||
// Chain id to get.
|
||||
ChainID []byte `protobuf:"bytes,3,opt,name=chainID,proto3" json:"chainID,omitempty"`
|
||||
}
|
||||
|
||||
func (x *GetPolicyRequest_Body) Reset() {
|
||||
|
@ -1116,9 +1197,16 @@ func (*GetPolicyRequest_Body) Descriptor() ([]byte, []int) {
|
|||
return file_pkg_service_control_service_proto_rawDescGZIP(), []int{7, 0}
|
||||
}
|
||||
|
||||
func (x *GetPolicyRequest_Body) GetNamespace() string {
|
||||
func (x *GetPolicyRequest_Body) GetTarget() PolicyTarget {
|
||||
if x != nil {
|
||||
return x.Namespace
|
||||
return x.Target
|
||||
}
|
||||
return PolicyTarget_TARGET_UNDEFINED
|
||||
}
|
||||
|
||||
func (x *GetPolicyRequest_Body) GetName() string {
|
||||
if x != nil {
|
||||
return x.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
@ -1183,8 +1271,10 @@ type ListPoliciesRequest_Body struct {
|
|||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// Namespace.
|
||||
Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"`
|
||||
// Policy entity type.
|
||||
Target PolicyTarget `protobuf:"varint,1,opt,name=target,proto3,enum=s3gw.control.PolicyTarget" json:"target,omitempty"`
|
||||
// Policy name.
|
||||
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
|
||||
}
|
||||
|
||||
func (x *ListPoliciesRequest_Body) Reset() {
|
||||
|
@ -1219,9 +1309,16 @@ func (*ListPoliciesRequest_Body) Descriptor() ([]byte, []int) {
|
|||
return file_pkg_service_control_service_proto_rawDescGZIP(), []int{9, 0}
|
||||
}
|
||||
|
||||
func (x *ListPoliciesRequest_Body) GetNamespace() string {
|
||||
func (x *ListPoliciesRequest_Body) GetTarget() PolicyTarget {
|
||||
if x != nil {
|
||||
return x.Namespace
|
||||
return x.Target
|
||||
}
|
||||
return PolicyTarget_TARGET_UNDEFINED
|
||||
}
|
||||
|
||||
func (x *ListPoliciesRequest_Body) GetName() string {
|
||||
if x != nil {
|
||||
return x.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
@ -1305,7 +1402,7 @@ var file_pkg_service_control_service_proto_rawDesc = []byte{
|
|||
0x0d, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01,
|
||||
0x20, 0x01, 0x28, 0x0e, 0x32, 0x1a, 0x2e, 0x73, 0x33, 0x67, 0x77, 0x2e, 0x63, 0x6f, 0x6e, 0x74,
|
||||
0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73,
|
||||
0x52, 0x0c, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x9b,
|
||||
0x52, 0x0c, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0xc5,
|
||||
0x02, 0x0a, 0x12, 0x50, 0x75, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x39, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20,
|
||||
0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x73, 0x33, 0x67, 0x77, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72,
|
||||
|
@ -1314,136 +1411,153 @@ var file_pkg_service_control_service_proto_rawDesc = []byte{
|
|||
0x12, 0x35, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20,
|
||||
0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x73, 0x33, 0x67, 0x77, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72,
|
||||
0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69,
|
||||
0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x3f, 0x0a, 0x09, 0x43, 0x68, 0x61, 0x69, 0x6e,
|
||||
0x44, 0x61, 0x74, 0x61, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63,
|
||||
0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61,
|
||||
0x63, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||
0x0c, 0x52, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x1a, 0x52, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79,
|
||||
0x12, 0x4a, 0x0a, 0x0a, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x73, 0x18, 0x01,
|
||||
0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x73, 0x33, 0x67, 0x77, 0x2e, 0x63, 0x6f, 0x6e, 0x74,
|
||||
0x72, 0x6f, 0x6c, 0x2e, 0x50, 0x75, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x52,
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x44, 0x61, 0x74, 0x61,
|
||||
0x52, 0x0a, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x73, 0x22, 0x90, 0x01, 0x0a,
|
||||
0x13, 0x50, 0x75, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70,
|
||||
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x0b, 0x32, 0x26, 0x2e, 0x73, 0x33, 0x67, 0x77, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f,
|
||||
0x6c, 0x2e, 0x50, 0x75, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73,
|
||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79,
|
||||
0x12, 0x35, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20,
|
||||
0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x73, 0x33, 0x67, 0x77, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72,
|
||||
0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69,
|
||||
0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22,
|
||||
0xa8, 0x02, 0x0a, 0x15, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69,
|
||||
0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3c, 0x0a, 0x04, 0x62, 0x6f, 0x64,
|
||||
0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x73, 0x33, 0x67, 0x77, 0x2e, 0x63,
|
||||
0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x50, 0x6f, 0x6c,
|
||||
0x69, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64,
|
||||
0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x35, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61,
|
||||
0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x73, 0x33, 0x67,
|
||||
0x77, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74,
|
||||
0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x43,
|
||||
0x0a, 0x09, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1c, 0x0a, 0x09, 0x6e,
|
||||
0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09,
|
||||
0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x68, 0x61,
|
||||
0x69, 0x6e, 0x49, 0x44, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69,
|
||||
0x6e, 0x49, 0x44, 0x1a, 0x55, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x4d, 0x0a, 0x0a, 0x63,
|
||||
0x68, 0x61, 0x69, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32,
|
||||
0x2d, 0x2e, 0x73, 0x33, 0x67, 0x77, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52,
|
||||
0x65, 0x6d, 0x6f, 0x76, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71,
|
||||
0x75, 0x65, 0x73, 0x74, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a,
|
||||
0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x73, 0x22, 0x96, 0x01, 0x0a, 0x16, 0x52,
|
||||
0x65, 0x6d, 0x6f, 0x76, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73,
|
||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20,
|
||||
0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x73, 0x33, 0x67, 0x77, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72,
|
||||
0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65,
|
||||
0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04,
|
||||
0x62, 0x6f, 0x64, 0x79, 0x12, 0x35, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72,
|
||||
0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x73, 0x33, 0x67, 0x77, 0x2e, 0x63,
|
||||
0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65,
|
||||
0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42,
|
||||
0x6f, 0x64, 0x79, 0x22, 0xc2, 0x01, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63,
|
||||
0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x37, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x73, 0x33, 0x67, 0x77, 0x2e, 0x63, 0x6f,
|
||||
0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52,
|
||||
0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x69, 0x0a, 0x09, 0x43, 0x68, 0x61, 0x69, 0x6e,
|
||||
0x44, 0x61, 0x74, 0x61, 0x12, 0x32, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01,
|
||||
0x20, 0x01, 0x28, 0x0e, 0x32, 0x1a, 0x2e, 0x73, 0x33, 0x67, 0x77, 0x2e, 0x63, 0x6f, 0x6e, 0x74,
|
||||
0x72, 0x6f, 0x6c, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74,
|
||||
0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65,
|
||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05,
|
||||
0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x63, 0x68, 0x61,
|
||||
0x69, 0x6e, 0x1a, 0x52, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x4a, 0x0a, 0x0a, 0x63, 0x68,
|
||||
0x61, 0x69, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a,
|
||||
0x2e, 0x73, 0x33, 0x67, 0x77, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x50, 0x75,
|
||||
0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||
0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x52, 0x0a, 0x63, 0x68, 0x61, 0x69,
|
||||
0x6e, 0x44, 0x61, 0x74, 0x61, 0x73, 0x22, 0x90, 0x01, 0x0a, 0x13, 0x50, 0x75, 0x74, 0x50, 0x6f,
|
||||
0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a,
|
||||
0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x73,
|
||||
0x33, 0x67, 0x77, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x50, 0x75, 0x74, 0x50,
|
||||
0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e,
|
||||
0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x35, 0x0a, 0x09, 0x73, 0x69,
|
||||
0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e,
|
||||
0x73, 0x33, 0x67, 0x77, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67,
|
||||
0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72,
|
||||
0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xd2, 0x02, 0x0a, 0x15, 0x52, 0x65,
|
||||
0x6d, 0x6f, 0x76, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75,
|
||||
0x65, 0x73, 0x74, 0x12, 0x3c, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||
0x0b, 0x32, 0x28, 0x2e, 0x73, 0x33, 0x67, 0x77, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
|
||||
0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x52,
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64,
|
||||
0x79, 0x12, 0x35, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02,
|
||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x73, 0x33, 0x67, 0x77, 0x2e, 0x63, 0x6f, 0x6e, 0x74,
|
||||
0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73,
|
||||
0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x3e, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79,
|
||||
0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x18,
|
||||
0x0a, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x44, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52,
|
||||
0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x44, 0x22, 0xa2, 0x01, 0x0a, 0x11, 0x47, 0x65, 0x74,
|
||||
0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38,
|
||||
0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x73,
|
||||
0x33, 0x67, 0x77, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x50,
|
||||
0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f,
|
||||
0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x6d, 0x0a, 0x09, 0x43, 0x68, 0x61, 0x69,
|
||||
0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x32, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1a, 0x2e, 0x73, 0x33, 0x67, 0x77, 0x2e, 0x63, 0x6f, 0x6e,
|
||||
0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x54, 0x61, 0x72, 0x67, 0x65,
|
||||
0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d,
|
||||
0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a,
|
||||
0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x44, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07,
|
||||
0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x44, 0x1a, 0x55, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12,
|
||||
0x4d, 0x0a, 0x0a, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x73, 0x18, 0x01, 0x20,
|
||||
0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x73, 0x33, 0x67, 0x77, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72,
|
||||
0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65,
|
||||
0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x6e,
|
||||
0x66, 0x6f, 0x52, 0x0a, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x73, 0x22, 0x96,
|
||||
0x01, 0x0a, 0x16, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65,
|
||||
0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x04, 0x62, 0x6f, 0x64,
|
||||
0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x73, 0x33, 0x67, 0x77, 0x2e, 0x63,
|
||||
0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x50, 0x6f, 0x6c,
|
||||
0x69, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f,
|
||||
0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x35, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e,
|
||||
0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x73, 0x33,
|
||||
0x67, 0x77, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61,
|
||||
0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a,
|
||||
0x1c, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x22, 0xae, 0x01,
|
||||
0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3a, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20,
|
||||
0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x73, 0x33, 0x67, 0x77, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72,
|
||||
0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x52,
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64,
|
||||
0x79, 0x12, 0x35, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02,
|
||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x73, 0x33, 0x67, 0x77, 0x2e, 0x63, 0x6f, 0x6e, 0x74,
|
||||
0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73,
|
||||
0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x24, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79,
|
||||
0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0xae,
|
||||
0x01, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x52,
|
||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x73, 0x33, 0x67, 0x77, 0x2e, 0x63, 0x6f, 0x6e,
|
||||
0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65,
|
||||
0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04,
|
||||
0x62, 0x6f, 0x64, 0x79, 0x12, 0x35, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72,
|
||||
0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x73, 0x33, 0x67, 0x77, 0x2e, 0x63,
|
||||
0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65,
|
||||
0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x22, 0x0a, 0x04, 0x42,
|
||||
0x6f, 0x64, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x44, 0x73, 0x18,
|
||||
0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x44, 0x73, 0x2a,
|
||||
0x57, 0x0a, 0x0c, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12,
|
||||
0x1b, 0x0a, 0x17, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53,
|
||||
0x5f, 0x55, 0x4e, 0x44, 0x45, 0x46, 0x49, 0x4e, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08,
|
||||
0x53, 0x54, 0x41, 0x52, 0x54, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x52, 0x45,
|
||||
0x41, 0x44, 0x59, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d, 0x53, 0x48, 0x55, 0x54, 0x54, 0x49, 0x4e,
|
||||
0x47, 0x5f, 0x44, 0x4f, 0x57, 0x4e, 0x10, 0x03, 0x32, 0xba, 0x03, 0x0a, 0x0e, 0x43, 0x6f, 0x6e,
|
||||
0x74, 0x72, 0x6f, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x52, 0x0a, 0x0b, 0x48,
|
||||
0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x20, 0x2e, 0x73, 0x33, 0x67,
|
||||
0x77, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68,
|
||||
0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x73,
|
||||
0x33, 0x67, 0x77, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c,
|
||||
0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
|
||||
0x52, 0x0a, 0x0b, 0x50, 0x75, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x12, 0x20,
|
||||
0x2e, 0x73, 0x33, 0x67, 0x77, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x50, 0x75,
|
||||
0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||
0x1a, 0x21, 0x2e, 0x73, 0x33, 0x67, 0x77, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e,
|
||||
0x50, 0x75, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||
0x6e, 0x73, 0x65, 0x12, 0x5b, 0x0a, 0x0e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x50, 0x6f, 0x6c,
|
||||
0x69, 0x63, 0x69, 0x65, 0x73, 0x12, 0x23, 0x2e, 0x73, 0x33, 0x67, 0x77, 0x2e, 0x63, 0x6f, 0x6e,
|
||||
0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63,
|
||||
0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x73, 0x33, 0x67,
|
||||
0x77, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65,
|
||||
0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
||||
0x12, 0x4c, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x1e, 0x2e,
|
||||
0x73, 0x33, 0x67, 0x77, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74,
|
||||
0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e,
|
||||
0x73, 0x33, 0x67, 0x77, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74,
|
||||
0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x55,
|
||||
0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x12, 0x21,
|
||||
0x2e, 0x73, 0x33, 0x67, 0x77, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69,
|
||||
0x73, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||
0x74, 0x1a, 0x22, 0x2e, 0x73, 0x33, 0x67, 0x77, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
|
||||
0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73,
|
||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x41, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, 0x6f,
|
||||
0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, 0x6c,
|
||||
0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, 0x73,
|
||||
0x33, 0x2d, 0x67, 0x77, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
|
||||
0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xec, 0x01, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x50,
|
||||
0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x37, 0x0a, 0x04,
|
||||
0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x73, 0x33, 0x67,
|
||||
0x77, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x6f, 0x6c,
|
||||
0x69, 0x63, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52,
|
||||
0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x35, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75,
|
||||
0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x73, 0x33, 0x67, 0x77, 0x2e,
|
||||
0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72,
|
||||
0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x68, 0x0a, 0x04,
|
||||
0x42, 0x6f, 0x64, 0x79, 0x12, 0x32, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01,
|
||||
0x20, 0x01, 0x28, 0x0e, 0x32, 0x1a, 0x2e, 0x73, 0x33, 0x67, 0x77, 0x2e, 0x63, 0x6f, 0x6e, 0x74,
|
||||
0x72, 0x6f, 0x6c, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74,
|
||||
0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65,
|
||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07,
|
||||
0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x44, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63,
|
||||
0x68, 0x61, 0x69, 0x6e, 0x49, 0x44, 0x22, 0xa2, 0x01, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x50, 0x6f,
|
||||
0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x04,
|
||||
0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x73, 0x33, 0x67,
|
||||
0x77, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x6f, 0x6c,
|
||||
0x69, 0x63, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79,
|
||||
0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x35, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74,
|
||||
0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x73, 0x33, 0x67, 0x77,
|
||||
0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75,
|
||||
0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x1c, 0x0a,
|
||||
0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, 0x01,
|
||||
0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x22, 0xd8, 0x01, 0x0a, 0x13,
|
||||
0x4c, 0x69, 0x73, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75,
|
||||
0x65, 0x73, 0x74, 0x12, 0x3a, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||
0x0b, 0x32, 0x26, 0x2e, 0x73, 0x33, 0x67, 0x77, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
|
||||
0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71,
|
||||
0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12,
|
||||
0x35, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01,
|
||||
0x28, 0x0b, 0x32, 0x17, 0x2e, 0x73, 0x33, 0x67, 0x77, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f,
|
||||
0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67,
|
||||
0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x4e, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x32,
|
||||
0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1a,
|
||||
0x2e, 0x73, 0x33, 0x67, 0x77, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x50, 0x6f,
|
||||
0x6c, 0x69, 0x63, 0x79, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67,
|
||||
0x65, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0xae, 0x01, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x50,
|
||||
0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
|
||||
0x3b, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e,
|
||||
0x73, 0x33, 0x67, 0x77, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73,
|
||||
0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
||||
0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x35, 0x0a, 0x09,
|
||||
0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
|
||||
0x17, 0x2e, 0x73, 0x33, 0x67, 0x77, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53,
|
||||
0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74,
|
||||
0x75, 0x72, 0x65, 0x1a, 0x22, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x63,
|
||||
0x68, 0x61, 0x69, 0x6e, 0x49, 0x44, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x08, 0x63,
|
||||
0x68, 0x61, 0x69, 0x6e, 0x49, 0x44, 0x73, 0x2a, 0x57, 0x0a, 0x0c, 0x48, 0x65, 0x61, 0x6c, 0x74,
|
||||
0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1b, 0x0a, 0x17, 0x48, 0x45, 0x41, 0x4c, 0x54,
|
||||
0x48, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x44, 0x45, 0x46, 0x49, 0x4e,
|
||||
0x45, 0x44, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x53, 0x54, 0x41, 0x52, 0x54, 0x49, 0x4e, 0x47,
|
||||
0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x52, 0x45, 0x41, 0x44, 0x59, 0x10, 0x02, 0x12, 0x11, 0x0a,
|
||||
0x0d, 0x53, 0x48, 0x55, 0x54, 0x54, 0x49, 0x4e, 0x47, 0x5f, 0x44, 0x4f, 0x57, 0x4e, 0x10, 0x03,
|
||||
0x2a, 0x57, 0x0a, 0x0c, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74,
|
||||
0x12, 0x14, 0x0a, 0x10, 0x54, 0x41, 0x52, 0x47, 0x45, 0x54, 0x5f, 0x55, 0x4e, 0x44, 0x45, 0x46,
|
||||
0x49, 0x4e, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x4e, 0x54, 0x41, 0x49,
|
||||
0x4e, 0x45, 0x52, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x4e, 0x41, 0x4d, 0x45, 0x53, 0x50, 0x41,
|
||||
0x43, 0x45, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x55, 0x53, 0x45, 0x52, 0x10, 0x03, 0x12, 0x09,
|
||||
0x0a, 0x05, 0x47, 0x52, 0x4f, 0x55, 0x50, 0x10, 0x04, 0x32, 0xba, 0x03, 0x0a, 0x0e, 0x43, 0x6f,
|
||||
0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x52, 0x0a, 0x0b,
|
||||
0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x20, 0x2e, 0x73, 0x33,
|
||||
0x67, 0x77, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74,
|
||||
0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e,
|
||||
0x73, 0x33, 0x67, 0x77, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61,
|
||||
0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
||||
0x12, 0x52, 0x0a, 0x0b, 0x50, 0x75, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x12,
|
||||
0x20, 0x2e, 0x73, 0x33, 0x67, 0x77, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x50,
|
||||
0x75, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||
0x74, 0x1a, 0x21, 0x2e, 0x73, 0x33, 0x67, 0x77, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
|
||||
0x2e, 0x50, 0x75, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70,
|
||||
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5b, 0x0a, 0x0e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x50, 0x6f,
|
||||
0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x12, 0x23, 0x2e, 0x73, 0x33, 0x67, 0x77, 0x2e, 0x63, 0x6f,
|
||||
0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x50, 0x6f, 0x6c, 0x69,
|
||||
0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x73, 0x33,
|
||||
0x67, 0x77, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76,
|
||||
0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
||||
0x65, 0x12, 0x4c, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x1e,
|
||||
0x2e, 0x73, 0x33, 0x67, 0x77, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65,
|
||||
0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f,
|
||||
0x2e, 0x73, 0x33, 0x67, 0x77, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65,
|
||||
0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
|
||||
0x55, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x12,
|
||||
0x21, 0x2e, 0x73, 0x33, 0x67, 0x77, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c,
|
||||
0x69, 0x73, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
|
||||
0x73, 0x74, 0x1a, 0x22, 0x2e, 0x73, 0x33, 0x67, 0x77, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f,
|
||||
0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65,
|
||||
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x41, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72,
|
||||
0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43,
|
||||
0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d,
|
||||
0x73, 0x33, 0x2d, 0x67, 0x77, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
|
||||
0x65, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
||||
0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
@ -1458,73 +1572,78 @@ func file_pkg_service_control_service_proto_rawDescGZIP() []byte {
|
|||
return file_pkg_service_control_service_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_pkg_service_control_service_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
|
||||
var file_pkg_service_control_service_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
|
||||
var file_pkg_service_control_service_proto_msgTypes = make([]protoimpl.MessageInfo, 23)
|
||||
var file_pkg_service_control_service_proto_goTypes = []interface{}{
|
||||
(HealthStatus)(0), // 0: s3gw.control.HealthStatus
|
||||
(*Signature)(nil), // 1: s3gw.control.Signature
|
||||
(*HealthCheckRequest)(nil), // 2: s3gw.control.HealthCheckRequest
|
||||
(*HealthCheckResponse)(nil), // 3: s3gw.control.HealthCheckResponse
|
||||
(*PutPoliciesRequest)(nil), // 4: s3gw.control.PutPoliciesRequest
|
||||
(*PutPoliciesResponse)(nil), // 5: s3gw.control.PutPoliciesResponse
|
||||
(*RemovePoliciesRequest)(nil), // 6: s3gw.control.RemovePoliciesRequest
|
||||
(*RemovePoliciesResponse)(nil), // 7: s3gw.control.RemovePoliciesResponse
|
||||
(*GetPolicyRequest)(nil), // 8: s3gw.control.GetPolicyRequest
|
||||
(*GetPolicyResponse)(nil), // 9: s3gw.control.GetPolicyResponse
|
||||
(*ListPoliciesRequest)(nil), // 10: s3gw.control.ListPoliciesRequest
|
||||
(*ListPoliciesResponse)(nil), // 11: s3gw.control.ListPoliciesResponse
|
||||
(*HealthCheckRequest_Body)(nil), // 12: s3gw.control.HealthCheckRequest.Body
|
||||
(*HealthCheckResponse_Body)(nil), // 13: s3gw.control.HealthCheckResponse.Body
|
||||
(*PutPoliciesRequest_ChainData)(nil), // 14: s3gw.control.PutPoliciesRequest.ChainData
|
||||
(*PutPoliciesRequest_Body)(nil), // 15: s3gw.control.PutPoliciesRequest.Body
|
||||
(*PutPoliciesResponse_Body)(nil), // 16: s3gw.control.PutPoliciesResponse.Body
|
||||
(*RemovePoliciesRequest_ChainInfo)(nil), // 17: s3gw.control.RemovePoliciesRequest.ChainInfo
|
||||
(*RemovePoliciesRequest_Body)(nil), // 18: s3gw.control.RemovePoliciesRequest.Body
|
||||
(*RemovePoliciesResponse_Body)(nil), // 19: s3gw.control.RemovePoliciesResponse.Body
|
||||
(*GetPolicyRequest_Body)(nil), // 20: s3gw.control.GetPolicyRequest.Body
|
||||
(*GetPolicyResponse_Body)(nil), // 21: s3gw.control.GetPolicyResponse.Body
|
||||
(*ListPoliciesRequest_Body)(nil), // 22: s3gw.control.ListPoliciesRequest.Body
|
||||
(*ListPoliciesResponse_Body)(nil), // 23: s3gw.control.ListPoliciesResponse.Body
|
||||
(PolicyTarget)(0), // 1: s3gw.control.PolicyTarget
|
||||
(*Signature)(nil), // 2: s3gw.control.Signature
|
||||
(*HealthCheckRequest)(nil), // 3: s3gw.control.HealthCheckRequest
|
||||
(*HealthCheckResponse)(nil), // 4: s3gw.control.HealthCheckResponse
|
||||
(*PutPoliciesRequest)(nil), // 5: s3gw.control.PutPoliciesRequest
|
||||
(*PutPoliciesResponse)(nil), // 6: s3gw.control.PutPoliciesResponse
|
||||
(*RemovePoliciesRequest)(nil), // 7: s3gw.control.RemovePoliciesRequest
|
||||
(*RemovePoliciesResponse)(nil), // 8: s3gw.control.RemovePoliciesResponse
|
||||
(*GetPolicyRequest)(nil), // 9: s3gw.control.GetPolicyRequest
|
||||
(*GetPolicyResponse)(nil), // 10: s3gw.control.GetPolicyResponse
|
||||
(*ListPoliciesRequest)(nil), // 11: s3gw.control.ListPoliciesRequest
|
||||
(*ListPoliciesResponse)(nil), // 12: s3gw.control.ListPoliciesResponse
|
||||
(*HealthCheckRequest_Body)(nil), // 13: s3gw.control.HealthCheckRequest.Body
|
||||
(*HealthCheckResponse_Body)(nil), // 14: s3gw.control.HealthCheckResponse.Body
|
||||
(*PutPoliciesRequest_ChainData)(nil), // 15: s3gw.control.PutPoliciesRequest.ChainData
|
||||
(*PutPoliciesRequest_Body)(nil), // 16: s3gw.control.PutPoliciesRequest.Body
|
||||
(*PutPoliciesResponse_Body)(nil), // 17: s3gw.control.PutPoliciesResponse.Body
|
||||
(*RemovePoliciesRequest_ChainInfo)(nil), // 18: s3gw.control.RemovePoliciesRequest.ChainInfo
|
||||
(*RemovePoliciesRequest_Body)(nil), // 19: s3gw.control.RemovePoliciesRequest.Body
|
||||
(*RemovePoliciesResponse_Body)(nil), // 20: s3gw.control.RemovePoliciesResponse.Body
|
||||
(*GetPolicyRequest_Body)(nil), // 21: s3gw.control.GetPolicyRequest.Body
|
||||
(*GetPolicyResponse_Body)(nil), // 22: s3gw.control.GetPolicyResponse.Body
|
||||
(*ListPoliciesRequest_Body)(nil), // 23: s3gw.control.ListPoliciesRequest.Body
|
||||
(*ListPoliciesResponse_Body)(nil), // 24: s3gw.control.ListPoliciesResponse.Body
|
||||
}
|
||||
var file_pkg_service_control_service_proto_depIdxs = []int32{
|
||||
12, // 0: s3gw.control.HealthCheckRequest.body:type_name -> s3gw.control.HealthCheckRequest.Body
|
||||
1, // 1: s3gw.control.HealthCheckRequest.signature:type_name -> s3gw.control.Signature
|
||||
13, // 2: s3gw.control.HealthCheckResponse.body:type_name -> s3gw.control.HealthCheckResponse.Body
|
||||
1, // 3: s3gw.control.HealthCheckResponse.signature:type_name -> s3gw.control.Signature
|
||||
15, // 4: s3gw.control.PutPoliciesRequest.body:type_name -> s3gw.control.PutPoliciesRequest.Body
|
||||
1, // 5: s3gw.control.PutPoliciesRequest.signature:type_name -> s3gw.control.Signature
|
||||
16, // 6: s3gw.control.PutPoliciesResponse.body:type_name -> s3gw.control.PutPoliciesResponse.Body
|
||||
1, // 7: s3gw.control.PutPoliciesResponse.signature:type_name -> s3gw.control.Signature
|
||||
18, // 8: s3gw.control.RemovePoliciesRequest.body:type_name -> s3gw.control.RemovePoliciesRequest.Body
|
||||
1, // 9: s3gw.control.RemovePoliciesRequest.signature:type_name -> s3gw.control.Signature
|
||||
19, // 10: s3gw.control.RemovePoliciesResponse.body:type_name -> s3gw.control.RemovePoliciesResponse.Body
|
||||
1, // 11: s3gw.control.RemovePoliciesResponse.signature:type_name -> s3gw.control.Signature
|
||||
20, // 12: s3gw.control.GetPolicyRequest.body:type_name -> s3gw.control.GetPolicyRequest.Body
|
||||
1, // 13: s3gw.control.GetPolicyRequest.signature:type_name -> s3gw.control.Signature
|
||||
21, // 14: s3gw.control.GetPolicyResponse.body:type_name -> s3gw.control.GetPolicyResponse.Body
|
||||
1, // 15: s3gw.control.GetPolicyResponse.signature:type_name -> s3gw.control.Signature
|
||||
22, // 16: s3gw.control.ListPoliciesRequest.body:type_name -> s3gw.control.ListPoliciesRequest.Body
|
||||
1, // 17: s3gw.control.ListPoliciesRequest.signature:type_name -> s3gw.control.Signature
|
||||
23, // 18: s3gw.control.ListPoliciesResponse.body:type_name -> s3gw.control.ListPoliciesResponse.Body
|
||||
1, // 19: s3gw.control.ListPoliciesResponse.signature:type_name -> s3gw.control.Signature
|
||||
13, // 0: s3gw.control.HealthCheckRequest.body:type_name -> s3gw.control.HealthCheckRequest.Body
|
||||
2, // 1: s3gw.control.HealthCheckRequest.signature:type_name -> s3gw.control.Signature
|
||||
14, // 2: s3gw.control.HealthCheckResponse.body:type_name -> s3gw.control.HealthCheckResponse.Body
|
||||
2, // 3: s3gw.control.HealthCheckResponse.signature:type_name -> s3gw.control.Signature
|
||||
16, // 4: s3gw.control.PutPoliciesRequest.body:type_name -> s3gw.control.PutPoliciesRequest.Body
|
||||
2, // 5: s3gw.control.PutPoliciesRequest.signature:type_name -> s3gw.control.Signature
|
||||
17, // 6: s3gw.control.PutPoliciesResponse.body:type_name -> s3gw.control.PutPoliciesResponse.Body
|
||||
2, // 7: s3gw.control.PutPoliciesResponse.signature:type_name -> s3gw.control.Signature
|
||||
19, // 8: s3gw.control.RemovePoliciesRequest.body:type_name -> s3gw.control.RemovePoliciesRequest.Body
|
||||
2, // 9: s3gw.control.RemovePoliciesRequest.signature:type_name -> s3gw.control.Signature
|
||||
20, // 10: s3gw.control.RemovePoliciesResponse.body:type_name -> s3gw.control.RemovePoliciesResponse.Body
|
||||
2, // 11: s3gw.control.RemovePoliciesResponse.signature:type_name -> s3gw.control.Signature
|
||||
21, // 12: s3gw.control.GetPolicyRequest.body:type_name -> s3gw.control.GetPolicyRequest.Body
|
||||
2, // 13: s3gw.control.GetPolicyRequest.signature:type_name -> s3gw.control.Signature
|
||||
22, // 14: s3gw.control.GetPolicyResponse.body:type_name -> s3gw.control.GetPolicyResponse.Body
|
||||
2, // 15: s3gw.control.GetPolicyResponse.signature:type_name -> s3gw.control.Signature
|
||||
23, // 16: s3gw.control.ListPoliciesRequest.body:type_name -> s3gw.control.ListPoliciesRequest.Body
|
||||
2, // 17: s3gw.control.ListPoliciesRequest.signature:type_name -> s3gw.control.Signature
|
||||
24, // 18: s3gw.control.ListPoliciesResponse.body:type_name -> s3gw.control.ListPoliciesResponse.Body
|
||||
2, // 19: s3gw.control.ListPoliciesResponse.signature:type_name -> s3gw.control.Signature
|
||||
0, // 20: s3gw.control.HealthCheckResponse.Body.health_status:type_name -> s3gw.control.HealthStatus
|
||||
14, // 21: s3gw.control.PutPoliciesRequest.Body.chainDatas:type_name -> s3gw.control.PutPoliciesRequest.ChainData
|
||||
17, // 22: s3gw.control.RemovePoliciesRequest.Body.chainInfos:type_name -> s3gw.control.RemovePoliciesRequest.ChainInfo
|
||||
2, // 23: s3gw.control.ControlService.HealthCheck:input_type -> s3gw.control.HealthCheckRequest
|
||||
4, // 24: s3gw.control.ControlService.PutPolicies:input_type -> s3gw.control.PutPoliciesRequest
|
||||
6, // 25: s3gw.control.ControlService.RemovePolicies:input_type -> s3gw.control.RemovePoliciesRequest
|
||||
8, // 26: s3gw.control.ControlService.GetPolicy:input_type -> s3gw.control.GetPolicyRequest
|
||||
10, // 27: s3gw.control.ControlService.ListPolicies:input_type -> s3gw.control.ListPoliciesRequest
|
||||
3, // 28: s3gw.control.ControlService.HealthCheck:output_type -> s3gw.control.HealthCheckResponse
|
||||
5, // 29: s3gw.control.ControlService.PutPolicies:output_type -> s3gw.control.PutPoliciesResponse
|
||||
7, // 30: s3gw.control.ControlService.RemovePolicies:output_type -> s3gw.control.RemovePoliciesResponse
|
||||
9, // 31: s3gw.control.ControlService.GetPolicy:output_type -> s3gw.control.GetPolicyResponse
|
||||
11, // 32: s3gw.control.ControlService.ListPolicies:output_type -> s3gw.control.ListPoliciesResponse
|
||||
28, // [28:33] is the sub-list for method output_type
|
||||
23, // [23:28] is the sub-list for method input_type
|
||||
23, // [23:23] is the sub-list for extension type_name
|
||||
23, // [23:23] is the sub-list for extension extendee
|
||||
0, // [0:23] is the sub-list for field type_name
|
||||
1, // 21: s3gw.control.PutPoliciesRequest.ChainData.target:type_name -> s3gw.control.PolicyTarget
|
||||
15, // 22: s3gw.control.PutPoliciesRequest.Body.chainDatas:type_name -> s3gw.control.PutPoliciesRequest.ChainData
|
||||
1, // 23: s3gw.control.RemovePoliciesRequest.ChainInfo.target:type_name -> s3gw.control.PolicyTarget
|
||||
18, // 24: s3gw.control.RemovePoliciesRequest.Body.chainInfos:type_name -> s3gw.control.RemovePoliciesRequest.ChainInfo
|
||||
1, // 25: s3gw.control.GetPolicyRequest.Body.target:type_name -> s3gw.control.PolicyTarget
|
||||
1, // 26: s3gw.control.ListPoliciesRequest.Body.target:type_name -> s3gw.control.PolicyTarget
|
||||
3, // 27: s3gw.control.ControlService.HealthCheck:input_type -> s3gw.control.HealthCheckRequest
|
||||
5, // 28: s3gw.control.ControlService.PutPolicies:input_type -> s3gw.control.PutPoliciesRequest
|
||||
7, // 29: s3gw.control.ControlService.RemovePolicies:input_type -> s3gw.control.RemovePoliciesRequest
|
||||
9, // 30: s3gw.control.ControlService.GetPolicy:input_type -> s3gw.control.GetPolicyRequest
|
||||
11, // 31: s3gw.control.ControlService.ListPolicies:input_type -> s3gw.control.ListPoliciesRequest
|
||||
4, // 32: s3gw.control.ControlService.HealthCheck:output_type -> s3gw.control.HealthCheckResponse
|
||||
6, // 33: s3gw.control.ControlService.PutPolicies:output_type -> s3gw.control.PutPoliciesResponse
|
||||
8, // 34: s3gw.control.ControlService.RemovePolicies:output_type -> s3gw.control.RemovePoliciesResponse
|
||||
10, // 35: s3gw.control.ControlService.GetPolicy:output_type -> s3gw.control.GetPolicyResponse
|
||||
12, // 36: s3gw.control.ControlService.ListPolicies:output_type -> s3gw.control.ListPoliciesResponse
|
||||
32, // [32:37] is the sub-list for method output_type
|
||||
27, // [27:32] is the sub-list for method input_type
|
||||
27, // [27:27] is the sub-list for extension type_name
|
||||
27, // [27:27] is the sub-list for extension extendee
|
||||
0, // [0:27] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_pkg_service_control_service_proto_init() }
|
||||
|
@ -1815,7 +1934,7 @@ func file_pkg_service_control_service_proto_init() {
|
|||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_pkg_service_control_service_proto_rawDesc,
|
||||
NumEnums: 1,
|
||||
NumEnums: 2,
|
||||
NumMessages: 23,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
|
|
|
@ -69,13 +69,33 @@ enum HealthStatus {
|
|||
SHUTTING_DOWN = 3;
|
||||
}
|
||||
|
||||
// Policy target to store chains.
|
||||
enum PolicyTarget {
|
||||
// Undefined target, invalid to use.
|
||||
TARGET_UNDEFINED = 0;
|
||||
|
||||
// Container target for bucket policies.
|
||||
CONTAINER = 1;
|
||||
|
||||
// Namespace target for namespace policies.
|
||||
NAMESPACE = 2;
|
||||
|
||||
// User target for namespace user policies.
|
||||
USER = 3;
|
||||
|
||||
// Group target for namespace target policies.
|
||||
GROUP = 4;
|
||||
}
|
||||
|
||||
// Put policies request.
|
||||
message PutPoliciesRequest {
|
||||
message ChainData {
|
||||
// Namespace.
|
||||
string namespace = 1;
|
||||
// Policy entity type.
|
||||
PolicyTarget target = 1;
|
||||
// Policy name.
|
||||
string name = 2;
|
||||
// Chain rules.
|
||||
bytes chain = 2;
|
||||
bytes chain = 3;
|
||||
}
|
||||
|
||||
message Body {
|
||||
|
@ -101,10 +121,12 @@ message PutPoliciesResponse {
|
|||
// Remove policies request.
|
||||
message RemovePoliciesRequest {
|
||||
message ChainInfo {
|
||||
// Namespace.
|
||||
string namespace = 1;
|
||||
// Policy entity type.
|
||||
PolicyTarget target = 1;
|
||||
// Policy name.
|
||||
string name = 2;
|
||||
// Chain id to remove.
|
||||
bytes chainID = 2;
|
||||
bytes chainID = 3;
|
||||
}
|
||||
|
||||
message Body {
|
||||
|
@ -130,10 +152,12 @@ message RemovePoliciesResponse {
|
|||
// Get policy request.
|
||||
message GetPolicyRequest {
|
||||
message Body {
|
||||
// Namespace.
|
||||
string namespace = 1;
|
||||
// Chain id to remove.
|
||||
bytes chainID = 2;
|
||||
// Policy entity type.
|
||||
PolicyTarget target = 1;
|
||||
// Policy name.
|
||||
string name = 2;
|
||||
// Chain id to get.
|
||||
bytes chainID = 3;
|
||||
}
|
||||
|
||||
Body body = 1;
|
||||
|
@ -157,8 +181,10 @@ message GetPolicyResponse {
|
|||
// List policies request.
|
||||
message ListPoliciesRequest {
|
||||
message Body {
|
||||
// Namespace.
|
||||
string namespace = 1;
|
||||
// Policy entity type.
|
||||
PolicyTarget target = 1;
|
||||
// Policy name.
|
||||
string name = 2;
|
||||
}
|
||||
|
||||
Body body = 1;
|
||||
|
|
|
@ -207,8 +207,9 @@ func (x *PutPoliciesRequest_ChainData) StableSize() (size int) {
|
|||
if x == nil {
|
||||
return 0
|
||||
}
|
||||
size += proto.StringSize(1, x.Namespace)
|
||||
size += proto.BytesSize(2, x.Chain)
|
||||
size += proto.EnumSize(1, int32(x.Target))
|
||||
size += proto.StringSize(2, x.Name)
|
||||
size += proto.BytesSize(3, x.Chain)
|
||||
return size
|
||||
}
|
||||
|
||||
|
@ -228,8 +229,9 @@ func (x *PutPoliciesRequest_ChainData) StableMarshal(buf []byte) []byte {
|
|||
buf = make([]byte, x.StableSize())
|
||||
}
|
||||
var offset int
|
||||
offset += proto.StringMarshal(1, buf[offset:], x.Namespace)
|
||||
offset += proto.BytesMarshal(2, buf[offset:], x.Chain)
|
||||
offset += proto.EnumMarshal(1, buf[offset:], int32(x.Target))
|
||||
offset += proto.StringMarshal(2, buf[offset:], x.Name)
|
||||
offset += proto.BytesMarshal(3, buf[offset:], x.Chain)
|
||||
return buf
|
||||
}
|
||||
|
||||
|
@ -407,8 +409,9 @@ func (x *RemovePoliciesRequest_ChainInfo) StableSize() (size int) {
|
|||
if x == nil {
|
||||
return 0
|
||||
}
|
||||
size += proto.StringSize(1, x.Namespace)
|
||||
size += proto.BytesSize(2, x.ChainID)
|
||||
size += proto.EnumSize(1, int32(x.Target))
|
||||
size += proto.StringSize(2, x.Name)
|
||||
size += proto.BytesSize(3, x.ChainID)
|
||||
return size
|
||||
}
|
||||
|
||||
|
@ -428,8 +431,9 @@ func (x *RemovePoliciesRequest_ChainInfo) StableMarshal(buf []byte) []byte {
|
|||
buf = make([]byte, x.StableSize())
|
||||
}
|
||||
var offset int
|
||||
offset += proto.StringMarshal(1, buf[offset:], x.Namespace)
|
||||
offset += proto.BytesMarshal(2, buf[offset:], x.ChainID)
|
||||
offset += proto.EnumMarshal(1, buf[offset:], int32(x.Target))
|
||||
offset += proto.StringMarshal(2, buf[offset:], x.Name)
|
||||
offset += proto.BytesMarshal(3, buf[offset:], x.ChainID)
|
||||
return buf
|
||||
}
|
||||
|
||||
|
@ -607,8 +611,9 @@ func (x *GetPolicyRequest_Body) StableSize() (size int) {
|
|||
if x == nil {
|
||||
return 0
|
||||
}
|
||||
size += proto.StringSize(1, x.Namespace)
|
||||
size += proto.BytesSize(2, x.ChainID)
|
||||
size += proto.EnumSize(1, int32(x.Target))
|
||||
size += proto.StringSize(2, x.Name)
|
||||
size += proto.BytesSize(3, x.ChainID)
|
||||
return size
|
||||
}
|
||||
|
||||
|
@ -628,8 +633,9 @@ func (x *GetPolicyRequest_Body) StableMarshal(buf []byte) []byte {
|
|||
buf = make([]byte, x.StableSize())
|
||||
}
|
||||
var offset int
|
||||
offset += proto.StringMarshal(1, buf[offset:], x.Namespace)
|
||||
offset += proto.BytesMarshal(2, buf[offset:], x.ChainID)
|
||||
offset += proto.EnumMarshal(1, buf[offset:], int32(x.Target))
|
||||
offset += proto.StringMarshal(2, buf[offset:], x.Name)
|
||||
offset += proto.BytesMarshal(3, buf[offset:], x.ChainID)
|
||||
return buf
|
||||
}
|
||||
|
||||
|
@ -781,7 +787,8 @@ func (x *ListPoliciesRequest_Body) StableSize() (size int) {
|
|||
if x == nil {
|
||||
return 0
|
||||
}
|
||||
size += proto.StringSize(1, x.Namespace)
|
||||
size += proto.EnumSize(1, int32(x.Target))
|
||||
size += proto.StringSize(2, x.Name)
|
||||
return size
|
||||
}
|
||||
|
||||
|
@ -801,7 +808,8 @@ func (x *ListPoliciesRequest_Body) StableMarshal(buf []byte) []byte {
|
|||
buf = make([]byte, x.StableSize())
|
||||
}
|
||||
var offset int
|
||||
offset += proto.StringMarshal(1, buf[offset:], x.Namespace)
|
||||
offset += proto.EnumMarshal(1, buf[offset:], int32(x.Target))
|
||||
offset += proto.StringMarshal(2, buf[offset:], x.Name)
|
||||
return buf
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.2.0
|
||||
// - protoc v3.21.9
|
||||
// - protoc v3.21.12
|
||||
// source: pkg/service/control/service.proto
|
||||
|
||||
package control
|
||||
|
|
|
@ -610,7 +610,7 @@ func (c *Tree) GetVersions(ctx context.Context, bktInfo *data.BucketInfo, filepa
|
|||
}
|
||||
|
||||
func (c *Tree) GetLatestVersion(ctx context.Context, bktInfo *data.BucketInfo, objectName string) (*data.NodeVersion, error) {
|
||||
meta := []string{oidKV, isUnversionedKV, isDeleteMarkerKV, etagKV, sizeKV, md5KV}
|
||||
meta := []string{oidKV, isCombinedKV, isUnversionedKV, isDeleteMarkerKV, etagKV, sizeKV, md5KV}
|
||||
path := pathFromName(objectName)
|
||||
|
||||
p := &GetNodesParams{
|
||||
|
@ -1375,7 +1375,7 @@ func (c *Tree) clearOutdatedVersionInfo(ctx context.Context, bktInfo *data.Bucke
|
|||
}
|
||||
|
||||
func (c *Tree) getVersions(ctx context.Context, bktInfo *data.BucketInfo, treeID, filepath string, onlyUnversioned bool) ([]*data.NodeVersion, error) {
|
||||
keysToReturn := []string{oidKV, isUnversionedKV, isDeleteMarkerKV, etagKV, sizeKV, md5KV}
|
||||
keysToReturn := []string{oidKV, isCombinedKV, isUnversionedKV, isDeleteMarkerKV, etagKV, sizeKV, md5KV}
|
||||
path := pathFromName(filepath)
|
||||
p := &GetNodesParams{
|
||||
BktInfo: bktInfo,
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"time"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
type nodeMeta struct {
|
||||
|
@ -184,6 +185,22 @@ func NewTreeServiceClientMemory() (*ServiceClientMemory, error) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
type nodeResponseWrapper struct {
|
||||
nodeResponse
|
||||
allAttr bool
|
||||
attrs []string
|
||||
}
|
||||
|
||||
func (n nodeResponseWrapper) GetMeta() []Meta {
|
||||
res := make([]Meta, 0, len(n.meta))
|
||||
for _, value := range n.meta {
|
||||
if n.allAttr || slices.Contains(n.attrs, value.key) {
|
||||
res = append(res, value)
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (c *ServiceClientMemory) GetNodes(_ context.Context, p *GetNodesParams) ([]NodeResponse, error) {
|
||||
cnr, ok := c.containers[p.BktInfo.CID.EncodeToString()]
|
||||
if !ok {
|
||||
|
@ -206,7 +223,11 @@ func (c *ServiceClientMemory) GetNodes(_ context.Context, p *GetNodesParams) ([]
|
|||
|
||||
res2 := make([]NodeResponse, len(res))
|
||||
for i, n := range res {
|
||||
res2[i] = n
|
||||
res2[i] = nodeResponseWrapper{
|
||||
nodeResponse: n,
|
||||
allAttr: p.AllAttrs,
|
||||
attrs: p.Meta,
|
||||
}
|
||||
}
|
||||
|
||||
return res2, nil
|
||||
|
@ -223,8 +244,6 @@ func (c *ServiceClientMemory) GetSubTree(_ context.Context, bktInfo *data.Bucket
|
|||
return nil, ErrNodeNotFound
|
||||
}
|
||||
|
||||
sortNode(tr.treeData)
|
||||
|
||||
node := tr.treeData.getNode(rootID)
|
||||
if node == nil {
|
||||
return nil, ErrNodeNotFound
|
||||
|
|
Loading…
Reference in a new issue