123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 |
- package oss
- import (
- "context"
- "crypto/hmac"
- "crypto/sha1"
- "crypto/tls"
- "gd_admin/common.in/utils"
- "encoding/base64"
- "encoding/json"
- "fmt"
- "go.uber.org/zap"
- "io/ioutil"
- "net/http"
- "net/url"
- "strconv"
- "time"
- )
- // ServiceError sts service error
- type ServiceError struct {
- Code string
- Message string
- RequestId string
- HostId string
- RawMessage string
- StatusCode int
- }
- // Credentials the credentials obtained by AssumedRole,
- // used for the peration of Alibaba Cloud service.
- type Credentials struct {
- AccessKeyId string
- AccessKeySecret string
- Expiration time.Time
- SecurityToken string
- }
- // AssumedRoleUser the user to AssumedRole
- type AssumedRoleUser struct {
- Arn string
- AssumedRoleId string
- }
- // Response the response of AssumeRole
- type Response struct {
- Credentials Credentials
- AssumedRoleUser AssumedRoleUser
- RequestId string
- }
- // Error implement interface error
- func (e *ServiceError) Error() string {
- return fmt.Sprintf("oss: service returned error: StatusCode=%d, ErrorCode=%s, ErrorMessage=%s, RequestId=%s",
- e.StatusCode, e.Code, e.Message, e.RequestId)
- }
- const (
- // StsSignVersion sts sign version
- StsSignVersion = "1.0"
- // StsAPIVersion sts api version
- StsAPIVersion = "2015-04-01"
- // StsHost sts host
- StsHost = "https://sts.cn-shanghai.aliyuncs.com/"
- // TimeFormat time fomrat
- TimeFormat = "2006-01-02T15:04:05Z"
- // RespBodyFormat respone body format
- RespBodyFormat = "JSON"
- // PercentEncode '/'
- PercentEncode = "%2F"
- // HTTPGet http get method
- HTTPGet = "GET"
- accessKeyId = "LTAI4Fjs1bNMd8k8LT41Fxxn"
- accessKeySecret = "WlQJwVbxHIY4TIZwMIFA5QCye6n0Pl"
- //accessKeyId = "LTAI4FrygJpD6m4BW1hQ88iE"
- //accessKeySecret = "GN3kTVcTvoa4QhFTo7sSqTsxW4WUtR"
- roleArn = "acs:ram::1889646856784226:role/aliyunosstokengeneratorrole"
- sessionName = "gd-username"
- expiredTime = 900 // 15分钟
- )
- // AssumeRole assume role
- func AssumeRole(ctx context.Context) (result *Response, err error) {
- defer func() {
- if l != nil {
- l.Info("thirdparty",
- zap.String("api", StsHost),
- zap.String("request", utils.MarshalJsonString(accessKeyId, accessKeySecret, roleArn, sessionName, expiredTime)),
- zap.String("response", utils.MarshalJsonString(result)))
- }
- }()
- url, err := generateSignedURL()
- if err != nil {
- return nil, err
- }
- body, status, err := sendRequest(url)
- if err != nil {
- return nil, err
- }
- result, err = handleResponse(body, status)
- return
- }
- // Private function
- func generateSignedURL() (string, error) {
- queryStr := "SignatureVersion=" + StsSignVersion
- queryStr += "&Format=" + RespBodyFormat
- queryStr += "&Timestamp=" + url.QueryEscape(time.Now().UTC().Format(TimeFormat))
- queryStr += "&RoleArn=" + url.QueryEscape(roleArn)
- queryStr += "&RoleSessionName=" + sessionName
- queryStr += "&AccessKeyId=" + accessKeyId
- queryStr += "&SignatureMethod=HMAC-SHA1"
- queryStr += "&Version=" + StsAPIVersion
- queryStr += "&Action=AssumeRole"
- queryStr += "&SignatureNonce=" + string(Krand(32, KC_RAND_KIND_ALL)) // uuid.NewV4().String()
- queryStr += "&DurationSeconds=" + strconv.FormatUint((uint64)(expiredTime), 10)
- // Sort query string
- queryParams, err := url.ParseQuery(queryStr)
- if err != nil {
- return "", err
- }
- result := queryParams.Encode()
- strToSign := HTTPGet + "&" + PercentEncode + "&" + url.QueryEscape(result)
- // Generate signature
- hashSign := hmac.New(sha1.New, []byte(accessKeySecret+"&"))
- hashSign.Write([]byte(strToSign))
- signature := base64.StdEncoding.EncodeToString(hashSign.Sum(nil))
- // Build url
- assumeURL := StsHost + "?" + queryStr + "&Signature=" + url.QueryEscape(signature)
- return assumeURL, nil
- }
- func sendRequest(url string) ([]byte, int, error) {
- tr := &http.Transport{
- TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
- }
- client := &http.Client{Transport: tr}
- resp, err := client.Get(url)
- if err != nil {
- return nil, -1, err
- }
- defer resp.Body.Close()
- body, err := ioutil.ReadAll(resp.Body)
- return body, resp.StatusCode, err
- }
- func handleResponse(responseBody []byte, statusCode int) (*Response, error) {
- if statusCode != http.StatusOK {
- se := ServiceError{StatusCode: statusCode, RawMessage: string(responseBody)}
- err := json.Unmarshal(responseBody, &se)
- if err != nil {
- return nil, err
- }
- return nil, &se
- }
- resp := Response{}
- err := json.Unmarshal(responseBody, &resp)
- if err != nil {
- return nil, err
- }
- return &resp, nil
- }
|