Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: remove create object & bucket approval #225

Merged
merged 23 commits into from
Mar 28, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ on:
- develop

env:
GreenfieldTag: master
GreenfieldStorageProviderTag: master
GreenfieldTag: 5a0729673be023c3c34f34d862e89a322bd75a8a
GreenfieldStorageProviderTag: 3f1ffe22d70a50bba0504f13e0867dd4e9e641c2
GOPRIVATE: github.com/bnb-chain
GH_ACCESS_TOKEN: ${{ secrets.GH_TOKEN }}
MYSQL_USER: root
Expand Down
13 changes: 13 additions & 0 deletions client/api_basic.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ import (
type IBasicClient interface {
EnableTrace(outputStream io.Writer, onlyTraceErr bool)

GetNonceByAddr(ctx context.Context, address sdk.AccAddress) (uint64, error)

GetNodeInfo(ctx context.Context) (*p2p.DefaultNodeInfo, *tmservice.VersionInfo, error)
GetStatus(ctx context.Context) (*ctypes.ResultStatus, error)
GetCommit(ctx context.Context, height int64) (*ctypes.ResultCommit, error)
Expand Down Expand Up @@ -83,6 +85,17 @@ func (c *Client) GetNodeInfo(ctx context.Context) (*p2p.DefaultNodeInfo, *tmserv
return nodeInfoResponse.DefaultNodeInfo, nodeInfoResponse.ApplicationVersion, nil
}

// GetNonceByAddr - Get the nonce value by address.
//
// - address: The operator address.
//
// - ret1: The nonce value for the Client
//
// - ret2: Return error when getting next nonce failed, otherwise return nil.
func (c *Client) GetNonceByAddr(ctx context.Context, address sdk.AccAddress) (uint64, error) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it better to clarify what kind of nonce here the SDK need to get?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As SP off-chain-auth also did have a nonce concept, it would better to explain what nonce is it .

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's just redundant function for local test, i will delete it

return c.chainClient.GetNonceByAddr(ctx, address)
}

// GetStatus - Get the status of connected Node.
//
// - ctx: Context variables for the current API call.
Expand Down
79 changes: 16 additions & 63 deletions client/api_bucket.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"fmt"
"io"
"math"
"math/rand"
"net/http"
"net/url"
"strconv"
Expand All @@ -32,7 +33,6 @@ import (
// IBucketClient interface defines functions related to bucket.
// The concept of "bucket" is the same as the concept of a bucket in AWS S3 storage.
type IBucketClient interface {
GetCreateBucketApproval(ctx context.Context, createBucketMsg *storageTypes.MsgCreateBucket) (*storageTypes.MsgCreateBucket, error)
CreateBucket(ctx context.Context, bucketName string, primaryAddr string, opts types.CreateBucketOptions) (string, error)
DeleteBucket(ctx context.Context, bucketName string, opt types.DeleteBucketOption) (string, error)
UpdateBucketVisibility(ctx context.Context, bucketName string, visibility storageTypes.VisibilityType, opt types.UpdateVisibilityOption) (string, error)
Expand All @@ -57,66 +57,6 @@ type IBucketClient interface {
ListBucketsByPaymentAccount(ctx context.Context, paymentAccount string, opts types.ListBucketsByPaymentAccountOptions) (types.ListBucketsByPaymentAccountResult, error)
}

// GetCreateBucketApproval - Send create bucket approval request to SP and returns the signature info for the approval of preCreating resources.
//
// - ctx: Context variables for the current API call.
//
// - createBucketMsg: The msg of create bucket which defined by the greenfield chain.
//
// - ret1: The msg of create bucket which contain the approval signature from the storage provider
//
// - ret2: Return error when get approval failed, otherwise return nil.
func (c *Client) GetCreateBucketApproval(ctx context.Context, createBucketMsg *storageTypes.MsgCreateBucket) (*storageTypes.MsgCreateBucket, error) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need to remove those old "getApproval" methods because we need make sure the change is backward compatible.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an exported method. Clients code might have already used it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we should not delete this part for now.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

unsignedBytes := createBucketMsg.GetSignBytes()

// set the action type
urlVal := make(url.Values)
urlVal["action"] = []string{types.CreateBucketAction}

reqMeta := requestMeta{
urlValues: urlVal,
urlRelPath: "get-approval",
contentSHA256: types.EmptyStringSHA256,
txnMsg: hex.EncodeToString(unsignedBytes),
}

sendOpt := sendOptions{
method: http.MethodGet,
adminInfo: AdminAPIInfo{
isAdminAPI: true,
adminVersion: types.AdminV1Version,
},
}

primarySPAddr := createBucketMsg.GetPrimarySpAddress()
endpoint, err := c.getSPUrlByAddr(primarySPAddr)
if err != nil {
log.Error().Msg(fmt.Sprintf("route endpoint by addr: %s failed, err: %s", primarySPAddr, err.Error()))
return nil, err
}

resp, err := c.sendReq(ctx, reqMeta, &sendOpt, endpoint)
if err != nil {
return nil, err
}

// fetch primary signed msg from sp response
signedRawMsg := resp.Header.Get(types.HTTPHeaderSignedMsg)
if signedRawMsg == "" {
return nil, errors.New("fail to fetch pre createBucket signature")
}

signedMsgBytes, err := hex.DecodeString(signedRawMsg)
if err != nil {
return nil, err
}

var signedMsg storageTypes.MsgCreateBucket
storageTypes.ModuleCdc.MustUnmarshalJSON(signedMsgBytes, &signedMsg)

return &signedMsg, nil
}

// CreateBucket - Create a new bucket in greenfield.
//
// This API sends a request to the storage provider to get approval for creating bucket and sends the createBucket transaction to the Greenfield.
Expand Down Expand Up @@ -159,17 +99,30 @@ func (c *Client) CreateBucket(ctx context.Context, bucketName string, primaryAdd
if err != nil {
return "", err
}
signedMsg, err := c.GetCreateBucketApproval(ctx, createBucketMsg)

accAddress, err := sdk.AccAddressFromHexUnsafe(primaryAddr)
if err != nil {
return "", err
}

sp, err := c.GetStorageProviderInfo(ctx, accAddress)
if err != nil {
return "", err
}

families, err := c.QuerySpAvailableGlobalVirtualGroupFamilies(ctx, sp.Id)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we'd better use the optimal API to get one VGF here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

if err != nil {
return "", err
}

createBucketMsg.PrimarySpApproval.GlobalVirtualGroupFamilyId = families[rand.Intn(len(families))]

// set the default txn broadcast mode as block mode
if opts.TxOpts == nil {
broadcastMode := tx.BroadcastMode_BROADCAST_MODE_SYNC
opts.TxOpts = &gnfdsdk.TxOption{Mode: &broadcastMode}
}
msgs := []sdk.Msg{signedMsg}
msgs := []sdk.Msg{createBucketMsg}

if opts.Tags != nil {
// Set tag
Expand Down
75 changes: 14 additions & 61 deletions client/api_object.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"bytes"
"context"
"encoding/base64"
"encoding/hex"
"encoding/xml"
"errors"
"fmt"
Expand Down Expand Up @@ -34,7 +33,6 @@ import (
// IObjectClient interface defines functions related to object operations.
// The concept of "object" is the same as the concept of the object in AWS S3 storage.
type IObjectClient interface {
GetCreateObjectApproval(ctx context.Context, createObjectMsg *storageTypes.MsgCreateObject) (*storageTypes.MsgCreateObject, error)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to delete this API for now.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

CreateObject(ctx context.Context, bucketName, objectName string, reader io.Reader, opts types.CreateObjectOptions) (string, error)
UpdateObjectContent(ctx context.Context, bucketName, objectName string, reader io.Reader, opts types.UpdateObjectOptions) (string, error)
PutObject(ctx context.Context, bucketName, objectName string, objectSize int64, reader io.Reader, opts types.PutObjectOptions) error
Expand Down Expand Up @@ -116,6 +114,19 @@ func (c *Client) CreateObject(ctx context.Context, bucketName, objectName string
return "", err
}

// This code block checks for unsupported or potentially risky formats in object names.
// The checks are essential for ensuring the security and compatibility of the object names within the system.
// 1. ".." in object names: Checked to prevent path traversal attacks which might access directories outside the intended scope.
// 2. Object name being "/": The root directory should not be used as an object name due to potential security risks and ambiguity.
// 3. "\\" in object names: Backslashes are checked because they are often not supported in UNIX-like file systems and can cause issues in path parsing.
// 4. SQL Injection patterns in object names: Ensures that the object name does not contain patterns that could be used for SQL injection attacks, maintaining the integrity of the database.
if strings.Contains(objectName, "..") ||
objectName == "/" ||
strings.Contains(objectName, "\\") ||
utils.IsSQLInjection(objectName) {
return "", fmt.Errorf("fail to check object name:%s", objectName)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you wrap these format check codes into a single function?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please also move the object name rules into the CheckObjectName function, not comment here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CheckObjectName already has the same comments, so i just delete it


// compute hash root of payload
expectCheckSums, size, redundancyType, err := c.ComputeHashRoots(reader, opts.IsSerialComputeMode)
if err != nil {
Expand Down Expand Up @@ -144,17 +155,12 @@ func (c *Client) CreateObject(ctx context.Context, bucketName, objectName string
return "", err
}

signedCreateObjectMsg, err := c.GetCreateObjectApproval(ctx, createObjectMsg)
if err != nil {
return "", err
}

// set the default txn broadcast mode as block mode
if opts.TxOpts == nil {
broadcastMode := tx.BroadcastMode_BROADCAST_MODE_SYNC
opts.TxOpts = &gnfdsdk.TxOption{Mode: &broadcastMode}
}
msgs := []sdk.Msg{signedCreateObjectMsg}
msgs := []sdk.Msg{createObjectMsg}

if opts.Tags != nil {
// Set tag
Expand Down Expand Up @@ -1031,59 +1037,6 @@ func (c *Client) ListObjects(ctx context.Context, bucketName string, opts types.
return listObjectsResult, nil
}

// GetCreateObjectApproval returns the signature info for the approval of preCreating resources
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// Deprecated: GetCreateObjectApproval returns the signature info for the approval of preCreating resources

No need to delete this API

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean change the comment to other than delete this line:

// Deprecated: GetCreateObjectApproval returns the signature info for the approval of preCreating resources

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And the same to GetCreateBucketApproval API

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

func (c *Client) GetCreateObjectApproval(ctx context.Context, createObjectMsg *storageTypes.MsgCreateObject) (*storageTypes.MsgCreateObject, error) {
unsignedBytes := createObjectMsg.GetSignBytes()

// set the action type
urlValues := url.Values{
"action": {types.CreateObjectAction},
}

reqMeta := requestMeta{
urlValues: urlValues,
urlRelPath: "get-approval",
contentSHA256: types.EmptyStringSHA256,
txnMsg: hex.EncodeToString(unsignedBytes),
}

sendOpt := sendOptions{
method: http.MethodGet,
adminInfo: AdminAPIInfo{
isAdminAPI: true,
adminVersion: types.AdminV1Version,
},
}

bucketName := createObjectMsg.BucketName
endpoint, err := c.getSPUrlByBucket(bucketName)
if err != nil {
log.Error().Msg(fmt.Sprintf("route endpoint by bucket: %s failed, err: %s", bucketName, err.Error()))
return nil, err
}

resp, err := c.sendReq(ctx, reqMeta, &sendOpt, endpoint)
if err != nil {
return nil, err
}

// fetch primary signed msg from sp response
signedRawMsg := resp.Header.Get(types.HTTPHeaderSignedMsg)
if signedRawMsg == "" {
return nil, errors.New("fail to fetch pre createObject signature")
}

signedMsgBytes, err := hex.DecodeString(signedRawMsg)
if err != nil {
return nil, err
}

var signedMsg storageTypes.MsgCreateObject
storageTypes.ModuleCdc.MustUnmarshalJSON(signedMsgBytes, &signedMsg)

return &signedMsg, nil
}

// CreateFolder send create empty object txn to greenfield chain
func (c *Client) CreateFolder(ctx context.Context, bucketName, objectName string, opts types.CreateObjectOptions) (string, error) {
if !strings.HasSuffix(objectName, "/") {
Expand Down
40 changes: 40 additions & 0 deletions client/api_virtual_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import (
// IVirtualGroupClient interface defines basic functions related to Virtual Group.
type IVirtualGroupClient interface {
QueryVirtualGroupFamily(ctx context.Context, globalVirtualGroupFamilyID uint32) (*types.GlobalVirtualGroupFamily, error)
QuerySpAvailableGlobalVirtualGroupFamilies(ctx context.Context, spID uint32) ([]uint32, error)
QueryVirtualGroupParams(ctx context.Context) (*types.Params, error)
}

// QueryVirtualGroupFamily - Query the virtual group family by ID.
Expand All @@ -31,3 +33,41 @@ func (c *Client) QueryVirtualGroupFamily(ctx context.Context, globalVirtualGroup
}
return queryResponse.GlobalVirtualGroupFamily, nil
}

// QuerySpAvailableGlobalVirtualGroupFamilies - Query the virtual group family IDs by SP ID.
//
// Virtual group family(VGF) serve as a means of grouping global virtual groups. Each bucket must be associated with a unique global virtual group family and cannot cross families.
//
// - ctx: Context variables for the current API call.
//
// - spID: Identify the storage provider.
//
// - ret1: The virtual group family detail.
//
// - ret2: Return error when the request failed, otherwise return nil.
func (c *Client) QuerySpAvailableGlobalVirtualGroupFamilies(ctx context.Context, spID uint32) ([]uint32, error) {
queryResponse, err := c.chainClient.QuerySpAvailableGlobalVirtualGroupFamilies(ctx, &types.QuerySPAvailableGlobalVirtualGroupFamiliesRequest{
SpId: spID,
})
if err != nil {
return nil, err
}
return queryResponse.GlobalVirtualGroupFamilyIds, nil
}

// QueryVirtualGroupParams - Query the virtual group family param.
//
// Virtual group family(VGF) serve as a means of grouping global virtual groups. Each bucket must be associated with a unique global virtual group family and cannot cross families.
//
// - ctx: Context variables for the current API call.
//
// - ret1: Params holds all the parameters of this module..
//
// - ret2: Return error when the request failed, otherwise return nil.
func (c *Client) QueryVirtualGroupParams(ctx context.Context) (*types.Params, error) {
queryResponse, err := c.chainClient.VirtualGroupQueryClient.Params(ctx, &types.QueryParamsRequest{})
if err != nil {
return nil, err
}
return &queryResponse.Params, nil
}
3 changes: 2 additions & 1 deletion e2e/basesuite/suite.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ import (
"bufio"
"context"
"fmt"
storageTypes "github.com/bnb-chain/greenfield/x/storage/types"
"os"
"path/filepath"
"time"

storageTypes "github.com/bnb-chain/greenfield/x/storage/types"

"github.com/bnb-chain/greenfield-go-sdk/client"
"github.com/bnb-chain/greenfield-go-sdk/types"
"github.com/stretchr/testify/suite"
Expand Down
7 changes: 7 additions & 0 deletions e2e/e2e_storage_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ func (s *StorageTestSuite) SetupSuite() {
break
}
}
//wait for sp to create
var families []uint32
for len(families) == 0 {
time.Sleep(5 * time.Second)
families, err = s.Client.QuerySpAvailableGlobalVirtualGroupFamilies(s.ClientContext, s.PrimarySP.Id)
s.Require().NoError(err)
}
}

func TestStorageTestSuite(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ go 1.20
require (
cosmossdk.io/errors v1.0.0-beta.7
cosmossdk.io/math v1.0.1
github.com/bnb-chain/greenfield v1.4.1-0.20240221082420-50b8ec14277e
github.com/bnb-chain/greenfield v1.4.1-0.20240304054852-5a0729673be0
github.com/bnb-chain/greenfield-common/go v0.0.0-20230906132736-eb2f0efea228
github.com/cometbft/cometbft v0.37.2
github.com/consensys/gnark-crypto v0.7.0
Expand Down
5 changes: 2 additions & 3 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,8 @@ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kB
github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 h1:41iFGWnSlI2gVpmOtVTJZNodLdLQLn/KsJqFvXwnd/s=
github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40/go.mod h1:8rLXio+WjiTceGBHIoTvn60HIbs7Hm7bcHjyrSqYB9c=
github.com/bnb-chain/greenfield v1.4.1-0.20240221082420-50b8ec14277e h1:7zxM7j3KjRQojNt40Jb+JiweL8Mxm0m4PU7YsaU9CZ4=
github.com/bnb-chain/greenfield v1.4.1-0.20240221082420-50b8ec14277e/go.mod h1:sIm6fjiv6WFNKNl1Lcg4WBEvyb8yy79eLs9xzbkmf4A=
github.com/bnb-chain/greenfield v1.4.1-0.20240304054852-5a0729673be0 h1:Yfyua44EJSNz/rV5Ojk+bxk+13rbW2VuKQe0ky/RY2k=
github.com/bnb-chain/greenfield v1.4.1-0.20240304054852-5a0729673be0/go.mod h1:sIm6fjiv6WFNKNl1Lcg4WBEvyb8yy79eLs9xzbkmf4A=
github.com/bnb-chain/greenfield-cometbft v1.2.0 h1:LTStppZS9WkVj0TfEYKkk5OAQDGfYlUefWByr7Zr018=
github.com/bnb-chain/greenfield-cometbft v1.2.0/go.mod h1:WVOEZ59UYM2XePQH47/IQfcInspDn8wbRXhFSJrbU1c=
github.com/bnb-chain/greenfield-cometbft-db v0.8.1-alpha.1 h1:XcWulGacHVRiSCx90Q8Y//ajOrLNBQWR/KDB89dy3cU=
Expand Down Expand Up @@ -353,7 +353,6 @@ github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x
github.com/getkin/kin-openapi v0.53.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4=
github.com/getkin/kin-openapi v0.61.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4=
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE=
Expand Down
Loading
Loading