Skip to content
Open
Show file tree
Hide file tree
Changes from all 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 oss/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ func (conn Conn) getAdditionalHeaderKeysV4(req *http.Request) ([]string, map[str
}

// signHeader signs the header and sets it as the authorization header.
func (conn Conn) signHeader(req *http.Request, canonicalizedResource string) {
akIf := conn.config.GetCredentials()
func (conn Conn) signHeader(req *http.Request, canonicalizedResource string, credentials Credentials) {
akIf := credentials
authorizationStr := ""
if conn.config.AuthVersion == AuthV4 {
strDay := ""
Expand Down
4 changes: 2 additions & 2 deletions oss/bucket.go
Original file line number Diff line number Diff line change
Expand Up @@ -892,7 +892,7 @@ func (bucket Bucket) RestoreObjectXML(objectKey, configXML string, options ...Op
// string returns the signed URL, when error is nil.
// error it's nil if no error, otherwise it's an error object.
func (bucket Bucket) SignURL(objectKey string, method HTTPMethod, expiredInSec int64, options ...Option) (string, error) {
err := CheckObjectName(objectKey)
err := CheckObjectNameEx(objectKey, bucket.GetConfig().VerifyObjectStrict)
if err != nil {
return "", err
}
Expand All @@ -913,7 +913,7 @@ func (bucket Bucket) SignURL(objectKey string, method HTTPMethod, expiredInSec i
return "", err
}

return bucket.Client.Conn.signURL(method, bucket.BucketName, objectKey, expiration, params, headers), nil
return bucket.Client.Conn.signURL(method, bucket.BucketName, objectKey, expiration, params, headers)
}

// PutObjectWithURL uploads an object with the URL. If the object exists, it will be overwritten.
Expand Down
183 changes: 168 additions & 15 deletions oss/bucket_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1222,7 +1222,7 @@ func (s *OssBucketSuite) TestGetObjectToFile(c *C) {

err = s.bucket.GetObjectToFile(objectName, newFile, NormalizedRange("-10"))
c.Assert(err, IsNil)
eq, err = compareFileData(newFile, val[(len(val)-10):len(val)])
eq, err = compareFileData(newFile, val[(len(val)-10):])
c.Assert(err, IsNil)
c.Assert(eq, Equals, true)
os.Remove(newFile)
Expand Down Expand Up @@ -4364,8 +4364,8 @@ func (s *OssBucketSuite) TestVersioningBatchDeleteVersionObjects(c *C) {
c.Assert(versionIdV1 != versionIdV2, Equals, true)

//batch delete objects
versionIds := []DeleteObject{DeleteObject{Key: objectName1, VersionId: versionIdV1},
DeleteObject{Key: objectName2, VersionId: versionIdV2}}
versionIds := []DeleteObject{{Key: objectName1, VersionId: versionIdV1},
{Key: objectName2, VersionId: versionIdV2}}
deleteResult, err := bucket.DeleteObjectVersions(versionIds)
c.Assert(err, IsNil)
c.Assert(len(deleteResult.DeletedObjectsDetail), Equals, 2)
Expand Down Expand Up @@ -4395,8 +4395,8 @@ func (s *OssBucketSuite) TestVersioningBatchDeleteVersionObjects(c *C) {
c.Assert(versionIdV1 != versionIdV2, Equals, true)

//batch delete objects
versionIds = []DeleteObject{DeleteObject{Key: objectName1, VersionId: versionIdV1},
DeleteObject{Key: objectName2, VersionId: versionIdV2}}
versionIds = []DeleteObject{{Key: objectName1, VersionId: versionIdV1},
{Key: objectName2, VersionId: versionIdV2}}
deleteResult, err = bucket.DeleteObjectVersions(versionIds)
c.Assert(err, IsNil)
c.Assert(len(deleteResult.DeletedObjectsDetail), Equals, 2)
Expand All @@ -4415,8 +4415,8 @@ func (s *OssBucketSuite) TestVersioningBatchDeleteVersionObjects(c *C) {
c.Assert(versionIdV1 != versionIdV2, Equals, true)

//batch delete objects
versionIds = []DeleteObject{DeleteObject{Key: objectName1, VersionId: versionIdV1},
DeleteObject{Key: objectName2, VersionId: versionIdV2}}
versionIds = []DeleteObject{{Key: objectName1, VersionId: versionIdV1},
{Key: objectName2, VersionId: versionIdV2}}
deleteResult, err = bucket.DeleteObjectVersions(versionIds)
c.Assert(err, IsNil)
c.Assert(len(deleteResult.DeletedObjectsDetail), Equals, 2)
Expand Down Expand Up @@ -4470,8 +4470,8 @@ func (s *OssBucketSuite) TestVersioningBatchDeleteDefaultVersionObjects(c *C) {
c.Assert(versionIdV1 != versionIdV2, Equals, true)

//batch delete objects
versionIds := []DeleteObject{DeleteObject{Key: objectName1, VersionId: ""},
DeleteObject{Key: objectName2, VersionId: ""}}
versionIds := []DeleteObject{{Key: objectName1, VersionId: ""},
{Key: objectName2, VersionId: ""}}
deleteResult, err := bucket.DeleteObjectVersions(versionIds)
c.Assert(err, IsNil)

Expand Down Expand Up @@ -4500,14 +4500,14 @@ func (s *OssBucketSuite) TestVersioningBatchDeleteDefaultVersionObjects(c *C) {
c.Assert(len(listResult.ObjectVersions), Equals, 2)

// delete version object
versionIds = []DeleteObject{DeleteObject{Key: objectName1, VersionId: versionIdV1},
DeleteObject{Key: objectName2, VersionId: versionIdV2}}
versionIds = []DeleteObject{{Key: objectName1, VersionId: versionIdV1},
{Key: objectName2, VersionId: versionIdV2}}
deleteResult, err = bucket.DeleteObjectVersions(versionIds)
c.Assert(err, IsNil)

// delete deleteMark object
versionIds = []DeleteObject{DeleteObject{Key: objectName1, VersionId: keyInfo1.DeleteMarkerVersionId},
DeleteObject{Key: objectName2, VersionId: keyInfo2.DeleteMarkerVersionId}}
versionIds = []DeleteObject{{Key: objectName1, VersionId: keyInfo1.DeleteMarkerVersionId},
{Key: objectName2, VersionId: keyInfo2.DeleteMarkerVersionId}}
deleteResult, err = bucket.DeleteObjectVersions(versionIds)
c.Assert(err, IsNil)

Expand Down Expand Up @@ -5113,7 +5113,7 @@ func (s *OssBucketSuite) TestVersioningObjectTagging(c *C) {

// ObjectTagging v1
var tagging1 Tagging
tagging1.Tags = []Tag{Tag{Key: "testkey1", Value: "testvalue1"}}
tagging1.Tags = []Tag{{Key: "testkey1", Value: "testvalue1"}}
err = bucket.PutObjectTagging(objectName, tagging1, VersionId(versionIdV1))
c.Assert(err, IsNil)
getResult, err := bucket.GetObjectTagging(objectName, VersionId(versionIdV1))
Expand All @@ -5123,7 +5123,7 @@ func (s *OssBucketSuite) TestVersioningObjectTagging(c *C) {

// ObjectTagging v2
var tagging2 Tagging
tagging2.Tags = []Tag{Tag{Key: "testkey2", Value: "testvalue2"}}
tagging2.Tags = []Tag{{Key: "testkey2", Value: "testvalue2"}}
err = bucket.PutObjectTagging(objectName, tagging2, VersionId(versionIdV2))
c.Assert(err, IsNil)
getResult, err = bucket.GetObjectTagging(objectName, VersionId(versionIdV2))
Expand Down Expand Up @@ -6022,3 +6022,156 @@ func (s *OssBucketSuite) TestPutObjectWithCallbackResult(c *C) {
c.Assert(err, IsNil)
c.Assert(str, Equals, objectValue)
}

type TestCredentialsProviderError struct {
AccessKeyId string
AccessKeySecret string
SecurityToken string
}

func (testInfBuild *TestCredentialsProviderError) GetCredentials() Credentials {
cred, _ := testInfBuild.GetCredentialsE()
return cred
}

func (testInfBuild *TestCredentialsProviderError) GetCredentialsE() (Credentials, error) {
var provider *TestCredentials
keyId := testInfBuild.AccessKeyId
if keyId == "" {
return provider, fmt.Errorf("access key id is empty!")
}
secret := testInfBuild.AccessKeySecret
if secret == "" {
return provider, fmt.Errorf("access key secret is empty!")
}
return &envCredentials{
AccessKeyId: keyId,
AccessKeySecret: secret,
SecurityToken: "",
}, nil
}

func (s *OssBucketSuite) TestCredentialsProviderError(c *C) {
var bucketNameTest = bucketNamePrefix + RandLowStr(6)
client, err := New(endpoint, accessID, accessKey)
c.Assert(err, IsNil)
// Create
err = client.CreateBucket(bucketNameTest)
c.Assert(err, IsNil)

bucket, err := client.Bucket(bucketNameTest)
c.Assert(err, IsNil)

objectName := objectNamePrefix + RandStr(8)
objectValue := "大江东去,浪淘尽,千古风流人物。 故垒西边,人道是、三国周郎赤壁。 乱石穿空,惊涛拍岸,卷起千堆雪。 江山如画,一时多少豪杰。" +
"遥想公谨当年,小乔初嫁了,雄姿英发。 羽扇纶巾,谈笑间、樯橹灰飞烟灭。故国神游,多情应笑我,早生华发,人生如梦,一尊还酹江月。"

// Put string
var respHeader http.Header
err = s.bucket.PutObject(objectName, strings.NewReader(objectValue), GetResponseHeader(&respHeader))
c.Assert(err, IsNil)

var defaultBuild TestCredentialsProviderError
defaultBuild.AccessKeyId = ""
defaultBuild.AccessKeySecret = accessKey
client, err = New(endpoint, "", "", SetCredentialsProvider(&defaultBuild))
c.Assert(err, IsNil)
err = client.DeleteBucket(bucketNameTest)
c.Assert(err, NotNil)
c.Assert(err.Error(), Equals, "access key id is empty!")

bucket, err = client.Bucket(bucketNameTest)
c.Assert(err, IsNil)
_, err = bucket.SignURL(objectName, http.MethodGet, 3600)
c.Assert(err, NotNil)
c.Assert(err.Error(), Equals, "access key id is empty!")

channelName := "test-sign-rtmp-url"
playlistName := "playlist.m3u8"
_, err = bucket.SignRtmpURL(channelName, playlistName, 3600)
c.Assert(err, IsNil)

defaultBuild.AccessKeyId = accessID
defaultBuild.AccessKeySecret = ""
client, err = New(endpoint, "", "", SetCredentialsProvider(&defaultBuild))
c.Assert(err, IsNil)
err = client.DeleteBucket(bucketNameTest)
c.Assert(err, NotNil)
c.Assert(err.Error(), Equals, "access key secret is empty!")

bucket, err = client.Bucket(bucketNameTest)
c.Assert(err, IsNil)
_, err = bucket.SignURL(objectName, http.MethodGet, 3600)
c.Assert(err, NotNil)
c.Assert(err.Error(), Equals, "access key secret is empty!")

_, err = bucket.SignRtmpURL(channelName, playlistName, 3600)
c.Assert(err, IsNil)

defaultBuild.AccessKeyId = accessID
defaultBuild.AccessKeySecret = accessKey
client, err = New(endpoint, "", "", SetCredentialsProvider(&defaultBuild))
c.Assert(err, IsNil)
err = client.DeleteBucket(bucketNameTest)
c.Assert(err, IsNil)

_, err = bucket.SignURL(objectName, http.MethodGet, 3600)
c.Assert(err, IsNil)

_, err = bucket.SignRtmpURL(channelName, playlistName, 3600)
c.Assert(err, IsNil)
}

func (s *OssBucketSuite) TestVerifyObjectStrict(c *C) {
var bucketNameTest = bucketNamePrefix + RandLowStr(6)
client, err := New(endpoint, accessID, accessKey)
c.Assert(err, IsNil)
// Create
err = client.CreateBucket(bucketNameTest)
c.Assert(err, IsNil)

bucket, err := client.Bucket(bucketNameTest)
c.Assert(err, IsNil)

objectName := "?" + objectNamePrefix + RandStr(8)
objectValue := "大江东去,浪淘尽,千古风流人物。 故垒西边,人道是、三国周郎赤壁。 乱石穿空,惊涛拍岸,卷起千堆雪。 江山如画,一时多少豪杰。" +
"遥想公谨当年,小乔初嫁了,雄姿英发。 羽扇纶巾,谈笑间、樯橹灰飞烟灭。故国神游,多情应笑我,早生华发,人生如梦,一尊还酹江月。"

// Put string
var respHeader http.Header
err = s.bucket.PutObject(objectName, strings.NewReader(objectValue), GetResponseHeader(&respHeader))
c.Assert(err, IsNil)

// Sign
_, err = bucket.SignURL(objectName, http.MethodGet, 3600)
c.Assert(err, NotNil)
c.Assert(err.Error(), Equals, "object name is invalid, can't start with '?'")

//
objectName = ""
_, err = bucket.SignURL(objectName, http.MethodGet, 3600)
c.Assert(err, NotNil)
c.Assert(err.Error(), Equals, "object name is empty")

//Disable VerifyObjectStrictFlag
client, err = New(endpoint, accessID, accessKey, VerifyObjectStrict(false))
c.Assert(err, IsNil)

bucket, err = client.Bucket(bucketNameTest)
c.Assert(err, IsNil)

objectName = "?"
url, err := bucket.SignURL(objectName, http.MethodGet, 3600)
c.Assert(err, IsNil)
c.Assert(strings.Contains(url, "/%3F?Expires="), Equals, true)

objectName = "?123"
url, err = bucket.SignURL(objectName, http.MethodGet, 3600)
c.Assert(err, IsNil)
c.Assert(strings.Contains(url, "/%3F123?Expires="), Equals, true)

objectName = "123?"
url, err = bucket.SignURL(objectName, http.MethodGet, 3600)
c.Assert(err, IsNil)
c.Assert(strings.Contains(url, "/123%3F?Expires="), Equals, true)
}
7 changes: 7 additions & 0 deletions oss/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -2908,6 +2908,13 @@ func Product(product string) ClientOption {
}
}

// VerifyObjectStrict sets the flag of verifying object name strictly.
func VerifyObjectStrict(enable bool) ClientOption {
return func(client *Client) {
client.Config.VerifyObjectStrict = enable
}
}

// Private
func (client Client) do(method, bucketName string, params map[string]interface{},
headers map[string]string, data io.Reader, options ...Option) (*Response, error) {
Expand Down
12 changes: 10 additions & 2 deletions oss/conf.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,23 @@ type HTTPMaxConns struct {
MaxConnsPerHost int
}

// CredentialInf is interface for get AccessKeyID,AccessKeySecret,SecurityToken
// Credentials is interface for get AccessKeyID,AccessKeySecret,SecurityToken
type Credentials interface {
GetAccessKeyID() string
GetAccessKeySecret() string
GetSecurityToken() string
}

// CredentialInfBuild is interface for get CredentialInf
// CredentialsProvider is interface for get Credential Info
type CredentialsProvider interface {
GetCredentials() Credentials
}

type CredentialsProviderE interface {
CredentialsProvider
GetCredentialsE() (Credentials, error)
}

type defaultCredentials struct {
config *Config
}
Expand Down Expand Up @@ -173,6 +178,7 @@ type Config struct {
Region string // such as cn-hangzhou
CloudBoxId string //
Product string // oss or oss-cloudbox, default is oss
VerifyObjectStrict bool // a flag of verifying object name strictly. Default is enable.
}

// LimitUploadSpeed uploadSpeed:KB/s, 0 is unlimited,default is 0
Expand Down Expand Up @@ -289,5 +295,7 @@ func getDefaultOssConfig() *Config {

config.Product = "oss"

config.VerifyObjectStrict = true

return &config
}
27 changes: 22 additions & 5 deletions oss/conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,15 @@ func (conn Conn) doRequest(ctx context.Context, method string, uri *url.URL, can
req.Header.Set(HttpHeaderOssContentSha256, DefaultContentSha256)
}

akIf := conn.config.GetCredentials()
var akIf Credentials
if providerE, ok := conn.config.CredentialsProvider.(CredentialsProviderE); ok {
if akIf, err = providerE.GetCredentialsE(); err != nil {
return nil, err
}
} else {
akIf = conn.config.GetCredentials()
}

if akIf.GetSecurityToken() != "" {
req.Header.Set(HTTPHeaderOssSecurityToken, akIf.GetSecurityToken())
}
Expand All @@ -349,7 +357,7 @@ func (conn Conn) doRequest(ctx context.Context, method string, uri *url.URL, can
}
}

conn.signHeader(req, canonicalizedResource)
conn.signHeader(req, canonicalizedResource, akIf)

// Transfer started
event := newProgressEvent(TransferStartedEvent, 0, req.ContentLength, 0)
Expand Down Expand Up @@ -381,8 +389,17 @@ func (conn Conn) doRequest(ctx context.Context, method string, uri *url.URL, can
return conn.handleResponse(resp, crc)
}

func (conn Conn) signURL(method HTTPMethod, bucketName, objectName string, expiration int64, params map[string]interface{}, headers map[string]string) string {
akIf := conn.config.GetCredentials()
func (conn Conn) signURL(method HTTPMethod, bucketName, objectName string, expiration int64, params map[string]interface{}, headers map[string]string) (string, error) {
var akIf Credentials
var err error
if providerE, ok := conn.config.CredentialsProvider.(CredentialsProviderE); ok {
if akIf, err = providerE.GetCredentialsE(); err != nil {
return "", err
}
} else {
akIf = conn.config.GetCredentials()
}

if akIf.GetSecurityToken() != "" {
params[HTTPParamSecurityToken] = akIf.GetSecurityToken()
}
Expand Down Expand Up @@ -430,7 +447,7 @@ func (conn Conn) signURL(method HTTPMethod, bucketName, objectName string, expir
params[HTTPParamSignatureV2] = signedStr
}
urlParams := conn.getURLParams(params)
return conn.url.getSignURL(bucketName, objectName, urlParams)
return conn.url.getSignURL(bucketName, objectName, urlParams), nil
}

func (conn Conn) signRtmpURL(bucketName, channelName, playlistName string, expiration int64) string {
Expand Down
5 changes: 4 additions & 1 deletion oss/conn_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,10 @@ func (s *OssConnSuite) TestAuth(c *C) {
req.Header.Set("X-OSS-Magic", "abracadabra")
req.Header.Set("Content-Md5", "ODBGOERFMDMzQTczRUY3NUE3NzA5QzdFNUYzMDQxNEM=")

conn.signHeader(req, conn.getResource("bucket", "object", ""))
var akIf Credentials
credProvider := conn.config.CredentialsProvider
akIf = credProvider.(CredentialsProvider).GetCredentials()
conn.signHeader(req, conn.getResource("bucket", "object", ""), akIf)
testLogger.Println("AUTHORIZATION:", req.Header.Get(HTTPHeaderAuthorization))
}

Expand Down
Loading