init repo

This commit is contained in:
liuyuanchuang
2025-12-10 18:33:37 +08:00
commit 48e63894eb
2408 changed files with 1053045 additions and 0 deletions

View File

@@ -0,0 +1,41 @@
package credentials
import "github.com/alibabacloud-go/tea/tea"
// AccessKeyCredential is a kind of credential
type AccessKeyCredential struct {
AccessKeyId string
AccessKeySecret string
}
func newAccessKeyCredential(accessKeyId, accessKeySecret string) *AccessKeyCredential {
return &AccessKeyCredential{
AccessKeyId: accessKeyId,
AccessKeySecret: accessKeySecret,
}
}
// GetAccessKeyId reutrns AccessKeyCreential's AccessKeyId
func (a *AccessKeyCredential) GetAccessKeyId() (*string, error) {
return tea.String(a.AccessKeyId), nil
}
// GetAccessSecret reutrns AccessKeyCreential's AccessKeySecret
func (a *AccessKeyCredential) GetAccessKeySecret() (*string, error) {
return tea.String(a.AccessKeySecret), nil
}
// GetSecurityToken is useless for AccessKeyCreential
func (a *AccessKeyCredential) GetSecurityToken() (*string, error) {
return tea.String(""), nil
}
// GetBearerToken is useless for AccessKeyCreential
func (a *AccessKeyCredential) GetBearerToken() *string {
return tea.String("")
}
// GetType reutrns AccessKeyCreential's type
func (a *AccessKeyCredential) GetType() *string {
return tea.String("access_key")
}

View File

@@ -0,0 +1,40 @@
package credentials
import "github.com/alibabacloud-go/tea/tea"
// BearerTokenCredential is a kind of credential
type BearerTokenCredential struct {
BearerToken string
}
// newBearerTokenCredential return a BearerTokenCredential object
func newBearerTokenCredential(token string) *BearerTokenCredential {
return &BearerTokenCredential{
BearerToken: token,
}
}
// GetAccessKeyId is useless for BearerTokenCredential
func (b *BearerTokenCredential) GetAccessKeyId() (*string, error) {
return tea.String(""), nil
}
// GetAccessSecret is useless for BearerTokenCredential
func (b *BearerTokenCredential) GetAccessKeySecret() (*string, error) {
return tea.String(("")), nil
}
// GetSecurityToken is useless for BearerTokenCredential
func (b *BearerTokenCredential) GetSecurityToken() (*string, error) {
return tea.String(""), nil
}
// GetBearerToken reutrns BearerTokenCredential's BearerToken
func (b *BearerTokenCredential) GetBearerToken() *string {
return tea.String(b.BearerToken)
}
// GetType reutrns BearerTokenCredential's type
func (b *BearerTokenCredential) GetType() *string {
return tea.String("bearer")
}

View File

@@ -0,0 +1,349 @@
package credentials
import (
"bufio"
"errors"
"fmt"
"net/http"
"net/url"
"os"
"strings"
"time"
"github.com/alibabacloud-go/debug/debug"
"github.com/alibabacloud-go/tea/tea"
"github.com/aliyun/credentials-go/credentials/request"
"github.com/aliyun/credentials-go/credentials/response"
"github.com/aliyun/credentials-go/credentials/utils"
)
var debuglog = debug.Init("credential")
var hookParse = func(err error) error {
return err
}
// Credential is an interface for getting actual credential
type Credential interface {
GetAccessKeyId() (*string, error)
GetAccessKeySecret() (*string, error)
GetSecurityToken() (*string, error)
GetBearerToken() *string
GetType() *string
}
// Config is important when call NewCredential
type Config struct {
Type *string `json:"type"`
AccessKeyId *string `json:"access_key_id"`
AccessKeySecret *string `json:"access_key_secret"`
RoleArn *string `json:"role_arn"`
RoleSessionName *string `json:"role_session_name"`
PublicKeyId *string `json:"public_key_id"`
RoleName *string `json:"role_name"`
SessionExpiration *int `json:"session_expiration"`
PrivateKeyFile *string `json:"private_key_file"`
BearerToken *string `json:"bearer_token"`
SecurityToken *string `json:"security_token"`
RoleSessionExpiration *int `json:"role_session_expiratioon"`
Policy *string `json:"policy"`
Host *string `json:"host"`
Timeout *int `json:"timeout"`
ConnectTimeout *int `json:"connect_timeout"`
Proxy *string `json:"proxy"`
}
func (s Config) String() string {
return tea.Prettify(s)
}
func (s Config) GoString() string {
return s.String()
}
func (s *Config) SetAccessKeyId(v string) *Config {
s.AccessKeyId = &v
return s
}
func (s *Config) SetAccessKeySecret(v string) *Config {
s.AccessKeySecret = &v
return s
}
func (s *Config) SetSecurityToken(v string) *Config {
s.SecurityToken = &v
return s
}
func (s *Config) SetRoleArn(v string) *Config {
s.RoleArn = &v
return s
}
func (s *Config) SetRoleSessionName(v string) *Config {
s.RoleSessionName = &v
return s
}
func (s *Config) SetPublicKeyId(v string) *Config {
s.PublicKeyId = &v
return s
}
func (s *Config) SetRoleName(v string) *Config {
s.RoleName = &v
return s
}
func (s *Config) SetSessionExpiration(v int) *Config {
s.SessionExpiration = &v
return s
}
func (s *Config) SetPrivateKeyFile(v string) *Config {
s.PrivateKeyFile = &v
return s
}
func (s *Config) SetBearerToken(v string) *Config {
s.BearerToken = &v
return s
}
func (s *Config) SetRoleSessionExpiration(v int) *Config {
s.RoleSessionExpiration = &v
return s
}
func (s *Config) SetPolicy(v string) *Config {
s.Policy = &v
return s
}
func (s *Config) SetHost(v string) *Config {
s.Host = &v
return s
}
func (s *Config) SetTimeout(v int) *Config {
s.Timeout = &v
return s
}
func (s *Config) SetConnectTimeout(v int) *Config {
s.ConnectTimeout = &v
return s
}
func (s *Config) SetProxy(v string) *Config {
s.Proxy = &v
return s
}
func (s *Config) SetType(v string) *Config {
s.Type = &v
return s
}
// NewCredential return a credential according to the type in config.
// if config is nil, the function will use default provider chain to get credential.
// please see README.md for detail.
func NewCredential(config *Config) (credential Credential, err error) {
if config == nil {
config, err = defaultChain.resolve()
if err != nil {
return
}
return NewCredential(config)
}
switch tea.StringValue(config.Type) {
case "access_key":
err = checkAccessKey(config)
if err != nil {
return
}
credential = newAccessKeyCredential(tea.StringValue(config.AccessKeyId), tea.StringValue(config.AccessKeySecret))
case "sts":
err = checkSTS(config)
if err != nil {
return
}
credential = newStsTokenCredential(tea.StringValue(config.AccessKeyId), tea.StringValue(config.AccessKeySecret), tea.StringValue(config.SecurityToken))
case "ecs_ram_role":
checkEcsRAMRole(config)
runtime := &utils.Runtime{
Host: tea.StringValue(config.Host),
Proxy: tea.StringValue(config.Proxy),
ReadTimeout: tea.IntValue(config.Timeout),
ConnectTimeout: tea.IntValue(config.ConnectTimeout),
}
credential = newEcsRAMRoleCredential(tea.StringValue(config.RoleName), runtime)
case "ram_role_arn":
err = checkRAMRoleArn(config)
if err != nil {
return
}
runtime := &utils.Runtime{
Host: tea.StringValue(config.Host),
Proxy: tea.StringValue(config.Proxy),
ReadTimeout: tea.IntValue(config.Timeout),
ConnectTimeout: tea.IntValue(config.ConnectTimeout),
}
credential = newRAMRoleArnCredential(tea.StringValue(config.AccessKeyId), tea.StringValue(config.AccessKeySecret), tea.StringValue(config.RoleArn), tea.StringValue(config.RoleSessionName), tea.StringValue(config.Policy), tea.IntValue(config.RoleSessionExpiration), runtime)
case "rsa_key_pair":
err = checkRSAKeyPair(config)
if err != nil {
return
}
file, err1 := os.Open(tea.StringValue(config.PrivateKeyFile))
if err1 != nil {
err = fmt.Errorf("InvalidPath: Can not open PrivateKeyFile, err is %s", err1.Error())
return
}
defer file.Close()
var privateKey string
scan := bufio.NewScanner(file)
for scan.Scan() {
if strings.HasPrefix(scan.Text(), "----") {
continue
}
privateKey += scan.Text() + "\n"
}
runtime := &utils.Runtime{
Host: tea.StringValue(config.Host),
Proxy: tea.StringValue(config.Proxy),
ReadTimeout: tea.IntValue(config.Timeout),
ConnectTimeout: tea.IntValue(config.ConnectTimeout),
}
credential = newRsaKeyPairCredential(privateKey, tea.StringValue(config.PublicKeyId), tea.IntValue(config.SessionExpiration), runtime)
case "bearer":
if tea.StringValue(config.BearerToken) == "" {
err = errors.New("BearerToken cannot be empty")
return
}
credential = newBearerTokenCredential(tea.StringValue(config.BearerToken))
default:
err = errors.New("Invalid type option, support: access_key, sts, ecs_ram_role, ram_role_arn, rsa_key_pair")
return
}
return credential, nil
}
func checkRSAKeyPair(config *Config) (err error) {
if tea.StringValue(config.PrivateKeyFile) == "" {
err = errors.New("PrivateKeyFile cannot be empty")
return
}
if tea.StringValue(config.PublicKeyId) == "" {
err = errors.New("PublicKeyId cannot be empty")
return
}
return
}
func checkRAMRoleArn(config *Config) (err error) {
if tea.StringValue(config.AccessKeySecret) == "" {
err = errors.New("AccessKeySecret cannot be empty")
return
}
if tea.StringValue(config.RoleArn) == "" {
err = errors.New("RoleArn cannot be empty")
return
}
if tea.StringValue(config.RoleSessionName) == "" {
err = errors.New("RoleSessionName cannot be empty")
return
}
if tea.StringValue(config.AccessKeyId) == "" {
err = errors.New("AccessKeyId cannot be empty")
return
}
return
}
func checkEcsRAMRole(config *Config) (err error) {
return
}
func checkSTS(config *Config) (err error) {
if tea.StringValue(config.AccessKeyId) == "" {
err = errors.New("AccessKeyId cannot be empty")
return
}
if tea.StringValue(config.AccessKeySecret) == "" {
err = errors.New("AccessKeySecret cannot be empty")
return
}
if tea.StringValue(config.SecurityToken) == "" {
err = errors.New("SecurityToken cannot be empty")
return
}
return
}
func checkAccessKey(config *Config) (err error) {
if tea.StringValue(config.AccessKeyId) == "" {
err = errors.New("AccessKeyId cannot be empty")
return
}
if tea.StringValue(config.AccessKeySecret) == "" {
err = errors.New("AccessKeySecret cannot be empty")
return
}
return
}
func doAction(request *request.CommonRequest, runtime *utils.Runtime) (content []byte, err error) {
httpRequest, err := http.NewRequest(request.Method, request.URL, strings.NewReader(""))
if err != nil {
return
}
httpRequest.Proto = "HTTP/1.1"
httpRequest.Host = request.Domain
debuglog("> %s %s %s", httpRequest.Method, httpRequest.URL.RequestURI(), httpRequest.Proto)
debuglog("> Host: %s", httpRequest.Host)
for key, value := range request.Headers {
if value != "" {
debuglog("> %s: %s", key, value)
httpRequest.Header[key] = []string{value}
}
}
debuglog(">")
httpClient := &http.Client{}
httpClient.Timeout = time.Duration(runtime.ReadTimeout) * time.Second
proxy := &url.URL{}
if runtime.Proxy != "" {
proxy, err = url.Parse(runtime.Proxy)
if err != nil {
return
}
}
trans := &http.Transport{}
if proxy != nil && runtime.Proxy != "" {
trans.Proxy = http.ProxyURL(proxy)
}
trans.DialContext = utils.Timeout(time.Duration(runtime.ConnectTimeout) * time.Second)
httpClient.Transport = trans
httpResponse, err := hookDo(httpClient.Do)(httpRequest)
if err != nil {
return
}
debuglog("< %s %s", httpResponse.Proto, httpResponse.Status)
for key, value := range httpResponse.Header {
debuglog("< %s: %v", key, strings.Join(value, ""))
}
debuglog("<")
resp := &response.CommonResponse{}
err = hookParse(resp.ParseFromHTTPResponse(httpResponse))
if err != nil {
return
}
debuglog("%s", resp.GetHTTPContentString())
if resp.GetHTTPStatus() != http.StatusOK {
err = fmt.Errorf("httpStatus: %d, message = %s", resp.GetHTTPStatus(), resp.GetHTTPContentString())
return
}
return resp.GetHTTPContentBytes(), nil
}

View File

@@ -0,0 +1,25 @@
package credentials
import (
"net/http"
"time"
)
const defaultInAdvanceScale = 0.95
var hookDo = func(fn func(req *http.Request) (*http.Response, error)) func(req *http.Request) (*http.Response, error) {
return fn
}
type credentialUpdater struct {
credentialExpiration int
lastUpdateTimestamp int64
inAdvanceScale float64
}
func (updater *credentialUpdater) needUpdateCredential() (result bool) {
if updater.inAdvanceScale == 0 {
updater.inAdvanceScale = defaultInAdvanceScale
}
return time.Now().Unix()-updater.lastUpdateTimestamp >= int64(float64(updater.credentialExpiration)*updater.inAdvanceScale)
}

View File

@@ -0,0 +1,136 @@
package credentials
import (
"encoding/json"
"fmt"
"time"
"github.com/alibabacloud-go/tea/tea"
"github.com/aliyun/credentials-go/credentials/request"
"github.com/aliyun/credentials-go/credentials/utils"
)
var securityCredURL = "http://100.100.100.200/latest/meta-data/ram/security-credentials/"
// EcsRAMRoleCredential is a kind of credential
type EcsRAMRoleCredential struct {
*credentialUpdater
RoleName string
sessionCredential *sessionCredential
runtime *utils.Runtime
}
type ecsRAMRoleResponse struct {
Code string `json:"Code" xml:"Code"`
AccessKeyId string `json:"AccessKeyId" xml:"AccessKeyId"`
AccessKeySecret string `json:"AccessKeySecret" xml:"AccessKeySecret"`
SecurityToken string `json:"SecurityToken" xml:"SecurityToken"`
Expiration string `json:"Expiration" xml:"Expiration"`
}
func newEcsRAMRoleCredential(roleName string, runtime *utils.Runtime) *EcsRAMRoleCredential {
return &EcsRAMRoleCredential{
RoleName: roleName,
credentialUpdater: new(credentialUpdater),
runtime: runtime,
}
}
// GetAccessKeyId reutrns EcsRAMRoleCredential's AccessKeyId
// if AccessKeyId is not exist or out of date, the function will update it.
func (e *EcsRAMRoleCredential) GetAccessKeyId() (*string, error) {
if e.sessionCredential == nil || e.needUpdateCredential() {
err := e.updateCredential()
if err != nil {
return tea.String(""), err
}
}
return tea.String(e.sessionCredential.AccessKeyId), nil
}
// GetAccessSecret reutrns EcsRAMRoleCredential's AccessKeySecret
// if AccessKeySecret is not exist or out of date, the function will update it.
func (e *EcsRAMRoleCredential) GetAccessKeySecret() (*string, error) {
if e.sessionCredential == nil || e.needUpdateCredential() {
err := e.updateCredential()
if err != nil {
return tea.String(""), err
}
}
return tea.String(e.sessionCredential.AccessKeySecret), nil
}
// GetSecurityToken reutrns EcsRAMRoleCredential's SecurityToken
// if SecurityToken is not exist or out of date, the function will update it.
func (e *EcsRAMRoleCredential) GetSecurityToken() (*string, error) {
if e.sessionCredential == nil || e.needUpdateCredential() {
err := e.updateCredential()
if err != nil {
return tea.String(""), err
}
}
return tea.String(e.sessionCredential.SecurityToken), nil
}
// GetBearerToken is useless for EcsRAMRoleCredential
func (e *EcsRAMRoleCredential) GetBearerToken() *string {
return tea.String("")
}
// GetType reutrns EcsRAMRoleCredential's type
func (e *EcsRAMRoleCredential) GetType() *string {
return tea.String("ecs_ram_role")
}
func getRoleName() (string, error) {
runtime := utils.NewRuntime(1, 1, "", "")
request := request.NewCommonRequest()
request.URL = securityCredURL
request.Method = "GET"
content, err := doAction(request, runtime)
if err != nil {
return "", err
}
return string(content), nil
}
func (e *EcsRAMRoleCredential) updateCredential() (err error) {
if e.runtime == nil {
e.runtime = new(utils.Runtime)
}
request := request.NewCommonRequest()
if e.RoleName == "" {
e.RoleName, err = getRoleName()
if err != nil {
return fmt.Errorf("refresh Ecs sts token err: %s", err.Error())
}
}
request.URL = securityCredURL + e.RoleName
request.Method = "GET"
content, err := doAction(request, e.runtime)
if err != nil {
return fmt.Errorf("refresh Ecs sts token err: %s", err.Error())
}
var resp *ecsRAMRoleResponse
err = json.Unmarshal(content, &resp)
if err != nil {
return fmt.Errorf("refresh Ecs sts token err: Json Unmarshal fail: %s", err.Error())
}
if resp.Code != "Success" {
return fmt.Errorf("refresh Ecs sts token err: Code is not Success")
}
if resp.AccessKeyId == "" || resp.AccessKeySecret == "" || resp.SecurityToken == "" || resp.Expiration == "" {
return fmt.Errorf("refresh Ecs sts token err: AccessKeyId: %s, AccessKeySecret: %s, SecurityToken: %s, Expiration: %s", resp.AccessKeyId, resp.AccessKeySecret, resp.SecurityToken, resp.Expiration)
}
expirationTime, err := time.Parse("2006-01-02T15:04:05Z", resp.Expiration)
e.lastUpdateTimestamp = time.Now().Unix()
e.credentialExpiration = int(expirationTime.Unix() - time.Now().Unix())
e.sessionCredential = &sessionCredential{
AccessKeyId: resp.AccessKeyId,
AccessKeySecret: resp.AccessKeySecret,
SecurityToken: resp.SecurityToken,
}
return
}

View File

@@ -0,0 +1,43 @@
package credentials
import (
"errors"
"os"
"github.com/alibabacloud-go/tea/tea"
)
type envProvider struct{}
var providerEnv = new(envProvider)
const (
// EnvVarAccessKeyId is a name of ALIBABA_CLOUD_ACCESS_KEY_Id
EnvVarAccessKeyId = "ALIBABA_CLOUD_ACCESS_KEY_Id"
// EnvVarAccessKeySecret is a name of ALIBABA_CLOUD_ACCESS_KEY_SECRET
EnvVarAccessKeySecret = "ALIBABA_CLOUD_ACCESS_KEY_SECRET"
)
func newEnvProvider() Provider {
return &envProvider{}
}
func (p *envProvider) resolve() (*Config, error) {
accessKeyId, ok1 := os.LookupEnv(EnvVarAccessKeyId)
accessKeySecret, ok2 := os.LookupEnv(EnvVarAccessKeySecret)
if !ok1 || !ok2 {
return nil, nil
}
if accessKeyId == "" {
return nil, errors.New(EnvVarAccessKeyId + " cannot be empty")
}
if accessKeySecret == "" {
return nil, errors.New(EnvVarAccessKeySecret + " cannot be empty")
}
config := &Config{
Type: tea.String("access_key"),
AccessKeyId: tea.String(accessKeyId),
AccessKeySecret: tea.String(accessKeySecret),
}
return config, nil
}

View File

@@ -0,0 +1,28 @@
package credentials
import (
"os"
"github.com/alibabacloud-go/tea/tea"
)
type instanceCredentialsProvider struct{}
var providerInstance = new(instanceCredentialsProvider)
func newInstanceCredentialsProvider() Provider {
return &instanceCredentialsProvider{}
}
func (p *instanceCredentialsProvider) resolve() (*Config, error) {
roleName, ok := os.LookupEnv(ENVEcsMetadata)
if !ok {
return nil, nil
}
config := &Config{
Type: tea.String("ecs_ram_role"),
RoleName: tea.String(roleName),
}
return config, nil
}

View File

@@ -0,0 +1,350 @@
package credentials
import (
"errors"
"fmt"
"os"
"runtime"
"strings"
"github.com/alibabacloud-go/tea/tea"
ini "gopkg.in/ini.v1"
)
type profileProvider struct {
Profile string
}
var providerProfile = newProfileProvider()
var hookOS = func(goos string) string {
return goos
}
var hookState = func(info os.FileInfo, err error) (os.FileInfo, error) {
return info, err
}
// NewProfileProvider receive zero or more parameters,
// when length of name is 0, the value of field Profile will be "default",
// and when there are multiple inputs, the function will take the
// first one and discard the other values.
func newProfileProvider(name ...string) Provider {
p := new(profileProvider)
if len(name) == 0 {
p.Profile = "default"
} else {
p.Profile = name[0]
}
return p
}
// resolve implements the Provider interface
// when credential type is rsa_key_pair, the content of private_key file
// must be able to be parsed directly into the required string
// that NewRsaKeyPairCredential function needed
func (p *profileProvider) resolve() (*Config, error) {
path, ok := os.LookupEnv(ENVCredentialFile)
if !ok {
path, err := checkDefaultPath()
if err != nil {
return nil, err
}
if path == "" {
return nil, nil
}
} else if path == "" {
return nil, errors.New(ENVCredentialFile + " cannot be empty")
}
value, section, err := getType(path, p.Profile)
if err != nil {
return nil, err
}
switch value.String() {
case "access_key":
config, err := getAccessKey(section)
if err != nil {
return nil, err
}
return config, nil
case "sts":
config, err := getSTS(section)
if err != nil {
return nil, err
}
return config, nil
case "bearer":
config, err := getBearerToken(section)
if err != nil {
return nil, err
}
return config, nil
case "ecs_ram_role":
config, err := getEcsRAMRole(section)
if err != nil {
return nil, err
}
return config, nil
case "ram_role_arn":
config, err := getRAMRoleArn(section)
if err != nil {
return nil, err
}
return config, nil
case "rsa_key_pair":
config, err := getRSAKeyPair(section)
if err != nil {
return nil, err
}
return config, nil
default:
return nil, errors.New("Invalid type option, support: access_key, sts, ecs_ram_role, ram_role_arn, rsa_key_pair")
}
}
func getRSAKeyPair(section *ini.Section) (*Config, error) {
publicKeyId, err := section.GetKey("public_key_id")
if err != nil {
return nil, errors.New("Missing required public_key_id option in profile for rsa_key_pair")
}
if publicKeyId.String() == "" {
return nil, errors.New("public_key_id cannot be empty")
}
privateKeyFile, err := section.GetKey("private_key_file")
if err != nil {
return nil, errors.New("Missing required private_key_file option in profile for rsa_key_pair")
}
if privateKeyFile.String() == "" {
return nil, errors.New("private_key_file cannot be empty")
}
sessionExpiration, _ := section.GetKey("session_expiration")
expiration := 0
if sessionExpiration != nil {
expiration, err = sessionExpiration.Int()
if err != nil {
return nil, errors.New("session_expiration must be an int")
}
}
config := &Config{
Type: tea.String("rsa_key_pair"),
PublicKeyId: tea.String(publicKeyId.String()),
PrivateKeyFile: tea.String(privateKeyFile.String()),
SessionExpiration: tea.Int(expiration),
}
err = setRuntimeToConfig(config, section)
if err != nil {
return nil, err
}
return config, nil
}
func getRAMRoleArn(section *ini.Section) (*Config, error) {
accessKeyId, err := section.GetKey("access_key_id")
if err != nil {
return nil, errors.New("Missing required access_key_id option in profile for ram_role_arn")
}
if accessKeyId.String() == "" {
return nil, errors.New("access_key_id cannot be empty")
}
accessKeySecret, err := section.GetKey("access_key_secret")
if err != nil {
return nil, errors.New("Missing required access_key_secret option in profile for ram_role_arn")
}
if accessKeySecret.String() == "" {
return nil, errors.New("access_key_secret cannot be empty")
}
roleArn, err := section.GetKey("role_arn")
if err != nil {
return nil, errors.New("Missing required role_arn option in profile for ram_role_arn")
}
if roleArn.String() == "" {
return nil, errors.New("role_arn cannot be empty")
}
roleSessionName, err := section.GetKey("role_session_name")
if err != nil {
return nil, errors.New("Missing required role_session_name option in profile for ram_role_arn")
}
if roleSessionName.String() == "" {
return nil, errors.New("role_session_name cannot be empty")
}
roleSessionExpiration, _ := section.GetKey("role_session_expiration")
expiration := 0
if roleSessionExpiration != nil {
expiration, err = roleSessionExpiration.Int()
if err != nil {
return nil, errors.New("role_session_expiration must be an int")
}
}
config := &Config{
Type: tea.String("ram_role_arn"),
AccessKeyId: tea.String(accessKeyId.String()),
AccessKeySecret: tea.String(accessKeySecret.String()),
RoleArn: tea.String(roleArn.String()),
RoleSessionName: tea.String(roleSessionName.String()),
RoleSessionExpiration: tea.Int(expiration),
}
err = setRuntimeToConfig(config, section)
if err != nil {
return nil, err
}
return config, nil
}
func getEcsRAMRole(section *ini.Section) (*Config, error) {
roleName, _ := section.GetKey("role_name")
config := &Config{
Type: tea.String("ecs_ram_role"),
}
if roleName != nil {
config.RoleName = tea.String(roleName.String())
}
err := setRuntimeToConfig(config, section)
if err != nil {
return nil, err
}
return config, nil
}
func getBearerToken(section *ini.Section) (*Config, error) {
bearerToken, err := section.GetKey("bearer_token")
if err != nil {
return nil, errors.New("Missing required bearer_token option in profile for bearer")
}
if bearerToken.String() == "" {
return nil, errors.New("bearer_token cannot be empty")
}
config := &Config{
Type: tea.String("bearer"),
BearerToken: tea.String(bearerToken.String()),
}
return config, nil
}
func getSTS(section *ini.Section) (*Config, error) {
accesskeyid, err := section.GetKey("access_key_id")
if err != nil {
return nil, errors.New("Missing required access_key_id option in profile for sts")
}
if accesskeyid.String() == "" {
return nil, errors.New("access_key_id cannot be empty")
}
accessKeySecret, err := section.GetKey("access_key_secret")
if err != nil {
return nil, errors.New("Missing required access_key_secret option in profile for sts")
}
if accessKeySecret.String() == "" {
return nil, errors.New("access_key_secret cannot be empty")
}
securityToken, err := section.GetKey("security_token")
if err != nil {
return nil, errors.New("Missing required security_token option in profile for sts")
}
if securityToken.String() == "" {
return nil, errors.New("security_token cannot be empty")
}
config := &Config{
Type: tea.String("sts"),
AccessKeyId: tea.String(accesskeyid.String()),
AccessKeySecret: tea.String(accessKeySecret.String()),
SecurityToken: tea.String(securityToken.String()),
}
return config, nil
}
func getAccessKey(section *ini.Section) (*Config, error) {
accesskeyid, err := section.GetKey("access_key_id")
if err != nil {
return nil, errors.New("Missing required access_key_id option in profile for access_key")
}
if accesskeyid.String() == "" {
return nil, errors.New("access_key_id cannot be empty")
}
accessKeySecret, err := section.GetKey("access_key_secret")
if err != nil {
return nil, errors.New("Missing required access_key_secret option in profile for access_key")
}
if accessKeySecret.String() == "" {
return nil, errors.New("access_key_secret cannot be empty")
}
config := &Config{
Type: tea.String("access_key"),
AccessKeyId: tea.String(accesskeyid.String()),
AccessKeySecret: tea.String(accessKeySecret.String()),
}
return config, nil
}
func getType(path, profile string) (*ini.Key, *ini.Section, error) {
ini, err := ini.Load(path)
if err != nil {
return nil, nil, errors.New("ERROR: Can not open file " + err.Error())
}
section, err := ini.GetSection(profile)
if err != nil {
return nil, nil, errors.New("ERROR: Can not load section " + err.Error())
}
value, err := section.GetKey("type")
if err != nil {
return nil, nil, errors.New("Missing required type option " + err.Error())
}
return value, section, nil
}
func getHomePath() string {
if hookOS(runtime.GOOS) == "windows" {
path, ok := os.LookupEnv("USERPROFILE")
if !ok {
return ""
}
return path
}
path, ok := os.LookupEnv("HOME")
if !ok {
return ""
}
return path
}
func checkDefaultPath() (path string, err error) {
path = getHomePath()
if path == "" {
return "", errors.New("The default credential file path is invalid")
}
path = strings.Replace("~/.alibabacloud/credentials", "~", path, 1)
_, err = hookState(os.Stat(path))
if err != nil {
return "", nil
}
return path, nil
}
func setRuntimeToConfig(config *Config, section *ini.Section) error {
rawTimeout, _ := section.GetKey("timeout")
rawConnectTimeout, _ := section.GetKey("connect_timeout")
rawProxy, _ := section.GetKey("proxy")
rawHost, _ := section.GetKey("host")
if rawProxy != nil {
config.Proxy = tea.String(rawProxy.String())
}
if rawConnectTimeout != nil {
connectTimeout, err := rawConnectTimeout.Int()
if err != nil {
return fmt.Errorf("Please set connect_timeout with an int value")
}
config.ConnectTimeout = tea.Int(connectTimeout)
}
if rawTimeout != nil {
timeout, err := rawTimeout.Int()
if err != nil {
return fmt.Errorf("Please set timeout with an int value")
}
config.Timeout = tea.Int(timeout)
}
if rawHost != nil {
config.Host = tea.String(rawHost.String())
}
return nil
}

View File

@@ -0,0 +1,13 @@
package credentials
//Environmental virables that may be used by the provider
const (
ENVCredentialFile = "ALIBABA_CLOUD_CREDENTIALS_FILE"
ENVEcsMetadata = "ALIBABA_CLOUD_ECS_METADATA"
PATHCredentialFile = "~/.alibabacloud/credentials"
)
// Provider will be implemented When you want to customize the provider.
type Provider interface {
resolve() (*Config, error)
}

View File

@@ -0,0 +1,32 @@
package credentials
import (
"errors"
)
type providerChain struct {
Providers []Provider
}
var defaultproviders = []Provider{providerEnv, providerProfile, providerInstance}
var defaultChain = newProviderChain(defaultproviders)
func newProviderChain(providers []Provider) Provider {
return &providerChain{
Providers: providers,
}
}
func (p *providerChain) resolve() (*Config, error) {
for _, provider := range p.Providers {
config, err := provider.resolve()
if err != nil {
return nil, err
} else if config == nil {
continue
}
return config, err
}
return nil, errors.New("No credential found")
}

View File

@@ -0,0 +1,59 @@
package request
import (
"fmt"
"net/url"
"strings"
"time"
"github.com/aliyun/credentials-go/credentials/utils"
)
// CommonRequest is for requesting credential
type CommonRequest struct {
Scheme string
Method string
Domain string
RegionId string
URL string
ReadTimeout time.Duration
ConnectTimeout time.Duration
isInsecure *bool
userAgent map[string]string
QueryParams map[string]string
Headers map[string]string
queries string
}
// NewCommonRequest returns a CommonRequest
func NewCommonRequest() *CommonRequest {
return &CommonRequest{
QueryParams: make(map[string]string),
Headers: make(map[string]string),
}
}
// BuildURL returns a url
func (request *CommonRequest) BuildURL() string {
url := fmt.Sprintf("%s://%s", strings.ToLower(request.Scheme), request.Domain)
request.queries = "/?" + utils.GetURLFormedMap(request.QueryParams)
return url + request.queries
}
// BuildStringToSign returns BuildStringToSign
func (request *CommonRequest) BuildStringToSign() (stringToSign string) {
signParams := make(map[string]string)
for key, value := range request.QueryParams {
signParams[key] = value
}
stringToSign = utils.GetURLFormedMap(signParams)
stringToSign = strings.Replace(stringToSign, "+", "%20", -1)
stringToSign = strings.Replace(stringToSign, "*", "%2A", -1)
stringToSign = strings.Replace(stringToSign, "%7E", "~", -1)
stringToSign = url.QueryEscape(stringToSign)
stringToSign = request.Method + "&%2F&" + stringToSign
return
}

View File

@@ -0,0 +1,53 @@
package response
import (
"io"
"io/ioutil"
"net/http"
)
var hookReadAll = func(fn func(r io.Reader) (b []byte, err error)) func(r io.Reader) (b []byte, err error) {
return fn
}
// CommonResponse is for storing message of httpResponse
type CommonResponse struct {
httpStatus int
httpHeaders map[string][]string
httpContentString string
httpContentBytes []byte
}
// ParseFromHTTPResponse assigns for CommonResponse, returns err when body is too large.
func (resp *CommonResponse) ParseFromHTTPResponse(httpResponse *http.Response) (err error) {
defer httpResponse.Body.Close()
body, err := hookReadAll(ioutil.ReadAll)(httpResponse.Body)
if err != nil {
return
}
resp.httpStatus = httpResponse.StatusCode
resp.httpHeaders = httpResponse.Header
resp.httpContentBytes = body
resp.httpContentString = string(body)
return
}
// GetHTTPStatus returns httpStatus
func (resp *CommonResponse) GetHTTPStatus() int {
return resp.httpStatus
}
// GetHTTPHeaders returns httpresponse's headers
func (resp *CommonResponse) GetHTTPHeaders() map[string][]string {
return resp.httpHeaders
}
// GetHTTPContentString return body content as string
func (resp *CommonResponse) GetHTTPContentString() string {
return resp.httpContentString
}
// GetHTTPContentBytes return body content as []byte
func (resp *CommonResponse) GetHTTPContentBytes() []byte {
return resp.httpContentBytes
}

View File

@@ -0,0 +1,145 @@
package credentials
import (
"encoding/json"
"errors"
"fmt"
"strconv"
"time"
"github.com/alibabacloud-go/tea/tea"
"github.com/aliyun/credentials-go/credentials/request"
"github.com/aliyun/credentials-go/credentials/utils"
)
// RsaKeyPairCredential is a kind of credentials
type RsaKeyPairCredential struct {
*credentialUpdater
PrivateKey string
PublicKeyId string
SessionExpiration int
sessionCredential *sessionCredential
runtime *utils.Runtime
}
type rsaKeyPairResponse struct {
SessionAccessKey *sessionAccessKey `json:"SessionAccessKey" xml:"SessionAccessKey"`
}
type sessionAccessKey struct {
SessionAccessKeyId string `json:"SessionAccessKeyId" xml:"SessionAccessKeyId"`
SessionAccessKeySecret string `json:"SessionAccessKeySecret" xml:"SessionAccessKeySecret"`
Expiration string `json:"Expiration" xml:"Expiration"`
}
func newRsaKeyPairCredential(privateKey, publicKeyId string, sessionExpiration int, runtime *utils.Runtime) *RsaKeyPairCredential {
return &RsaKeyPairCredential{
PrivateKey: privateKey,
PublicKeyId: publicKeyId,
SessionExpiration: sessionExpiration,
credentialUpdater: new(credentialUpdater),
runtime: runtime,
}
}
// GetAccessKeyId reutrns RsaKeyPairCredential's AccessKeyId
// if AccessKeyId is not exist or out of date, the function will update it.
func (r *RsaKeyPairCredential) GetAccessKeyId() (*string, error) {
if r.sessionCredential == nil || r.needUpdateCredential() {
err := r.updateCredential()
if err != nil {
return tea.String(""), err
}
}
return tea.String(r.sessionCredential.AccessKeyId), nil
}
// GetAccessSecret reutrns RsaKeyPairCredential's AccessKeySecret
// if AccessKeySecret is not exist or out of date, the function will update it.
func (r *RsaKeyPairCredential) GetAccessKeySecret() (*string, error) {
if r.sessionCredential == nil || r.needUpdateCredential() {
err := r.updateCredential()
if err != nil {
return tea.String(""), err
}
}
return tea.String(r.sessionCredential.AccessKeySecret), nil
}
// GetSecurityToken is useless RsaKeyPairCredential
func (r *RsaKeyPairCredential) GetSecurityToken() (*string, error) {
return tea.String(""), nil
}
// GetBearerToken is useless for RsaKeyPairCredential
func (r *RsaKeyPairCredential) GetBearerToken() *string {
return tea.String("")
}
// GetType reutrns RsaKeyPairCredential's type
func (r *RsaKeyPairCredential) GetType() *string {
return tea.String("rsa_key_pair")
}
func (r *RsaKeyPairCredential) updateCredential() (err error) {
if r.runtime == nil {
r.runtime = new(utils.Runtime)
}
request := request.NewCommonRequest()
request.Domain = "sts.aliyuncs.com"
if r.runtime.Host != "" {
request.Domain = r.runtime.Host
}
request.Scheme = "HTTPS"
request.Method = "GET"
request.QueryParams["AccessKeyId"] = r.PublicKeyId
request.QueryParams["Action"] = "GenerateSessionAccessKey"
request.QueryParams["Format"] = "JSON"
if r.SessionExpiration > 0 {
if r.SessionExpiration >= 900 && r.SessionExpiration <= 3600 {
request.QueryParams["DurationSeconds"] = strconv.Itoa(r.SessionExpiration)
} else {
err = errors.New("[InvalidParam]:Key Pair session duration should be in the range of 15min - 1Hr")
return
}
} else {
request.QueryParams["DurationSeconds"] = strconv.Itoa(defaultDurationSeconds)
}
request.QueryParams["SignatureMethod"] = "SHA256withRSA"
request.QueryParams["SignatureType"] = "PRIVATEKEY"
request.QueryParams["SignatureVersion"] = "1.0"
request.QueryParams["Version"] = "2015-04-01"
request.QueryParams["Timestamp"] = utils.GetTimeInFormatISO8601()
request.QueryParams["SignatureNonce"] = utils.GetUUID()
signature := utils.Sha256WithRsa(request.BuildStringToSign(), r.PrivateKey)
request.QueryParams["Signature"] = signature
request.Headers["Host"] = request.Domain
request.Headers["Accept-Encoding"] = "identity"
request.URL = request.BuildURL()
content, err := doAction(request, r.runtime)
if err != nil {
return fmt.Errorf("refresh KeyPair err: %s", err.Error())
}
var resp *rsaKeyPairResponse
err = json.Unmarshal(content, &resp)
if err != nil {
return fmt.Errorf("refresh KeyPair err: Json Unmarshal fail: %s", err.Error())
}
if resp == nil || resp.SessionAccessKey == nil {
return fmt.Errorf("refresh KeyPair err: SessionAccessKey is empty")
}
sessionAccessKey := resp.SessionAccessKey
if sessionAccessKey.SessionAccessKeyId == "" || sessionAccessKey.SessionAccessKeySecret == "" || sessionAccessKey.Expiration == "" {
return fmt.Errorf("refresh KeyPair err: SessionAccessKeyId: %v, SessionAccessKeySecret: %v, Expiration: %v", sessionAccessKey.SessionAccessKeyId, sessionAccessKey.SessionAccessKeySecret, sessionAccessKey.Expiration)
}
expirationTime, err := time.Parse("2006-01-02T15:04:05Z", sessionAccessKey.Expiration)
r.lastUpdateTimestamp = time.Now().Unix()
r.credentialExpiration = int(expirationTime.Unix() - time.Now().Unix())
r.sessionCredential = &sessionCredential{
AccessKeyId: sessionAccessKey.SessionAccessKeyId,
AccessKeySecret: sessionAccessKey.SessionAccessKeySecret,
}
return
}

View File

@@ -0,0 +1,7 @@
package credentials
type sessionCredential struct {
AccessKeyId string
AccessKeySecret string
SecurityToken string
}

View File

@@ -0,0 +1,43 @@
package credentials
import "github.com/alibabacloud-go/tea/tea"
// StsTokenCredential is a kind of credentials
type StsTokenCredential struct {
AccessKeyId string
AccessKeySecret string
SecurityToken string
}
func newStsTokenCredential(accessKeyId, accessKeySecret, securityToken string) *StsTokenCredential {
return &StsTokenCredential{
AccessKeyId: accessKeyId,
AccessKeySecret: accessKeySecret,
SecurityToken: securityToken,
}
}
// GetAccessKeyId reutrns StsTokenCredential's AccessKeyId
func (s *StsTokenCredential) GetAccessKeyId() (*string, error) {
return tea.String(s.AccessKeyId), nil
}
// GetAccessSecret reutrns StsTokenCredential's AccessKeySecret
func (s *StsTokenCredential) GetAccessKeySecret() (*string, error) {
return tea.String(s.AccessKeySecret), nil
}
// GetSecurityToken reutrns StsTokenCredential's SecurityToken
func (s *StsTokenCredential) GetSecurityToken() (*string, error) {
return tea.String(s.SecurityToken), nil
}
// GetBearerToken is useless StsTokenCredential
func (s *StsTokenCredential) GetBearerToken() *string {
return tea.String("")
}
// GetType reutrns StsTokenCredential's type
func (s *StsTokenCredential) GetType() *string {
return tea.String("sts")
}

View File

@@ -0,0 +1,163 @@
package credentials
import (
"encoding/json"
"errors"
"fmt"
"strconv"
"time"
"github.com/alibabacloud-go/tea/tea"
"github.com/aliyun/credentials-go/credentials/request"
"github.com/aliyun/credentials-go/credentials/utils"
)
const defaultDurationSeconds = 3600
// RAMRoleArnCredential is a kind of credentials
type RAMRoleArnCredential struct {
*credentialUpdater
AccessKeyId string
AccessKeySecret string
RoleArn string
RoleSessionName string
RoleSessionExpiration int
Policy string
sessionCredential *sessionCredential
runtime *utils.Runtime
}
type ramRoleArnResponse struct {
Credentials *credentialsInResponse `json:"Credentials" xml:"Credentials"`
}
type credentialsInResponse struct {
AccessKeyId string `json:"AccessKeyId" xml:"AccessKeyId"`
AccessKeySecret string `json:"AccessKeySecret" xml:"AccessKeySecret"`
SecurityToken string `json:"SecurityToken" xml:"SecurityToken"`
Expiration string `json:"Expiration" xml:"Expiration"`
}
func newRAMRoleArnCredential(accessKeyId, accessKeySecret, roleArn, roleSessionName, policy string, roleSessionExpiration int, runtime *utils.Runtime) *RAMRoleArnCredential {
return &RAMRoleArnCredential{
AccessKeyId: accessKeyId,
AccessKeySecret: accessKeySecret,
RoleArn: roleArn,
RoleSessionName: roleSessionName,
RoleSessionExpiration: roleSessionExpiration,
Policy: policy,
credentialUpdater: new(credentialUpdater),
runtime: runtime,
}
}
// GetAccessKeyId reutrns RamRoleArnCredential's AccessKeyId
// if AccessKeyId is not exist or out of date, the function will update it.
func (r *RAMRoleArnCredential) GetAccessKeyId() (*string, error) {
if r.sessionCredential == nil || r.needUpdateCredential() {
err := r.updateCredential()
if err != nil {
return tea.String(""), err
}
}
return tea.String(r.sessionCredential.AccessKeyId), nil
}
// GetAccessSecret reutrns RamRoleArnCredential's AccessKeySecret
// if AccessKeySecret is not exist or out of date, the function will update it.
func (r *RAMRoleArnCredential) GetAccessKeySecret() (*string, error) {
if r.sessionCredential == nil || r.needUpdateCredential() {
err := r.updateCredential()
if err != nil {
return tea.String(""), err
}
}
return tea.String(r.sessionCredential.AccessKeySecret), nil
}
// GetSecurityToken reutrns RamRoleArnCredential's SecurityToken
// if SecurityToken is not exist or out of date, the function will update it.
func (r *RAMRoleArnCredential) GetSecurityToken() (*string, error) {
if r.sessionCredential == nil || r.needUpdateCredential() {
err := r.updateCredential()
if err != nil {
return tea.String(""), err
}
}
return tea.String(r.sessionCredential.SecurityToken), nil
}
// GetBearerToken is useless RamRoleArnCredential
func (r *RAMRoleArnCredential) GetBearerToken() *string {
return tea.String("")
}
// GetType reutrns RamRoleArnCredential's type
func (r *RAMRoleArnCredential) GetType() *string {
return tea.String("ram_role_arn")
}
func (r *RAMRoleArnCredential) updateCredential() (err error) {
if r.runtime == nil {
r.runtime = new(utils.Runtime)
}
request := request.NewCommonRequest()
request.Domain = "sts.aliyuncs.com"
request.Scheme = "HTTPS"
request.Method = "GET"
request.QueryParams["AccessKeyId"] = r.AccessKeyId
request.QueryParams["Action"] = "AssumeRole"
request.QueryParams["Format"] = "JSON"
if r.RoleSessionExpiration > 0 {
if r.RoleSessionExpiration >= 900 && r.RoleSessionExpiration <= 3600 {
request.QueryParams["DurationSeconds"] = strconv.Itoa(r.RoleSessionExpiration)
} else {
err = errors.New("[InvalidParam]:Assume Role session duration should be in the range of 15min - 1Hr")
return
}
} else {
request.QueryParams["DurationSeconds"] = strconv.Itoa(defaultDurationSeconds)
}
request.QueryParams["RoleArn"] = r.RoleArn
if r.Policy != "" {
request.QueryParams["Policy"] = r.Policy
}
request.QueryParams["RoleSessionName"] = r.RoleSessionName
request.QueryParams["SignatureMethod"] = "HMAC-SHA1"
request.QueryParams["SignatureVersion"] = "1.0"
request.QueryParams["Version"] = "2015-04-01"
request.QueryParams["Timestamp"] = utils.GetTimeInFormatISO8601()
request.QueryParams["SignatureNonce"] = utils.GetUUID()
signature := utils.ShaHmac1(request.BuildStringToSign(), r.AccessKeySecret+"&")
request.QueryParams["Signature"] = signature
request.Headers["Host"] = request.Domain
request.Headers["Accept-Encoding"] = "identity"
request.URL = request.BuildURL()
content, err := doAction(request, r.runtime)
if err != nil {
return fmt.Errorf("refresh RoleArn sts token err: %s", err.Error())
}
var resp *ramRoleArnResponse
err = json.Unmarshal(content, &resp)
if err != nil {
return fmt.Errorf("refresh RoleArn sts token err: Json.Unmarshal fail: %s", err.Error())
}
if resp == nil || resp.Credentials == nil {
return fmt.Errorf("refresh RoleArn sts token err: Credentials is empty")
}
respCredentials := resp.Credentials
if respCredentials.AccessKeyId == "" || respCredentials.AccessKeySecret == "" || respCredentials.SecurityToken == "" || respCredentials.Expiration == "" {
return fmt.Errorf("refresh RoleArn sts token err: AccessKeyId: %s, AccessKeySecret: %s, SecurityToken: %s, Expiration: %s", respCredentials.AccessKeyId, respCredentials.AccessKeySecret, respCredentials.SecurityToken, respCredentials.Expiration)
}
expirationTime, err := time.Parse("2006-01-02T15:04:05Z", respCredentials.Expiration)
r.lastUpdateTimestamp = time.Now().Unix()
r.credentialExpiration = int(expirationTime.Unix() - time.Now().Unix())
r.sessionCredential = &sessionCredential{
AccessKeyId: respCredentials.AccessKeyId,
AccessKeySecret: respCredentials.AccessKeySecret,
SecurityToken: respCredentials.SecurityToken,
}
return
}

View File

@@ -0,0 +1,35 @@
package utils
import (
"context"
"net"
"time"
)
// Runtime is for setting timeout, proxy and host
type Runtime struct {
ReadTimeout int
ConnectTimeout int
Proxy string
Host string
}
// NewRuntime returns a Runtime
func NewRuntime(readTimeout, connectTimeout int, proxy string, host string) *Runtime {
return &Runtime{
ReadTimeout: readTimeout,
ConnectTimeout: connectTimeout,
Proxy: proxy,
Host: host,
}
}
// Timeout is for connect Timeout
func Timeout(connectTimeout time.Duration) func(cxt context.Context, net, addr string) (c net.Conn, err error) {
return func(ctx context.Context, network, address string) (net.Conn, error) {
return (&net.Dialer{
Timeout: connectTimeout,
DualStack: true,
}).DialContext(ctx, network, address)
}
}

View File

@@ -0,0 +1,146 @@
package utils
import (
"crypto"
"crypto/hmac"
"crypto/md5"
"crypto/rand"
"crypto/rsa"
"crypto/sha1"
"crypto/x509"
"encoding/base64"
"encoding/hex"
"hash"
"io"
rand2 "math/rand"
"net/url"
"time"
)
type uuid [16]byte
const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
var hookRead = func(fn func(p []byte) (n int, err error)) func(p []byte) (n int, err error) {
return fn
}
var hookRSA = func(fn func(rand io.Reader, priv *rsa.PrivateKey, hash crypto.Hash, hashed []byte) ([]byte, error)) func(rand io.Reader, priv *rsa.PrivateKey, hash crypto.Hash, hashed []byte) ([]byte, error) {
return fn
}
// GetUUID returns a uuid
func GetUUID() (uuidHex string) {
uuid := newUUID()
uuidHex = hex.EncodeToString(uuid[:])
return
}
// RandStringBytes returns a rand string
func RandStringBytes(n int) string {
b := make([]byte, n)
for i := range b {
b[i] = letterBytes[rand2.Intn(len(letterBytes))]
}
return string(b)
}
// ShaHmac1 return a string which has been hashed
func ShaHmac1(source, secret string) string {
key := []byte(secret)
hmac := hmac.New(sha1.New, key)
hmac.Write([]byte(source))
signedBytes := hmac.Sum(nil)
signedString := base64.StdEncoding.EncodeToString(signedBytes)
return signedString
}
// Sha256WithRsa return a string which has been hashed with Rsa
func Sha256WithRsa(source, secret string) string {
decodeString, err := base64.StdEncoding.DecodeString(secret)
if err != nil {
panic(err)
}
private, err := x509.ParsePKCS8PrivateKey(decodeString)
if err != nil {
panic(err)
}
h := crypto.Hash.New(crypto.SHA256)
h.Write([]byte(source))
hashed := h.Sum(nil)
signature, err := hookRSA(rsa.SignPKCS1v15)(rand.Reader, private.(*rsa.PrivateKey),
crypto.SHA256, hashed)
if err != nil {
panic(err)
}
return base64.StdEncoding.EncodeToString(signature)
}
// GetMD5Base64 returns a string which has been base64
func GetMD5Base64(bytes []byte) (base64Value string) {
md5Ctx := md5.New()
md5Ctx.Write(bytes)
md5Value := md5Ctx.Sum(nil)
base64Value = base64.StdEncoding.EncodeToString(md5Value)
return
}
// GetTimeInFormatISO8601 returns a time string
func GetTimeInFormatISO8601() (timeStr string) {
gmt := time.FixedZone("GMT", 0)
return time.Now().In(gmt).Format("2006-01-02T15:04:05Z")
}
// GetURLFormedMap returns a url encoded string
func GetURLFormedMap(source map[string]string) (urlEncoded string) {
urlEncoder := url.Values{}
for key, value := range source {
urlEncoder.Add(key, value)
}
urlEncoded = urlEncoder.Encode()
return
}
func newUUID() uuid {
ns := uuid{}
safeRandom(ns[:])
u := newFromHash(md5.New(), ns, RandStringBytes(16))
u[6] = (u[6] & 0x0f) | (byte(2) << 4)
u[8] = (u[8]&(0xff>>2) | (0x02 << 6))
return u
}
func newFromHash(h hash.Hash, ns uuid, name string) uuid {
u := uuid{}
h.Write(ns[:])
h.Write([]byte(name))
copy(u[:], h.Sum(nil))
return u
}
func safeRandom(dest []byte) {
if _, err := hookRead(rand.Read)(dest); err != nil {
panic(err)
}
}
func (u uuid) String() string {
buf := make([]byte, 36)
hex.Encode(buf[0:8], u[0:4])
buf[8] = '-'
hex.Encode(buf[9:13], u[4:6])
buf[13] = '-'
hex.Encode(buf[14:18], u[6:8])
buf[18] = '-'
hex.Encode(buf[19:23], u[8:10])
buf[23] = '-'
hex.Encode(buf[24:], u[10:])
return string(buf)
}