123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349 |
- 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
- }
|