oss/lib/ecs_role.go (134 lines of code) (raw):
package lib
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strings"
"sync"
"time"
oss "github.com/aliyun/aliyun-oss-go-sdk/oss"
)
const (
AdvanceSeconds int64 = 60
)
type STSAkJson struct {
AccessKeyId string `json:"AccessKeyId,omitempty"`
AccessKeySecret string `json:"AccessKeySecret,omitempty"`
SecurityToken string `json:"SecurityToken,omitempty"`
Expiration string `json:"Expiration,omitempty"`
LastUpDated string `json:"LastUpDated,omitempty"`
Code string `json:"Code,omitempty"`
}
func (stsJson *STSAkJson) String() string {
return fmt.Sprintf("AccessKeyId:%s,AccessKeySecret:%s,SecurityToken:%s,Expiration:%s,LastUpDated:%s",
stsJson.AccessKeyId, stsJson.AccessKeySecret, stsJson.SecurityToken, stsJson.Expiration, stsJson.LastUpDated)
}
type EcsRoleAK struct {
AccessKeyId string
AccessKeySecret string
SecurityToken string
}
func (ecsRole *EcsRoleAK) GetAccessKeyID() string {
return ecsRole.AccessKeyId
}
func (ecsRole *EcsRoleAK) GetAccessKeySecret() string {
return ecsRole.AccessKeySecret
}
func (ecsRole *EcsRoleAK) GetSecurityToken() string {
return ecsRole.SecurityToken
}
// for ecs bind ram and get ak by ossutil automaticly
type EcsRoleAKBuild struct {
lock sync.Mutex
HasGet bool
url string //url for get ak,such as http://100.100.100.200/latest/meta-data/Ram/security-credentials/RamRoleName
AccessKeyId string
AccessKeySecret string
SecurityToken string
Expiration string
LastUpDated string
}
func (roleBuild *EcsRoleAKBuild) GetCredentials() oss.Credentials {
cred, _ := roleBuild.GetCredentialsE()
return cred
}
func (roleBuild *EcsRoleAKBuild) GetCredentialsE() (oss.Credentials, error) {
roleBuild.lock.Lock()
defer roleBuild.lock.Unlock()
akJson := STSAkJson{}
var err error = nil
bTimeOut := false
if !roleBuild.HasGet {
bTimeOut = true
} else {
bTimeOut = roleBuild.IsTimeOut()
}
if bTimeOut {
tStart := time.Now().UnixNano() / 1000 / 1000
akJson, err = roleBuild.HttpReqAk()
tEnd := time.Now().UnixNano() / 1000 / 1000
if err != nil {
return &EcsRoleAK{}, err
} else {
roleBuild.AccessKeyId = akJson.AccessKeyId
roleBuild.AccessKeySecret = akJson.AccessKeySecret
roleBuild.SecurityToken = akJson.SecurityToken
roleBuild.Expiration = akJson.Expiration
LogInfo("get sts ak success,%s,cost:%d(ms)\n", akJson.String(), tEnd-tStart)
}
}
return &EcsRoleAK{
AccessKeyId: roleBuild.AccessKeyId,
AccessKeySecret: roleBuild.AccessKeySecret,
SecurityToken: roleBuild.SecurityToken,
}, nil
}
func (roleBuild *EcsRoleAKBuild) IsTimeOut() bool {
if roleBuild.Expiration == "" {
return false
}
// attention: can't use time.ParseInLocation(),ecsRole.Expiration is UTC time
utcExpirationTime, _ := time.Parse("2006-01-02T15:04:05Z", roleBuild.Expiration)
// Now() returns the current local time
nowLocalTime := time.Now()
// Unix() returns the number of seconds elapsedsince January 1, 1970 UTC.
if utcExpirationTime.Unix()-nowLocalTime.Unix()-AdvanceSeconds <= 0 {
return true
}
return false
}
func (roleBuild *EcsRoleAKBuild) HttpReqAk() (STSAkJson, error) {
akJson := STSAkJson{}
//http time out
c := &http.Client{
Timeout: 15 * time.Second,
}
resp, err := c.Get(roleBuild.url)
if err != nil {
LogError("insight getAK,http client get error,url is %s,%s\n", roleBuild.url, err.Error())
return akJson, err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return akJson, err
}
err = json.Unmarshal(body, &akJson)
if err != nil {
LogError("insight getAK,json.Unmarshal error,body is %s,%s\n", string(body), err.Error())
return akJson, err
}
// parsar json,such as
//{
// "AccessKeyId" : "XXXXXXXXX",
// "AccessKeySecret" : "XXXXXXXXX",
// "Expiration" : "2017-11-01T05:20:01Z",
// "SecurityToken" : "XXXXXXXXX",
// "LastUpdated" : "2017-10-31T23:20:01Z",
// "Code" : "Success"
// }
if akJson.Code != "" && strings.ToUpper(akJson.Code) != "SUCCESS" {
LogError("insight getAK,get sts ak error,code:%s\n", akJson.Code)
return akJson, fmt.Errorf("insight getAK,get sts ak error,code:%s", akJson.Code)
}
if akJson.AccessKeyId == "" || akJson.AccessKeySecret == "" {
LogError("insight getAK,parsar http json body error:\n%s\n", string(body))
return akJson, fmt.Errorf("insight getAK,parsar http json body error:\n%s\n", string(body))
}
if akJson.Expiration != "" {
_, err := time.Parse("2006-01-02T15:04:05Z", akJson.Expiration)
if err != nil {
LogError("time.Parse error,Expiration is %s,%s\n", akJson.Expiration, err.Error())
return akJson, err
}
}
roleBuild.HasGet = true
return akJson, nil
}