package api import ( "context" "encoding/json" "encoding/xml" "fmt" "io" "net/http" "testing" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data" apierr "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/creds/accessbox" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" bearertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer/test" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/pool" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/stretchr/testify/require" ) const ( FrostfsNamespaceHeader = "X-Frostfs-Namespace" FrostfsVHSHeader = "X-Frostfs-S3-VHS" FrostfsServernameHeader = "X-Frostfs-Servername" ) type poolStatisticMock struct { } func (p *poolStatisticMock) Statistic() pool.Statistic { return pool.Statistic{} } type centerMock struct { t *testing.T anon bool noAuthHeader bool isError bool attrs []object.Attribute } func (c *centerMock) Authenticate(*http.Request) (*middleware.Box, error) { if c.noAuthHeader { return nil, middleware.ErrNoAuthorizationHeader } if c.isError { return nil, fmt.Errorf("some error") } var token *bearer.Token if !c.anon { bt := bearertest.Token() token = &bt key, err := keys.NewPrivateKey() require.NoError(c.t, err) require.NoError(c.t, token.Sign(key.PrivateKey)) } return &middleware.Box{ AuthHeaders: &middleware.AuthHeader{}, AccessBox: &accessbox.Box{ Gate: &accessbox.GateData{ BearerToken: token, }, }, Attributes: c.attrs, }, nil } type middlewareSettingsMock struct { denyByDefault bool sourceIPHeader string domains []string vhsEnabled bool vhsNamespacesEnabled map[string]bool logHTTP middleware.LogHTTPConfig } func (r *middlewareSettingsMock) SourceIPHeader() string { return r.sourceIPHeader } func (r *middlewareSettingsMock) NamespaceHeader() string { return FrostfsNamespaceHeader } func (r *middlewareSettingsMock) ResolveNamespaceAlias(ns string) string { return ns } func (r *middlewareSettingsMock) PolicyDenyByDefault() bool { return r.denyByDefault } func (r *middlewareSettingsMock) Domains() []string { return r.domains } func (r *middlewareSettingsMock) GlobalVHS() bool { return r.vhsEnabled } func (r *middlewareSettingsMock) VHSHeader() string { return FrostfsVHSHeader } func (r *middlewareSettingsMock) ServernameHeader() string { return FrostfsServernameHeader } func (r *middlewareSettingsMock) VHSNamespacesEnabled() map[string]bool { return r.vhsNamespacesEnabled } func (r *middlewareSettingsMock) LogHTTPConfig() middleware.LogHTTPConfig { return r.logHTTP } type frostFSIDMock struct { tags map[string]string validateError bool userGroupsError bool } func (f *frostFSIDMock) ValidatePublicKey(*keys.PublicKey) error { if f.validateError { return fmt.Errorf("some error") } return nil } func (f *frostFSIDMock) GetUserGroupIDsAndClaims(util.Uint160) ([]string, map[string]string, error) { if f.userGroupsError { return nil, nil, fmt.Errorf("some error") } return []string{}, f.tags, nil } type xmlMock struct { } func (m *xmlMock) NewXMLDecoder(r io.Reader) *xml.Decoder { return xml.NewDecoder(r) } type resourceTaggingMock struct { bucketTags map[string]string objectTags map[string]string noSuchObjectKey bool noSuchBucketKey bool } func (m *resourceTaggingMock) GetBucketTagging(context.Context, *data.BucketInfo) (map[string]string, error) { if m.noSuchBucketKey { return nil, apierr.GetAPIError(apierr.ErrNoSuchKey) } return m.bucketTags, nil } func (m *resourceTaggingMock) GetObjectTagging(context.Context, *data.GetObjectTaggingParams) (string, map[string]string, error) { if m.noSuchObjectKey { return "", nil, apierr.GetAPIError(apierr.ErrNoSuchKey) } return "", m.objectTags, nil } type handlerMock struct { t *testing.T cfg *middlewareSettingsMock buckets map[string]*data.BucketInfo } type handlerResult struct { Method string ReqInfo *middleware.ReqInfo } func (h *handlerMock) HeadObjectHandler(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) GetObjectACLHandler(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) PutObjectACLHandler(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) GetObjectTaggingHandler(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) PutObjectTaggingHandler(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) DeleteObjectTaggingHandler(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) SelectObjectContentHandler(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) GetObjectRetentionHandler(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) GetObjectLegalHoldHandler(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) GetObjectHandler(w http.ResponseWriter, r *http.Request) { res := &handlerResult{ Method: middleware.GetObjectOperation, ReqInfo: middleware.GetReqInfo(r.Context()), } h.writeResponse(w, res) } func (h *handlerMock) GetObjectAttributesHandler(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) CopyObjectHandler(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) PutObjectRetentionHandler(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) PutObjectLegalHoldHandler(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) PutObjectHandler(w http.ResponseWriter, r *http.Request) { res := &handlerResult{ Method: middleware.PutObjectOperation, ReqInfo: middleware.GetReqInfo(r.Context()), } h.writeResponse(w, res) } func (h *handlerMock) DeleteObjectHandler(w http.ResponseWriter, r *http.Request) { res := &handlerResult{ Method: middleware.DeleteObjectOperation, ReqInfo: middleware.GetReqInfo(r.Context()), } h.writeResponse(w, res) } func (h *handlerMock) GetBucketLocationHandler(http.ResponseWriter, *http.Request) { //TODO implement me 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") } func (h *handlerMock) GetBucketLifecycleHandler(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) GetBucketEncryptionHandler(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) GetBucketACLHandler(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) PutBucketACLHandler(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) GetBucketCorsHandler(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) PutBucketCorsHandler(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) DeleteBucketCorsHandler(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) GetBucketWebsiteHandler(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) GetBucketAccelerateHandler(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) GetBucketRequestPaymentHandler(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) GetBucketLoggingHandler(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) GetBucketReplicationHandler(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) GetBucketTaggingHandler(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) DeleteBucketWebsiteHandler(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) DeleteBucketTaggingHandler(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) GetBucketObjectLockConfigHandler(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) GetBucketVersioningHandler(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) GetBucketNotificationHandler(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) ListenBucketNotificationHandler(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) ListObjectsV2MHandler(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) ListObjectsV2Handler(w http.ResponseWriter, r *http.Request) { res := &handlerResult{ Method: "ListObjectsV2", ReqInfo: middleware.GetReqInfo(r.Context()), } h.writeResponse(w, res) } func (h *handlerMock) ListBucketObjectVersionsHandler(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) ListObjectsV1Handler(w http.ResponseWriter, r *http.Request) { res := &handlerResult{ Method: "ListObjectsV1", ReqInfo: middleware.GetReqInfo(r.Context()), } h.writeResponse(w, res) } func (h *handlerMock) PutBucketLifecycleHandler(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) PutBucketEncryptionHandler(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) PutBucketPolicyHandler(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) PutBucketObjectLockConfigHandler(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) PutBucketTaggingHandler(w http.ResponseWriter, r *http.Request) { res := &handlerResult{ Method: middleware.PutBucketTaggingOperation, ReqInfo: middleware.GetReqInfo(r.Context()), } h.writeResponse(w, res) } func (h *handlerMock) PutBucketVersioningHandler(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) PutBucketNotificationHandler(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) CreateBucketHandler(w http.ResponseWriter, r *http.Request) { reqInfo := middleware.GetReqInfo(r.Context()) h.buckets[reqInfo.Namespace+reqInfo.BucketName] = &data.BucketInfo{ Name: reqInfo.BucketName, } res := &handlerResult{ Method: middleware.CreateBucketOperation, ReqInfo: middleware.GetReqInfo(r.Context()), } h.writeResponse(w, res) } func (h *handlerMock) HeadBucketHandler(w http.ResponseWriter, r *http.Request) { res := &handlerResult{ Method: middleware.HeadBucketOperation, ReqInfo: middleware.GetReqInfo(r.Context()), } h.writeResponse(w, res) } func (h *handlerMock) PostObject(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) DeleteMultipleObjectsHandler(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) DeleteBucketPolicyHandler(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) DeleteBucketLifecycleHandler(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) DeleteBucketEncryptionHandler(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) DeleteBucketHandler(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) ListBucketsHandler(w http.ResponseWriter, r *http.Request) { res := &handlerResult{ Method: middleware.ListBucketsOperation, ReqInfo: middleware.GetReqInfo(r.Context()), } h.writeResponse(w, res) } func (h *handlerMock) Preflight(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) AppendCORSHeaders(http.ResponseWriter, *http.Request) { } func (h *handlerMock) CreateMultipartUploadHandler(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) UploadPartHandler(w http.ResponseWriter, r *http.Request) { res := &handlerResult{ Method: "UploadPart", ReqInfo: middleware.GetReqInfo(r.Context()), } h.writeResponse(w, res) } func (h *handlerMock) UploadPartCopy(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) CompleteMultipartUploadHandler(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) AbortMultipartUploadHandler(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) ListPartsHandler(http.ResponseWriter, *http.Request) { //TODO implement me panic("implement me") } func (h *handlerMock) ListMultipartUploadsHandler(w http.ResponseWriter, r *http.Request) { res := &handlerResult{ Method: "ListMultipartUploads", ReqInfo: middleware.GetReqInfo(r.Context()), } h.writeResponse(w, res) } func (h *handlerMock) PatchObjectHandler(http.ResponseWriter, *http.Request) { panic("implement me") } func (h *handlerMock) ResolveBucket(ctx context.Context, name string) (*data.BucketInfo, error) { reqInfo := middleware.GetReqInfo(ctx) bktInfo, ok := h.buckets[reqInfo.Namespace+name] if !ok { return nil, apierr.GetAPIError(apierr.ErrNoSuchBucket) } return bktInfo, nil } func (h *handlerMock) ResolveCID(ctx context.Context, bucket string) (cid.ID, error) { bktInfo, err := h.ResolveBucket(ctx, bucket) if err != nil { return cid.ID{}, err } return bktInfo.CID, nil } func (h *handlerMock) writeResponse(w http.ResponseWriter, resp *handlerResult) { respData, err := json.Marshal(resp) require.NoError(h.t, err) _, err = w.Write(respData) require.NoError(h.t, err) }