Просмотр исходного кода

由归邪发起的CORE SDK自动发布, BUILD_ID=99, 版本号:0.2.0

Signed-off-by: haowei.yao <haowei.yao@alibaba-inc.com>
haowei.yao 8 лет назад
Родитель
Сommit
e870512a2b

+ 3 - 0
ChangeLog.txt

@@ -1,3 +1,6 @@
+2017-11-28 Version: 0.2.0
+1, AK2.0 & StsToken
+
 2017-11-27 Version: 0.1.3
 1, format ft code with gofmt
 

+ 7 - 0
sdk/auth/credentials/KeyPairCredential.go

@@ -0,0 +1,7 @@
+package credentials
+
+type KeyPairCredential struct {
+	PrivateKey        string
+	PublicKeyId       string
+	SessionExpiration int
+}

+ 9 - 1
sdk/auth/signer.go

@@ -34,7 +34,7 @@ type Signer interface {
 	Shutdown()
 }
 
-func NewSignerWithCredential(credential Credential, commonApi func(request *requests.CommonRequest) (response *responses.CommonResponse, err error)) (signer Signer, err error) {
+func NewSignerWithCredential(credential Credential, commonApi func(request *requests.CommonRequest, signer interface{}) (response *responses.CommonResponse, err error)) (signer Signer, err error) {
 	switch instance := credential.(type) {
 	case *credentials.BaseCredential:
 		{
@@ -48,6 +48,14 @@ func NewSignerWithCredential(credential Credential, commonApi func(request *requ
 		{
 			signer, err = signers.NewSignerStsAssumeRole(instance, commonApi)
 		}
+	case *credentials.KeyPairCredential:
+		{
+			signer, err = signers.NewSignerKeyPair(instance, commonApi)
+		}
+	case *credentials.EcsInstanceCredential:
+		{
+			signer, err = signers.NewSignereEcsInstance(instance, commonApi)
+		}
 	default:
 		message := fmt.Sprintf(errors.UnsupportedCredentialMessage, reflect.TypeOf(credential))
 		err = errors.NewClientError(errors.UnsupportedCredentialCode, message, nil)

+ 34 - 1
sdk/auth/signers/algorithms.go

@@ -15,10 +15,18 @@
 package signers
 
 import (
+	"crypto"
 	"crypto/hmac"
+	"crypto/rand"
+	"crypto/rsa"
 	"crypto/sha1"
+	"crypto/x509"
 	"encoding/base64"
-)
+	"fmt"
+	/*"encoding/pem"
+	"io/ioutil"
+	"os/user"
+	"crypto/sha256"*/)
 
 func ShaHmac1(source, secret string) string {
 	key := []byte(secret)
@@ -28,3 +36,28 @@ func ShaHmac1(source, secret string) string {
 	signedString := base64.StdEncoding.EncodeToString(signedBytes)
 	return signedString
 }
+
+func Sha256WithRsa(source, secret string) string {
+	decodeString, err := base64.StdEncoding.DecodeString(secret)
+	if err != nil {
+		fmt.Println("DecodeString err", err)
+	}
+	private, err := x509.ParsePKCS8PrivateKey(decodeString)
+	if err != nil {
+		fmt.Println("ParsePKCS8PrivateKey err", err)
+	}
+
+	h := crypto.Hash.New(crypto.SHA256)
+	h.Write([]byte(source))
+	hashed := h.Sum(nil)
+	signature, err := rsa.SignPKCS1v15(rand.Reader, private.(*rsa.PrivateKey),
+		crypto.SHA256, hashed)
+	if err != nil {
+		fmt.Println("Error from signing:", err)
+		return ""
+	}
+
+	signedString := base64.StdEncoding.EncodeToString(signature)
+	fmt.Printf("Encoded: %v\n", signedString)
+	return signedString
+}

+ 5 - 4
sdk/auth/signers/credential_updater.go

@@ -28,7 +28,7 @@ type credentialUpdater struct {
 	inAdvanceScale       float64
 	buildRequestMethod   func() (*requests.CommonRequest, error)
 	responseCallBack     func(response *responses.CommonResponse) error
-	commonApi            func(request *requests.CommonRequest) (response *responses.CommonResponse, err error)
+	refreshApi           func(request *requests.CommonRequest) (response *responses.CommonResponse, err error)
 }
 
 func (updater *credentialUpdater) needUpdateCredential() (result bool) {
@@ -40,13 +40,14 @@ func (updater *credentialUpdater) needUpdateCredential() (result bool) {
 
 func (updater *credentialUpdater) updateCredential() (err error) {
 	request, err := updater.buildRequestMethod()
-	if err == nil {
+	if err != nil {
 		return
 	}
-	response, err := updater.commonApi(request)
-	if err == nil {
+	response, err := updater.refreshApi(request)
+	if err != nil {
 		return
 	}
+	updater.lastUpdateTimestamp = time.Now().Unix()
 	err = updater.responseCallBack(response)
 	return
 }

+ 121 - 6
sdk/auth/signers/signer_ecs_instance.go

@@ -15,17 +15,38 @@
 package signers
 
 import (
+	"encoding/json"
+	"fmt"
 	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials"
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses"
+	"github.com/jmespath/go-jmespath"
+	"net/http"
+	"strings"
+	"time"
 )
 
 type SignerEcsInstance struct {
-	credential *credentials.EcsInstanceCredential
+	*credentialUpdater
+	sessionCredential *sessionCredential
+	credential        *credentials.EcsInstanceCredential
+	commonApi         func(request *requests.CommonRequest, signer interface{}) (response *responses.CommonResponse, err error)
 }
 
-func NewSignerEcsInstance(credential *credentials.EcsInstanceCredential) *SignerEcsInstance {
-	return &SignerEcsInstance{
+func NewSignereEcsInstance(credential *credentials.EcsInstanceCredential, commonApi func(*requests.CommonRequest, interface{}) (response *responses.CommonResponse, err error)) (signer *SignerEcsInstance, err error) {
+	signer = &SignerEcsInstance{
 		credential: credential,
+		commonApi:  commonApi,
 	}
+
+	signer.credentialUpdater = &credentialUpdater{
+		credentialExpiration: defaultDurationSeconds / 60,
+		buildRequestMethod:   signer.buildCommonRequest,
+		responseCallBack:     signer.refreshCredential,
+		refreshApi:           signer.refreshApi,
+	}
+
+	return
 }
 
 func (*SignerEcsInstance) GetName() string {
@@ -41,18 +62,112 @@ func (*SignerEcsInstance) GetVersion() string {
 }
 
 func (signer *SignerEcsInstance) GetAccessKeyId() string {
-	return signer.credential.RoleName
+	if signer.sessionCredential == nil || signer.needUpdateCredential() {
+		signer.updateCredential()
+	}
+	if len(signer.sessionCredential.accessKeyId) <= 0 {
+		return ""
+	}
+	return signer.sessionCredential.accessKeyId
 }
 
 func (signer *SignerEcsInstance) GetExtraParam() map[string]string {
-	return map[string]string{"SecurityToken": signer.credential.RoleName}
+	if signer.sessionCredential == nil {
+		return make(map[string]string)
+	}
+	if len(signer.sessionCredential.securityToken) <= 0 {
+		return make(map[string]string)
+	}
+	return map[string]string{"SecurityToken": signer.sessionCredential.securityToken}
 }
 
 func (signer *SignerEcsInstance) Sign(stringToSign, secretSuffix string) string {
-	secret := signer.credential.RoleName + secretSuffix
+	secret := signer.sessionCredential.accessKeySecret + secretSuffix
 	return ShaHmac1(stringToSign, secret)
 }
 
+func (signer *SignerEcsInstance) buildCommonRequest() (request *requests.CommonRequest, err error) {
+	request = requests.NewCommonRequest()
+	return
+}
+
+func (signer *SignerEcsInstance) refreshApi(request *requests.CommonRequest) (response *responses.CommonResponse, err error) {
+	requestUrl := "http://100.100.100.200/latest/meta-data/ram/security-credentials/" + signer.credential.RoleName
+	httpRequest, err := http.NewRequest(requests.GET, requestUrl, strings.NewReader(""))
+	if err != nil {
+		fmt.Println("refresh Ecs sts token err", err)
+		return
+	}
+	httpClient := &http.Client{}
+	httpResponse, err := httpClient.Do(httpRequest)
+	if err != nil {
+		fmt.Println("refresh Ecs sts token err", err)
+		return
+	}
+
+	response = responses.NewCommonResponse()
+	err = responses.Unmarshal(response, httpResponse, "")
+
+	return
+}
+
+func (signer *SignerEcsInstance) refreshCredential(response *responses.CommonResponse) (err error) {
+	if response.GetHttpStatus() != http.StatusOK {
+		fmt.Println("refresh Ecs sts token err, httpStatus: " + string(response.GetHttpStatus()) + ", message = " + response.GetHttpContentString())
+		return
+	}
+	var data interface{}
+	err = json.Unmarshal(response.GetHttpContentBytes(), &data)
+	if err != nil {
+		fmt.Println("refresh Ecs sts token err, json.Unmarshal fail", err)
+		return
+	}
+	code, err := jmespath.Search("Code", data)
+	if err != nil {
+		fmt.Println("refresh Ecs sts token err, fail to get Code", err)
+		return
+	}
+	if code.(string) != "Success" {
+		fmt.Println("refresh Ecs sts token err, Code is not Success", err)
+		return
+	}
+	accessKeyId, err := jmespath.Search("AccessKeyId", data)
+	if err != nil {
+		fmt.Println("refresh Ecs sts token err, fail to get AccessKeyId", err)
+		return
+	}
+	accessKeySecret, err := jmespath.Search("AccessKeySecret", data)
+	if err != nil {
+		fmt.Println("refresh Ecs sts token err, fail to get AccessKeySecret", err)
+		return
+	}
+	securityToken, err := jmespath.Search("SecurityToken", data)
+	if err != nil {
+		fmt.Println("refresh Ecs sts token err, fail to get SecurityToken", err)
+		return
+	}
+	expiration, err := jmespath.Search("Expiration", data)
+	if err != nil {
+		fmt.Println("refresh Ecs sts token err, fail to get Expiration", err)
+		return
+	}
+	if accessKeyId == nil || accessKeySecret == nil || securityToken == nil {
+		if signer.sessionCredential == nil {
+			panic("refresh Ecs sts token failed, accessKeyId, accessKeySecret or securityToken is null")
+		}
+	}
+
+	expirationTime, err := time.Parse("2006-01-02T15:04:05Z", expiration.(string))
+	signer.credentialExpiration = int(expirationTime.Unix() - time.Now().Unix())
+	signer.sessionCredential = &sessionCredential{
+		accessKeyId:     accessKeyId.(string),
+		accessKeySecret: accessKeySecret.(string),
+		securityToken:   securityToken.(string),
+	}
+
+	return
+}
+
 func (signer *SignerEcsInstance) Shutdown() {
 
 }

+ 158 - 0
sdk/auth/signers/signer_key_pair.go

@@ -0,0 +1,158 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package signers
+
+import (
+	"encoding/json"
+	"fmt"
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials"
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors"
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses"
+	"github.com/jmespath/go-jmespath"
+	"net/http"
+	"strconv"
+)
+
+type SignerKeyPair struct {
+	*credentialUpdater
+	sessionCredential *SessionAkCredential
+	credential        *credentials.KeyPairCredential
+	commonApi         func(request *requests.CommonRequest, signer interface{}) (response *responses.CommonResponse, err error)
+}
+
+type SessionAkCredential struct {
+	accessKeyId     string
+	accessKeySecret string
+}
+
+func NewSignerKeyPair(credential *credentials.KeyPairCredential, commonApi func(*requests.CommonRequest, interface{}) (response *responses.CommonResponse, err error)) (signer *SignerKeyPair, err error) {
+	signer = &SignerKeyPair{
+		credential: credential,
+		commonApi:  commonApi,
+	}
+
+	signer.credentialUpdater = &credentialUpdater{
+		credentialExpiration: credential.SessionExpiration,
+		buildRequestMethod:   signer.buildCommonRequest,
+		responseCallBack:     signer.refreshCredential,
+		refreshApi:           signer.refreshApi,
+	}
+
+	if credential.SessionExpiration > 0 {
+		if credential.SessionExpiration > 900 && credential.SessionExpiration < 3600 {
+			signer.credentialExpiration = credential.SessionExpiration
+		} else {
+			err = errors.NewClientError(errors.InvalidParamCode, "Key Pair session duration should be in the range of 15min - 1Hr", nil)
+		}
+	} else {
+		signer.credentialExpiration = defaultDurationSeconds
+	}
+	return
+}
+
+func (*SignerKeyPair) GetName() string {
+	return "HMAC-SHA1"
+}
+
+func (*SignerKeyPair) GetType() string {
+	return ""
+}
+
+func (*SignerKeyPair) GetVersion() string {
+	return "1.0"
+}
+
+func (signer *SignerKeyPair) GetAccessKeyId() string {
+	if signer.sessionCredential == nil || signer.needUpdateCredential() {
+		signer.updateCredential()
+	}
+	if signer.sessionCredential == nil || len(signer.sessionCredential.accessKeyId) <= 0 {
+		return ""
+	}
+	return signer.sessionCredential.accessKeyId
+}
+
+func (signer *SignerKeyPair) GetExtraParam() map[string]string {
+	if signer.sessionCredential == nil || signer.needUpdateCredential() {
+		signer.updateCredential()
+	}
+	if signer.sessionCredential == nil || len(signer.sessionCredential.accessKeyId) <= 0 {
+		return make(map[string]string)
+	}
+	return make(map[string]string)
+}
+
+func (signer *SignerKeyPair) Sign(stringToSign, secretSuffix string) string {
+	secret := signer.sessionCredential.accessKeySecret + secretSuffix
+	return ShaHmac1(stringToSign, secret)
+}
+
+func (signer *SignerKeyPair) buildCommonRequest() (request *requests.CommonRequest, err error) {
+	request = requests.NewCommonRequest()
+	request.Product = "Sts"
+	request.Version = "2015-04-01"
+	request.ApiName = "GenerateSessionAccessKey"
+	request.Scheme = requests.HTTPS
+	request.QueryParams["PublicKeyId"] = signer.credential.PublicKeyId
+	request.QueryParams["DurationSeconds"] = strconv.Itoa(signer.credentialExpiration)
+	return
+}
+
+func (signerKeyPair *SignerKeyPair) refreshApi(request *requests.CommonRequest) (response *responses.CommonResponse, err error) {
+	signerV2, err := NewSignerV2(signerKeyPair.credential)
+	return signerKeyPair.commonApi(request, signerV2)
+}
+
+func (signer *SignerKeyPair) refreshCredential(response *responses.CommonResponse) (err error) {
+	if response.GetHttpStatus() != http.StatusOK {
+		message := "refresh session AccessKey failed, message = " + response.GetHttpContentString()
+		err = errors.NewServerError(response.GetHttpStatus(), response.GetOriginHttpResponse().Status, message)
+		if signer.sessionCredential == nil {
+			panic(err)
+		}
+		return
+	}
+	var data interface{}
+	err = json.Unmarshal(response.GetHttpContentBytes(), &data)
+	if err != nil {
+		fmt.Println("refresh KeyPair err, json.Unmarshal fail", err)
+		return
+	}
+	accessKeyId, err := jmespath.Search("SessionAccessKey.SessionAccessKeyId", data)
+	if err != nil {
+		fmt.Println("refresh KeyPair err, fail to get SessionAccessKeyId", err)
+		return
+	}
+	accessKeySecret, err := jmespath.Search("SessionAccessKey.SessionAccessKeySecret", data)
+	if err != nil {
+		fmt.Println("refresh KeyPair err, fail to get SessionAccessKeySecret", err)
+		return
+	}
+	if accessKeyId == nil || accessKeySecret == nil {
+		if signer.sessionCredential == nil {
+			panic("refresh KeyPair, accessKeyId or accessKeySecret is null")
+		}
+	}
+	signer.sessionCredential = &SessionAkCredential{
+		accessKeyId:     accessKeyId.(string),
+		accessKeySecret: accessKeySecret.(string),
+	}
+	return
+}
+
+func (signer *SignerKeyPair) Shutdown() {
+
+}

+ 53 - 17
sdk/auth/signers/signer_sts_assume_role.go

@@ -16,6 +16,7 @@ package signers
 
 import (
 	"encoding/json"
+	"fmt"
 	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials"
 	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors"
 	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
@@ -35,6 +36,7 @@ type SignerStsAssumeRole struct {
 	roleSessionName   string
 	sessionCredential *sessionCredential
 	credential        *credentials.StsAssumeRoleCredential
+	commonApi         func(request *requests.CommonRequest, signer interface{}) (response *responses.CommonResponse, err error)
 }
 
 type sessionCredential struct {
@@ -43,16 +45,19 @@ type sessionCredential struct {
 	securityToken   string
 }
 
-func NewSignerStsAssumeRole(credential *credentials.StsAssumeRoleCredential, commonApi func(request *requests.CommonRequest) (response *responses.CommonResponse, err error)) (signer *SignerStsAssumeRole, err error) {
+func NewSignerStsAssumeRole(credential *credentials.StsAssumeRoleCredential, commonApi func(request *requests.CommonRequest, signer interface{}) (response *responses.CommonResponse, err error)) (signer *SignerStsAssumeRole, err error) {
 	signer = &SignerStsAssumeRole{
-		credentialUpdater: &credentialUpdater{
-			credentialExpiration: credential.RoleSessionExpiration,
-			buildRequestMethod:   signer.buildCommonRequest,
-			responseCallBack:     signer.refreshCredential,
-			commonApi:            commonApi,
-		},
 		credential: credential,
+		commonApi:  commonApi,
 	}
+
+	signer.credentialUpdater = &credentialUpdater{
+		credentialExpiration: credential.RoleSessionExpiration,
+		buildRequestMethod:   signer.buildCommonRequest,
+		responseCallBack:     signer.refreshCredential,
+		refreshApi:           signer.refreshApi,
+	}
+
 	if len(credential.RoleSessionName) > 0 {
 		signer.roleSessionName = credential.RoleSessionName
 	} else {
@@ -83,18 +88,27 @@ func (*SignerStsAssumeRole) GetVersion() string {
 }
 
 func (signer *SignerStsAssumeRole) GetAccessKeyId() string {
-	return signer.credential.AccessKeyId
+	if signer.sessionCredential == nil || signer.needUpdateCredential() {
+		signer.updateCredential()
+	}
+	if signer.sessionCredential == nil || len(signer.sessionCredential.accessKeyId) <= 0 {
+		return ""
+	}
+	return signer.sessionCredential.accessKeyId
 }
 
 func (signer *SignerStsAssumeRole) GetExtraParam() map[string]string {
-	return map[string]string{"SecurityToken": signer.credential.RoleArn}
-}
-
-func (signer *SignerStsAssumeRole) Sign(stringToSign, secretSuffix string) string {
 	if signer.sessionCredential == nil || signer.needUpdateCredential() {
 		signer.updateCredential()
 	}
-	secret := signer.credential.AccessKeySecret + secretSuffix
+	if signer.sessionCredential == nil || len(signer.sessionCredential.securityToken) <= 0 {
+		return make(map[string]string)
+	}
+	return map[string]string{"SecurityToken": signer.sessionCredential.securityToken}
+}
+
+func (signer *SignerStsAssumeRole) Sign(stringToSign, secretSuffix string) string {
+	secret := signer.sessionCredential.accessKeySecret + secretSuffix
 	return ShaHmac1(stringToSign, secret)
 }
 
@@ -103,35 +117,57 @@ func (signer *SignerStsAssumeRole) buildCommonRequest() (request *requests.Commo
 	request.Product = "Sts"
 	request.Version = "2015-04-01"
 	request.ApiName = "AssumeRole"
+	request.Scheme = requests.HTTPS
 	request.QueryParams["RoleArn"] = signer.credential.RoleArn
 	request.QueryParams["RoleSessionName"] = signer.credential.RoleSessionName
 	request.QueryParams["DurationSeconds"] = strconv.Itoa(signer.credentialExpiration)
 	return
 }
 
+func (signerStsAssumeRole *SignerStsAssumeRole) refreshApi(request *requests.CommonRequest) (response *responses.CommonResponse, err error) {
+	credential := &credentials.BaseCredential{
+		AccessKeyId:     signerStsAssumeRole.credential.AccessKeyId,
+		AccessKeySecret: signerStsAssumeRole.credential.AccessKeySecret,
+	}
+	signerV1, err := NewSignerV1(credential)
+	return signerStsAssumeRole.commonApi(request, signerV1)
+}
+
 func (signer *SignerStsAssumeRole) refreshCredential(response *responses.CommonResponse) (err error) {
 	if response.GetHttpStatus() != http.StatusOK {
 		message := "refresh session token failed, message = " + response.GetHttpContentString()
 		err = errors.NewServerError(response.GetHttpStatus(), response.GetOriginHttpResponse().Status, message)
+		if signer.sessionCredential == nil {
+			panic(err)
+		}
 		return
 	}
 	var data interface{}
-	err = json.Unmarshal(response.GetHttpContentBytes(), data)
+	err = json.Unmarshal(response.GetHttpContentBytes(), &data)
 	if err != nil {
+		fmt.Println("refresh RoleArn sts token err, json.Unmarshal fail", err)
 		return
 	}
-	accessKeyId, err := jmespath.Search("AssumeRoleResponse.Credentials.AccessKeyId", data)
+	accessKeyId, err := jmespath.Search("Credentials.AccessKeyId", data)
 	if err != nil {
+		fmt.Println("refresh RoleArn sts token err, fail to get AccessKeyId", err)
 		return
 	}
-	accessKeySecret, err := jmespath.Search("AssumeRoleResponse.Credentials.AccessKeySecret", data)
+	accessKeySecret, err := jmespath.Search("Credentials.AccessKeySecret", data)
 	if err != nil {
+		fmt.Println("refresh RoleArn sts token err, fail to get AccessKeySecret", err)
 		return
 	}
-	securityToken, err := jmespath.Search("AssumeRoleResponse.Credentials.SecurityToken", data)
+	securityToken, err := jmespath.Search("Credentials.SecurityToken", data)
 	if err != nil {
+		fmt.Println("refresh RoleArn sts token err, fail to get SecurityToken", err)
 		return
 	}
+	if accessKeyId == nil || accessKeySecret == nil || securityToken == nil {
+		if signer.sessionCredential == nil {
+			panic("refresh session token failed, accessKeyId, accessKeySecret or securityToken is null")
+		}
+	}
 	signer.sessionCredential = &sessionCredential{
 		accessKeyId:     accessKeyId.(string),
 		accessKeySecret: accessKeySecret.(string),

+ 58 - 0
sdk/auth/signers/signer_v2.go

@@ -0,0 +1,58 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package signers
+
+import (
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials"
+)
+
+type SignerV2 struct {
+	credential *credentials.KeyPairCredential
+}
+
+func (signer *SignerV2) GetExtraParam() map[string]string {
+	return nil
+}
+
+func NewSignerV2(credential *credentials.KeyPairCredential) (*SignerV2, error) {
+	return &SignerV2{
+		credential: credential,
+	}, nil
+}
+
+func (*SignerV2) GetName() string {
+	return "SHA256withRSA"
+}
+
+func (*SignerV2) GetType() string {
+	return "PRIVATEKEY"
+}
+
+func (*SignerV2) GetVersion() string {
+	return "1.0"
+}
+
+func (signer *SignerV2) GetAccessKeyId() string {
+	return signer.credential.PublicKeyId
+}
+
+func (signer *SignerV2) Sign(stringToSign, secretSuffix string) string {
+	secret := signer.credential.PrivateKey
+	return Sha256WithRsa(stringToSign, secret)
+}
+
+func (signer *SignerV2) Shutdown() {
+
+}

+ 65 - 3
sdk/client.go

@@ -15,6 +15,7 @@
 package sdk
 
 import (
+	"fmt"
 	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth"
 	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials"
 	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/endpoints"
@@ -46,7 +47,6 @@ func (client *Client) InitWithOptions(regionId string, config *Config, credentia
 	client.isRunning = true
 	client.regionId = regionId
 	client.config = config
-	client.signer, err = auth.NewSignerWithCredential(credential, client.ProcessCommonRequest)
 	if err != nil {
 		return
 	}
@@ -63,6 +63,9 @@ func (client *Client) InitWithOptions(regionId string, config *Config, credentia
 	if config.EnableAsync {
 		client.EnableAsync(config.GoRoutinePoolSize, config.MaxTaskQueueSize)
 	}
+
+	client.signer, err = auth.NewSignerWithCredential(credential, client.ProcessCommonRequestWithSigner)
+
 	return
 }
 
@@ -81,7 +84,7 @@ func (client *Client) EnableAsync(routinePoolSize, maxTaskQueueSize int) {
 }
 
 func (client *Client) InitWithAccessKey(regionId, accessKeyId, accessKeySecret string) (err error) {
-	config := NewConfig()
+	config := client.InitClientConfig()
 	credential := &credentials.BaseCredential{
 		AccessKeyId:     accessKeyId,
 		AccessKeySecret: accessKeySecret,
@@ -89,7 +92,49 @@ func (client *Client) InitWithAccessKey(regionId, accessKeyId, accessKeySecret s
 	return client.InitWithOptions(regionId, config, credential)
 }
 
+func (client *Client) InitWithRoleArn(regionId, accessKeyId, accessKeySecret, roleArn, roleSessionName string) (err error) {
+	config := client.InitClientConfig()
+	credential := &credentials.StsAssumeRoleCredential{
+		AccessKeyId:     accessKeyId,
+		AccessKeySecret: accessKeySecret,
+		RoleArn:         roleArn,
+		RoleSessionName: roleSessionName,
+	}
+	return client.InitWithOptions(regionId, config, credential)
+}
+
+func (client *Client) InitWithKeyPair(regionId, publicKeyId, privateKey string, sessionExpiration int) (err error) {
+	config := client.InitClientConfig()
+	credential := &credentials.KeyPairCredential{
+		PrivateKey:        privateKey,
+		PublicKeyId:       publicKeyId,
+		SessionExpiration: sessionExpiration,
+	}
+	return client.InitWithOptions(regionId, config, credential)
+}
+
+func (client *Client) InitWithEcsInstance(regionId, roleName string) (err error) {
+	config := client.InitClientConfig()
+	credential := &credentials.EcsInstanceCredential{
+		RoleName: roleName,
+	}
+	return client.InitWithOptions(regionId, config, credential)
+}
+
+func (client *Client) InitClientConfig() (config *Config) {
+	config = NewConfig()
+	if client.config != nil {
+		config = client.config
+	}
+
+	return
+}
+
 func (client *Client) DoAction(request requests.AcsRequest, response responses.AcsResponse) (err error) {
+	return client.DoActionWithSigner(request, response, nil)
+}
+
+func (client *Client) DoActionWithSigner(request requests.AcsRequest, response responses.AcsResponse, signer auth.Signer) (err error) {
 
 	// add clientVersion
 	request.GetHeaders()["x-sdk-core-version"] = Version
@@ -121,7 +166,12 @@ func (client *Client) DoAction(request requests.AcsRequest, response responses.A
 	}
 
 	// signature
-	err = auth.Sign(request, client.signer, regionId)
+	if signer != nil {
+		err = auth.Sign(request, signer, regionId)
+	} else {
+		err = auth.Sign(request, client.signer, regionId)
+	}
+
 	if err != nil {
 		return
 	}
@@ -138,6 +188,7 @@ func (client *Client) DoAction(request requests.AcsRequest, response responses.A
 	}
 	httpResponse, err := client.httpClient.Do(httpRequest)
 	if err != nil {
+		fmt.Println(err)
 		return
 	}
 	err = responses.Unmarshal(response, httpResponse, request.GetAcceptFormat())
@@ -178,6 +229,17 @@ func (client *Client) ProcessCommonRequest(request *requests.CommonRequest) (res
 	return
 }
 
+func (client *Client) ProcessCommonRequestWithSigner(request *requests.CommonRequest, signerInterface interface{}) (response *responses.CommonResponse, err error) {
+	if signer, isSigner := signerInterface.(auth.Signer); isSigner {
+		request.TransToAcsRequest()
+		response = responses.NewCommonResponse()
+		err = client.DoActionWithSigner(request, response, signer)
+		return
+	} else {
+		panic("should not be here")
+	}
+}
+
 func (client *Client) Shutdown() {
 	client.signer.Shutdown()
 	close(client.asyncTaskQueue)

+ 131 - 2
sdk/client_test.go

@@ -15,6 +15,7 @@
 package sdk
 
 import (
+	"crypto/tls"
 	"encoding/json"
 	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
 	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses"
@@ -26,11 +27,16 @@ import (
 	"testing"
 )
 
-var client *Client
+var client, clientKeyPair, clientEcs, clientRoleArn *Client
 
 type TestConfig struct {
 	AccessKeyId     string
 	AccessKeySecret string
+	PublicKeyId     string
+	PrivateKey      string
+	RoleArn         string
+	ChildAK         string
+	ChildSecret     string
 }
 
 type MockResponse struct {
@@ -62,8 +68,29 @@ func testSetup() {
 	}
 	var config TestConfig
 	json.Unmarshal(data, &config)
-	client = &Client{}
+	tr := &http.Transport{
+		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
+	}
+	client = &Client{
+		config: &Config{
+			HttpTransport: tr,
+		},
+	}
+	clientEcs = &Client{}
+	clientRoleArn = &Client{
+		config: &Config{
+			HttpTransport: tr,
+		},
+	}
+	clientKeyPair = &Client{
+		config: &Config{
+			HttpTransport: tr,
+		},
+	}
 	err = client.InitWithAccessKey("cn-hangzhou", config.AccessKeyId, config.AccessKeySecret)
+	err = clientKeyPair.InitWithKeyPair("cn-hangzhou", config.PublicKeyId, config.PrivateKey, 3600)
+	err = clientEcs.InitWithEcsInstance("cn-hangzhou", "conan")
+	err = clientRoleArn.InitWithRoleArn("cn-hangzhou", config.ChildAK, config.ChildSecret, config.RoleArn, "clientTest")
 }
 
 func testTearDown() {
@@ -168,6 +195,40 @@ func TestRpcGet(t *testing.T) {
 	assert.Equal(t, "QueryParamValue", responseBean.Params["QueryParam"])
 }
 
+func TestRpcGetForHttps(t *testing.T) {
+	request := getFtTestRpcRequest()
+	request.Method = requests.GET
+	request.Scheme = requests.HTTPS
+
+	response := &responses.BaseResponse{}
+	err := client.DoAction(request, response)
+	assert.Nil(t, err)
+	assert.Equal(t, http.StatusOK, response.GetHttpStatus(), response.GetHttpContentString())
+	assert.NotNil(t, response.GetHttpContentString())
+
+	var responseBean MockResponse
+	json.Unmarshal([]byte(response.GetHttpContentString()), &responseBean)
+
+	assert.Equal(t, "QueryParamValue", responseBean.Params["QueryParam"])
+}
+
+func TestRoaGetForHttps(t *testing.T) {
+	request := getFtTestRoaRequest()
+	request.Scheme = requests.HTTPS
+
+	response := &responses.BaseResponse{}
+	err := client.DoAction(request, response)
+	assert.Nil(t, err)
+	assert.Equal(t, http.StatusOK, response.GetHttpStatus(), response.GetHttpContentString())
+	assert.NotNil(t, response.GetHttpContentString())
+
+	var responseBean MockResponse
+	json.Unmarshal([]byte(response.GetHttpContentString()), &responseBean)
+
+	assert.Equal(t, "QueryParamValue", responseBean.Params["QueryParam"])
+	assert.Equal(t, "HeaderParamValue", responseBean.Headers["Header-Param"])
+}
+
 func TestRpcPost(t *testing.T) {
 	request := getFtTestRpcRequest()
 	request.FormParams["BodyParam"] = "BodyParamValue"
@@ -320,3 +381,71 @@ func TestRpcGetForLocationCache(t *testing.T) {
 
 	assert.Equal(t, "QueryParamValue", responseBean.Params["QueryParam"])
 }
+
+func TestRpcGetForKeyPair(t *testing.T) {
+	request := getFtTestRpcRequest()
+	request.Method = requests.GET
+
+	response := &responses.BaseResponse{}
+	err := clientKeyPair.DoAction(request, response)
+	assert.Nil(t, err)
+	assert.Equal(t, http.StatusOK, response.GetHttpStatus(), response.GetHttpContentString())
+	assert.NotNil(t, response.GetHttpContentString())
+
+	var responseBean MockResponse
+	json.Unmarshal([]byte(response.GetHttpContentString()), &responseBean)
+
+	assert.Equal(t, "QueryParamValue", responseBean.Params["QueryParam"])
+}
+
+/*func TestRpcGetForEcs(t *testing.T) {
+	//测试接口,想测试的时候,要替换掉singer_ecs_instance中对应的变量,并且还要提供一个mock服务
+	//requestUrl := "http://localhost:3500/latest/meta-data/ram/security-credentials/roleNameTest.json"
+	request := getFtTestRpcRequest()
+	request.Method = requests.GET
+
+	response := &responses.BaseResponse{}
+	err := clientEcs.DoAction(request, response)
+	assert.Nil(t, err)
+	assert.Equal(t, http.StatusOK, response.GetHttpStatus(), response.GetHttpContentString())
+	assert.NotNil(t, response.GetHttpContentString())
+
+	var responseBean MockResponse
+	json.Unmarshal([]byte(response.GetHttpContentString()), &responseBean)
+
+	assert.Equal(t, "QueryParamValue", responseBean.Params["QueryParam"])
+
+	err = clientEcs.DoAction(request, response)
+	assert.Nil(t, err)
+	assert.Equal(t, http.StatusOK, response.GetHttpStatus(), response.GetHttpContentString())
+	assert.NotNil(t, response.GetHttpContentString())
+
+	json.Unmarshal([]byte(response.GetHttpContentString()), &responseBean)
+
+	assert.Equal(t, "QueryParamValue", responseBean.Params["QueryParam"])
+}*/
+
+func TestRpcGetForRoleArn(t *testing.T) {
+	request := getFtTestRpcRequest()
+	request.Method = requests.GET
+
+	response := &responses.BaseResponse{}
+	err := clientRoleArn.DoAction(request, response)
+	assert.Nil(t, err)
+	assert.Equal(t, http.StatusOK, response.GetHttpStatus(), response.GetHttpContentString())
+	assert.NotNil(t, response.GetHttpContentString())
+
+	var responseBean MockResponse
+	json.Unmarshal([]byte(response.GetHttpContentString()), &responseBean)
+
+	assert.Equal(t, "QueryParamValue", responseBean.Params["QueryParam"])
+
+	err = clientRoleArn.DoAction(request, response)
+	assert.Nil(t, err)
+	assert.Equal(t, http.StatusOK, response.GetHttpStatus(), response.GetHttpContentString())
+	assert.NotNil(t, response.GetHttpContentString())
+
+	json.Unmarshal([]byte(response.GetHttpContentString()), &responseBean)
+
+	assert.Equal(t, "QueryParamValue", responseBean.Params["QueryParam"])
+}

+ 0 - 1
sdk/requests/acs_reqeust.go

@@ -169,7 +169,6 @@ func (request *baseRequest) GetContentType() (contentType string, contains bool)
 func defaultBaseRequest() (request *baseRequest) {
 	request = &baseRequest{
 		Scheme:       HTTP,
-		Port:         DefaultHttpPort,
 		acceptFormat: "JSON",
 		Method:       GET,
 		QueryParams:  make(map[string]string),

+ 5 - 1
sdk/requests/common_request.go

@@ -56,7 +56,11 @@ func (request *CommonRequest) TransToAcsRequest() {
 }
 
 func (request *CommonRequest) GetUrl() string {
-	return strings.ToLower(request.Scheme) + "://" + request.Domain + ":" + request.Port + request.GetQueries()
+	if len(request.Port) > 0 {
+		return strings.ToLower(request.Scheme) + "://" + request.Domain + ":" + request.Port + request.GetQueries()
+	}
+
+	return strings.ToLower(request.Scheme) + "://" + request.Domain + request.GetQueries()
 }
 
 func (request *CommonRequest) GetBodyReader() io.Reader {

+ 2 - 1
sdk/requests/rpc_request.go

@@ -50,7 +50,8 @@ func (request *RpcRequest) GetQueries() string {
 }
 
 func (request *RpcRequest) GetUrl() string {
-	return strings.ToLower(request.Scheme) + "://" + request.Domain + ":" + request.Port + request.GetQueries()
+	//return strings.ToLower(request.Scheme) + "://" + request.Domain + ":" + request.Port + request.GetQueries()
+	return strings.ToLower(request.Scheme) + "://" + request.Domain + request.GetQueries()
 }
 
 func (request *RpcRequest) GetVersion() string {