[#405] English Check

Signed-off-by: Elizaveta Chichindaeva <elizaveta@nspcc.ru>
This commit is contained in:
Elizaveta Chichindaeva 2022-04-13 19:56:58 +03:00 committed by Alex Vanin
parent a0a04a73bd
commit bf38007692
42 changed files with 205 additions and 205 deletions

View file

@ -252,7 +252,7 @@ func hmacSHA256(key []byte, data []byte) []byte {
return hash.Sum(nil) return hash.Sum(nil)
} }
// MultipartFormValue get value by key from multipart form. // MultipartFormValue gets value by key from multipart form.
func MultipartFormValue(r *http.Request, key string) string { func MultipartFormValue(r *http.Request, key string) string {
if r.MultipartForm == nil { if r.MultipartForm == nil {
return "" return ""

View file

@ -9,7 +9,7 @@ import (
) )
type ( type (
// AccessBoxCache stores access box by its address. // AccessBoxCache stores an access box by its address.
AccessBoxCache struct { AccessBoxCache struct {
cache gcache.Cache cache gcache.Cache
} }
@ -24,11 +24,11 @@ type (
const ( const (
// DefaultAccessBoxCacheSize is a default maximum number of entries in cache. // DefaultAccessBoxCacheSize is a default maximum number of entries in cache.
DefaultAccessBoxCacheSize = 100 DefaultAccessBoxCacheSize = 100
// DefaultAccessBoxCacheLifetime is a default lifetime of entries in cache. // DefaultAccessBoxCacheLifetime is a default lifetime of entries in cache.
DefaultAccessBoxCacheLifetime = 10 * time.Minute DefaultAccessBoxCacheLifetime = 10 * time.Minute
) )
// DefaultAccessBoxConfig return new default cache expiration values. // DefaultAccessBoxConfig returns new default cache expiration values.
func DefaultAccessBoxConfig() *Config { func DefaultAccessBoxConfig() *Config {
return &Config{Size: DefaultAccessBoxCacheSize, Lifetime: DefaultAccessBoxCacheLifetime} return &Config{Size: DefaultAccessBoxCacheSize, Lifetime: DefaultAccessBoxCacheLifetime}
} }
@ -40,7 +40,7 @@ func NewAccessBoxCache(config *Config) *AccessBoxCache {
return &AccessBoxCache{cache: gc} return &AccessBoxCache{cache: gc}
} }
// Get returns cached object. // Get returns a cached object.
func (o *AccessBoxCache) Get(address *address.Address) *accessbox.Box { func (o *AccessBoxCache) Get(address *address.Address) *accessbox.Box {
entry, err := o.cache.Get(address.String()) entry, err := o.cache.Get(address.String())
if err != nil { if err != nil {

View file

@ -7,7 +7,7 @@ import (
"github.com/nspcc-dev/neofs-s3-gw/api/data" "github.com/nspcc-dev/neofs-s3-gw/api/data"
) )
// BucketCache contains cache with objects and lifetime of cache entries. // BucketCache contains cache with objects and the lifetime of cache entries.
type BucketCache struct { type BucketCache struct {
cache gcache.Cache cache gcache.Cache
} }
@ -15,11 +15,11 @@ type BucketCache struct {
const ( const (
// DefaultBucketCacheSize is a default maximum number of entries in cache. // DefaultBucketCacheSize is a default maximum number of entries in cache.
DefaultBucketCacheSize = 1e3 DefaultBucketCacheSize = 1e3
// DefaultBucketCacheLifetime is a default lifetime of entries in cache. // DefaultBucketCacheLifetime is a default lifetime of entries in cache.
DefaultBucketCacheLifetime = time.Minute DefaultBucketCacheLifetime = time.Minute
) )
// DefaultBucketConfig return new default cache expiration values. // DefaultBucketConfig returns new default cache expiration values.
func DefaultBucketConfig() *Config { func DefaultBucketConfig() *Config {
return &Config{Size: DefaultBucketCacheSize, Lifetime: DefaultBucketCacheLifetime} return &Config{Size: DefaultBucketCacheSize, Lifetime: DefaultBucketCacheLifetime}
} }
@ -30,7 +30,7 @@ func NewBucketCache(config *Config) *BucketCache {
return &BucketCache{cache: gc} return &BucketCache{cache: gc}
} }
// Get returns cached object. // Get returns a cached object.
func (o *BucketCache) Get(key string) *data.BucketInfo { func (o *BucketCache) Get(key string) *data.BucketInfo {
entry, err := o.cache.Get(key) entry, err := o.cache.Get(key)
if err != nil { if err != nil {

10
api/cache/names.go vendored
View file

@ -7,8 +7,8 @@ import (
"github.com/nspcc-dev/neofs-sdk-go/object/address" "github.com/nspcc-dev/neofs-sdk-go/object/address"
) )
// ObjectsNameCache provides for lru cache for objects. // ObjectsNameCache provides lru cache for objects.
// This cache contains mapping nice name to object addresses. // This cache contains mapping nice names to object addresses.
// Key is bucketName+objectName. // Key is bucketName+objectName.
type ObjectsNameCache struct { type ObjectsNameCache struct {
cache gcache.Cache cache gcache.Cache
@ -17,11 +17,11 @@ type ObjectsNameCache struct {
const ( const (
// DefaultObjectsNameCacheSize is a default maximum number of entries in cache. // DefaultObjectsNameCacheSize is a default maximum number of entries in cache.
DefaultObjectsNameCacheSize = 1e4 DefaultObjectsNameCacheSize = 1e4
// DefaultObjectsNameCacheLifetime is a default lifetime of entries in cache. // DefaultObjectsNameCacheLifetime is a default lifetime of entries in cache.
DefaultObjectsNameCacheLifetime = time.Minute DefaultObjectsNameCacheLifetime = time.Minute
) )
// DefaultObjectsNameConfig return new default cache expiration values. // DefaultObjectsNameConfig returns new default cache expiration values.
func DefaultObjectsNameConfig() *Config { func DefaultObjectsNameConfig() *Config {
return &Config{Size: DefaultObjectsNameCacheSize, Lifetime: DefaultObjectsNameCacheLifetime} return &Config{Size: DefaultObjectsNameCacheSize, Lifetime: DefaultObjectsNameCacheLifetime}
} }
@ -32,7 +32,7 @@ func NewObjectsNameCache(config *Config) *ObjectsNameCache {
return &ObjectsNameCache{cache: gc} return &ObjectsNameCache{cache: gc}
} }
// Get returns cached object. // Get returns a cached object.
func (o *ObjectsNameCache) Get(key string) *address.Address { func (o *ObjectsNameCache) Get(key string) *address.Address {
entry, err := o.cache.Get(key) entry, err := o.cache.Get(key)
if err != nil { if err != nil {

View file

@ -16,11 +16,11 @@ type ObjectsCache struct {
const ( const (
// DefaultObjectsCacheLifetime is a default lifetime of entries in objects' cache. // DefaultObjectsCacheLifetime is a default lifetime of entries in objects' cache.
DefaultObjectsCacheLifetime = time.Minute * 5 DefaultObjectsCacheLifetime = time.Minute * 5
// DefaultObjectsCacheSize is a default maximum number of entries in objects' in cache. // DefaultObjectsCacheSize is a default maximum number of entries in objects' cache.
DefaultObjectsCacheSize = 1e6 DefaultObjectsCacheSize = 1e6
) )
// DefaultObjectsConfig return new default cache expiration values. // DefaultObjectsConfig returns new default cache expiration values.
func DefaultObjectsConfig() *Config { func DefaultObjectsConfig() *Config {
return &Config{Size: DefaultObjectsCacheSize, Lifetime: DefaultObjectsCacheLifetime} return &Config{Size: DefaultObjectsCacheSize, Lifetime: DefaultObjectsCacheLifetime}
} }
@ -31,7 +31,7 @@ func New(config *Config) *ObjectsCache {
return &ObjectsCache{cache: gc} return &ObjectsCache{cache: gc}
} }
// Get returns cached object. // Get returns a cached object.
func (o *ObjectsCache) Get(address *address.Address) *object.Object { func (o *ObjectsCache) Get(address *address.Address) *object.Object {
entry, err := o.cache.Get(address.String()) entry, err := o.cache.Get(address.String())
if err != nil { if err != nil {

View file

@ -11,16 +11,16 @@ import (
) )
/* /*
This is an implementation of a cache which keeps unsorted lists of objects' IDs (all versions) This is an implementation of cache which keeps unsorted lists of objects' IDs (all versions)
for a specified bucket and a prefix. for a specified bucket and a prefix.
The cache contains gcache whose entries have a key: ObjectsListKey struct and a value: list of ids. The cache contains gcache whose entries have a key: ObjectsListKey struct and a value: list of ids.
After putting a record it lives for a while (default value is 60 seconds). After putting a record, it lives for a while (default value is 60 seconds).
When we receive a request from the user we try to find the suitable and non-expired cache entry, go through the list When we receive a request from a user, we try to find the suitable and non-expired cache entry, go through the list
and get ObjectInfos from common object cache or with a request to NeoFS. and get ObjectInfos from common object cache or with a request to NeoFS.
When we put an object into a container we invalidate entries with prefixes that are prefixes of the object's name. When we put an object into a container, we invalidate entries with prefixes that are prefixes of the object's name.
*/ */
type ( type (
@ -43,18 +43,18 @@ const (
DefaultObjectsListCacheSize = 1e5 DefaultObjectsListCacheSize = 1e5
) )
// DefaultObjectsListConfig return new default cache expiration values. // DefaultObjectsListConfig returns new default cache expiration values.
func DefaultObjectsListConfig() *Config { func DefaultObjectsListConfig() *Config {
return &Config{Size: DefaultObjectsListCacheSize, Lifetime: DefaultObjectsListCacheLifetime} return &Config{Size: DefaultObjectsListCacheSize, Lifetime: DefaultObjectsListCacheLifetime}
} }
// NewObjectsListCache is a constructor which creates an object of ListObjectsCache with given lifetime of entries. // NewObjectsListCache is a constructor which creates an object of ListObjectsCache with the given lifetime of entries.
func NewObjectsListCache(config *Config) *ObjectsListCache { func NewObjectsListCache(config *Config) *ObjectsListCache {
gc := gcache.New(config.Size).LRU().Expiration(config.Lifetime).Build() gc := gcache.New(config.Size).LRU().Expiration(config.Lifetime).Build()
return &ObjectsListCache{cache: gc} return &ObjectsListCache{cache: gc}
} }
// Get return list of ObjectInfo. // Get returns a list of ObjectInfo.
func (l *ObjectsListCache) Get(key ObjectsListKey) []oid.ID { func (l *ObjectsListCache) Get(key ObjectsListKey) []oid.ID {
entry, err := l.cache.Get(key) entry, err := l.cache.Get(key)
if err != nil { if err != nil {
@ -93,7 +93,7 @@ func (l *ObjectsListCache) CleanCacheEntriesContainingObject(objectName string,
} }
} }
// CreateObjectsListCacheKey returns ObjectsListKey with given CID and prefix. // CreateObjectsListCacheKey returns ObjectsListKey with the given CID and prefix.
func CreateObjectsListCacheKey(cid *cid.ID, prefix string) ObjectsListKey { func CreateObjectsListCacheKey(cid *cid.ID, prefix string) ObjectsListKey {
p := ObjectsListKey{ p := ObjectsListKey{
cid: cid.String(), cid: cid.String(),

6
api/cache/system.go vendored
View file

@ -17,11 +17,11 @@ type SystemCache struct {
const ( const (
// DefaultSystemCacheSize is a default maximum number of entries in cache. // DefaultSystemCacheSize is a default maximum number of entries in cache.
DefaultSystemCacheSize = 1e4 DefaultSystemCacheSize = 1e4
// DefaultSystemCacheLifetime is a default lifetime of entries in cache. // DefaultSystemCacheLifetime is a default lifetime of entries in cache.
DefaultSystemCacheLifetime = 5 * time.Minute DefaultSystemCacheLifetime = 5 * time.Minute
) )
// DefaultSystemConfig return new default cache expiration values. // DefaultSystemConfig returns new default cache expiration values.
func DefaultSystemConfig() *Config { func DefaultSystemConfig() *Config {
return &Config{Size: DefaultSystemCacheSize, Lifetime: DefaultSystemCacheLifetime} return &Config{Size: DefaultSystemCacheSize, Lifetime: DefaultSystemCacheLifetime}
} }
@ -32,7 +32,7 @@ func NewSystemCache(config *Config) *SystemCache {
return &SystemCache{cache: gc} return &SystemCache{cache: gc}
} }
// GetObject returns cached object. // GetObject returns a cached object.
func (o *SystemCache) GetObject(key string) *data.ObjectInfo { func (o *SystemCache) GetObject(key string) *data.ObjectInfo {
entry, err := o.cache.Get(key) entry, err := o.cache.Get(key)
if err != nil { if err != nil {

View file

@ -68,10 +68,10 @@ type (
} }
) )
// SettingsObjectName is system name for bucket settings file. // SettingsObjectName is a system name for a bucket settings file.
func (b *BucketInfo) SettingsObjectName() string { return bktSettingsObject } func (b *BucketInfo) SettingsObjectName() string { return bktSettingsObject }
// CORSObjectName returns system name for bucket CORS configuration file. // CORSObjectName returns a system name for a bucket CORS configuration file.
func (b *BucketInfo) CORSObjectName() string { return bktCORSConfigurationObject } func (b *BucketInfo) CORSObjectName() string { return bktCORSConfigurationObject }
func (b *BucketInfo) NotificationConfigurationObjectName() string { func (b *BucketInfo) NotificationConfigurationObjectName() string {
@ -82,7 +82,7 @@ func (b *BucketInfo) NotificationConfigurationObjectName() string {
func (o *ObjectInfo) Version() string { return o.ID.String() } func (o *ObjectInfo) Version() string { return o.ID.String() }
// NullableVersion returns object version from ObjectInfo. // NullableVersion returns object version from ObjectInfo.
// Return "null" if "S3-Versions-unversioned" header present. // Return "null" if "S3-Versions-unversioned" header is present.
func (o *ObjectInfo) NullableVersion() string { func (o *ObjectInfo) NullableVersion() string {
if _, ok := o.Headers["S3-Versions-unversioned"]; ok { if _, ok := o.Headers["S3-Versions-unversioned"]; ok {
return "null" return "null"
@ -102,11 +102,11 @@ func (o *ObjectInfo) Address() *address.Address {
return addr return addr
} }
// TagsObject returns name of system object for tags. // TagsObject returns the name of a system object for tags.
func (o *ObjectInfo) TagsObject() string { return ".tagset." + o.Name + "." + o.Version() } func (o *ObjectInfo) TagsObject() string { return ".tagset." + o.Name + "." + o.Version() }
// LegalHoldObject returns name of system object for lock object. // LegalHoldObject returns the name of a system object for a lock object.
func (o *ObjectInfo) LegalHoldObject() string { return ".lock." + o.Name + "." + o.Version() } func (o *ObjectInfo) LegalHoldObject() string { return ".lock." + o.Name + "." + o.Version() }
// RetentionObject returns name of system object for retention lock object. // RetentionObject returns the name of a system object for a retention lock object.
func (o *ObjectInfo) RetentionObject() string { return ".retention." + o.Name + "." + o.Version() } func (o *ObjectInfo) RetentionObject() string { return ".retention." + o.Name + "." + o.Version() }

View file

@ -28,7 +28,7 @@ type (
Value string `xml:"Value" json:"Value"` Value string `xml:"Value" json:"Value"`
} }
// TopicConfiguration and LambdaFunctionConfiguration -- we don't support these configurations // TopicConfiguration and LambdaFunctionConfiguration -- we don't support these configurations,
// but we need them to detect in notification configurations in requests. // but we need them to detect in notification configurations in requests.
TopicConfiguration struct{} TopicConfiguration struct{}
LambdaFunctionConfiguration struct{} LambdaFunctionConfiguration struct{}

View file

@ -6,7 +6,7 @@ import (
) )
type ( type (
// ErrorCode type of error status. // ErrorCode type of an error status.
ErrorCode int ErrorCode int
errorCodeMap map[ErrorCode]Error errorCodeMap map[ErrorCode]Error
@ -20,7 +20,7 @@ type (
} }
) )
// Error codes, non exhaustive list - http://docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.html // Error codes, non exhaustive list -- http://docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.html
const ( const (
_ ErrorCode = iota _ ErrorCode = iota
ErrAccessDenied ErrAccessDenied
@ -273,7 +273,7 @@ const (
) )
// error code to Error structure, these fields carry respective // error code to Error structure, these fields carry respective
// descriptions for all the error responses. // descriptions for all error responses.
var errorCodes = errorCodeMap{ var errorCodes = errorCodeMap{
ErrInvalidCopyDest: { ErrInvalidCopyDest: {
ErrCode: ErrInvalidCopyDest, ErrCode: ErrInvalidCopyDest,
@ -768,7 +768,7 @@ var errorCodes = errorCodeMap{
HTTPStatusCode: http.StatusBadRequest, HTTPStatusCode: http.StatusBadRequest,
}, },
// FIXME: Actual XML error response also contains the header which missed in list of signed header parameters. // FIXME: Actual XML error response also contains the header which is missed in the list of signed header parameters.
ErrUnsignedHeaders: { ErrUnsignedHeaders: {
ErrCode: ErrUnsignedHeaders, ErrCode: ErrUnsignedHeaders,
Code: "AccessDenied", Code: "AccessDenied",
@ -1663,7 +1663,7 @@ var errorCodes = errorCodeMap{
// Add your error structure here. // Add your error structure here.
} }
// IsS3Error check if the provided error is a specific s3 error. // IsS3Error checks if the provided error is a specific s3 error.
func IsS3Error(err error, code ErrorCode) bool { func IsS3Error(err error, code ErrorCode) bool {
e, ok := err.(Error) e, ok := err.(Error)
return ok && e.ErrCode == code return ok && e.ErrCode == code
@ -1688,7 +1688,7 @@ func (e Error) Error() string {
return fmt.Sprintf("%s: %d => %s", e.Code, e.HTTPStatusCode, e.Description) return fmt.Sprintf("%s: %d => %s", e.Code, e.HTTPStatusCode, e.Description)
} }
// GetAPIError provides API Error for input API error code. // GetAPIError provides API Error for an input API error code.
func GetAPIError(code ErrorCode) Error { func GetAPIError(code ErrorCode) Error {
if apiErr, ok := errorCodes[code]; ok { if apiErr, ok := errorCodes[code]; ok {
return apiErr return apiErr
@ -1696,12 +1696,12 @@ func GetAPIError(code ErrorCode) Error {
return errorCodes.toAPIErr(ErrInternalError) return errorCodes.toAPIErr(ErrInternalError)
} }
// GetAPIErrorWithError provides API Error with additional error message for input API error code. // GetAPIErrorWithError provides API Error with additional error message for an input API error code.
func GetAPIErrorWithError(code ErrorCode, err error) Error { func GetAPIErrorWithError(code ErrorCode, err error) Error {
return errorCodes.toAPIErrWithErr(code, err) return errorCodes.toAPIErrWithErr(code, err)
} }
// ObjectError - error that linked to specific object. // ObjectError -- error that is linked to a specific object.
type ObjectError struct { type ObjectError struct {
Err error Err error
Object string Object string
@ -1712,7 +1712,7 @@ func (e ObjectError) Error() string {
return fmt.Sprintf("%s (%s:%s)", e.Err, e.Object, e.Version) return fmt.Sprintf("%s (%s:%s)", e.Err, e.Object, e.Version)
} }
// ObjectVersion get "object:version" string. // ObjectVersion gets "object:version" string.
func (e ObjectError) ObjectVersion() string { func (e ObjectError) ObjectVersion() string {
return e.Object + ":" + e.Version return e.Object + ":" + e.Version
} }

View file

@ -357,7 +357,7 @@ func checkOwner(info *data.BucketInfo, owner string) error {
return nil return nil
} }
// maybe need to convert owner to appropriate format // may need to convert owner to appropriate format
if info.Owner.String() != owner { if info.Owner.String() != owner {
return errors.GetAPIError(errors.ErrAccessDenied) return errors.GetAPIError(errors.ErrAccessDenied)
} }

View file

@ -16,14 +16,14 @@ type (
cfg *Config cfg *Config
} }
// Config contains data which handler need to keep. // Config contains data which handler needs to keep.
Config struct { Config struct {
DefaultPolicy *netmap.PlacementPolicy DefaultPolicy *netmap.PlacementPolicy
DefaultMaxAge int DefaultMaxAge int
} }
) )
// DefaultPolicy is a default policy of placing container in NeoFS if it's not set at the request. // DefaultPolicy is a default policy of placing containers in NeoFS if it's not set at the request.
const DefaultPolicy = "REP 3" const DefaultPolicy = "REP 3"
var _ api.Handler = (*handler)(nil) var _ api.Handler = (*handler)(nil)

View file

@ -20,7 +20,7 @@ type copyObjectArgs struct {
const replaceMetadataDirective = "REPLACE" const replaceMetadataDirective = "REPLACE"
// path2BucketObject returns bucket and object. // path2BucketObject returns a bucket and an object.
func path2BucketObject(path string) (bucket, prefix string) { func path2BucketObject(path string) (bucket, prefix string) {
path = strings.TrimPrefix(path, api.SlashSeparator) path = strings.TrimPrefix(path, api.SlashSeparator)
m := strings.Index(path, api.SlashSeparator) m := strings.Index(path, api.SlashSeparator)

View file

@ -11,7 +11,7 @@ import (
) )
const ( const (
// DefaultMaxAge -- default value of Access-Control-Max-Age if this value is not set in a rule. // DefaultMaxAge is a default value of Access-Control-Max-Age if this value is not set in a rule.
DefaultMaxAge = 600 DefaultMaxAge = 600
wildcard = "*" wildcard = "*"
) )

View file

@ -15,7 +15,7 @@ import (
"go.uber.org/zap/zapcore" "go.uber.org/zap/zapcore"
) )
// DeleteObjectsRequest - xml carrying the object key names which needs to be deleted. // DeleteObjectsRequest -- xml carrying the object key names which should be deleted.
type DeleteObjectsRequest struct { type DeleteObjectsRequest struct {
// Element to enable quiet mode for the request // Element to enable quiet mode for the request
Quiet bool Quiet bool
@ -23,13 +23,13 @@ type DeleteObjectsRequest struct {
Objects []ObjectIdentifier `xml:"Object"` Objects []ObjectIdentifier `xml:"Object"`
} }
// ObjectIdentifier carries key name for the object to delete. // ObjectIdentifier carries the key name for the object to delete.
type ObjectIdentifier struct { type ObjectIdentifier struct {
ObjectName string `xml:"Key"` ObjectName string `xml:"Key"`
VersionID string `xml:"VersionId,omitempty"` VersionID string `xml:"VersionId,omitempty"`
} }
// DeletedObject carries key name for the object to delete. // DeletedObject carries the key name for the object to delete.
type DeletedObject struct { type DeletedObject struct {
ObjectIdentifier ObjectIdentifier
DeleteMarker bool `xml:"DeleteMarker,omitempty"` DeleteMarker bool `xml:"DeleteMarker,omitempty"`
@ -144,7 +144,7 @@ func (h *handler) DeleteObjectHandler(w http.ResponseWriter, r *http.Request) {
func (h *handler) DeleteMultipleObjectsHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) DeleteMultipleObjectsHandler(w http.ResponseWriter, r *http.Request) {
reqInfo := api.GetReqInfo(r.Context()) reqInfo := api.GetReqInfo(r.Context())
// Content-Md5 is requied should be set // Content-Md5 is required and should be set
// http://docs.aws.amazon.com/AmazonS3/latest/API/multiobjectdeleteapi.html // http://docs.aws.amazon.com/AmazonS3/latest/API/multiobjectdeleteapi.html
if _, ok := r.Header[api.ContentMD5]; !ok { if _, ok := r.Header[api.ContentMD5]; !ok {
h.logAndSendError(w, "missing Content-MD5", reqInfo, errors.GetAPIError(errors.ErrMissingContentMD5)) h.logAndSendError(w, "missing Content-MD5", reqInfo, errors.GetAPIError(errors.ErrMissingContentMD5))

View file

@ -480,7 +480,7 @@ func TestObjectLegalHold(t *testing.T) {
hc.Handler().GetObjectLegalHoldHandler(w, r) hc.Handler().GetObjectLegalHoldHandler(w, r)
assertLegalHold(t, w, legalHoldOn) assertLegalHold(t, w, legalHoldOn)
// to make sure put hold is idempotent operation // to make sure put hold is an idempotent operation
w, r = prepareTestRequest(t, bktName, objName, &data.LegalHold{Status: legalHoldOn}) w, r = prepareTestRequest(t, bktName, objName, &data.LegalHold{Status: legalHoldOn})
hc.Handler().PutObjectLegalHoldHandler(w, r) hc.Handler().PutObjectLegalHoldHandler(w, r)
require.Equal(t, http.StatusOK, w.Code) require.Equal(t, http.StatusOK, w.Code)
@ -493,7 +493,7 @@ func TestObjectLegalHold(t *testing.T) {
hc.Handler().GetObjectLegalHoldHandler(w, r) hc.Handler().GetObjectLegalHoldHandler(w, r)
assertLegalHold(t, w, legalHoldOff) assertLegalHold(t, w, legalHoldOff)
// to make sure put hold is idempotent operation // to make sure put hold is an idempotent operation
w, r = prepareTestRequest(t, bktName, objName, &data.LegalHold{Status: legalHoldOff}) w, r = prepareTestRequest(t, bktName, objName, &data.LegalHold{Status: legalHoldOff})
hc.Handler().PutObjectLegalHoldHandler(w, r) hc.Handler().PutObjectLegalHoldHandler(w, r)
require.Equal(t, http.StatusOK, w.Code) require.Equal(t, http.StatusOK, w.Code)

View file

@ -2,7 +2,7 @@ package handler
import "encoding/xml" import "encoding/xml"
// ListBucketsResponse - format for list buckets response. // ListBucketsResponse -- format for list buckets response.
type ListBucketsResponse struct { type ListBucketsResponse struct {
XMLName xml.Name `xml:"http://s3.amazonaws.com/doc/2006-03-01/ ListAllMyBucketsResult" json:"-"` XMLName xml.Name `xml:"http://s3.amazonaws.com/doc/2006-03-01/ ListAllMyBucketsResult" json:"-"`
@ -85,7 +85,7 @@ func NewGrantee(t GranteeType) *Grantee {
} }
} }
// Owner - bucket owner/principal. // Owner -- bucket owner/principal.
type Owner struct { type Owner struct {
ID string ID string
DisplayName string DisplayName string
@ -106,7 +106,7 @@ type Object struct {
// Owner of the object. // Owner of the object.
Owner *Owner `xml:"Owner,omitempty"` Owner *Owner `xml:"Owner,omitempty"`
// The class of storage used to store the object. // Class of storage used to store the object.
StorageClass string `xml:"StorageClass,omitempty"` StorageClass string `xml:"StorageClass,omitempty"`
} }
@ -134,7 +134,7 @@ type DeleteMarkerEntry struct {
// StringMap is a map[string]string. // StringMap is a map[string]string.
type StringMap map[string]string type StringMap map[string]string
// LocationResponse - format for location response. // LocationResponse -- format for location response.
type LocationResponse struct { type LocationResponse struct {
XMLName xml.Name `xml:"http://s3.amazonaws.com/doc/2006-03-01/ LocationConstraint" json:"-"` XMLName xml.Name `xml:"http://s3.amazonaws.com/doc/2006-03-01/ LocationConstraint" json:"-"`
Location string `xml:",chardata"` Location string `xml:",chardata"`
@ -182,13 +182,13 @@ type PostResponse struct {
ETag string `xml:"Etag"` ETag string `xml:"Etag"`
} }
// Tag is AWS key-value tag. // Tag is an AWS key-value tag.
type Tag struct { type Tag struct {
Key string Key string
Value string Value string
} }
// MarshalXML - StringMap marshals into XML. // MarshalXML -- StringMap marshals into XML.
func (s StringMap) MarshalXML(e *xml.Encoder, start xml.StartElement) error { func (s StringMap) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
tokens := []xml.Token{start} tokens := []xml.Token{start}

View file

@ -28,7 +28,7 @@ func shouldEscape(c byte) bool {
return true return true
} }
// s3URLEncode is based on url.QueryEscape() code, // s3URLEncode is based on url.QueryEscape() code
// while considering some S3 exceptions. // while considering some S3 exceptions.
func s3URLEncode(s string, mode encoding) string { func s3URLEncode(s string, mode encoding) string {
spaceCount, hexCount := 0, 0 spaceCount, hexCount := 0, 0

View file

@ -270,8 +270,8 @@ func DefaultCachesConfigs() *CachesConfig {
} }
} }
// NewLayer creates instance of layer. It checks credentials // NewLayer creates an instance of a layer. It checks credentials
// and establishes gRPC connection with node. // and establishes gRPC connection with the node.
func NewLayer(log *zap.Logger, neoFS neofs.NeoFS, config *Config) Client { func NewLayer(log *zap.Logger, neoFS neofs.NeoFS, config *Config) Client {
return &layer{ return &layer{
neoFS: neoFS, neoFS: neoFS,
@ -307,7 +307,7 @@ func (n *layer) IsNotificationEnabled() bool {
return n.ncontroller != nil return n.ncontroller != nil
} }
// IsAuthenticatedRequest check if access box exists in current request. // IsAuthenticatedRequest checks if access box exists in the current request.
func IsAuthenticatedRequest(ctx context.Context) bool { func IsAuthenticatedRequest(ctx context.Context) bool {
_, ok := ctx.Value(api.BoxData).(*accessbox.Box) _, ok := ctx.Value(api.BoxData).(*accessbox.Box)
return ok return ok
@ -364,12 +364,12 @@ func (n *layer) GetBucketACL(ctx context.Context, bktInfo *data.BucketInfo) (*Bu
}, nil }, nil
} }
// PutBucketACL put bucket acl by name. // PutBucketACL puts bucket acl by name.
func (n *layer) PutBucketACL(ctx context.Context, param *PutBucketACLParams) error { func (n *layer) PutBucketACL(ctx context.Context, param *PutBucketACLParams) error {
return n.setContainerEACLTable(ctx, param.BktInfo.CID, param.EACL) return n.setContainerEACLTable(ctx, param.BktInfo.CID, param.EACL)
} }
// ListBuckets returns all user containers. Name of the bucket is a container // ListBuckets returns all user containers. The name of the bucket is a container
// id. Timestamp is omitted since it is not saved in neofs container. // id. Timestamp is omitted since it is not saved in neofs container.
func (n *layer) ListBuckets(ctx context.Context) ([]*data.BucketInfo, error) { func (n *layer) ListBuckets(ctx context.Context) ([]*data.BucketInfo, error) {
return n.containerList(ctx) return n.containerList(ctx)
@ -532,7 +532,7 @@ func (n *layer) CopyObject(ctx context.Context, p *CopyObjectParams) (*data.Obje
}) })
} }
// DeleteObject removes all objects with passed nice name. // DeleteObject removes all objects with the passed nice name.
func (n *layer) deleteObject(ctx context.Context, bkt *data.BucketInfo, settings *data.BucketSettings, obj *VersionedObject) *VersionedObject { func (n *layer) deleteObject(ctx context.Context, bkt *data.BucketInfo, settings *data.BucketSettings, obj *VersionedObject) *VersionedObject {
var ( var (
err error err error

View file

@ -255,7 +255,7 @@ func (n *layer) CompleteMultipartUpload(ctx context.Context, p *CompleteMultipar
zap.String("uploadID", p.Info.UploadID), zap.String("uploadID", p.Info.UploadID),
zap.String("uploadKey", p.Info.Key), zap.String("uploadKey", p.Info.Key),
) )
// we return InternalError because if we are here it means we've checked InitPart before in handler and // we return InternalError because if we are here it means we've checked InitPart in handler before and
// received successful result, it's strange we didn't get the InitPart again // received successful result, it's strange we didn't get the InitPart again
return nil, errors.GetAPIError(errors.ErrInternalError) return nil, errors.GetAPIError(errors.ErrInternalError)
} }
@ -284,7 +284,7 @@ func (n *layer) CompleteMultipartUpload(ctx context.Context, p *CompleteMultipar
initMetadata[api.ContentType] = objects[0].ContentType initMetadata[api.ContentType] = objects[0].ContentType
} }
/* We will keep "S3-Upload-Id" attribute in completed object to determine is it "common" object or completed object. /* We will keep "S3-Upload-Id" attribute in a completed object to determine if it is a "common" object or a completed object.
We will need to differ these objects if something goes wrong during completing multipart upload. We will need to differ these objects if something goes wrong during completing multipart upload.
I.e. we had completed the object but didn't put tagging/acl for some reason */ I.e. we had completed the object but didn't put tagging/acl for some reason */
delete(initMetadata, UploadPartNumberAttributeName) delete(initMetadata, UploadPartNumberAttributeName)

View file

@ -57,7 +57,7 @@ type PrmObjectSelect struct {
// Container to select the objects from. // Container to select the objects from.
Container cid.ID Container cid.ID
// Key-value object attribute which should exactly be // Key-value object attribute which should be
// presented in selected objects. Optional, empty key means any. // presented in selected objects. Optional, empty key means any.
ExactAttribute [2]string ExactAttribute [2]string
@ -141,53 +141,53 @@ var ErrAccessDenied = errors.New("access denied")
// NeoFS represents virtual connection to NeoFS network. // NeoFS represents virtual connection to NeoFS network.
type NeoFS interface { type NeoFS interface {
// CreateContainer creates and saves parameterized container in NeoFS. // CreateContainer creates and saves parameterized container in NeoFS.
// It sets 'Timestamp' attribute to current time. // It sets 'Timestamp' attribute to the current time.
// Returns ID of the saved container. // It returns the ID of the saved container.
// //
// Returns exactly one non-nil value. Returns any error encountered which // It returns exactly one non-nil value. It returns any error encountered which
// prevented the container to be created. // prevented the container from being created.
CreateContainer(context.Context, PrmContainerCreate) (*cid.ID, error) CreateContainer(context.Context, PrmContainerCreate) (*cid.ID, error)
// Container reads container from NeoFS by ID. // Container reads a container from NeoFS by ID.
// //
// Returns exactly one non-nil value. Returns any error encountered which // It returns exactly one non-nil value. It returns any error encountered which
// prevented the container to be read. // prevented the container from being read.
Container(context.Context, cid.ID) (*container.Container, error) Container(context.Context, cid.ID) (*container.Container, error)
// UserContainers reads list of the containers owned by specified user. // UserContainers reads a list of the containers owned by the specified user.
// //
// Returns exactly one non-nil value. Returns any error encountered which // It returns exactly one non-nil value. It returns any error encountered which
// prevented the containers to be listed. // prevented the containers from being listed.
UserContainers(context.Context, owner.ID) ([]cid.ID, error) UserContainers(context.Context, owner.ID) ([]cid.ID, error)
// SetContainerEACL saves eACL table of the container in NeoFS. // SetContainerEACL saves the eACL table of the container in NeoFS.
// //
// Returns any error encountered which prevented the eACL to be saved. // It returns any error encountered which prevented the eACL from being saved.
SetContainerEACL(context.Context, eacl.Table) error SetContainerEACL(context.Context, eacl.Table) error
// ContainerEACL reads container eACL from NeoFS by container ID. // ContainerEACL reads the container eACL from NeoFS by the container ID.
// //
// Returns exactly one non-nil value. Returns any error encountered which // It returns exactly one non-nil value. It returns any error encountered which
// prevented the eACL to be read. // prevented the eACL from being read.
ContainerEACL(context.Context, cid.ID) (*eacl.Table, error) ContainerEACL(context.Context, cid.ID) (*eacl.Table, error)
// DeleteContainer marks the container to be removed from NeoFS by ID. // DeleteContainer marks the container to be removed from NeoFS by ID.
// Request is sent within session if the session token is specified. // Request is sent within session if the session token is specified.
// Successful return does not guarantee the actual removal. // Successful return does not guarantee actual removal.
// //
// Returns any error encountered which prevented the removal request to be sent. // It returns any error encountered which prevented the removal request from being sent.
DeleteContainer(context.Context, cid.ID, *session.Token) error DeleteContainer(context.Context, cid.ID, *session.Token) error
// SelectObjects perform object selection from the NeoFS container according // SelectObjects performs object selection from the NeoFS container according
// to specified parameters. Selects user objects only. // to the specified parameters. It selects user's objects only.
// //
// Returns ErrAccessDenied on selection access violation. // It returns ErrAccessDenied on selection access violation.
// //
// Returns exactly one non-nil value. Returns any error encountered which // It returns exactly one non-nil value. It returns any error encountered which
// prevented the objects to be selected. // prevented the objects from being selected.
SelectObjects(context.Context, PrmObjectSelect) ([]oid.ID, error) SelectObjects(context.Context, PrmObjectSelect) ([]oid.ID, error)
// ReadObject reads part of the object from the NeoFS container by identifier. // ReadObject reads a part of the object from the NeoFS container by identifier.
// Exact part is returned according to the parameters: // Exact part is returned according to the parameters:
// * with header only: empty payload (both in-mem and reader parts are nil); // * with header only: empty payload (both in-mem and reader parts are nil);
// * with payload only: header is nil (zero range means full payload); // * with payload only: header is nil (zero range means full payload);
@ -197,37 +197,37 @@ type NeoFS interface {
// //
// Payload reader should be closed if it is no longer needed. // Payload reader should be closed if it is no longer needed.
// //
// Returns ErrAccessDenied on read access violation. // It returns ErrAccessDenied on read access violation.
// //
// Returns exactly one non-nil value. Returns any error encountered which // It returns exactly one non-nil value. It returns any error encountered which
// prevented the object header to be read. // prevented the object header from being read.
ReadObject(context.Context, PrmObjectRead) (*ObjectPart, error) ReadObject(context.Context, PrmObjectRead) (*ObjectPart, error)
// CreateObject creates and saves parameterized object in the NeoFS container. // CreateObject creates and saves a parameterized object in the NeoFS container.
// It sets 'Timestamp' attribute to current time. // It sets 'Timestamp' attribute to the current time.
// Returns ID of the saved object. // It returns the ID of the saved object.
// //
// Creation time should be written into object (UTC). // Creation time should be written into the object (UTC).
// //
// Returns ErrAccessDenied on write access violation. // It returns ErrAccessDenied on write access violation.
// //
// Returns exactly one non-nil value. Returns any error encountered which // It returns exactly one non-nil value. It returns any error encountered which
// prevented the container to be created. // prevented the container from being created.
CreateObject(context.Context, PrmObjectCreate) (*oid.ID, error) CreateObject(context.Context, PrmObjectCreate) (*oid.ID, error)
// DeleteObject marks the object to be removed from the NeoFS container by identifier. // DeleteObject marks the object to be removed from the NeoFS container by identifier.
// Successful return does not guarantee the actual removal. // Successful return does not guarantee actual removal.
// //
// Returns ErrAccessDenied on remove access violation. // It returns ErrAccessDenied on remove access violation.
// //
// Returns any error encountered which prevented the removal request to be sent. // It returns any error encountered which prevented the removal request from being sent.
DeleteObject(context.Context, PrmObjectDelete) error DeleteObject(context.Context, PrmObjectDelete) error
// TimeToEpoch compute current epoch and epoch that corresponds provided time. // TimeToEpoch computes current epoch and the epoch that corresponds to the provided time.
// Note: // Note:
// * time must be in the future // * time must be in the future
// * time will be ceil rounded to match epoch // * time will be ceil rounded to match epoch
// //
// Returns any error encountered which prevented computing epochs. // It returns any error encountered which prevented computing epochs.
TimeToEpoch(context.Context, time.Time) (uint64, uint64, error) TimeToEpoch(context.Context, time.Time) (uint64, uint64, error)
} }

View file

@ -210,7 +210,7 @@ func (n *layer) SendNotifications(ctx context.Context, p *SendNotificationParams
return n.ncontroller.SendNotifications(topics, p) return n.ncontroller.SendNotifications(topics, p)
} }
// checkBucketConfiguration checks notification configuration and generates ID for configurations with empty ids. // checkBucketConfiguration checks notification configuration and generates an ID for configurations with empty ids.
func (n *layer) checkBucketConfiguration(conf *data.NotificationConfiguration, r *api.ReqInfo) (completed bool, err error) { func (n *layer) checkBucketConfiguration(conf *data.NotificationConfiguration, r *api.ReqInfo) (completed bool, err error) {
if conf == nil { if conf == nil {
return return
@ -248,7 +248,7 @@ func filterSubjects(conf *data.NotificationConfiguration, eventType, objName str
for _, t := range conf.QueueConfigurations { for _, t := range conf.QueueConfigurations {
event := false event := false
for _, e := range t.Events { for _, e := range t.Events {
// the second condition is comparison with events ending with *: // the second condition is comparison with the events ending with *:
// s3:ObjectCreated:*, s3:ObjectRemoved:* etc without the last char // s3:ObjectCreated:*, s3:ObjectRemoved:* etc without the last char
if eventType == e || strings.HasPrefix(eventType, e[:len(e)-1]) { if eventType == e || strings.HasPrefix(eventType, e[:len(e)-1]) {
event = true event = true

View file

@ -40,7 +40,7 @@ type (
IsLatest bool IsLatest bool
} }
// ListObjectVersionsInfo stores info and list of objects' versions. // ListObjectVersionsInfo stores info and list of objects versions.
ListObjectVersionsInfo struct { ListObjectVersionsInfo struct {
CommonPrefixes []string CommonPrefixes []string
IsTruncated bool IsTruncated bool
@ -138,7 +138,7 @@ func filenameFromObject(o *object.Object) string {
return name return name
} }
// NameFromString splits name into base file name and directory path. // NameFromString splits name into a base file name and a directory path.
func NameFromString(name string) (string, string) { func NameFromString(name string) (string, string) {
ind := strings.LastIndex(name, PathSeparator) ind := strings.LastIndex(name, PathSeparator)
return name[ind+1:], name[:ind+1] return name[ind+1:], name[:ind+1]

View file

@ -8,7 +8,7 @@ import (
) )
type ( type (
// MaxClients provides HTTP handler wrapper with client limit. // MaxClients provides HTTP handler wrapper with the client limit.
MaxClients interface { MaxClients interface {
Handle(http.HandlerFunc) http.HandlerFunc Handle(http.HandlerFunc) http.HandlerFunc
} }
@ -22,7 +22,7 @@ type (
const defaultRequestDeadline = time.Second * 30 const defaultRequestDeadline = time.Second * 30
// NewMaxClientsMiddleware returns MaxClients interface with handler wrapper based on // NewMaxClientsMiddleware returns MaxClients interface with handler wrapper based on
// provided count and timeout limits. // the provided count and the timeout limits.
func NewMaxClientsMiddleware(count int, timeout time.Duration) MaxClients { func NewMaxClientsMiddleware(count int, timeout time.Duration) MaxClients {
if timeout <= 0 { if timeout <= 0 {
timeout = defaultRequestDeadline timeout = defaultRequestDeadline

View file

@ -13,7 +13,7 @@ import (
type ( type (
// HTTPAPIStats holds statistics information about // HTTPAPIStats holds statistics information about
// a given API in the requests. // the API given in the requests.
HTTPAPIStats struct { HTTPAPIStats struct {
apiStats map[string]int apiStats map[string]int
sync.RWMutex sync.RWMutex
@ -64,7 +64,7 @@ var (
) )
// Collects HTTP metrics for NeoFS S3 Gate in Prometheus specific format // Collects HTTP metrics for NeoFS S3 Gate in Prometheus specific format
// and sends to given channel. // and sends to the given channel.
func collectHTTPMetrics(ch chan<- prometheus.Metric) { func collectHTTPMetrics(ch chan<- prometheus.Metric) {
for api, value := range httpStatsMetric.currentS3Requests.Load() { for api, value := range httpStatsMetric.currentS3Requests.Load() {
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(
@ -122,7 +122,7 @@ func APIStats(api string, f http.HandlerFunc) http.HandlerFunc {
f.ServeHTTP(statsWriter, r) f.ServeHTTP(statsWriter, r)
// Time duration in secs since the call started. // Time duration in secs since the call started.
// We don't need to do nanosecond precision in this // We don't need to do nanosecond precision here
// simply for the fact that it is not human readable. // simply for the fact that it is not human readable.
durationSecs := time.Since(statsWriter.startTime).Seconds() durationSecs := time.Since(statsWriter.startTime).Seconds()
@ -201,7 +201,7 @@ func (st *HTTPStats) updateStats(api string, w http.ResponseWriter, r *http.Requ
} }
} }
// WriteHeader - writes http status code. // WriteHeader -- writes http status code.
func (w *responseWrapper) WriteHeader(code int) { func (w *responseWrapper) WriteHeader(code int) {
w.Do(func() { w.Do(func() {
w.statusCode = code w.statusCode = code
@ -209,7 +209,7 @@ func (w *responseWrapper) WriteHeader(code int) {
}) })
} }
// Flush - Calls the underlying Flush. // Flush -- calls the underlying Flush.
func (w *responseWrapper) Flush() { func (w *responseWrapper) Flush() {
if f, ok := w.ResponseWriter.(http.Flusher); ok { if f, ok := w.ResponseWriter.(http.Flusher); ok {
f.Flush() f.Flush()

View file

@ -13,7 +13,7 @@ import (
) )
type ( type (
// KeyVal - appended to ReqInfo.Tags. // KeyVal -- appended to ReqInfo.Tags.
KeyVal struct { KeyVal struct {
Key string Key string
Val string Val string
@ -27,7 +27,7 @@ type (
UserAgent string // User Agent UserAgent string // User Agent
DeploymentID string // random generated s3-deployment-id DeploymentID string // random generated s3-deployment-id
RequestID string // x-amz-request-id RequestID string // x-amz-request-id
API string // API name - GetObject PutObject NewMultipartUpload etc. API string // API name -- GetObject PutObject NewMultipartUpload etc.
BucketName string // Bucket name BucketName string // Bucket name
ObjectName string // Object name ObjectName string // Object name
URL *url.URL // Request url URL *url.URL // Request url
@ -64,15 +64,15 @@ var (
) )
// GetSourceIP retrieves the IP from the X-Forwarded-For, X-Real-IP and RFC7239 // GetSourceIP retrieves the IP from the X-Forwarded-For, X-Real-IP and RFC7239
// Forwarded headers (in that order), falls back to r.RemoteAddr when all // Forwarded headers (in that order), falls back to r.RemoteAddr when everything
// else fails. // else fails.
func GetSourceIP(r *http.Request) string { func GetSourceIP(r *http.Request) string {
var addr string var addr string
if fwd := r.Header.Get(xForwardedFor); fwd != "" { if fwd := r.Header.Get(xForwardedFor); fwd != "" {
// Only grab the first (client) address. Note that '192.168.0.1, // Only grabs the first (client) address. Note that '192.168.0.1,
// 10.1.1.1' is a valid key for X-Forwarded-For where addresses after // 10.1.1.1' is a valid key for X-Forwarded-For where addresses after
// the first may represent forwarding proxies earlier in the chain. // the first one may represent forwarding proxies earlier in the chain.
s := strings.Index(fwd, ", ") s := strings.Index(fwd, ", ")
if s == -1 { if s == -1 {
s = len(fwd) s = len(fwd)
@ -141,7 +141,7 @@ func NewReqInfo(w http.ResponseWriter, r *http.Request, req ObjectRequest) *ReqI
} }
} }
// AppendTags - appends key/val to ReqInfo.tags. // AppendTags -- appends key/val to ReqInfo.tags.
func (r *ReqInfo) AppendTags(key string, val string) *ReqInfo { func (r *ReqInfo) AppendTags(key string, val string) *ReqInfo {
if r == nil { if r == nil {
return nil return nil
@ -152,14 +152,14 @@ func (r *ReqInfo) AppendTags(key string, val string) *ReqInfo {
return r return r
} }
// SetTags - sets key/val to ReqInfo.tags. // SetTags -- sets key/val to ReqInfo.tags.
func (r *ReqInfo) SetTags(key string, val string) *ReqInfo { func (r *ReqInfo) SetTags(key string, val string) *ReqInfo {
if r == nil { if r == nil {
return nil return nil
} }
r.Lock() r.Lock()
defer r.Unlock() defer r.Unlock()
// Search of tag key already exists in tags // Search for a tag key already existing in tags
var updated bool var updated bool
for _, tag := range r.tags { for _, tag := range r.tags {
if tag.Key == key { if tag.Key == key {
@ -175,7 +175,7 @@ func (r *ReqInfo) SetTags(key string, val string) *ReqInfo {
return r return r
} }
// GetTags - returns the user defined tags. // GetTags -- returns the user defined tags.
func (r *ReqInfo) GetTags() []KeyVal { func (r *ReqInfo) GetTags() []KeyVal {
if r == nil { if r == nil {
return nil return nil

View file

@ -18,8 +18,8 @@ const (
type NeoFS interface { type NeoFS interface {
// SystemDNS reads system DNS network parameters of the NeoFS. // SystemDNS reads system DNS network parameters of the NeoFS.
// //
// Returns exactly on non-zero value. Returns any error encountered // It returns exactly on non-zero value. It returns any error encountered
// which prevented the parameter to be read. // which prevented the parameter from being read.
SystemDNS(context.Context) (string, error) SystemDNS(context.Context) (string, error)
} }

View file

@ -13,7 +13,7 @@ import (
) )
type ( type (
// ErrorResponse - error response format. // ErrorResponse -- error response format.
ErrorResponse struct { ErrorResponse struct {
XMLName xml.Name `xml:"Error" json:"-"` XMLName xml.Name `xml:"Error" json:"-"`
Code string Code string
@ -24,7 +24,7 @@ type (
RequestID string `xml:"RequestId" json:"RequestId"` RequestID string `xml:"RequestId" json:"RequestId"`
HostID string `xml:"HostId" json:"HostId"` HostID string `xml:"HostId" json:"HostId"`
// Region where the bucket is located. This header is returned // The region where the bucket is located. This header is returned
// only in HEAD bucket and ListObjects response. // only in HEAD bucket and ListObjects response.
Region string `xml:"Region,omitempty" json:"Region,omitempty"` Region string `xml:"Region,omitempty" json:"Region,omitempty"`
@ -126,7 +126,7 @@ func WriteErrorResponse(w http.ResponseWriter, reqInfo *ReqInfo, err error) {
} }
} }
// Generate error response. // Generates error response.
errorResponse := getAPIErrorResponse(reqInfo, err) errorResponse := getAPIErrorResponse(reqInfo, err)
encodedErrorResponse := EncodeResponse(errorResponse) encodedErrorResponse := EncodeResponse(errorResponse)
WriteResponse(w, code, encodedErrorResponse, MimeXML) WriteResponse(w, code, encodedErrorResponse, MimeXML)
@ -152,7 +152,7 @@ func setCommonHeaders(w http.ResponseWriter) {
} }
// removeSensitiveHeaders removes confidential encryption // removeSensitiveHeaders removes confidential encryption
// information - e.g. the SSE-C key - from the HTTP headers. // information -- e.g. the SSE-C key -- from the HTTP headers.
// It has the same semantics as RemoveSensitiveEntries. // It has the same semantics as RemoveSensitiveEntries.
func removeSensitiveHeaders(h http.Header) { func removeSensitiveHeaders(h http.Header) {
h.Del(hdrSSECustomerKey) h.Del(hdrSSECustomerKey)
@ -212,7 +212,7 @@ func WriteSuccessResponseHeadersOnly(w http.ResponseWriter) {
WriteResponse(w, http.StatusOK, nil, MimeNone) WriteResponse(w, http.StatusOK, nil, MimeNone)
} }
// Error - Returns S3 error string. // Error -- Returns S3 error string.
func (e ErrorResponse) Error() string { func (e ErrorResponse) Error() string {
if e.Message == "" { if e.Message == "" {
msg, ok := s3ErrorResponseMap[e.Code] msg, ok := s3ErrorResponseMap[e.Code]
@ -225,7 +225,7 @@ func (e ErrorResponse) Error() string {
} }
// getErrorResponse gets in standard error and resource value and // getErrorResponse gets in standard error and resource value and
// provides a encodable populated response values. // provides an encodable populated response values.
func getAPIErrorResponse(info *ReqInfo, err error) ErrorResponse { func getAPIErrorResponse(info *ReqInfo, err error) ErrorResponse {
code := "InternalError" code := "InternalError"
desc := err.Error() desc := err.Error()

View file

@ -83,7 +83,7 @@ type (
ListMultipartUploadsHandler(http.ResponseWriter, *http.Request) ListMultipartUploadsHandler(http.ResponseWriter, *http.Request)
} }
// mimeType represents various MIME type used API responses. // mimeType represents various MIME types used in API responses.
mimeType string mimeType string
logResponseWriter struct { logResponseWriter struct {
@ -95,7 +95,7 @@ type (
) )
const ( const (
// SlashSeparator - slash separator. // SlashSeparator -- slash separator.
SlashSeparator = "/" SlashSeparator = "/"
// MimeNone means no response type. // MimeNone means no response type.
@ -172,7 +172,7 @@ func logErrorResponse(l *zap.Logger) mux.MiddlewareFunc {
} }
} }
// GetRequestID returns request ID from response writer or context. // GetRequestID returns the request ID from the response writer or the context.
func GetRequestID(v interface{}) string { func GetRequestID(v interface{}) string {
switch t := v.(type) { switch t := v.(type) {
case context.Context: case context.Context:
@ -244,11 +244,11 @@ func Attach(r *mux.Router, domains []string, m MaxClients, h Handler, center aut
bucket.Methods(http.MethodGet).HandlerFunc( bucket.Methods(http.MethodGet).HandlerFunc(
m.Handle(metrics.APIStats("listmultipartuploads", h.ListMultipartUploadsHandler))).Queries("uploads", ""). m.Handle(metrics.APIStats("listmultipartuploads", h.ListMultipartUploadsHandler))).Queries("uploads", "").
Name("ListMultipartUploads") Name("ListMultipartUploads")
// GetObjectACL - this is a dummy call. // GetObjectACL -- this is a dummy call.
bucket.Methods(http.MethodGet).Path("/{object:.+}").HandlerFunc( bucket.Methods(http.MethodGet).Path("/{object:.+}").HandlerFunc(
m.Handle(metrics.APIStats("getobjectacl", h.GetObjectACLHandler))).Queries("acl", ""). m.Handle(metrics.APIStats("getobjectacl", h.GetObjectACLHandler))).Queries("acl", "").
Name("GetObjectACL") Name("GetObjectACL")
// PutObjectACL - this is a dummy call. // PutObjectACL -- this is a dummy call.
bucket.Methods(http.MethodPut).Path("/{object:.+}").HandlerFunc( bucket.Methods(http.MethodPut).Path("/{object:.+}").HandlerFunc(
m.Handle(metrics.APIStats("putobjectacl", h.PutObjectACLHandler))).Queries("acl", ""). m.Handle(metrics.APIStats("putobjectacl", h.PutObjectACLHandler))).Queries("acl", "").
Name("PutObjectACL") Name("PutObjectACL")
@ -336,27 +336,27 @@ func Attach(r *mux.Router, domains []string, m MaxClients, h Handler, center aut
bucket.Methods(http.MethodPut).HandlerFunc( bucket.Methods(http.MethodPut).HandlerFunc(
m.Handle(metrics.APIStats("putbucketacl", h.PutBucketACLHandler))).Queries("acl", ""). m.Handle(metrics.APIStats("putbucketacl", h.PutBucketACLHandler))).Queries("acl", "").
Name("PutBucketACL") Name("PutBucketACL")
// GetBucketWebsiteHandler - this is a dummy call. // GetBucketWebsiteHandler -- this is a dummy call.
bucket.Methods(http.MethodGet).HandlerFunc( bucket.Methods(http.MethodGet).HandlerFunc(
m.Handle(metrics.APIStats("getbucketwebsite", h.GetBucketWebsiteHandler))).Queries("website", ""). m.Handle(metrics.APIStats("getbucketwebsite", h.GetBucketWebsiteHandler))).Queries("website", "").
Name("GetBucketWebsite") Name("GetBucketWebsite")
// GetBucketAccelerateHandler - this is a dummy call. // GetBucketAccelerateHandler -- this is a dummy call.
bucket.Methods(http.MethodGet).HandlerFunc( bucket.Methods(http.MethodGet).HandlerFunc(
m.Handle(metrics.APIStats("getbucketaccelerate", h.GetBucketAccelerateHandler))).Queries("accelerate", ""). m.Handle(metrics.APIStats("getbucketaccelerate", h.GetBucketAccelerateHandler))).Queries("accelerate", "").
Name("GetBucketAccelerate") Name("GetBucketAccelerate")
// GetBucketRequestPaymentHandler - this is a dummy call. // GetBucketRequestPaymentHandler -- this is a dummy call.
bucket.Methods(http.MethodGet).HandlerFunc( bucket.Methods(http.MethodGet).HandlerFunc(
m.Handle(metrics.APIStats("getbucketrequestpayment", h.GetBucketRequestPaymentHandler))).Queries("requestPayment", ""). m.Handle(metrics.APIStats("getbucketrequestpayment", h.GetBucketRequestPaymentHandler))).Queries("requestPayment", "").
Name("GetBucketRequestPayment") Name("GetBucketRequestPayment")
// GetBucketLoggingHandler - this is a dummy call. // GetBucketLoggingHandler -- this is a dummy call.
bucket.Methods(http.MethodGet).HandlerFunc( bucket.Methods(http.MethodGet).HandlerFunc(
m.Handle(metrics.APIStats("getbucketlogging", h.GetBucketLoggingHandler))).Queries("logging", ""). m.Handle(metrics.APIStats("getbucketlogging", h.GetBucketLoggingHandler))).Queries("logging", "").
Name("GetBucketLogging") Name("GetBucketLogging")
// GetBucketLifecycleHandler - this is a dummy call. // GetBucketLifecycleHandler -- this is a dummy call.
bucket.Methods(http.MethodGet).HandlerFunc( bucket.Methods(http.MethodGet).HandlerFunc(
m.Handle(metrics.APIStats("getbucketlifecycle", h.GetBucketLifecycleHandler))).Queries("lifecycle", ""). m.Handle(metrics.APIStats("getbucketlifecycle", h.GetBucketLifecycleHandler))).Queries("lifecycle", "").
Name("GetBucketLifecycle") Name("GetBucketLifecycle")
// GetBucketReplicationHandler - this is a dummy call. // GetBucketReplicationHandler -- this is a dummy call.
bucket.Methods(http.MethodGet).HandlerFunc( bucket.Methods(http.MethodGet).HandlerFunc(
m.Handle(metrics.APIStats("getbucketreplication", h.GetBucketReplicationHandler))).Queries("replication", ""). m.Handle(metrics.APIStats("getbucketreplication", h.GetBucketReplicationHandler))).Queries("replication", "").
Name("GetBucketReplication") Name("GetBucketReplication")
@ -480,7 +480,7 @@ func Attach(r *mux.Router, domains []string, m MaxClients, h Handler, center aut
m.Handle(metrics.APIStats("listbuckets", h.ListBucketsHandler))). m.Handle(metrics.APIStats("listbuckets", h.ListBucketsHandler))).
Name("ListBuckets") Name("ListBuckets")
// If none of the routes match add default error handler routes // If none of the routes match, add default error handler routes
api.NotFoundHandler = metrics.APIStats("notfound", errorResponseHandler) api.NotFoundHandler = metrics.APIStats("notfound", errorResponseHandler)
api.MethodNotAllowedHandler = metrics.APIStats("methodnotallowed", errorResponseHandler) api.MethodNotAllowedHandler = metrics.APIStats("methodnotallowed", errorResponseHandler)
} }

View file

@ -54,26 +54,26 @@ type NeoFS interface {
tokens.NeoFS tokens.NeoFS
// ContainerExists checks container presence in NeoFS by identifier. // ContainerExists checks container presence in NeoFS by identifier.
// Returns nil iff container exists. // Returns nil if container exists.
ContainerExists(context.Context, cid.ID) error ContainerExists(context.Context, cid.ID) error
// CreateContainer creates and saves parameterized container in NeoFS. // CreateContainer creates and saves parameterized container in NeoFS.
// It sets 'Timestamp' attribute to current time. // It sets 'Timestamp' attribute to the current time.
// Returns ID of the saved container. // It returns the ID of the saved container.
// //
// The container must be private with GET access of OTHERS group. // The container must be private with GET access for OTHERS group.
// Creation time should also be stamped. // Creation time should also be stamped.
// //
// Returns exactly one non-nil value. Returns any error encountered which // It returns exactly one non-nil value. It returns any error encountered which
// prevented the container to be created. // prevented the container from being created.
CreateContainer(context.Context, PrmContainerCreate) (*cid.ID, error) CreateContainer(context.Context, PrmContainerCreate) (*cid.ID, error)
// TimeToEpoch compute current epoch and epoch that corresponds provided time. // TimeToEpoch computes the current epoch and the epoch that corresponds to the provided time.
// Note: // Note:
// * time must be in the future // * time must be in the future
// * time will be ceil rounded to match epoch // * time will be ceil rounded to match epoch
// //
// Returns any error encountered which prevented computing epochs. // It returns any error encountered which prevented computing epochs.
TimeToEpoch(context.Context, time.Time) (uint64, uint64, error) TimeToEpoch(context.Context, time.Time) (uint64, uint64, error)
} }
@ -119,7 +119,7 @@ type (
} }
) )
// lifetimeOptions holds NeoFS epochs, iat -- epoch, which a token was issued at, exp -- epoch, when the token expires. // lifetimeOptions holds NeoFS epochs, iat -- epoch which the token was issued at, exp -- epoch when the token expires.
type lifetimeOptions struct { type lifetimeOptions struct {
Iat uint64 Iat uint64
Exp uint64 Exp uint64
@ -141,7 +141,7 @@ type (
func (a *Agent) checkContainer(ctx context.Context, opts ContainerOptions, idOwner *owner.ID) (*cid.ID, error) { func (a *Agent) checkContainer(ctx context.Context, opts ContainerOptions, idOwner *owner.ID) (*cid.ID, error) {
if opts.ID != nil { if opts.ID != nil {
// check that container exists // check that the container exists
return opts.ID, a.neoFS.ContainerExists(ctx, *opts.ID) return opts.ID, a.neoFS.ContainerExists(ctx, *opts.ID)
} }

View file

@ -345,7 +345,7 @@ func getJSONRules(val string) ([]byte, error) {
} }
// getSessionRules reads json session rules. // getSessionRules reads json session rules.
// Returns true if rules must be skipped. // It returns true if rules must be skipped.
func getSessionRules(r string) ([]byte, bool, error) { func getSessionRules(r string) ([]byte, bool, error) {
if r == "none" { if r == "none" {
return nil, true, nil return nil, true, nil

View file

@ -194,11 +194,11 @@ func newApp(ctx context.Context, l *zap.Logger, v *viper.Viper) *App {
} }
} }
// Wait waits for application to finish. // Wait waits for an application to finish.
// //
// Pre-logs a message about the launch of the application mentioning its // Pre-logs a message about the launch of the application mentioning its
// version (version.Version) and name (neofs-s3-gw). At the end writes to the // version (version.Version) and its name (neofs-s3-gw). At the end, it writes
// log about the stop. // about the stop to the log.
func (a *App) Wait() { func (a *App) Wait() {
a.log.Info("application started", a.log.Info("application started",
zap.String("name", "neofs-s3-gw"), zap.String("name", "neofs-s3-gw"),

View file

@ -99,7 +99,7 @@ const ( // Settings.
cmdVersion = "version" cmdVersion = "version"
cmdConfig = "config" cmdConfig = "config"
// envPrefix is environment variables prefix used for configuration. // envPrefix is an environment variables prefix used for configuration.
envPrefix = "S3_GW" envPrefix = "S3_GW"
) )

View file

@ -11,7 +11,7 @@ import (
"go.uber.org/zap/zapcore" "go.uber.org/zap/zapcore"
) )
// newLogger constructs a zap.Logger instance for current application. // newLogger constructs a zap.Logger instance for the current application.
// Panics on failure. // Panics on failure.
// //
// Logger is built from zap's production logging configuration with: // Logger is built from zap's production logging configuration with:

View file

@ -40,22 +40,22 @@ type GateData struct {
GateKey *keys.PublicKey GateKey *keys.PublicKey
} }
// NewGateData returns GateData from provided bearer token and public gate key. // NewGateData returns GateData from the provided bearer token and the public gate key.
func NewGateData(gateKey *keys.PublicKey, bearerTkn *token.BearerToken) *GateData { func NewGateData(gateKey *keys.PublicKey, bearerTkn *token.BearerToken) *GateData {
return &GateData{GateKey: gateKey, BearerToken: bearerTkn} return &GateData{GateKey: gateKey, BearerToken: bearerTkn}
} }
// SessionTokenForPut return the first suitable container session context for PUT operation. // SessionTokenForPut returns the first suitable container session context for PUT operation.
func (g *GateData) SessionTokenForPut() *session.Token { func (g *GateData) SessionTokenForPut() *session.Token {
return g.containerSessionToken(apisession.ContainerVerbPut) return g.containerSessionToken(apisession.ContainerVerbPut)
} }
// SessionTokenForDelete return the first suitable container session context for DELETE operation. // SessionTokenForDelete returns the first suitable container session context for DELETE operation.
func (g *GateData) SessionTokenForDelete() *session.Token { func (g *GateData) SessionTokenForDelete() *session.Token {
return g.containerSessionToken(apisession.ContainerVerbDelete) return g.containerSessionToken(apisession.ContainerVerbDelete)
} }
// SessionTokenForSetEACL return the first suitable container session context for SetEACL operation. // SessionTokenForSetEACL returns the first suitable container session context for SetEACL operation.
func (g *GateData) SessionTokenForSetEACL() *session.Token { func (g *GateData) SessionTokenForSetEACL() *session.Token {
return g.containerSessionToken(apisession.ContainerVerbSetEACL) return g.containerSessionToken(apisession.ContainerVerbSetEACL)
} }
@ -78,7 +78,7 @@ func isAppropriateContainerContext(ctx *session.ContainerContext, verb apisessio
verb == apisession.ContainerVerbSetEACL && ctx.IsForSetEACL() verb == apisession.ContainerVerbSetEACL && ctx.IsForSetEACL()
} }
// Secrets represents AccessKey and key to encrypt gate tokens. // Secrets represents AccessKey and the key to encrypt gate tokens.
type Secrets struct { type Secrets struct {
AccessKey string AccessKey string
EphemeralKey *keys.PrivateKey EphemeralKey *keys.PrivateKey
@ -94,7 +94,7 @@ func (x *AccessBox) Unmarshal(data []byte) error {
return proto.Unmarshal(data, x) return proto.Unmarshal(data, x)
} }
// PackTokens adds a bearer and session tokens to BearerTokens and SessionToken lists respectively. // PackTokens adds bearer and session tokens to BearerTokens and SessionToken lists respectively.
// Session token can be nil. // Session token can be nil.
func PackTokens(gatesData []*GateData) (*AccessBox, *Secrets, error) { func PackTokens(gatesData []*GateData) (*AccessBox, *Secrets, error) {
box := &AccessBox{} box := &AccessBox{}
@ -156,7 +156,7 @@ func (x *AccessBox) GetPlacementPolicy() ([]*ContainerPolicy, error) {
return result, nil return result, nil
} }
// GetBox parse AccessBox to Box. // GetBox parses AccessBox to Box.
func (x *AccessBox) GetBox(owner *keys.PrivateKey) (*Box, error) { func (x *AccessBox) GetBox(owner *keys.PrivateKey) (*Box, error) {
tokens, err := x.GetTokens(owner) tokens, err := x.GetTokens(owner)
if err != nil { if err != nil {

View file

@ -51,18 +51,18 @@ type PrmObjectCreate struct {
// NeoFS represents virtual connection to NeoFS network. // NeoFS represents virtual connection to NeoFS network.
type NeoFS interface { type NeoFS interface {
// CreateObject creates and saves a parameterized object in the specified // CreateObject creates and saves a parameterized object in the specified
// NeoFS container from a specific user. It sets 'Timestamp' attribute to current time. // NeoFS container from a specific user. It sets 'Timestamp' attribute to the current time.
// Returns ID of the saved object. // It returns the ID of the saved object.
// //
// Returns exactly one non-nil value. Returns any error encountered which // It returns exactly one non-nil value. It returns any error encountered which
// prevented the object to be created. // prevented the object from being created.
CreateObject(context.Context, PrmObjectCreate) (*oid.ID, error) CreateObject(context.Context, PrmObjectCreate) (*oid.ID, error)
// ReadObjectPayload reads payload of the object from NeoFS network by address // ReadObjectPayload reads payload of the object from NeoFS network by address
// into memory. // into memory.
// //
// Returns exactly one non-nil value. Returns any error encountered which // It returns exactly one non-nil value. It returns any error encountered which
// prevented the object payload to be read. // prevented the object payload from being read.
ReadObjectPayload(context.Context, address.Address) ([]byte, error) ReadObjectPayload(context.Context, address.Address) ([]byte, error)
} }
@ -75,7 +75,7 @@ var (
var _ = New var _ = New
// New creates new Credentials instance using given cli and key. // New creates a new Credentials instance using the given cli and key.
func New(neoFS NeoFS, key *keys.PrivateKey, config *cache.Config) Credentials { func New(neoFS NeoFS, key *keys.PrivateKey, config *cache.Config) Credentials {
return &cred{neoFS: neoFS, key: key, cache: cache.NewAccessBoxCache(config)} return &cred{neoFS: neoFS, key: key, cache: cache.NewAccessBoxCache(config)}
} }

View file

@ -2,18 +2,18 @@
Authmate is a tool to create gateway AWS credentials. AWS users Authmate is a tool to create gateway AWS credentials. AWS users
are authenticated with access key IDs and secrets, while NeoFS users are are authenticated with access key IDs and secrets, while NeoFS users are
authenticated with key pairs. To complicate things further we have S3 gateway authenticated with key pairs. To complicate things further, we have S3 gateway
that usually acts on behalf of some user, but user doesn't necessarily want to that usually acts on behalf of some user, but the user doesn't necessarily want to
give their keys to the gateway. give their keys to the gateway.
To solve this, we use NeoFS bearer tokens that are signed by the owner (NeoFS To solve this, we use NeoFS bearer tokens that are signed by the owner (NeoFS
"user") and that can implement any kind of policy for NeoFS requests allowed "user") and that can implement any kind of policy for NeoFS requests allowed
using this token. However, tokens can't be used as AWS credentials directly, thus to use this token. However, tokens can't be used as AWS credentials directly. Thus,
they're stored on NeoFS as regular objects, and access key ID is just an they're stored on NeoFS as regular objects, and an access key ID is just an
address of this object while secret is generated randomly. address of this object while a secret is generated randomly.
Tokens are not stored on NeoFS in plaintext, they're encrypted with a set of Tokens are not stored on NeoFS in plaintext, they're encrypted with a set of
gateway keys. So in order for a gateway to be able to successfully extract bearer gateway keys. So, in order for a gateway to be able to successfully extract bearer
token, the object needs to be stored in a container available for the gateway token, the object needs to be stored in a container available for the gateway
to read, and it needs to be encrypted with this gateway's key (among others to read, and it needs to be encrypted with this gateway's key (among others
potentially). potentially).
@ -67,10 +67,10 @@ Confirm passphrase >
} }
} }
wallet successfully created, file location is wallet.json wallet is successfully created, the file location is wallet.json
``` ```
To get public key from the wallet: To get the public key from the wallet:
```shell ```shell
$ ./bin/neo-go wallet dump-keys -w wallet.json $ ./bin/neo-go wallet dump-keys -w wallet.json
@ -80,23 +80,23 @@ NhLQpDnerpviUWDF77j5qyjFgavCmasJ4p (simple signature contract):
## Issuance of a secret ## Issuance of a secret
To issue a secret means to create a Bearer and, optionally, Session tokens and To issue a secret means to create Bearer and, optionally, Session tokens and
put them as an object into a container on the NeoFS network. put them as an object into a container on the NeoFS network.
### CLI parameters ### CLI parameters
**Required parameters:** **Required parameters:**
* `--wallet` - a path to a wallet `.json` file. You can provide a passphrase to decrypt * `--wallet` is a path to a wallet `.json` file. You can provide a passphrase to decrypt
a wallet via environment variable `AUTHMATE_WALLET_PASSPHRASE`, or you will be asked to enter a passphrase a wallet via environment variable `AUTHMATE_WALLET_PASSPHRASE`, or you will be asked to enter a passphrase
interactively. You can also specify an account address to use from a wallet using the `--address` parameter. interactively. You can also specify an account address to use from a wallet using the `--address` parameter.
* `--peer` - address of a NeoFS peer to connect to * `--peer` is an address of a NeoFS peer to connect to
* `--gate-public-key` -- public `secp256r1` 33-byte short key of a gate (use flags repeatedly for multiple gates). The tokens are encrypted * `--gate-public-key` is a public `secp256r1` 33-byte short key of a gate (use flags repeatedly for multiple gates). The tokens are encrypted
by a set of gateway keys, so you need to pass them as well. by a set of gateway keys, so you need to pass them as well.
You can issue a secret using the parameters above only. The tool will You can issue a secret using the parameters above only. The tool will
1. create a new container 1. create a new container
1. without a friendly name 1. without a friendly name
2. with ACL `0x3c8c8cce` - all operations are forbidden for `OTHERS` and `BEARER` user groups, except for `GET` 2. with ACL `0x3c8c8cce` -- all operations are forbidden for `OTHERS` and `BEARER` user groups, except for `GET`
3. with policy `REP 2 IN X CBF 3 SELECT 2 FROM * AS X` 3. with policy `REP 2 IN X CBF 3 SELECT 2 FROM * AS X`
2. put bearer and session tokens with default rules (details in [Bearer tokens](#Bearer tokens) and 2. put bearer and session tokens with default rules (details in [Bearer tokens](#Bearer tokens) and
[Session tokens](#Session tokens)) [Session tokens](#Session tokens))
@ -135,9 +135,9 @@ the secret. Format of `access_key_id`: `%cid0%oid`, where 0(zero) is a delimiter
### Bearer tokens ### Bearer tokens
Creation of the bearer tokens is mandatory. Creation of bearer tokens is mandatory.
Rules for bearer token can be set via parameter `--bearer-rules` (json-string and file path allowed): Rules for a bearer token can be set via parameter `--bearer-rules` (json-string and file path allowed):
```shell ```shell
$ neofs-authmate issue-secret --wallet wallet.json \ $ neofs-authmate issue-secret --wallet wallet.json \
--peer 192.168.130.71:8080 \ --peer 192.168.130.71:8080 \
@ -186,7 +186,7 @@ If bearer rules are not set, a token will be auto-generated with a value:
### Session tokens ### Session tokens
With session token, there are 3 options: With a session token, there are 3 options:
1. append `--session-tokens` parameter with your custom rules in json format (as a string or file path). E.g.: 1. append `--session-tokens` parameter with your custom rules in json format (as a string or file path). E.g.:
```shell ```shell
$ neofs-authmate issue-secret --wallet wallet.json \ $ neofs-authmate issue-secret --wallet wallet.json \

View file

@ -4,7 +4,7 @@
### Credentials ### Credentials
To configure basic settings that the AWS CLI uses to interact with the Gateway, follow steps below: To configure basic settings that the AWS CLI uses to interact with the Gateway, follow the steps below:
1. issue a secret with neofs-authmate tool (see [NeoFS Authmate] (#neofs-authmate)) 1. issue a secret with neofs-authmate tool (see [NeoFS Authmate] (#neofs-authmate))
2. execute the command 2. execute the command

View file

@ -30,7 +30,7 @@ Reference:
## ACL ## ACL
For now there are some limitations: For now there are some limitations:
* [Bucket policy](https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucket-policies.html) support only one `Principal` (type `AWS`) per `Statement`. To refer all users use `"AWS": "*"` * [Bucket policy](https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucket-policies.html) supports only one `Principal` (type `AWS`) per `Statement`. To refer all users use `"AWS": "*"`
* AWS conditions and wildcard are not supported in [resources](https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-arn-format.html) * AWS conditions and wildcard are not supported in [resources](https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-arn-format.html)
* Only `CanonicalUser` (with hex encoded public key) and `All Users Group` are supported in [ACL](https://docs.aws.amazon.com/AmazonS3/latest/userguide/acl-overview.html) * Only `CanonicalUser` (with hex encoded public key) and `All Users Group` are supported in [ACL](https://docs.aws.amazon.com/AmazonS3/latest/userguide/acl-overview.html)

View file

@ -35,7 +35,7 @@ a gateway spread requests equally among them (using weight 1 for every node):
$ neofs-s3-gw -p 192.168.130.72:8080 -p 192.168.130.71:8080 $ neofs-s3-gw -p 192.168.130.72:8080 -p 192.168.130.71:8080
``` ```
If you want some specific load distribution proportions, use weights and priorities, they If you want some specific load distribution proportions, use weights and priorities, they
can only be specified via environment variables or configuration file. can only be specified via environment variables or a configuration file.
### Wallet ### Wallet
@ -49,8 +49,8 @@ Gateway listens on `0.0.0.0:8080` by default, and you can change that with the `
It can also provide TLS interface for its users, just specify paths to the key and It can also provide TLS interface for its users, just specify paths to the key and
certificate files via `--tls.key_file` and `--tls.cert_file` parameters. Note certificate files via `--tls.key_file` and `--tls.cert_file` parameters. Note
that using these options makes gateway TLS-only, if you need to serve both TLS that using these options makes gateway TLS-only. If you need to serve both TLS
and plain text you either have to run two gateway instances or use some and plain text, you either have to run two gateway instances or use some
external redirecting solution. external redirecting solution.
Example to bind to `192.168.130.130:443` and serve TLS there (keys and nodes are Example to bind to `192.168.130.130:443` and serve TLS there (keys and nodes are
@ -100,7 +100,7 @@ default. To enable them, use `--pprof` and `--metrics` flags or
## YAML file and environment variables ## YAML file and environment variables
Example of YAML configuration file: [.yaml-example](/config/config.yaml) Example of a YAML configuration file: [.yaml-example](/config/config.yaml)
Examples of environment variables: [.env-example](/config/config.env). Examples of environment variables: [.env-example](/config/config.env).
A path to a configuration file can be specified with `--config` parameter: A path to a configuration file can be specified with `--config` parameter:
@ -109,7 +109,7 @@ A path to a configuration file can be specified with `--config` parameter:
$ neofs-s3-gw --config your-config.yaml $ neofs-s3-gw --config your-config.yaml
``` ```
Parameters of the following groups can be configured via `.yaml` file or environment variables only: Parameters of the following groups can be configured via a `.yaml` file or environment variables only:
1. logging -- logging level 1. logging -- logging level
2. caching -- lifetime and size for each cache 2. caching -- lifetime and size for each cache
3. notifications 3. notifications

View file

@ -1,6 +1,6 @@
# S3 compatibility test results # S3 compatibility test results
To update this file using tests result run: To update this file using tests result, run:
```sh ```sh
./updateTestsResult.sh ceph_tests_result.txt ./updateTestsResult.sh ceph_tests_result.txt
``` ```

View file

@ -11,7 +11,7 @@ import (
"github.com/spf13/viper" "github.com/spf13/viper"
) )
// GetPassword gets passphrase for wallet. // GetPassword gets the passphrase for a wallet.
func GetPassword(v *viper.Viper, variable string) *string { func GetPassword(v *viper.Viper, variable string) *string {
var password *string var password *string
if v.IsSet(variable) { if v.IsSet(variable) {
@ -21,7 +21,7 @@ func GetPassword(v *viper.Viper, variable string) *string {
return password return password
} }
// GetKeyFromPath reads wallet and gets private key. // GetKeyFromPath reads a wallet and gets the private key.
func GetKeyFromPath(walletPath, addrStr string, password *string) (*keys.PrivateKey, error) { func GetKeyFromPath(walletPath, addrStr string, password *string) (*keys.PrivateKey, error) {
if len(walletPath) == 0 { if len(walletPath) == 0 {
return nil, fmt.Errorf("wallet path must not be empty") return nil, fmt.Errorf("wallet path must not be empty")