Compare commits

..

15 commits

Author SHA1 Message Date
f02bad65a8 [#362] Check user and groups during policy check
Signed-off-by: Alex Vanin <a.vanin@yadro.com>
2024-04-12 16:52:08 +03:00
13d00dd7ce [#362] Expand control service
Signed-off-by: Alex Vanin <a.vanin@yadro.com>
2024-04-12 16:52:08 +03:00
02122892ca [#362] Update policy-engine to support 'u' and 'g' targets
Signed-off-by: Alex Vanin <a.vanin@yadro.com>
2024-04-12 16:52:08 +03:00
272e3a0f03 [#363] Fix removing combined object
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2024-04-12 14:56:06 +03:00
65a8e2dadc [#360] Reuse single target during policy check
Policy engine library is able to manage multiple
targets and resolve different status results.

Signed-off-by: Alex Vanin <a.vanin@yadro.com>
2024-04-10 17:40:25 +03:00
b7e15402a1 [#360] Use 'c' prefix for bucket policies instead of 'n'
With 'c' prefix, acl chains become shorter, thus gateway
receives shorter results and avoids sessions to neo-go.

There is still issue with many IAM rules.

Signed-off-by: Alex Vanin <a.vanin@yadro.com>
2024-04-10 17:40:25 +03:00
0cc6b41b2d [#358] Update APE to allow put tombstone on delete object
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2024-04-10 15:11:25 +03:00
51be9d9778 [#354] Remove policies when delete bucket
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2024-04-09 17:30:20 +03:00
1cad101609 [#354] Update frostfs-contract to terminate session iterator
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2024-04-09 17:30:10 +03:00
d631ee55c9 [#351] policy: Use iterators to list chains
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2024-04-03 11:32:43 +03:00
85c8210ffd [#347] Explicitly specify sorting order of subtree for object listing
Signed-off-by: Alex Vanin <a.vanin@yadro.com>
2024-04-02 18:14:43 +03:00
bcfbcdc82f [#345] acl: Update APE and fix using
* Remove native policy when remove bucket policy
* Allow policies that contain only s3 compatible statements
(now deny rules cannot be converted to native rules)

Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2024-04-02 12:42:43 +00:00
fd310f5e9f [#343] docs: Actualize s3 compatibility table
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2024-04-02 10:00:44 +03:00
1f5f2bd3d5 [#306] In APE buckets forbid canned acl except private
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2024-03-19 16:56:32 +03:00
a32b41716f [#328] Log error on failed response writing
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2024-03-15 11:04:05 +03:00
41 changed files with 575 additions and 2362 deletions

View file

@ -11,7 +11,6 @@ This document outlines major changes between releases.
- Fix possibility of panic during SIGHUP (#288)
- Fix flaky `TestErrorTimeoutChecking` (`make test` sometimes failed) (#290)
- Fix user owner ID in billing metrics (#321)
- Fix HTTP/2 requests (#341)
### Added
- Add new `frostfs.buffer_max_size_for_put` config param and sync TZ hash for PUT operations (#197)
@ -27,8 +26,6 @@ This document outlines major changes between releases.
- Support `policy` contract (#259)
- Support `proxy` contract (#287)
- Authmate: support custom attributes (#292)
- Add new `reconnect_interval` config param (#291)
- Support `GetBucketPolicyStatus` (#301)
### Changed
- Generalise config param `use_default_xmlns_for_complete_multipart` to `use_default_xmlns` so that use default xmlns for all requests (#221)

View file

@ -91,7 +91,6 @@ const (
ErrBucketNotEmpty
ErrAllAccessDisabled
ErrMalformedPolicy
ErrMalformedPolicyNotPrincipal
ErrMissingFields
ErrMissingCredTag
ErrCredMalformed
@ -666,12 +665,6 @@ var errorCodes = errorCodeMap{
Description: "Policy has invalid resource.",
HTTPStatusCode: http.StatusBadRequest,
},
ErrMalformedPolicyNotPrincipal: {
ErrCode: ErrMalformedPolicyNotPrincipal,
Code: "MalformedPolicy",
Description: "Allow with NotPrincipal is not allowed.",
HTTPStatusCode: http.StatusBadRequest,
},
ErrMissingFields: {
ErrCode: ErrMissingFields,
Code: "MissingFields",

View file

@ -650,48 +650,6 @@ func (h *handler) PutObjectACLHandler(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
}
func (h *handler) GetBucketPolicyStatusHandler(w http.ResponseWriter, r *http.Request) {
reqInfo := middleware.GetReqInfo(r.Context())
bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName)
if err != nil {
h.logAndSendError(w, "could not get bucket info", reqInfo, err)
return
}
jsonPolicy, err := h.ape.GetBucketPolicy(reqInfo.Namespace, bktInfo.CID)
if err != nil {
if strings.Contains(err.Error(), "not found") {
err = fmt.Errorf("%w: %s", errors.GetAPIError(errors.ErrNoSuchBucketPolicy), err.Error())
}
h.logAndSendError(w, "failed to get policy from storage", reqInfo, err)
return
}
var bktPolicy engineiam.Policy
if err = json.Unmarshal(jsonPolicy, &bktPolicy); err != nil {
h.logAndSendError(w, "could not parse bucket policy", reqInfo, err)
return
}
policyStatus := &PolicyStatus{
IsPublic: PolicyStatusIsPublicFalse,
}
for _, st := range bktPolicy.Statement {
// https://docs.aws.amazon.com/AmazonS3/latest/userguide/access-control-block-public-access.html#access-control-block-public-access-policy-status
if _, ok := st.Principal[engineiam.Wildcard]; ok {
policyStatus.IsPublic = PolicyStatusIsPublicTrue
break
}
}
if err = middleware.EncodeToResponse(w, policyStatus); err != nil {
h.logAndSendError(w, "encode and write response", reqInfo, err)
return
}
}
func (h *handler) GetBucketPolicyHandler(w http.ResponseWriter, r *http.Request) {
reqInfo := middleware.GetReqInfo(r.Context())
@ -774,11 +732,6 @@ func (h *handler) PutBucketPolicyHandler(w http.ResponseWriter, r *http.Request)
return
}
if len(stat.NotPrincipal) != 0 && stat.Effect == engineiam.AllowEffect {
h.logAndSendError(w, "invalid NotPrincipal", reqInfo, errors.GetAPIError(errors.ErrMalformedPolicyNotPrincipal))
return
}
for _, resource := range stat.Resource {
if reqInfo.BucketName != strings.Split(strings.TrimPrefix(resource, arnAwsPrefix), "/")[0] {
h.logAndSendError(w, "policy resource mismatched bucket", reqInfo, errors.GetAPIError(errors.ErrMalformedPolicy))
@ -1630,26 +1583,6 @@ func isWriteOperation(op eacl.Operation) bool {
return op == eacl.OperationDelete || op == eacl.OperationPut
}
type access struct {
recipient string
operations []eacl.Operation
}
type accessList struct {
list []access
}
func (c *accessList) addAccess(recipient string, operation eacl.Operation) {
for i, v := range c.list {
if v.recipient == recipient {
c.list[i].operations = append(c.list[i].operations, operation)
return
}
}
c.list = append(c.list, access{recipient, []eacl.Operation{operation}})
}
func (h *handler) encodeObjectACL(ctx context.Context, bucketACL *layer.BucketACL, bucketName, objectVersion string) *AccessControlPolicy {
res := &AccessControlPolicy{
Owner: Owner{
@ -1658,7 +1591,7 @@ func (h *handler) encodeObjectACL(ctx context.Context, bucketACL *layer.BucketAC
},
}
m := &accessList{}
m := make(map[string][]eacl.Operation)
astList := tableToAst(bucketACL.EACL, bucketName)
@ -1673,20 +1606,22 @@ func (h *handler) encodeObjectACL(ctx context.Context, bucketACL *layer.BucketAC
}
if len(op.Users) == 0 {
m.addAccess(allUsersGroup, op.Op)
list := append(m[allUsersGroup], op.Op)
m[allUsersGroup] = list
} else {
for _, user := range op.Users {
m.addAccess(user, op.Op)
list := append(m[user], op.Op)
m[user] = list
}
}
}
}
for _, val := range m.list {
for key, val := range m {
permission := aclFullControl
read := true
for op := eacl.OperationGet; op <= eacl.OperationRangeHash; op++ {
if !contains(val.operations, op) && !isWriteOperation(op) {
if !contains(val, op) && !isWriteOperation(op) {
read = false
}
}
@ -1698,12 +1633,12 @@ func (h *handler) encodeObjectACL(ctx context.Context, bucketACL *layer.BucketAC
}
var grantee *Grantee
if val.recipient == allUsersGroup {
if key == allUsersGroup {
grantee = NewGrantee(acpGroup)
grantee.URI = allUsersGroup
} else {
grantee = NewGrantee(acpCanonicalUser)
grantee.ID = val.recipient
grantee.ID = key
}
grant := &Grant{

View file

@ -7,7 +7,6 @@ import (
"crypto/sha256"
"encoding/hex"
"encoding/json"
"encoding/xml"
"fmt"
"io"
"net/http"
@ -1469,42 +1468,6 @@ func TestBucketPolicy(t *testing.T) {
require.Equal(t, newPolicy, bktPolicy)
}
func TestBucketPolicyStatus(t *testing.T) {
hc := prepareHandlerContext(t)
bktName := "bucket-for-policy"
createTestBucket(hc, bktName)
getBucketPolicy(hc, bktName, s3errors.ErrNoSuchBucketPolicy)
newPolicy := engineiam.Policy{
Version: "2012-10-17",
Statement: []engineiam.Statement{{
NotPrincipal: engineiam.Principal{engineiam.Wildcard: {}},
Effect: engineiam.AllowEffect,
Action: engineiam.Action{"s3:PutObject"},
Resource: engineiam.Resource{arnAwsPrefix + bktName + "/*"},
}},
}
putBucketPolicy(hc, bktName, newPolicy, s3errors.ErrMalformedPolicyNotPrincipal)
newPolicy.Statement[0].NotPrincipal = nil
newPolicy.Statement[0].Principal = map[engineiam.PrincipalType][]string{engineiam.Wildcard: {}}
putBucketPolicy(hc, bktName, newPolicy)
bktPolicyStatus := getBucketPolicyStatus(hc, bktName)
require.True(t, PolicyStatusIsPublicTrue == bktPolicyStatus.IsPublic)
key, err := keys.NewPrivateKey()
require.NoError(t, err)
hc.Handler().frostfsid.(*frostfsidMock).data["devenv"] = key.PublicKey()
newPolicy.Statement[0].Principal = map[engineiam.PrincipalType][]string{engineiam.AWSPrincipalType: {"arn:aws:iam:::user/devenv"}}
putBucketPolicy(hc, bktName, newPolicy)
bktPolicyStatus = getBucketPolicyStatus(hc, bktName)
require.True(t, PolicyStatusIsPublicFalse == bktPolicyStatus.IsPublic)
}
func TestDeleteBucketWithPolicy(t *testing.T) {
hc := prepareHandlerContext(t)
@ -1624,22 +1587,6 @@ func getBucketPolicy(hc *handlerContext, bktName string, errCode ...s3errors.Err
return policy
}
func getBucketPolicyStatus(hc *handlerContext, bktName string, errCode ...s3errors.ErrorCode) PolicyStatus {
w, r := prepareTestRequest(hc, bktName, "", nil)
hc.Handler().GetBucketPolicyStatusHandler(w, r)
var policyStatus PolicyStatus
if len(errCode) == 0 {
assertStatus(hc.t, w, http.StatusOK)
err := xml.NewDecoder(w.Result().Body).Decode(&policyStatus)
require.NoError(hc.t, err)
} else {
assertS3Error(hc.t, w, s3errors.GetAPIError(errCode[0]))
}
return policyStatus
}
func putBucketPolicy(hc *handlerContext, bktName string, bktPolicy engineiam.Policy, errCode ...s3errors.ErrorCode) {
body, err := json.Marshal(bktPolicy)
require.NoError(hc.t, err)

View file

@ -4,10 +4,8 @@ import (
"bytes"
"context"
"crypto/rand"
"encoding/hex"
"encoding/xml"
"errors"
"fmt"
"io"
"net/http"
"net/http/httptest"
@ -179,11 +177,10 @@ func prepareHandlerContextBase(t *testing.T, cacheCfg *layer.CachesConfig) *hand
defaultPolicy: pp,
}
h := &handler{
log: l,
obj: layer.NewLayer(l, tp, layerCfg),
cfg: cfg,
ape: newAPEMock(),
frostfsid: newFrostfsIDMock(),
log: l,
obj: layer.NewLayer(l, tp, layerCfg),
cfg: cfg,
ape: newAPEMock(),
}
return &handlerContext{
@ -310,32 +307,6 @@ func (a *apeMock) SaveACLChains(cid string, chains []*chain.Chain) error {
return nil
}
type frostfsidMock struct {
data map[string]*keys.PublicKey
}
func newFrostfsIDMock() *frostfsidMock {
return &frostfsidMock{data: map[string]*keys.PublicKey{}}
}
func (f *frostfsidMock) GetUserAddress(account, user string) (string, error) {
res, ok := f.data[account+user]
if !ok {
return "", fmt.Errorf("not found")
}
return res.Address(), nil
}
func (f *frostfsidMock) GetUserKey(account, user string) (string, error) {
res, ok := f.data[account+user]
if !ok {
return "", fmt.Errorf("not found")
}
return hex.EncodeToString(res.Bytes()), nil
}
func createTestBucket(hc *handlerContext, bktName string) *data.BucketInfo {
info := createBucket(hc, bktName)
return info.BktInfo

View file

@ -55,19 +55,6 @@ type Bucket struct {
CreationDate string // time string of format "2006-01-02T15:04:05.000Z"
}
// PolicyStatus contains status of bucket policy.
type PolicyStatus struct {
XMLName xml.Name `xml:"http://s3.amazonaws.com/doc/2006-03-01/ PolicyStatus" json:"-"`
IsPublic PolicyStatusIsPublic `xml:"IsPublic"`
}
type PolicyStatusIsPublic string
const (
PolicyStatusIsPublicFalse = "FALSE"
PolicyStatusIsPublicTrue = "TRUE"
)
// AccessControlPolicy contains ACL.
type AccessControlPolicy struct {
XMLName xml.Name `xml:"http://s3.amazonaws.com/doc/2006-03-01/ AccessControlPolicy" json:"-"`

View file

@ -9,7 +9,6 @@ const (
HeadBucketOperation = "HeadBucket"
ListMultipartUploadsOperation = "ListMultipartUploads"
GetBucketLocationOperation = "GetBucketLocation"
GetBucketPolicyStatusOperation = "GetBucketPolicyStatus"
GetBucketPolicyOperation = "GetBucketPolicy"
GetBucketLifecycleOperation = "GetBucketLifecycle"
GetBucketEncryptionOperation = "GetBucketEncryption"
@ -78,7 +77,6 @@ const (
const (
UploadsQuery = "uploads"
LocationQuery = "location"
PolicyStatusQuery = "policyStatus"
PolicyQuery = "policy"
LifecycleQuery = "lifecycle"
EncryptionQuery = "encryption"

View file

@ -20,13 +20,6 @@ import (
"go.uber.org/zap"
)
const (
QueryVersionID = "versionId"
QueryPrefix = "prefix"
QueryDelimiter = "delimiter"
QueryMaxKeys = "max-keys"
)
type PolicySettings interface {
PolicyDenyByDefault() bool
ACLEnabled() bool
@ -67,7 +60,7 @@ 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
}
@ -87,6 +80,19 @@ func policyCheck(r *http.Request, cfg PolicyConfig) error {
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
@ -115,24 +121,25 @@ func policyCheck(r *http.Request, cfg PolicyConfig) error {
return 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,12 +152,15 @@ func getPolicyRequest(r *http.Request, frostfsid FrostFSIDInformer, reqType ReqT
res = fmt.Sprintf(s3.ResourceFormatS3Bucket, bktName)
}
properties := determineProperties(ctx, reqType, op, owner, groups)
reqLogOrDefault(r.Context(), log).Debug(logs.PolicyRequest, zap.String("action", op),
zap.String("resource", res), zap.Any("properties", properties))
zap.String("resource", res), zap.String("owner", owner))
return testutil.NewRequest(op, testutil.NewResource(res, nil), properties), nil
return testutil.NewRequest(op, testutil.NewResource(res, nil),
map[string]string{
s3.PropertyKeyOwner: owner,
common.PropertyKeyFrostFSIDGroupID: chain.FormCondSliceContainsValue(groups),
},
), pk, groups, nil
}
type ReqType int
@ -375,32 +385,3 @@ func determineGeneralOperation(r *http.Request) string {
}
return "UnmatchedOperation"
}
func determineProperties(ctx context.Context, reqType ReqType, op, owner string, groups []string) map[string]string {
res := map[string]string{
s3.PropertyKeyOwner: owner,
common.PropertyKeyFrostFSIDGroupID: chain.FormCondSliceContainsValue(groups),
}
queries := GetReqInfo(ctx).URL.Query()
if reqType == objectType {
if versionID := queries.Get(QueryVersionID); len(versionID) > 0 {
res[s3.PropertyKeyVersionID] = versionID
}
}
if reqType == bucketType && (strings.HasSuffix(op, ListObjectsV1Operation) || strings.HasSuffix(op, ListObjectsV2Operation) ||
strings.HasSuffix(op, ListBucketObjectVersionsOperation) || strings.HasSuffix(op, ListMultipartUploadsOperation)) {
if prefix := queries.Get(QueryPrefix); len(prefix) > 0 {
res[s3.PropertyKeyPrefix] = prefix
}
if delimiter := queries.Get(QueryDelimiter); len(delimiter) > 0 {
res[s3.PropertyKeyDelimiter] = delimiter
}
if maxKeys := queries.Get(QueryMaxKeys); len(maxKeys) > 0 {
res[s3.PropertyKeyMaxKeys] = maxKeys
}
}
return res
}

View file

@ -37,7 +37,6 @@ type (
PutObjectHandler(http.ResponseWriter, *http.Request)
DeleteObjectHandler(http.ResponseWriter, *http.Request)
GetBucketLocationHandler(http.ResponseWriter, *http.Request)
GetBucketPolicyStatusHandler(http.ResponseWriter, *http.Request)
GetBucketPolicyHandler(http.ResponseWriter, *http.Request)
GetBucketLifecycleHandler(http.ResponseWriter, *http.Request)
GetBucketEncryptionHandler(http.ResponseWriter, *http.Request)
@ -231,9 +230,6 @@ func bucketRouter(h Handler, log *zap.Logger) chi.Router {
Add(NewFilter().
Queries(s3middleware.LocationQuery).
Handler(named(s3middleware.GetBucketLocationOperation, h.GetBucketLocationHandler))).
Add(NewFilter().
Queries(s3middleware.PolicyStatusQuery).
Handler(named(s3middleware.GetBucketPolicyStatusOperation, h.GetBucketPolicyStatusHandler))).
Add(NewFilter().
Queries(s3middleware.PolicyQuery).
Handler(named(s3middleware.GetBucketPolicyOperation, h.GetBucketPolicyHandler))).

View file

@ -186,11 +186,6 @@ func (h *handlerMock) GetBucketLocationHandler(http.ResponseWriter, *http.Reques
panic("implement me")
}
func (h *handlerMock) GetBucketPolicyStatusHandler(http.ResponseWriter, *http.Request) {
//TODO implement me
panic("implement me")
}
func (h *handlerMock) GetBucketPolicyHandler(http.ResponseWriter, *http.Request) {
//TODO implement me
panic("implement me")

View file

@ -8,7 +8,6 @@ import (
"net/http"
"net/http/httptest"
"net/url"
"strconv"
"testing"
"time"
@ -272,7 +271,7 @@ func TestACLAPE(t *testing.T) {
listBucketsErr(router, ns, apiErrors.ErrAccessDenied)
// Allow operations and check
allowOperations(router, ns, []string{"s3:CreateBucket", "s3:ListAllMyBuckets"}, nil)
allowOperations(router, ns, []string{"s3:CreateBucket", "s3:ListAllMyBuckets"})
createBucket(router, ns, bktName)
listBuckets(router, ns)
})
@ -298,7 +297,7 @@ func TestACLAPE(t *testing.T) {
listBuckets(router, ns)
// Deny operations and check
denyOperations(router, ns, []string{"s3:CreateBucket", "s3:ListAllMyBuckets"}, nil)
denyOperations(router, ns, []string{"s3:CreateBucket", "s3:ListAllMyBuckets"})
createBucketErr(router, ns, bktName, apiErrors.ErrAccessDenied)
listBucketsErr(router, ns, apiErrors.ErrAccessDenied)
})
@ -346,136 +345,22 @@ func TestACLAPE(t *testing.T) {
})
}
func TestRequestParametersCheck(t *testing.T) {
t.Run("prefix parameter, allow specific value", func(t *testing.T) {
router := prepareRouter(t)
ns, bktName, prefix := "", "bucket", "prefix"
router.middlewareSettings.denyByDefault = true
allowOperations(router, ns, []string{"s3:CreateBucket"}, nil)
createBucket(router, ns, bktName)
// Add policies and check
denyOperations(router, ns, []string{"s3:ListBucket"}, engineiam.Conditions{
engineiam.CondStringNotEquals: engineiam.Condition{s3.PropertyKeyPrefix: []string{prefix}},
})
allowOperations(router, ns, []string{"s3:ListBucket"}, engineiam.Conditions{
engineiam.CondStringEquals: engineiam.Condition{s3.PropertyKeyPrefix: []string{prefix}},
})
listObjectsV1(router, ns, bktName, prefix, "", "")
listObjectsV1Err(router, ns, bktName, "", "", "", apiErrors.ErrAccessDenied)
listObjectsV1Err(router, ns, bktName, "invalid", "", "", apiErrors.ErrAccessDenied)
})
t.Run("delimiter parameter, prohibit specific value", func(t *testing.T) {
router := prepareRouter(t)
ns, bktName, delimiter := "", "bucket", "delimiter"
router.middlewareSettings.denyByDefault = true
allowOperations(router, ns, []string{"s3:CreateBucket"}, nil)
createBucket(router, ns, bktName)
// Add policies and check
denyOperations(router, ns, []string{"s3:ListBucket"}, engineiam.Conditions{
engineiam.CondStringEquals: engineiam.Condition{s3.PropertyKeyDelimiter: []string{delimiter}},
})
allowOperations(router, ns, []string{"s3:ListBucket"}, engineiam.Conditions{
engineiam.CondStringNotEquals: engineiam.Condition{s3.PropertyKeyDelimiter: []string{delimiter}},
})
listObjectsV1(router, ns, bktName, "", "", "")
listObjectsV1(router, ns, bktName, "", "some-delimiter", "")
listObjectsV1Err(router, ns, bktName, "", delimiter, "", apiErrors.ErrAccessDenied)
})
t.Run("max-keys parameter, allow specific value", func(t *testing.T) {
router := prepareRouter(t)
ns, bktName, maxKeys := "", "bucket", 10
router.middlewareSettings.denyByDefault = true
allowOperations(router, ns, []string{"s3:CreateBucket"}, nil)
createBucket(router, ns, bktName)
// Add policies and check
denyOperations(router, ns, []string{"s3:ListBucket"}, engineiam.Conditions{
engineiam.CondNumericNotEquals: engineiam.Condition{s3.PropertyKeyMaxKeys: []string{strconv.Itoa(maxKeys)}},
})
allowOperations(router, ns, []string{"s3:ListBucket"}, engineiam.Conditions{
engineiam.CondNumericEquals: engineiam.Condition{s3.PropertyKeyMaxKeys: []string{strconv.Itoa(maxKeys)}},
})
listObjectsV1(router, ns, bktName, "", "", strconv.Itoa(maxKeys))
listObjectsV1Err(router, ns, bktName, "", "", "", apiErrors.ErrAccessDenied)
listObjectsV1Err(router, ns, bktName, "", "", strconv.Itoa(maxKeys-1), apiErrors.ErrAccessDenied)
listObjectsV1Err(router, ns, bktName, "", "", "invalid", apiErrors.ErrAccessDenied)
})
t.Run("max-keys parameter, allow range of values", func(t *testing.T) {
router := prepareRouter(t)
ns, bktName, maxKeys := "", "bucket", 10
router.middlewareSettings.denyByDefault = true
allowOperations(router, ns, []string{"s3:CreateBucket"}, nil)
createBucket(router, ns, bktName)
// Add policies and check
denyOperations(router, ns, []string{"s3:ListBucket"}, engineiam.Conditions{
engineiam.CondNumericGreaterThan: engineiam.Condition{s3.PropertyKeyMaxKeys: []string{strconv.Itoa(maxKeys)}},
})
allowOperations(router, ns, []string{"s3:ListBucket"}, engineiam.Conditions{
engineiam.CondNumericLessThanEquals: engineiam.Condition{s3.PropertyKeyMaxKeys: []string{strconv.Itoa(maxKeys)}},
})
listObjectsV1(router, ns, bktName, "", "", strconv.Itoa(maxKeys))
listObjectsV1(router, ns, bktName, "", "", strconv.Itoa(maxKeys-1))
listObjectsV1Err(router, ns, bktName, "", "", strconv.Itoa(maxKeys+1), apiErrors.ErrAccessDenied)
})
t.Run("max-keys parameter, prohibit specific value", func(t *testing.T) {
router := prepareRouter(t)
ns, bktName, maxKeys := "", "bucket", 10
router.middlewareSettings.denyByDefault = true
allowOperations(router, ns, []string{"s3:CreateBucket"}, nil)
createBucket(router, ns, bktName)
// Add policies and check
denyOperations(router, ns, []string{"s3:ListBucket"}, engineiam.Conditions{
engineiam.CondNumericEquals: engineiam.Condition{s3.PropertyKeyMaxKeys: []string{strconv.Itoa(maxKeys)}},
})
allowOperations(router, ns, []string{"s3:ListBucket"}, engineiam.Conditions{
engineiam.CondNumericNotEquals: engineiam.Condition{s3.PropertyKeyMaxKeys: []string{strconv.Itoa(maxKeys)}},
})
listObjectsV1(router, ns, bktName, "", "", "")
listObjectsV1(router, ns, bktName, "", "", strconv.Itoa(maxKeys-1))
listObjectsV1Err(router, ns, bktName, "", "", strconv.Itoa(maxKeys), apiErrors.ErrAccessDenied)
})
func allowOperations(router *routerMock, ns string, operations []string) {
addPolicy(router, ns, "allow", engineiam.AllowEffect, operations)
}
func allowOperations(router *routerMock, ns string, operations []string, conditions engineiam.Conditions) {
addPolicy(router, ns, "allow", engineiam.AllowEffect, operations, conditions)
func denyOperations(router *routerMock, ns string, operations []string) {
addPolicy(router, ns, "deny", engineiam.DenyEffect, operations)
}
func denyOperations(router *routerMock, ns string, operations []string, conditions engineiam.Conditions) {
addPolicy(router, ns, "deny", engineiam.DenyEffect, operations, conditions)
}
func addPolicy(router *routerMock, ns string, id string, effect engineiam.Effect, operations []string, conditions engineiam.Conditions) {
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,
Action: engineiam.Action(operations),
Resource: engineiam.Resource{fmt.Sprintf(s3.ResourceFormatS3All)},
Conditions: conditions,
Principal: map[engineiam.PrincipalType][]string{engineiam.Wildcard: {}},
Effect: effect,
Action: engineiam.Action(operations),
Resource: engineiam.Resource{fmt.Sprintf(s3.ResourceFormatS3All)},
}},
}
@ -557,38 +442,6 @@ func putObjectBase(router *routerMock, namespace, bktName, objName string) *http
return w
}
func listObjectsV1(router *routerMock, namespace, bktName, prefix, delimiter, maxKeys string) handlerResult {
w := listObjectsV1Base(router, namespace, bktName, prefix, delimiter, maxKeys)
resp := readResponse(router.t, w)
require.Equal(router.t, s3middleware.ListObjectsV1Operation, resp.Method)
return resp
}
func listObjectsV1Err(router *routerMock, namespace, bktName, prefix, delimiter, maxKeys string, errCode apiErrors.ErrorCode) {
w := listObjectsV1Base(router, namespace, bktName, prefix, delimiter, maxKeys)
assertAPIError(router.t, w, errCode)
}
func listObjectsV1Base(router *routerMock, namespace, bktName, prefix, delimiter, maxKeys string) *httptest.ResponseRecorder {
queries := url.Values{}
if len(prefix) > 0 {
queries.Add(s3middleware.QueryPrefix, prefix)
}
if len(delimiter) > 0 {
queries.Add(s3middleware.QueryDelimiter, delimiter)
}
if len(maxKeys) > 0 {
queries.Add(s3middleware.QueryMaxKeys, maxKeys)
}
encoded := queries.Encode()
w, r := httptest.NewRecorder(), httptest.NewRequest(http.MethodGet, "/"+bktName, nil)
r.URL.RawQuery = encoded
r.Header.Set(FrostfsNamespaceHeader, namespace)
router.ServeHTTP(w, r)
return w
}
func TestOwnerIDRetrieving(t *testing.T) {
chiRouter := prepareRouter(t)

View file

@ -71,9 +71,7 @@ type (
policyStorage *policy.Storage
servers []Server
unbindServers []ServerInfo
mu sync.RWMutex
servers []Server
controlAPI *grpc.Server
@ -90,7 +88,6 @@ type (
logLevel zap.AtomicLevel
maxClient maxClientsConfig
defaultMaxAge int
reconnectInterval time.Duration
notificatorEnabled bool
resolveZoneList []string
isResolveListAllow bool // True if ResolveZoneList contains allowed zones
@ -208,7 +205,6 @@ func newAppSettings(log *Logger, v *viper.Viper, key *keys.PrivateKey) *appSetti
logLevel: log.lvl,
maxClient: newMaxClients(v),
defaultMaxAge: fetchDefaultMaxAge(v, log.logger),
reconnectInterval: fetchReconnectInterval(v),
notificatorEnabled: v.GetBool(cfgEnableNATS),
frostfsidValidation: v.GetBool(cfgFrostfsIDValidationEnabled),
}
@ -703,23 +699,17 @@ func (a *App) Serve(ctx context.Context) {
a.startServices()
servs := a.getServers()
for i := range servs {
for i := range a.servers {
go func(i int) {
a.log.Info(logs.StartingServer, zap.String("address", servs[i].Address()))
a.log.Info(logs.StartingServer, zap.String("address", a.servers[i].Address()))
if err := srv.Serve(servs[i].Listener()); err != nil && err != http.ErrServerClosed {
a.metrics.MarkUnhealthy(servs[i].Address())
if err := srv.Serve(a.servers[i].Listener()); err != nil && err != http.ErrServerClosed {
a.metrics.MarkUnhealthy(a.servers[i].Address())
a.log.Fatal(logs.ListenAndServe, zap.Error(err))
}
}(i)
}
if len(a.unbindServers) != 0 {
a.scheduleReconnect(ctx, srv)
}
go func() {
address := a.cfg.GetString(cfgControlGRPCEndpoint)
a.log.Info(logs.StartingControlAPI, zap.String("address", address))
@ -836,7 +826,7 @@ func (a *App) startServices() {
}
func (a *App) initServers(ctx context.Context) {
serversInfo := fetchServers(a.cfg, a.log)
serversInfo := fetchServers(a.cfg)
a.servers = make([]Server, 0, len(serversInfo))
for _, serverInfo := range serversInfo {
@ -846,7 +836,6 @@ func (a *App) initServers(ctx context.Context) {
}
srv, err := newServer(ctx, serverInfo)
if err != nil {
a.unbindServers = append(a.unbindServers, serverInfo)
a.metrics.MarkUnhealthy(serverInfo.Address)
a.log.Warn(logs.FailedToAddServer, append(fields, zap.Error(err))...)
continue
@ -863,24 +852,21 @@ func (a *App) initServers(ctx context.Context) {
}
func (a *App) updateServers() error {
serversInfo := fetchServers(a.cfg, a.log)
a.mu.Lock()
defer a.mu.Unlock()
serversInfo := fetchServers(a.cfg)
var found bool
for _, serverInfo := range serversInfo {
ser := a.getServer(serverInfo.Address)
if ser != nil {
if serverInfo.TLS.Enabled {
if err := ser.UpdateCert(serverInfo.TLS.CertFile, serverInfo.TLS.KeyFile); err != nil {
return fmt.Errorf("failed to update tls certs: %w", err)
}
found = true
}
} else if unbind := a.updateUnbindServerInfo(serverInfo); unbind {
found = true
index := a.serverIndex(serverInfo.Address)
if index == -1 {
continue
}
if serverInfo.TLS.Enabled {
if err := a.servers[index].UpdateCert(serverInfo.TLS.CertFile, serverInfo.TLS.KeyFile); err != nil {
return fmt.Errorf("failed to update tls certs: %w", err)
}
}
found = true
}
if !found {
@ -890,6 +876,15 @@ func (a *App) updateServers() error {
return nil
}
func (a *App) serverIndex(address string) int {
for i := range a.servers {
if a.servers[i].Address() == address {
return i
}
}
return -1
}
func (a *App) stopServices() {
ctx, cancel := shutdownContext()
defer cancel()
@ -964,31 +959,6 @@ func (a *App) initHandler() {
}
}
func (a *App) getServer(address string) Server {
for i := range a.servers {
if a.servers[i].Address() == address {
return a.servers[i]
}
}
return nil
}
func (a *App) updateUnbindServerInfo(info ServerInfo) bool {
for i := range a.unbindServers {
if a.unbindServers[i].Address == info.Address {
a.unbindServers[i] = info
return true
}
}
return false
}
func (a *App) getServers() []Server {
a.mu.RLock()
defer a.mu.RUnlock()
return a.servers
}
func (a *App) setRuntimeParameters() {
if len(os.Getenv("GOMEMLIMIT")) != 0 {
// default limit < yaml limit < app env limit < GOMEMLIMIT
@ -1004,60 +974,3 @@ func (a *App) setRuntimeParameters() {
zap.Int64("old_value", previous))
}
}
func (a *App) scheduleReconnect(ctx context.Context, srv *http.Server) {
go func() {
t := time.NewTicker(a.settings.reconnectInterval)
defer t.Stop()
for {
select {
case <-t.C:
if a.tryReconnect(ctx, srv) {
return
}
t.Reset(a.settings.reconnectInterval)
case <-ctx.Done():
return
}
}
}()
}
func (a *App) tryReconnect(ctx context.Context, sr *http.Server) bool {
a.mu.Lock()
defer a.mu.Unlock()
a.log.Info(logs.ServerReconnecting)
var failedServers []ServerInfo
for _, serverInfo := range a.unbindServers {
fields := []zap.Field{
zap.String("address", serverInfo.Address), zap.Bool("tls enabled", serverInfo.TLS.Enabled),
zap.String("tls cert", serverInfo.TLS.CertFile), zap.String("tls key", serverInfo.TLS.KeyFile),
}
srv, err := newServer(ctx, serverInfo)
if err != nil {
a.log.Warn(logs.ServerReconnectFailed, zap.Error(err))
failedServers = append(failedServers, serverInfo)
a.metrics.MarkUnhealthy(serverInfo.Address)
continue
}
go func() {
a.log.Info(logs.StartingServer, zap.String("address", srv.Address()))
a.metrics.MarkHealthy(serverInfo.Address)
if err = sr.Serve(srv.Listener()); err != nil && !errors.Is(err, http.ErrServerClosed) {
a.log.Warn(logs.ListenAndServe, zap.Error(err))
a.metrics.MarkUnhealthy(serverInfo.Address)
}
}()
a.servers = append(a.servers, srv)
a.log.Info(logs.ServerReconnectedSuccessfully, fields...)
}
a.unbindServers = failedServers
return len(a.unbindServers) == 0
}

View file

@ -59,8 +59,6 @@ const (
defaultConstraintName = "default"
defaultNamespace = ""
defaultReconnectInterval = time.Minute
)
var (
@ -224,9 +222,6 @@ const ( // Settings.
// Proxy.
cfgProxyContract = "proxy.contract"
// Server.
cfgReconnectInterval = "reconnect_interval"
// envPrefix is an environment variables prefix used for configuration.
envPrefix = "S3_GW"
)
@ -249,15 +244,6 @@ func fetchConnectTimeout(cfg *viper.Viper) time.Duration {
return connTimeout
}
func fetchReconnectInterval(cfg *viper.Viper) time.Duration {
reconnect := cfg.GetDuration(cfgReconnectInterval)
if reconnect <= 0 {
reconnect = defaultReconnectInterval
}
return reconnect
}
func fetchStreamTimeout(cfg *viper.Viper) time.Duration {
streamTimeout := cfg.GetDuration(cfgStreamTimeout)
if streamTimeout <= 0 {
@ -625,9 +611,8 @@ func fetchPeers(l *zap.Logger, v *viper.Viper) []pool.NodeParam {
return nodes
}
func fetchServers(v *viper.Viper, log *zap.Logger) []ServerInfo {
func fetchServers(v *viper.Viper) []ServerInfo {
var servers []ServerInfo
seen := make(map[string]struct{})
for i := 0; ; i++ {
key := cfgServer + "." + strconv.Itoa(i) + "."
@ -642,11 +627,6 @@ func fetchServers(v *viper.Viper, log *zap.Logger) []ServerInfo {
break
}
if _, ok := seen[serverInfo.Address]; ok {
log.Warn(logs.WarnDuplicateAddress, zap.String("address", serverInfo.Address))
continue
}
seen[serverInfo.Address] = struct{}{}
servers = append(servers, serverInfo)
}

View file

@ -74,7 +74,6 @@ func newServer(ctx context.Context, serverInfo ServerInfo) (*server, error) {
ln = tls.NewListener(ln, &tls.Config{
GetCertificate: tlsProvider.GetCertificate,
NextProtos: []string{"h2"}, // required to enable HTTP/2 requests in `http.Serve`
})
}

View file

@ -1,119 +0,0 @@
package main
import (
"context"
"crypto/rand"
"crypto/rsa"
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"fmt"
"math/big"
"net"
"net/http"
"os"
"path"
"testing"
"time"
"github.com/stretchr/testify/require"
"golang.org/x/net/http2"
)
const (
expHeaderKey = "Foo"
expHeaderValue = "Bar"
)
func TestHTTP2TLS(t *testing.T) {
ctx := context.Background()
certPath, keyPath := prepareTestCerts(t)
srv := &http.Server{
Handler: http.HandlerFunc(testHandler),
}
tlsListener, err := newServer(ctx, ServerInfo{
Address: ":0",
TLS: ServerTLSInfo{
Enabled: true,
CertFile: certPath,
KeyFile: keyPath,
},
})
require.NoError(t, err)
port := tlsListener.Listener().Addr().(*net.TCPAddr).Port
addr := fmt.Sprintf("https://localhost:%d", port)
go func() {
_ = srv.Serve(tlsListener.Listener())
}()
// Server is running, now send HTTP/2 request
tlsClientConfig := &tls.Config{
InsecureSkipVerify: true,
}
cliHTTP1 := http.Client{Transport: &http.Transport{TLSClientConfig: tlsClientConfig}}
cliHTTP2 := http.Client{Transport: &http2.Transport{TLSClientConfig: tlsClientConfig}}
req, err := http.NewRequest("GET", addr, nil)
require.NoError(t, err)
req.Header[expHeaderKey] = []string{expHeaderValue}
resp, err := cliHTTP1.Do(req)
require.NoError(t, err)
require.Equal(t, http.StatusOK, resp.StatusCode)
resp, err = cliHTTP2.Do(req)
require.NoError(t, err)
require.Equal(t, http.StatusOK, resp.StatusCode)
}
func testHandler(resp http.ResponseWriter, req *http.Request) {
hdr, ok := req.Header[expHeaderKey]
if !ok || len(hdr) != 1 || hdr[0] != expHeaderValue {
resp.WriteHeader(http.StatusBadRequest)
} else {
resp.WriteHeader(http.StatusOK)
}
}
func prepareTestCerts(t *testing.T) (certPath, keyPath string) {
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
require.NoError(t, err)
template := x509.Certificate{
SerialNumber: big.NewInt(1),
Subject: pkix.Name{CommonName: "localhost"},
NotBefore: time.Now(),
NotAfter: time.Now().Add(time.Hour * 24 * 365),
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
BasicConstraintsValid: true,
}
derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &privateKey.PublicKey, privateKey)
require.NoError(t, err)
dir := t.TempDir()
certPath = path.Join(dir, "cert.pem")
keyPath = path.Join(dir, "key.pem")
certFile, err := os.Create(certPath)
require.NoError(t, err)
defer certFile.Close()
keyFile, err := os.Create(keyPath)
require.NoError(t, err)
defer keyFile.Close()
err = pem.Encode(certFile, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
require.NoError(t, err)
err = pem.Encode(keyFile, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(privateKey)})
require.NoError(t, err)
return certPath, keyPath
}

View file

@ -33,9 +33,6 @@ S3_GW_SERVER_1_TLS_ENABLED=true
S3_GW_SERVER_1_TLS_CERT_FILE=/path/to/tls/cert
S3_GW_SERVER_1_TLS_KEY_FILE=/path/to/tls/key
# How often to reconnect to the servers
S3_GW_RECONNECT_INTERVAL: 1m
# Control API
# List of hex-encoded public keys that have rights to use the Control Service
S3_GW_CONTROL_AUTHORIZED_KEYS=035839e45d472a3b7769a2a1bd7d54c4ccd4943c3b40f547870e83a8fcbfb3ce11 028f42cfcb74499d7b15b35d9bff260a1c8d27de4f446a627406a382d8961486d6

View file

@ -25,8 +25,6 @@ peers:
priority: 2
weight: 0.9
reconnect_interval: 1m
server:
- address: 0.0.0.0:8080
tls:

View file

@ -1,313 +0,0 @@
# Authentication and authorization scheme
This document describes s3-gw authentication and authorization mechanism.
## General overview
Basic provisions:
* A request to s3-gw can be signed or not (request that isn't signed we will cal anonymous or just anon)
* To manage resources (buckets/objects) using s3-gw you must have appropriate access rights
Each request must be authenticated (at least as anonymous) and authorized. The following scheme shows components that
are involved to this
process.
<a>
<img src="images/authentication/auth-overview.svg" alt="Auth general overview"/>
</a>
There are several participants of this process:
1. User that make a request
2. S3-GW that accepts a request
3. FrostFS Storage that stores AccessObjects (objects are needed for authentication)
4. Blockchain smart contracts (`frostfsid`, `policy`) that stores user info and access rules.
## Data auth process
Let's look at the process in more detail:
<a>
<img src="images/authentication/auth-sequence.svg" alt="Auth sequence diagram"/>
</a>
* First of all, someone make a request. If request is signed we will check its signature (`Authentication`) after that
we will check access rights using policies (`Auhorization`). For anonymous requests only authorization be performed.
* **Authentication steps**:
* Each signed request is provided with `AccessKeyId` and signature. So if request is signed we must check its
signature. To do this we must know the `AccessKeyId`/`SecretAccessKey` pair (How the signature is calculated
using this pair see [signing](#aws-signing). Client and server (s3-gw) use the same credentials and algorithm to
compute signature). The `AccessKeyId` is a public part of credentials, and it's passed to gate in request. The
private part of credentials is `SecretAccessKey` and it's encrypted and stored in [AccessBox](#accessbox). So on
this step we must find appropriate `AccessBox` in FrostFS storage node (How to find appropriate `AccessBox`
knowing `AccessKeyId` see [search algorithm](#search-algorithm)). On this stage we can get `AccessDenied` from
FrostFS storage node if the s3-gw doesn't have permission to read this `AccessBox` object.
* After successful retrieving object we must extract `SecretAccessKey` from it. Since it's encrypted the s3-gw must
decrypt (see [encryption](#encryption)) this object using own private key and `SeedKey` from `AccessBox`
(see [AccessBox inner structure](#accessbox)). After s3-gw have got the `AccessKeyId`/`SecretAccessKey` pair it
[calculate signature](#aws-signing) and compare got signature with provided withing request. If signature doesn't
match the `AccessDenied` is returned.
* `AccessBox` also contains `OwnerID` that is related to `AccessKeyId` that was provided. So we have to check if
such `OwnerID` exists in `frsotfsid` contract (that stores all registered valid users). If user doesn't exist in
contract the `AccessDenied` is returned.
* **Authorization steps**:
* To know if user has access right to do what he wants to do we must find appropriate access policies. Such policies
are stored in `policy` contract and locally (can be manged using [control api](#control-auth-process)). So we need
to get policies from contract and [check them](#policies) along with local to decide if user has access right. If
he doesn't have such right the `AccessDenied` is returned.
* After successful authentication and authorization the request will be processed by s3-gw business logic and finally be
propagated to FrostFS storage node which also performs some auth checks and can return `AccessDenied`. If this happens
s3-gw also returns `AccessDenied` as response.
### AWS Signing
Every interaction with FrostFS S3 gateway is either authenticated or anonymous. This section explains request
authentication with the AWS Signature Version 4 algorithm. More info in AWS documentation:
* [Authenticating Requests (AWS Signature Version 4)](https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html)
* [Signing AWS API requests](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_aws-signing.html)
#### Authentication Methods
You can express authentication information by using one of the following methods:
* **HTTP Authorization header** - Using the HTTP Authorization header is the most common method of authenticating an
FrostFS S3 request. All the FrostFS S3 REST operations (except for browser-based uploads using POST requests) require
this header. For more information about the Authorization header value, and how to calculate signature and related
options,
see [Authenticating Requests: Using the Authorization Header (AWS Signature Version 4)](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-auth-using-authorization-header.html).
* **Query string parameters** - You can use a query string to express a request entirely in a URL. In this case, you use
query parameters to provide request information, including the authentication information. Because the request
signature is part of the URL, this type of URL is often referred to as a presigned URL. You can use presigned URLs to
embed clickable links, which can be valid for up to seven days, in HTML. For more information,
see [Authenticating Requests: Using Query Parameters (AWS Signature Version 4)](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html).
FrostFS S3 also supports browser-based uploads that use HTTP POST requests. With an HTTP POST request, you can upload
content to FrostFS S3 directly from the browser. For information about authenticating POST requests,
see [Browser-Based Uploads Using POST (AWS Signature Version 4)](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-UsingHTTPPOST.html).
#### Introduction to Signing Requests
Authentication information that you send in a request must include a signature. To calculate a signature, you first
concatenate select request elements to form a string, referred to as the string to sign. You then use a signing key to
calculate the hash-based message authentication code (HMAC) of the string to sign.
In AWS Signature Version 4, you don't use your secret access key to sign the request. Instead, you first use your secret
access key to derive a signing key. The derived signing key is specific to the date, service, and Region. For more
information about how to derive a signing key in different programming languages, see Examples of how to derive a
signing key for Signature Version 4.
The following diagram illustrates the general process of computing a signature.
<a>
<img src="images/authentication/aws-signing.png" alt="AWS Signing"/>
</a>
The string to sign depends on the request type. For example, when you use the HTTP Authorization header or the query
parameters for authentication, you use a varying combination of request elements to create the string to sign. For an
HTTP POST request, the POST policy in the request is the string you sign. For more information about computing string to
sign, follow links provided at the end of this section.
For signing key, the diagram shows series of calculations, where result of each step you feed into the next step. The
final step is the signing key.
Upon receiving an authenticated request, FrostFS S3 servers re-create the signature by using the authentication
information that is contained in the request. If the signatures match, FrostFS S3 processes your request; otherwise, the
request is rejected.
##### Signature Calculations for the Authorization Header
To calculate a signature, you first need a string to sign. You then calculate a HMAC-SHA256 hash of the string to sign
by using a signing key. The following diagram illustrates the process, including the various components of the string
that you create for signing.
When FrostFS S3 receives an authenticated request, it computes the signature and then compares it with the signature
that you provided in the request. For that reason, you must compute the signature by using the same method that is used
by FrostFS S3. The process of putting a request in an agreed-upon form for signing is called canonicalization.
<a>
<img src="images/authentication/auth-header-signing.png" alt="Signature Calculations for the Authorization Header"/>
</a>
See detains in [AWS documentation](https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-header-based-auth.html).
#### s3-gw
s3-gw support the following ways to provide the singed request:
* [HTTP Authorization header](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-auth-using-authorization-header.html)
* [Query string parameters](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html)
* [Browser-Based Uploads Using POST](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-UsingHTTPPOST.html)
All these methods provide `AccessKeyId` and signature. Using `AccessKeyId` s3-gw can get `SecretAccessKey`
(see [data auth](#data-auth-process)) to compute signature using exactly the same mechanics
as [client does](#introduction-to-signing-requests). After signature calculation the s3-gw just compares signatures and
if they don't match the access denied is returned.
### AccessBox
`AccessBox` is an ordinary object in FrostFS storage. It contains all information that can be used by s3-gw to
successfully authenticate request. Also, it contains data that is required to successful authentication in FrostFS
storage node.
Based on this object s3 credentials are formed:
* `AccessKeyId` - is concatenated container id and object id (`<cid>0<oid>`) of `AccessBox` (
e.g. `2XGRML5EW3LMHdf64W2DkBy1Nkuu4y4wGhUj44QjbXBi05ZNvs8WVwy1XTmSEkcVkydPKzCgtmR7U3zyLYTj3Snxf`)
* `SecretAccessKey` - hex-encoded random generated 32 bytes (that is encrypted and stored in object payload)
> **Note**: sensitive info in `AccessBox` is [encrypted](#encryption), so only someone who posses specific private key
> can decrypt such info.
`AccessBox` has the following structure:
<a>
<img src="images/authentication/accessbox-object.svg" alt="AccessBox object structure"/>
</a>
**Headers:**
`AccessBox` object has the following attributes (at least them, it also can contain custom one):
* `Timestamp` - unix timestamp when object was created
* `__SYSTEM__EXPIRATION_EPOCH` - epoch after which the object isn't available anymore
* `S3-CRDT-Versions-Add` - comma separated list of previous versions of `AccessBox` (
see [AccessBox versions](#accessbox-versions))
* `S3-Access-Box-CRDT-Name` - `AccessKeyId` of credentials to which current `AccessBox` is related (
see [AccessBox versions](#accessbox-versions))
* `FilePath` - just object name
**Payload:**
The `AccessBox` payload is an encoded [AccessBox protobuf type](../creds/accessbox/accessbox.proto) .
It contains:
* Seed key - hex-encoded public seed key to compute shared secret using ECDH (see [encryption](#encryption))
* List of gate data:
* Gate public key (so that gate (when it will decrypt data later) know which one item from list it should process)
* Encrypted tokens:
* `SecretAccessKey` - hex-encoded random generated 32 bytes
* Marshaled bearer token - more detail
in [spec](https://git.frostfs.info/TrueCloudLab/frostfs-api/src/commit/4c68d92468503b10282c8a92af83a56f170c8a3a/acl/types.proto#L189)
* Marshaled session token - more detail
in [spec](https://git.frostfs.info/TrueCloudLab/frostfs-api/src/commit/4c68d92468503b10282c8a92af83a56f170c8a3a/session/types.proto#L89)
* Container placement policies:
* `LocationsConstraint` - name of location constraint that can be used to create bucket/container using s3
credentials related to this `AccessBox`
* Marshaled placement policy - more detail
in [spec](https://git.frostfs.info/TrueCloudLab/frostfs-api/src/commit/4c68d92468503b10282c8a92af83a56f170c8a3a/netmap/types.proto#L111)
#### AccessBox versions
Imagine the following scenario:
* There is a system where only one s3-gw exist
* There is a `AccessBox` that can be used by this s3-gw
* User has s3 credentials (`AccessKeyId`/`SecretAccessKey`) related to corresponded `AccessBox` and can successfully
make request to s3-gw
* The system is expanded and new one s3-gw is added
* User must be able to use the credentials (that he has already had) to make request to new one s3-gw
Since `AccessBox` object is immutable and `SecretAccessKey` is encrypted only for restricted list of keys (can be used
(decrypted) only by limited number of s3-gw) we have to create new `AccessBox` that has encrypted secrets for new list
of s3-gw and be related to initial s3 credentials (`AccessKeyId`/`SecretAccessKey`). Such relationship is done
by `S3-Access-Box-CRDT-Name`.
##### Search algorithm
To support scenario from previous section and find appropriate version of `AccessBox` (that contains more recent and
relevant data) the following sequence is used:
<a>
<img src="images/authentication/accessbox-search.svg" alt="AccessBox search process"/>
</a>
* Search all object whose attribute `S3-Access-Box-CRDT-Name` is equal to `AccessKeyId` (extract container id
from `AccessKeyId` that has format: `<cid>0<oid>`).
* Get metadata for these object using `HEAD` requests (not `Get` to reduce network traffic)
* Sort all these objects by creation epoch and object id
* Pick last object id (If no object is found then extract object id from `AccessKeyId` that has format: `<cid>0<oid>`.
We need to do this because versions of `AccessBox` can miss the `S3-Access-Box-CRDT-Name` attribute.)
* Get appropriate object from FrostFS storage
* Decrypt `AccessBox` (see [encryption](#encryption))
#### Encryption
Each `AccessBox` contains sensitive information (`AccessSecretKey`, bearer/session tokens etc.) that must be protected
and available only to trusted parties (in our case it's a s3-gw).
To encrypt/decrypt data the authenticated encryption with associated
data ([AEAD](https://en.wikipedia.org/wiki/Authenticated_encryption)) is used. The encryption algorithm
is [ChaCha20-Poly1305](https://en.wikipedia.org/wiki/ChaCha20-Poly1305) ([RFC](https://datatracker.ietf.org/doc/html/rfc7905)).
Is the following algorithm the ECDSA keys (with curve implements NIST P-256 (FIPS 186-3, section D.2.3) also known as
secp256r1 or prime256v1) is used (unless otherwise stated).
**Encryption:**
* Create ephemeral key (`SeedKey`), it's need to generate shared secret
* Generate random 32-byte (that after hex-encoded be `SecretAccessKey`) or use existing secret access key
(if `AccessBox` is being updated rather than creating brand new)
* Generate shared secret as [ECDH](https://en.wikipedia.org/wiki/Elliptic-curve_Diffie%E2%80%93Hellman)
* Derive 32-byte key using shared secret from previous step with key derivation function based on
HMAC with SHA256 [HKDF](https://en.wikipedia.org/wiki/HKDF)
* Encrypt marshaled [Tokens](../creds/accessbox) using derived key
with [ChaCha20-Poly1305](https://en.wikipedia.org/wiki/ChaCha20-Poly1305) algorithm without additional data.
**Decryption:**
* Get public part of `SeedKey` from `AccessBox`
* Generate shared secret as follows:
* Make scalar curve multiplication of public part of `SeedKey` and private part of s3-gw key
* Use `X` part of multiplication (with zero padding at the beginning to fit 32-byte)
* Derive 32-byte key using shared secret from previous step with key derivation function based on
HMAC with SHA256 [HKDF](https://en.wikipedia.org/wiki/HKDF)
* Decrypt encrypted marshaled [Tokens](../creds/accessbox) using derived key
with [ChaCha20-Poly1305](https://en.wikipedia.org/wiki/ChaCha20-Poly1305) algorithm without additional data.
### Policies
The main repository that contains policy implementation is https://git.frostfs.info/TrueCloudLab/policy-engine.
Policies can be stored locally (using [control api](#control-auth-process)) or in `policy` contract. When policies check
is performed the following algorithm is applied:
* Check local policies:
* If any rule was matched return checking result.
* Check contract policies:
* If any rule was matched return checking result.
* If no rules were matched return `deny` status.
To local and contract policies `deny first` scheme is applied. This means that if several rules were matched for
reqeust (with both statuses `allow` and `deny`) the resulting status be `deny`.
Policy rules validate if specified request can be performed on the specific resource. Request and resource can contain
some properties and rules can contain conditions on some such properties.
In s3-gw resource is `/bucket/object`, `/bucket` or just `/` (if request is trying to list buckets).
Currently, request that is checked contains the following properties (so policy rule can contain conditions on them):
* `Owner` - address of owner that is performing request (this is taken from bearer token from `AccessBox`)
* `frostfsid:groupID` - groups to which the owner belongs (this is taken from `frostfsid` contract)
## Control auth process
There are control path [grpc api](../pkg/service/control/service.proto) in s3-gw that also has their own authentication
and authorization process.
But this process is quite straight forward:
* Get grpc request
* Check if signing key belongs to [allowed key list](configuration.md#control-section) (that is located in config file)
* Validate signature
For signing process the asymmetric encryption based on elliptic curves (`ECDSA_SHA512`) is used.
For more details see the appropriate code
in [frostfs-api](https://git.frostfs.info/TrueCloudLab/frostfs-api/src/commit/4c68d92468503b10282c8a92af83a56f170c8a3a/refs/types.proto#L94)
and [frostfs-api-go](https://git.frostfs.info/TrueCloudLab/frostfs-api-go/src/commit/a85146250b312fcdd6da9a71285527fed544234f/refs/types.go#L38).

View file

@ -192,51 +192,17 @@ See also `GetObject` and other method parameters.
## Policy and replication
Bucket policy has the following limitations
* Supports only AWS principals in format `arn:aws:iam::<namespace>:user/<user>` or wildcard `*`.
* No complex conditions (only conditions for groups now supported)
Simple valid policy example:
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Principal": {
"AWS": [
"arn:aws:iam::111122223333:role/JohnDoe"
]
},
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:GetObjectVersion"
],
"Resource": [
"arn:aws:s3:::DOC-EXAMPLE-BUCKET/*"
]
}
]
}
```
Bucket policy status determines using the following scheme:
* If policy has statement with principal that is wildcard (`*`) then policy is considered as public
| | Method | Comments |
|-----|-------------------------|---------------------------------------------------|
| 🟢 | DeleteBucketPolicy | See Policy limitations |
| 🔵 | DeleteBucketReplication | |
| 🔵 | DeletePublicAccessBlock | |
| 🟢 | GetBucketPolicy | See Policy limitations |
| 🟢 | GetBucketPolicyStatus | See rule determining status in Policy limitations |
| 🔵 | GetBucketReplication | |
| 🟢 | PostPolicyBucket | Upload file using POST form |
| 🟡 | PutBucketPolicy | See Policy limitations |
| 🔵 | PutBucketReplication | |
| | Method | Comments |
|-----|-------------------------|------------------------------|
| 🟢 | DeleteBucketPolicy | |
| 🔵 | DeleteBucketReplication | |
| 🔵 | DeletePublicAccessBlock | |
| 🟢 | GetBucketPolicy | |
| 🔵 | GetBucketPolicyStatus | |
| 🔵 | GetBucketReplication | |
| 🟢 | PostPolicyBucket | Upload file using POST form |
| 🟡 | PutBucketPolicy | Conditions are not supported |
| 🔵 | PutBucketReplication | |
## Request payment

View file

@ -1,131 +0,0 @@
# Bucket policy
A bucket policy is a resource-based policy that you can use to grant access permissions to your S3 bucket and the
objects in it https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucket-policies.html.
## Conditions
In AWS there are a lot of condition
keys https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.htm
but s3-gw currently supports only the following conditions in bucket policy:
> Note: all condition keys and values must be string formatted in json policy (even if they are numbers).
| Condition key | Description |
|-------------------------------|---------------------------------------------------------------------------|
| [s3:max-keys](#s3-max-keys) | Filters access by maximum number of keys returned in a ListBucket request |
| [s3:delimiter](#s3-delimiter) | Filters access by delimiter parameter |
| [s3:prefix](#s3-prefix) | Filters access by key name prefix |
| [s3:VersionId](#s3-versionid) | Filters access by a specific object version |
Each key can be used only with specific set of
operators https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_condition_operators.html
(it depends on type of key).
### s3 max-keys
**Key:** `s3:max-keys`
**Type:** `Numeric`
**Description:** Filters access by maximum number of keys returned in a ListBucket request
```json
{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Principal": "*",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::example_bucket",
"Condition": {
"NumericLessThanEquals": {
"s3:max-keys": "10"
}
}
}
}
```
### s3 delimiter
**Key:** `s3:delimiter`
**Type:** `String`
**Description:** Filters access by delimiter parameter
```json
{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Principal": "*",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::example_bucket",
"Condition": {
"StringEquals": {
"s3:delimiter": "/"
}
}
}
}
```
### s3 prefix
**Key:** `s3:prefix`
**Type:** `String`
**Description:** Filters access by key name prefix
```json
{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::111122223333:user/JohnDoe"
]
},
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::example_bucket",
"Condition": {
"StringEquals": {
"s3:prefix": "home/JohnDoe"
}
}
}
}
```
### s3 VersionId
**Key:** `s3:VersionId`
**Type:** `String`
**Description:** Filters access by a specific object version
```json
{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::111122223333:user/JohnDoe"
]
},
"Action": "s3:GetObjectVersion",
"Resource": "arn:aws:s3:::example_bucket/some-file.txt",
"Condition": {
"StringEquals": {
"s3:VersionId": "AT2L3qER7CHGk4TDooocEzkz2RyqTm4Zh2b1QLzAhLbH"
}
}
}
}
```

View file

@ -218,8 +218,6 @@ max_clients_deadline: 30s
allowed_access_key_id_prefixes:
- Ck9BHsgKcnwfCTUSFm6pxhoNS4cBqgN2NQ8zVgPjqZDX
- 3stjWenX15YwYzczMr88gy3CQr4NYFBQ8P7keGzH5QFn
reconnect_interval: 1m
```
| Parameter | Type | SIGHUP reload | Default value | Description |
@ -235,7 +233,6 @@ reconnect_interval: 1m
| `max_clients_count` | `int` | no | `100` | Limits for processing of clients' requests. |
| `max_clients_deadline` | `duration` | no | `30s` | Deadline after which the gate sends error `RequestTimeout` to a client. |
| `allowed_access_key_id_prefixes` | `[]string` | no | | List of allowed `AccessKeyID` prefixes which S3 GW serve. If the parameter is omitted, all `AccessKeyID` will be accepted. |
| `reconnect_interval` | `duration` | no | `1m` | Listeners reconnection interval. |
### `wallet` section

View file

@ -1,44 +0,0 @@
@startuml
package AccessBox {
map Tokens {
SecretKey => Private key
BearerToken => Encoded bearer token
SessionTokens => List of encoded session tokens
}
map Gate {
GateKey => Encoded public gate key
Encrypted tokens *--> Tokens
}
map ContainerPolicy {
LocationConstraint => Policy name
PlacementPolicy => Encoded placement policy
}
map Box {
SeedKey => Encoded public seed key
List of Gates *--> Gate
List of container policies *--> ContainerPolicy
}
map ObjectAttributes {
Timestamp => 1710418478
_~_SYSTEM_~_EXPIRATION_EPOCH => 10801
S3-CRDT-Versions-Add => 5ZNvs8WVwy1XTmSEkcVkydPKzCgtmR7U3zyLYTj3Snxf,9bLtL1EsUpuSiqmHnqFf6RuT6x5QMLMNBqx7vCcCcNhy
S3-Access-Box-CRDT-Name => 2XGRML5EW3LMHdf64W2DkBy1Nkuu4y4wGhUj44QjbXBi05ZNvs8WVwy1XTmSEkcVkydPKzCgtmR7U3zyLYTj3Snxf
FilePath => 1710418478_access.box
}
map FrostFSObject {
Header *-> ObjectAttributes
Payload *--> Box
}
}
@enduml

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 13 KiB

View file

@ -1,29 +0,0 @@
@startuml
User -> "S3-GW": AccessKey
"S3-GW" -> "FrostFS Node": Search objects
note right
Search by exact attribute matching:
**S3-Access-Box-CRDT-Name:** //AccessKey//
end note
"FrostFS Node" --> "S3-GW": AccessBox objects ids
"S3-GW" -> "FrostFS Node" : Head AccessBox objects
"FrostFS Node" --> "S3-GW": AccessBox object headers
"S3-GW" -> "S3-GW": Choose latest AccessBox
note left
Sort AccessBox headers by creation epoch
and then by ObjectID
Pick last
end note
"S3-GW" -> "FrostFS Node" : Get AccessBox object
"FrostFS Node" --> "S3-GW": AccessBox object
"S3-GW" -> "S3-GW": Decrypt and validate AccessBox
@enduml

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 133 KiB

View file

@ -1,25 +0,0 @@
@startuml
!include <c4/C4_Container.puml>
AddElementTag("smart-contract", $bgColor=#0abab5)
Person(user, "User", "User with or without credentials")
System_Boundary(c1, "FrostFS") {
Container(s3, "S3 Gateway", $descr="AWS S3 compatible gate")
Container(stor, "FrostFS Storage", $descr="Storage service")
}
System_Boundary(c3, "Blockchain") {
Interface "NeoGo"
Container(ffsid, "FrostFS ID", $tags="smart-contract", $descr="Stores namespaces and users")
Container(policy, "Policy", $tags="smart-contract", $descr="Stores APE rules")
}
Rel_R(user, s3, "Requests", "HTTP")
Rel_R(s3, stor, "Get data to validate request, store objects")
Rel_D(s3, NeoGo, "Get data to validate request")
Rel("NeoGo", ffsid, "Fetch users")
Rel("NeoGo", policy, "Fetch policies")
SHOW_LEGEND(true)
@enduml

View file

@ -1,611 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentStyleType="text/css" height="660px" preserveAspectRatio="none" style="width:851px;height:660px;background:#FFFFFF;" version="1.1" viewBox="0 0 851 660" width="851px" zoomAndPan="magnify"><defs/><g><!--MD5=[84dda40acb3410cad7262261daba2aaf]
cluster c1--><g id="cluster_c1"><rect fill="none" height="152" rx="2.5" ry="2.5" style="stroke:#444444;stroke-width:1.0;stroke-dasharray:7.0,7.0;" width="587" x="258" y="7"/><text fill="#444444" font-family="sans-serif" font-size="16" font-weight="bold" lengthAdjust="spacing" textLength="71" x="516" y="23.8516">FrostFS</text><text fill="#444444" font-family="sans-serif" font-size="12" font-weight="bold" lengthAdjust="spacing" textLength="61" x="521" y="38.7637">[System]</text></g><!--MD5=[fb252dd5a834d4be8567d0df3f6bbec4]
cluster c3--><g id="cluster_c3"><rect fill="none" height="301" rx="2.5" ry="2.5" style="stroke:#444444;stroke-width:1.0;stroke-dasharray:7.0,7.0;" width="405" x="259" y="243.5"/><text fill="#444444" font-family="sans-serif" font-size="16" font-weight="bold" lengthAdjust="spacing" textLength="95" x="414" y="260.3516">Blockchain</text><text fill="#444444" font-family="sans-serif" font-size="12" font-weight="bold" lengthAdjust="spacing" textLength="61" x="431" y="275.2637">[System]</text></g><!--MD5=[b165ca7cce796f881c879adda4a6bef9]
entity s3--><g id="elem_s3"><rect fill="#438DD5" height="85.1875" rx="2.5" ry="2.5" style="stroke:#3C7FC0;stroke-width:0.5;" width="199" x="274.5" y="58"/><text fill="#FFFFFF" font-family="sans-serif" font-size="16" font-weight="bold" lengthAdjust="spacing" textLength="108" x="320" y="82.8516">S3 Gateway</text><text fill="#FFFFFF" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="10" x="369" y="97.7637">[]</text><text fill="#FFFFFF" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="4" x="372" y="113.5889"> </text><text fill="#FFFFFF" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="175" x="288.5" y="129.8857">AWS S3 compatible gate</text></g><!--MD5=[b631bc93683c8d3c6bcd86869bd62c2d]
entity stor--><g id="elem_stor"><rect fill="#438DD5" height="85.1875" rx="2.5" ry="2.5" style="stroke:#3C7FC0;stroke-width:0.5;" width="169" x="660.5" y="58"/><text fill="#FFFFFF" font-family="sans-serif" font-size="16" font-weight="bold" lengthAdjust="spacing" textLength="149" x="670.5" y="82.8516">FrostFS Storage</text><text fill="#FFFFFF" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="10" x="740" y="97.7637">[]</text><text fill="#FFFFFF" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="4" x="743" y="113.5889"> </text><text fill="#FFFFFF" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="111" x="691.5" y="129.8857">Storage service</text></g><!--MD5=[d75780de534459f9083ff96c63e26824]
entity NeoGo--><g id="elem_NeoGo"><ellipse cx="374" cy="323.5" fill="#F1F1F1" rx="8" ry="8" style="stroke:#181818;stroke-width:0.5;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="48" x="350" y="353.4951">NeoGo</text></g><!--MD5=[a1c7fbed12783ec305c3357d72c64f9e]
entity ffsid--><g id="elem_ffsid"><rect fill="#0ABAB5" height="101.4844" rx="2.5" ry="2.5" style="stroke:#3C7FC0;stroke-width:0.5;" width="198" x="275" y="427.5"/><text fill="#FFFFFF" font-family="sans-serif" font-size="16" font-weight="bold" lengthAdjust="spacing" textLength="96" x="326" y="452.3516">FrostFS ID</text><text fill="#FFFFFF" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="10" x="369" y="467.2637">[]</text><text fill="#FFFFFF" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="4" x="372" y="483.0889"> </text><text fill="#FFFFFF" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="170" x="289" y="499.3857">Stores namespaces and</text><text fill="#FFFFFF" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="38" x="355" y="515.6826">users</text></g><!--MD5=[4361443624774238dacd0e01c3165ecf]
entity policy--><g id="elem_policy"><rect fill="#0ABAB5" height="85.1875" rx="2.5" ry="2.5" style="stroke:#3C7FC0;stroke-width:0.5;" width="139" x="508.5" y="435.5"/><text fill="#FFFFFF" font-family="sans-serif" font-size="16" font-weight="bold" lengthAdjust="spacing" textLength="52" x="552" y="460.3516">Policy</text><text fill="#FFFFFF" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="10" x="573" y="475.2637">[]</text><text fill="#FFFFFF" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="4" x="576" y="491.0889"> </text><text fill="#FFFFFF" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="115" x="522.5" y="507.3857">Stores APE rules</text></g><!--MD5=[8fc3522a43f8c7199df5e09e5bb0188e]
entity user--><g id="elem_user"><rect fill="#08427B" height="135.5156" rx="2.5" ry="2.5" style="stroke:#073B6F;stroke-width:0.5;" width="168" x="7" y="32.5"/><image height="48" width="48" x="67" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAIAAADYYG7QAAACD0lEQVR4Xu2YoU4EMRCGT+4j8Ai8AhaH4QHgAUjQuFMECUgMIUgwJAgMhgQsAYUiJCiQIBBY+EITsjfTdme6V24v4c8vyGbb+ZjOtN0bNcvjQXmkH83WvYBWto6PLm6v7p7uH1/w2fXD+PBycX1Pv2l3IdDm/vn7x+dXQiAubRzoURa7gRZWd0iGRIiJbOnhnfYBQZNJjNbuyY2eJG8fkDE3bbG4ep6MHUAsgYxmE3nVs6VsBWJSGccsOlFPmLIViMzLOB7pCVO2AtHJMohH7Fh6zqitQK7m0rJvAVYgGcEpe//PLdDz65sM4pF9N7ICcXDKIB5Nv6j7tD0NoSdM2QrU9Gg0ewE1LqBhHR3BBdvj2vapnidjHxD/q6vd7Pvhr31AwcY8eXMTXAKECZZJFXuEq27aLgQK5uLMohCenGGuGewOxSjBvYBqeG6B+Nqiblggdjnc+ZXDy+FNFpFzw76O3UBAROuXh6FoiAcf5g9eTvUgzy0nWg6I8cXHRUpg5bOVBCo+KDpFajOf23GgPme7RSQ+lacIENUgJ6gg1k6HjgOlqnLqip4tEuhv0hNEMXUD0clyXE3p6pZA0S2nnvTlXwLJEZWlb7cTQH1+USgTN4VhAenm/wea1OCAOmqo6fE1WCb9WSKBah+rbUWPWAmE2Rvk0ApiB45eOyNAzU8xcTvj8KvkKEoOaIYeHNA3ZuygAvFMUO0AAAAASUVORK5CYII=" y="42.5"/><text fill="#FFFFFF" font-family="sans-serif" font-size="16" font-weight="bold" lengthAdjust="spacing" textLength="42" x="70" y="105.3516">User</text><text fill="#FFFFFF" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="4" x="89" y="122.1201"> </text><text fill="#FFFFFF" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="140" x="21" y="138.417">User with or without</text><text fill="#FFFFFF" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="79" x="51.5" y="154.7139">credentials</text></g><!--MD5=[52d0c115c7d06b979b7f69659773ccc0]
link user to s3--><g id="link_user_s3"><path d="M175.14,100.5 C203.78,100.5 236.2,100.5 266.42,100.5 " fill="none" id="user-to-s3" style="stroke:#666666;stroke-width:1.0;"/><polygon fill="#666666" points="274.47,100.5,266.47,97.5,266.47,103.5,274.47,100.5" style="stroke:#666666;stroke-width:1.0;"/><text fill="#666666" font-family="sans-serif" font-size="12" font-weight="bold" lengthAdjust="spacing" textLength="63" x="193.25" y="80.6387">Requests</text><text fill="#666666" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="40" x="204.75" y="94.6074">[HTTP]</text></g><!--MD5=[22d466a8c2458259cbad703a0636b8fb]
link s3 to stor--><g id="link_s3_stor"><path d="M473.91,100.5 C529.33,100.5 597.81,100.5 652.08,100.5 " fill="none" id="s3-to-stor" style="stroke:#666666;stroke-width:1.0;"/><polygon fill="#666666" points="660.32,100.5,652.32,97.5,652.32,103.5,660.32,100.5" style="stroke:#666666;stroke-width:1.0;"/><text fill="#666666" font-family="sans-serif" font-size="12" font-weight="bold" lengthAdjust="spacing" textLength="136" x="497" y="80.6387">Get data to validate</text><text fill="#666666" font-family="sans-serif" font-size="12" font-weight="bold" lengthAdjust="spacing" textLength="150" x="492" y="94.6074">request, store objects</text></g><!--MD5=[8c98dd26c815ae7a8024bcc2d9dd4f66]
link s3 to NeoGo--><g id="link_s3_NeoGo"><path d="M374,143.07 C374,192.21 374,271.65 374,305.9 " fill="none" id="s3-to-NeoGo" style="stroke:#666666;stroke-width:1.0;"/><polygon fill="#666666" points="374,314.3,377,306.3,371,306.3,374,314.3" style="stroke:#666666;stroke-width:1.0;"/><text fill="#666666" font-family="sans-serif" font-size="12" font-weight="bold" lengthAdjust="spacing" textLength="136" x="375" y="210.6387">Get data to validate</text><text fill="#666666" font-family="sans-serif" font-size="12" font-weight="bold" lengthAdjust="spacing" textLength="53" x="418.5" y="224.6074">request</text></g><!--MD5=[67f0c0ebd6d2a23c30e202ac0cd81435]
link NeoGo to ffsid--><g id="link_NeoGo_ffsid"><path d="M374,332.7 C374,348.95 374,386.52 374,419.25 " fill="none" id="NeoGo-to-ffsid" style="stroke:#666666;stroke-width:1.0;"/><polygon fill="#666666" points="374,427.45,377,419.45,371,419.45,374,427.45" style="stroke:#666666;stroke-width:1.0;"/><text fill="#666666" font-family="sans-serif" font-size="12" font-weight="bold" lengthAdjust="spacing" textLength="79" x="375" y="394.6387">Fetch users</text></g><!--MD5=[d37da9b99a3aca6bfa9447725e2e6374]
link NeoGo to policy--><g id="link_NeoGo_policy"><path d="M383.06,329.95 C399.4,339.87 434.74,361.78 463,382.5 C483.22,397.33 504.63,414.49 523.43,430.09 " fill="none" id="NeoGo-to-policy" style="stroke:#666666;stroke-width:1.0;"/><polygon fill="#666666" points="529.7,435.31,525.4816,427.88,521.6363,432.4858,529.7,435.31" style="stroke:#666666;stroke-width:1.0;"/><text fill="#666666" font-family="sans-serif" font-size="12" font-weight="bold" lengthAdjust="spacing" textLength="93" x="483" y="394.6387">Fetch policies</text></g><rect fill="none" height="16.2969" style="stroke:none;stroke-width:1.0;" width="236" x="584" y="568.5"/><text fill="#000000" font-family="sans-serif" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="59" x="584" y="581.4951">Legend</text><text fill="#FFFFFF" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="4" x="643" y="581.4951"> </text><rect fill="#08427B" height="16.2969" style="stroke:none;stroke-width:1.0;" width="236" x="584" y="584.7969"/><text fill="#073B6F" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="8" x="588" y="597.792"></text><text fill="#FFFFFF" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="4" x="596" y="597.792"> </text><text fill="#FFFFFF" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="49" x="604" y="597.792">person</text><text fill="#FFFFFF" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="4" x="657" y="597.792"> </text><rect fill="#438DD5" height="16.2969" style="stroke:none;stroke-width:1.0;" width="236" x="584" y="601.0938"/><text fill="#3C7FC0" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="8" x="588" y="614.0889"></text><text fill="#FFFFFF" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="4" x="596" y="614.0889"> </text><text fill="#FFFFFF" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="68" x="604" y="614.0889">container</text><text fill="#FFFFFF" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="4" x="676" y="614.0889"> </text><rect fill="#0ABAB5" height="16.2969" style="stroke:none;stroke-width:1.0;" width="236" x="584" y="617.3906"/><text fill="#0ABAB5" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="8" x="588" y="630.3857"></text><text fill="#FFFFFF" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="4" x="596" y="630.3857"> </text><text fill="#66622E" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="208" x="604" y="630.3857">smart-contract (no text color)</text><text fill="#FFFFFF" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="4" x="816" y="630.3857"> </text><line style="stroke:none;stroke-width:1.0;" x1="584" x2="820" y1="568.5" y2="568.5"/><line style="stroke:none;stroke-width:1.0;" x1="584" x2="820" y1="584.7969" y2="584.7969"/><line style="stroke:none;stroke-width:1.0;" x1="584" x2="820" y1="601.0938" y2="601.0938"/><line style="stroke:none;stroke-width:1.0;" x1="584" x2="820" y1="617.3906" y2="617.3906"/><line style="stroke:none;stroke-width:1.0;" x1="584" x2="820" y1="633.6875" y2="633.6875"/><line style="stroke:none;stroke-width:1.0;" x1="584" x2="584" y1="568.5" y2="633.6875"/><line style="stroke:none;stroke-width:1.0;" x1="820" x2="820" y1="568.5" y2="633.6875"/><!--MD5=[c02d88aa5b998c40021c1d715125d393]
@startuml
!include <c4/C4_Container.puml>
AddElementTag("smart-contract", $bgColor=#0abab5)
Person(user, "User", "User with or without credentials")
System_Boundary(c1, "FrostFS") {
Container(s3, "S3 Gateway", $descr="AWS S3 compatible gate")
Container(stor, "FrostFS Storage", $descr="Storage service")
}
System_Boundary(c3, "Blockchain") {
Interface "NeoGo"
Container(ffsid, "FrostFS ID", $tags="smart-contract", $descr="Stores namespaces and users")
Container(policy, "Policy", $tags="smart-contract", $descr="Stores APE rules")
}
Rel_R(user, s3, "Requests", "HTTP")
Rel_R(s3, stor, "Get data to validate request, store objects")
Rel_D(s3, NeoGo, "Get data to validate request")
Rel("NeoGo", ffsid, "Fetch users")
Rel("NeoGo", policy, "Fetch policies")
SHOW_LEGEND(true)
@enduml
@startuml
skinparam defaultTextAlignment center
skinparam wrapWidth 200
skinparam maxMessageSize 150
skinparam LegendBorderColor transparent
skinparam LegendBackgroundColor transparent
skinparam LegendFontColor #FFFFFF
skinparam shadowing<<legendArea>> false
skinparam rectangle<<legendArea>> {
backgroundcolor #00000000
bordercolor #00000000
}
skinparam rectangle {
StereotypeFontSize 12
shadowing false
}
skinparam database {
StereotypeFontSize 12
shadowing false
}
skinparam queue {
StereotypeFontSize 12
shadowing false
}
skinparam arrow {
Color #666666
FontColor #666666
FontSize 12
}
skinparam actor {
StereotypeFontSize 12
shadowing false
style awesome
}
skinparam person {
StereotypeFontSize 12
shadowing false
}
skinparam package {
StereotypeFontSize 6
StereotypeFontColor transparent
FontStyle plain
BackgroundColor transparent
}
skinparam rectangle<<boundary>> {
Shadowing false
StereotypeFontSize 6
StereotypeFontColor transparent
FontColor #444444
BorderColor #444444
BackgroundColor transparent
BorderStyle dashed
}
skinparam rectangle<<person>> {
StereotypeFontColor #FFFFFF
FontColor #FFFFFF
BackgroundColor #08427B
BorderColor #073B6F
}
skinparam database<<person>> {
StereotypeFontColor #FFFFFF
FontColor #FFFFFF
BackgroundColor #08427B
BorderColor #073B6F
}
skinparam queue<<person>> {
StereotypeFontColor #FFFFFF
FontColor #FFFFFF
BackgroundColor #08427B
BorderColor #073B6F
}
skinparam actor<<person>> {
StereotypeFontColor #08427B
FontColor #08427B
BackgroundColor #08427B
BorderColor #073B6F
}
skinparam person<<person>> {
StereotypeFontColor #FFFFFF
FontColor #FFFFFF
BackgroundColor #08427B
BorderColor #073B6F
}
skinparam rectangle<<external_person>> {
StereotypeFontColor #FFFFFF
FontColor #FFFFFF
BackgroundColor #686868
BorderColor #8A8A8A
}
skinparam database<<external_person>> {
StereotypeFontColor #FFFFFF
FontColor #FFFFFF
BackgroundColor #686868
BorderColor #8A8A8A
}
skinparam queue<<external_person>> {
StereotypeFontColor #FFFFFF
FontColor #FFFFFF
BackgroundColor #686868
BorderColor #8A8A8A
}
skinparam actor<<external_person>> {
StereotypeFontColor #686868
FontColor #686868
BackgroundColor #686868
BorderColor #8A8A8A
}
skinparam person<<external_person>> {
StereotypeFontColor #FFFFFF
FontColor #FFFFFF
BackgroundColor #686868
BorderColor #8A8A8A
}
skinparam rectangle<<system>> {
StereotypeFontColor #FFFFFF
FontColor #FFFFFF
BackgroundColor #1168BD
BorderColor #3C7FC0
}
skinparam database<<system>> {
StereotypeFontColor #FFFFFF
FontColor #FFFFFF
BackgroundColor #1168BD
BorderColor #3C7FC0
}
skinparam queue<<system>> {
StereotypeFontColor #FFFFFF
FontColor #FFFFFF
BackgroundColor #1168BD
BorderColor #3C7FC0
}
skinparam actor<<system>> {
StereotypeFontColor #1168BD
FontColor #1168BD
BackgroundColor #1168BD
BorderColor #3C7FC0
}
skinparam person<<system>> {
StereotypeFontColor #FFFFFF
FontColor #FFFFFF
BackgroundColor #1168BD
BorderColor #3C7FC0
}
skinparam rectangle<<external_system>> {
StereotypeFontColor #FFFFFF
FontColor #FFFFFF
BackgroundColor #999999
BorderColor #8A8A8A
}
skinparam database<<external_system>> {
StereotypeFontColor #FFFFFF
FontColor #FFFFFF
BackgroundColor #999999
BorderColor #8A8A8A
}
skinparam queue<<external_system>> {
StereotypeFontColor #FFFFFF
FontColor #FFFFFF
BackgroundColor #999999
BorderColor #8A8A8A
}
skinparam actor<<external_system>> {
StereotypeFontColor #999999
FontColor #999999
BackgroundColor #999999
BorderColor #8A8A8A
}
skinparam person<<external_system>> {
StereotypeFontColor #FFFFFF
FontColor #FFFFFF
BackgroundColor #999999
BorderColor #8A8A8A
}
sprite $person [48x48/16] {
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
0000000000000000000049BCCA7200000000000000000000
0000000000000000006EFFFFFFFFB3000000000000000000
00000000000000001CFFFFFFFFFFFF700000000000000000
0000000000000001EFFFFFFFFFFFFFF80000000000000000
000000000000000CFFFFFFFFFFFFFFFF6000000000000000
000000000000007FFFFFFFFFFFFFFFFFF100000000000000
00000000000001FFFFFFFFFFFFFFFFFFF900000000000000
00000000000006FFFFFFFFFFFFFFFFFFFF00000000000000
0000000000000BFFFFFFFFFFFFFFFFFFFF40000000000000
0000000000000EFFFFFFFFFFFFFFFFFFFF70000000000000
0000000000000FFFFFFFFFFFFFFFFFFFFF80000000000000
0000000000000FFFFFFFFFFFFFFFFFFFFF80000000000000
0000000000000DFFFFFFFFFFFFFFFFFFFF60000000000000
0000000000000AFFFFFFFFFFFFFFFFFFFF40000000000000
00000000000006FFFFFFFFFFFFFFFFFFFE00000000000000
00000000000000EFFFFFFFFFFFFFFFFFF800000000000000
000000000000007FFFFFFFFFFFFFFFFFF100000000000000
000000000000000BFFFFFFFFFFFFFFFF5000000000000000
0000000000000001DFFFFFFFFFFFFFF70000000000000000
00000000000000000BFFFFFFFFFFFF500000000000000000
0000000000000000005DFFFFFFFFA1000000000000000000
0000000000000000000037ABB96100000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000025788300000000005886410000000000000
000000000007DFFFFFFD9643347BFFFFFFFB400000000000
0000000004EFFFFFFFFFFFFFFFFFFFFFFFFFFB1000000000
000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFD200000000
00000006FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE10000000
0000003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB0000000
000000BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5000000
000003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD000000
000009FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF200000
00000DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF600000
00000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000
00001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA00000
00001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB00000
00001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB00000
00001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB00000
00001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA00000
00000EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF700000
000006FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE100000
0000008FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD3000000
000000014555555555555555555555555555555300000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
}
sprite $person2 [48x48/16] {
0000000000000000000049BCCA7200000000000000000000
0000000000000000006EFFFFFFFFB3000000000000000000
00000000000000001CFFFFFFFFFFFF700000000000000000
0000000000000001EFFFFFFFFFFFFFF80000000000000000
000000000000000CFFFFFFFFFFFFFFFF6000000000000000
000000000000007FFFFFFFFFFFFFFFFFF100000000000000
00000000000001FFFFFFFFFFFFFFFFFFF900000000000000
00000000000006FFFFFFFFFFFFFFFFFFFF00000000000000
0000000000000BFFFFFFFFFFFFFFFFFFFF40000000000000
0000000000000EFFFFFFFFFFFFFFFFFFFF70000000000000
0000000000000FFFFFFFFFFFFFFFFFFFFF80000000000000
0000000000000FFFFFFFFFFFFFFFFFFFFF80000000000000
0000000000000DFFFFFFFFFFFFFFFFFFFF60000000000000
0000000000000AFFFFFFFFFFFFFFFFFFFF40000000000000
00000000000006FFFFFFFFFFFFFFFFFFFE00000000000000
00000000000000EFFFFFFFFFFFFFFFFFF800000000000000
000000000000007FFFFFFFFFFFFFFFFFF100000000000000
000000000000000BFFFFFFFFFFFFFFFF5000000000000000
0000000000000001DFFFFFFFFFFFFFF70000000000000000
00000000000000000BFFFFFFFFFFFF500000000000000000
0000000000000000005DFFFFFFFFA1000000000000000000
0000000000000000000037ABB96100000000000000000000
000000000002578888300000000005888864100000000000
0000000007DFFFFFFFFD9643347BFFFFFFFFFB4000000000
00000004EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB10000000
0000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD2000000
000006FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE100000
00003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB00000
0000BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF50000
0003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD0000
0009FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2000
000DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6000
000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8000
001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB000
001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB000
001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB000
001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA000
000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8000
000DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6000
0009FFFFFFFF8FFFFFFFFFFFFFFFFFFFFFF8FFFFFFFF2000
0003FFFFFFFF8FFFFFFFFFFFFFFFFFFFFFF8FFFFFFFD0000
0000BFFFFFFF8FFFFFFFFFFFFFFFFFFFFFF8FFFFFFF50000
00003FFFFFFF8FFFFFFFFFFFFFFFFFFFFFF8FFFFFFB00000
000006FFFFFF8FFFFFFFFFFFFFFFFFFFFFF8FFFFFE100000
0000007FFFFF8FFFFFFFFFFFFFFFFFFFFFF8FFFFD2000000
00000004EFFF8FFFFFFFFFFFFFFFFFFFFFF8FFFB10000000
0000000007DF8FFFFFFFFFFFFFFFFFFFFFF8FB4000000000
000000000002578888888888888888888864100000000000
}
skinparam rectangle<<container>> {
StereotypeFontColor #FFFFFF
FontColor #FFFFFF
BackgroundColor #438DD5
BorderColor #3C7FC0
}
skinparam database<<container>> {
StereotypeFontColor #FFFFFF
FontColor #FFFFFF
BackgroundColor #438DD5
BorderColor #3C7FC0
}
skinparam queue<<container>> {
StereotypeFontColor #FFFFFF
FontColor #FFFFFF
BackgroundColor #438DD5
BorderColor #3C7FC0
}
skinparam actor<<container>> {
StereotypeFontColor #438DD5
FontColor #438DD5
BackgroundColor #438DD5
BorderColor #3C7FC0
}
skinparam person<<container>> {
StereotypeFontColor #FFFFFF
FontColor #FFFFFF
BackgroundColor #438DD5
BorderColor #3C7FC0
}
skinparam rectangle<<external_container>> {
StereotypeFontColor #FFFFFF
FontColor #FFFFFF
BackgroundColor #B3B3B3
BorderColor #A6A6A6
}
skinparam database<<external_container>> {
StereotypeFontColor #FFFFFF
FontColor #FFFFFF
BackgroundColor #B3B3B3
BorderColor #A6A6A6
}
skinparam queue<<external_container>> {
StereotypeFontColor #FFFFFF
FontColor #FFFFFF
BackgroundColor #B3B3B3
BorderColor #A6A6A6
}
skinparam actor<<external_container>> {
StereotypeFontColor #B3B3B3
FontColor #B3B3B3
BackgroundColor #B3B3B3
BorderColor #A6A6A6
}
skinparam person<<external_container>> {
StereotypeFontColor #FFFFFF
FontColor #FFFFFF
BackgroundColor #B3B3B3
BorderColor #A6A6A6
}
skinparam rectangle<<smart-contract>> {
BackgroundColor #0abab5
}
skinparam database<<smart-contract>> {
BackgroundColor #0abab5
}
skinparam queue<<smart-contract>> {
BackgroundColor #0abab5
}
skinparam actor<<smart-contract>> {
StereotypeFontColor #0abab5
FontColor #0abab5
BackgroundColor #0abab5
}
skinparam person<<smart-contract>> {
BackgroundColor #0abab5
}
rectangle "<$person>\n==User\n\n User with or without credentials" <<person>> as user
rectangle "==FrostFS\n<size:12>[System]</size>" <<boundary>> as c1 {
rectangle "==S3 Gateway\n//<size:12>[]</size>//\n\n AWS S3 compatible gate" <<container>> as s3
rectangle "==FrostFS Storage\n//<size:12>[]</size>//\n\n Storage service" <<container>> as stor
}
rectangle "==Blockchain\n<size:12>[System]</size>" <<boundary>> as c3 {
Interface "NeoGo"
rectangle "==FrostFS ID\n//<size:12>[]</size>//\n\n Stores namespaces and users" <<smart-contract>><<container>> as ffsid
rectangle "==Policy\n//<size:12>[]</size>//\n\n Stores APE rules" <<smart-contract>><<container>> as policy
}
user -RIGHT->> s3 : **Requests**\n//<size:12>[HTTP]</size>//
s3 -RIGHT->> stor : **Get data to validate request, store objects**
s3 -DOWN->> NeoGo : **Get data to validate request**
NeoGo - ->> ffsid : **Fetch users**
NeoGo - ->> policy : **Fetch policies**
hide stereotype
legend right
<#00000000,#00000000>|<color:#000000>**Legend**</color> |
|<#08427B><color:#073B6F> <U+25AF></color> <color:#FFFFFF> person </color> |
|<#438DD5><color:#3C7FC0> <U+25AF></color> <color:#FFFFFF> container </color> |
|<#0abab5><color:#0abab5> <U+25AF></color> <color:#66622E> smart-contract (no text color) </color> |
endlegend
@enduml
PlantUML version 1.2022.13(Sat Nov 19 16:22:17 MSK 2022)
(GPL source distribution)
Java Runtime: OpenJDK Runtime Environment
JVM: OpenJDK 64-Bit Server VM
Default Encoding: UTF-8
Language: en
Country: US
--></g></svg>

Before

Width:  |  Height:  |  Size: 25 KiB

View file

@ -1,60 +0,0 @@
@startuml
participant User
participant "S3-GW"
collections "FrostFS Storage"
User -> "S3-GW": Request
group signed request
"S3-GW" -> "FrostFS Storage": Find Access Box
"FrostFS Storage" -> "FrostFS Storage": Check request
alt #pink Check failure
"FrostFS Storage" -->> "S3-GW": Access Denied
"S3-GW" -->> User: Access Denied
end
"FrostFS Storage" -->> "S3-GW": Access Box
"S3-GW" -> "S3-GW": Check sign
alt #pink Check failure
"S3-GW" -->> User: Access Denied
end
"S3-GW" -> "frostfsid contract": Find user
"frostfsid contract" -->> "S3-GW": User info
"S3-GW" -> "S3-GW": Check user info
alt #pink Check failure
"S3-GW" -->> User: Access Denied
end
end
"S3-GW" -> "policy contract": Get policies
"policy contract" -->> "S3-GW": Policies
"S3-GW" -> "S3-GW": Check policy
alt #pink Check failure
"S3-GW" -->> User: Access Denied
end
"S3-GW" -> "FrostFS Storage": User Request
"FrostFS Storage" -> "FrostFS Storage": Check request
alt #pink Check failure
"FrostFS Storage" -->> "S3-GW": Access Denied
"S3-GW" -->> User: Access Denied
end
"FrostFS Storage" -->> "S3-GW": Response
"S3-GW" -->> User: Response
box "Neo Go"
participant "frostfsid contract"
participant "policy contract"
end box
@enduml

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

8
go.mod
View file

@ -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.20240327095603-491a47e7fe24
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-20240402141549-3790142b10c7
git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240412102212-530248de754c
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
@ -30,7 +30,6 @@ require (
go.uber.org/zap v1.26.0
golang.org/x/crypto v0.17.0
golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63
golang.org/x/net v0.17.0
google.golang.org/grpc v1.59.0
google.golang.org/protobuf v1.33.0
)
@ -92,6 +91,7 @@ require (
go.opentelemetry.io/otel/sdk v1.16.0 // indirect
go.opentelemetry.io/proto/otlp v0.19.0 // indirect
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.15.0 // indirect
golang.org/x/term v0.15.0 // indirect

12
go.sum
View file

@ -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.20240327095603-491a47e7fe24 h1:uIkl0mKWwDICUZTbNWZ38HLYDBI9rMgdAhYQWZ0C9iQ=
git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240327095603-491a47e7fe24/go.mod h1:OBDSr+DqV1z4VDouoX3YMleNc4DPBVBWTG3WDT2PK1o=
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-20240402141549-3790142b10c7 h1:sjvYXV0WJAF4iNF3l0uhcN8zhXmpY1gYI0WyJpeFe6s=
git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240402141549-3790142b10c7/go.mod h1:i0RKqiF4z3UOxLSNwhHw+cUz/JyYWuTRpnn9ere4Y3w=
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-20240412102212-530248de754c h1:Ei15WKKLDXoFqEIe292szb3RfsyLqRZfeJX2FjFvz6k=
git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240412102212-530248de754c/go.mod h1:H/AW85RtYxVTbcgwHW76DqXeKlsiCIOeNXHPqyDBrfQ=
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=

View file

@ -117,12 +117,16 @@ func (c *MorphRuleChainStorage) SaveACLChains(cid string, chains []*chain.Chain)
}
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 {

View file

@ -135,9 +135,6 @@ const (
ControlAPIGetPolicy = "get policy request"
ControlAPIListPolicies = "list policies request"
PolicyValidationFailed = "policy validation failed"
ServerReconnecting = "reconnecting server..."
ServerReconnectedSuccessfully = "server reconnected successfully"
ServerReconnectFailed = "failed to reconnect server"
ParseTreeNode = "parse tree node"
FailedToGetRealObjectSize = "failed to get real object size"
CouldntDeleteObjectFromStorageContinueDeleting = "couldn't delete object from storage, continue deleting from tree"
@ -152,6 +149,5 @@ const (
InvalidBucketObjectLockEnabledHeader = "invalid X-Amz-Bucket-Object-Lock-Enabled header"
InvalidTreeKV = "invalid tree service meta KV"
FailedToWriteResponse = "failed to write response"
WarnDuplicateAddress = "duplicate address"
PolicyCouldntBeConvertedToNativeRules = "policy couldn't be converted to native rules, only s3 rules be applied"
)

View file

@ -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,
},
}

View file

@ -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())
}

View file

@ -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,

View file

@ -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;

View file

@ -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
}

View file

@ -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