...

Source file src/github.com/aliyun/credentials-go/credentials/oidc_credential.go

Documentation: github.com/aliyun/credentials-go/credentials

     1  package credentials
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"os"
     8  	"strconv"
     9  	"time"
    10  
    11  	"github.com/alibabacloud-go/tea/tea"
    12  	"github.com/aliyun/credentials-go/credentials/request"
    13  	"github.com/aliyun/credentials-go/credentials/utils"
    14  )
    15  
    16  const defaultOIDCDurationSeconds = 3600
    17  
    18  // OIDCCredential is a kind of credentials
    19  type OIDCCredential struct {
    20  	*credentialUpdater
    21  	AccessKeyId           string
    22  	AccessKeySecret       string
    23  	RoleArn               string
    24  	OIDCProviderArn       string
    25  	OIDCTokenFilePath     string
    26  	Policy                string
    27  	RoleSessionName       string
    28  	RoleSessionExpiration int
    29  	sessionCredential     *sessionCredential
    30  	runtime               *utils.Runtime
    31  }
    32  
    33  type OIDCResponse struct {
    34  	Credentials *credentialsInResponse `json:"Credentials" xml:"Credentials"`
    35  }
    36  
    37  type OIDCcredentialsInResponse struct {
    38  	AccessKeyId     string `json:"AccessKeyId" xml:"AccessKeyId"`
    39  	AccessKeySecret string `json:"AccessKeySecret" xml:"AccessKeySecret"`
    40  	SecurityToken   string `json:"SecurityToken" xml:"SecurityToken"`
    41  	Expiration      string `json:"Expiration" xml:"Expiration"`
    42  }
    43  
    44  func newOIDCRoleArnCredential(accessKeyId, accessKeySecret, roleArn, OIDCProviderArn, OIDCTokenFilePath, RoleSessionName, policy string, RoleSessionExpiration int, runtime *utils.Runtime) *OIDCCredential {
    45  	return &OIDCCredential{
    46  		AccessKeyId:           accessKeyId,
    47  		AccessKeySecret:       accessKeySecret,
    48  		RoleArn:               roleArn,
    49  		OIDCProviderArn:       OIDCProviderArn,
    50  		OIDCTokenFilePath:     OIDCTokenFilePath,
    51  		RoleSessionName:       RoleSessionName,
    52  		Policy:                policy,
    53  		RoleSessionExpiration: RoleSessionExpiration,
    54  		credentialUpdater:     new(credentialUpdater),
    55  		runtime:               runtime,
    56  	}
    57  }
    58  
    59  func (e *OIDCCredential) GetCredential() (*CredentialModel, error) {
    60  	if e.sessionCredential == nil || e.needUpdateCredential() {
    61  		err := e.updateCredential()
    62  		if err != nil {
    63  			return nil, err
    64  		}
    65  	}
    66  	credential := &CredentialModel{
    67  		AccessKeyId:     tea.String(e.sessionCredential.AccessKeyId),
    68  		AccessKeySecret: tea.String(e.sessionCredential.AccessKeySecret),
    69  		SecurityToken:   tea.String(e.sessionCredential.SecurityToken),
    70  		Type:            tea.String("oidc_role_arn"),
    71  	}
    72  	return credential, nil
    73  }
    74  
    75  // GetAccessKeyId reutrns OIDCCredential's AccessKeyId
    76  // if AccessKeyId is not exist or out of date, the function will update it.
    77  func (r *OIDCCredential) GetAccessKeyId() (*string, error) {
    78  	if r.sessionCredential == nil || r.needUpdateCredential() {
    79  		err := r.updateCredential()
    80  		if err != nil {
    81  			return tea.String(""), err
    82  		}
    83  	}
    84  	return tea.String(r.sessionCredential.AccessKeyId), nil
    85  }
    86  
    87  // GetAccessSecret reutrns OIDCCredential's AccessKeySecret
    88  // if AccessKeySecret is not exist or out of date, the function will update it.
    89  func (r *OIDCCredential) GetAccessKeySecret() (*string, error) {
    90  	if r.sessionCredential == nil || r.needUpdateCredential() {
    91  		err := r.updateCredential()
    92  		if err != nil {
    93  			return tea.String(""), err
    94  		}
    95  	}
    96  	return tea.String(r.sessionCredential.AccessKeySecret), nil
    97  }
    98  
    99  // GetSecurityToken reutrns OIDCCredential's SecurityToken
   100  // if SecurityToken is not exist or out of date, the function will update it.
   101  func (r *OIDCCredential) GetSecurityToken() (*string, error) {
   102  	if r.sessionCredential == nil || r.needUpdateCredential() {
   103  		err := r.updateCredential()
   104  		if err != nil {
   105  			return tea.String(""), err
   106  		}
   107  	}
   108  	return tea.String(r.sessionCredential.SecurityToken), nil
   109  }
   110  
   111  // GetBearerToken is useless OIDCCredential
   112  func (r *OIDCCredential) GetBearerToken() *string {
   113  	return tea.String("")
   114  }
   115  
   116  // GetType reutrns OIDCCredential's type
   117  func (r *OIDCCredential) GetType() *string {
   118  	return tea.String("oidc_role_arn")
   119  }
   120  
   121  func (r *OIDCCredential) GetOIDCToken(OIDCTokenFilePath string) *string {
   122  	tokenPath := OIDCTokenFilePath
   123  	_, err := os.Stat(tokenPath)
   124  	if os.IsNotExist(err) {
   125  		tokenPath = os.Getenv("ALIBABA_CLOUD_OIDC_TOKEN_FILE")
   126  		if tokenPath == "" {
   127  			return nil
   128  		}
   129  	}
   130  	byt, err := ioutil.ReadFile(tokenPath)
   131  	if err != nil {
   132  		return nil
   133  	}
   134  	return tea.String(string(byt))
   135  }
   136  
   137  func (r *OIDCCredential) updateCredential() (err error) {
   138  	if r.runtime == nil {
   139  		r.runtime = new(utils.Runtime)
   140  	}
   141  	request := request.NewCommonRequest()
   142  	request.Domain = "sts.aliyuncs.com"
   143  	if r.runtime.STSEndpoint != "" {
   144  		request.Domain = r.runtime.STSEndpoint
   145  	}
   146  	request.Scheme = "HTTPS"
   147  	request.Method = "POST"
   148  	request.QueryParams["Timestamp"] = utils.GetTimeInFormatISO8601()
   149  	request.QueryParams["Action"] = "AssumeRoleWithOIDC"
   150  	request.QueryParams["Format"] = "JSON"
   151  	request.BodyParams["RoleArn"] = r.RoleArn
   152  	request.BodyParams["OIDCProviderArn"] = r.OIDCProviderArn
   153  	token := r.GetOIDCToken(r.OIDCTokenFilePath)
   154  	request.BodyParams["OIDCToken"] = tea.StringValue(token)
   155  	if r.Policy != "" {
   156  		request.QueryParams["Policy"] = r.Policy
   157  	}
   158  	if r.RoleSessionExpiration > 0 {
   159  		request.QueryParams["DurationSeconds"] = strconv.Itoa(r.RoleSessionExpiration)
   160  	}
   161  	request.QueryParams["RoleSessionName"] = r.RoleSessionName
   162  	request.QueryParams["Version"] = "2015-04-01"
   163  	request.QueryParams["SignatureNonce"] = utils.GetUUID()
   164  	request.Headers["Host"] = request.Domain
   165  	request.Headers["Accept-Encoding"] = "identity"
   166  	request.Headers["content-type"] = "application/x-www-form-urlencoded"
   167  	request.URL = request.BuildURL()
   168  	content, err := doAction(request, r.runtime)
   169  	if err != nil {
   170  		return fmt.Errorf("refresh RoleArn sts token err: %s", err.Error())
   171  	}
   172  	var resp *OIDCResponse
   173  	err = json.Unmarshal(content, &resp)
   174  	if err != nil {
   175  		return fmt.Errorf("refresh RoleArn sts token err: Json.Unmarshal fail: %s", err.Error())
   176  	}
   177  	if resp == nil || resp.Credentials == nil {
   178  		return fmt.Errorf("refresh RoleArn sts token err: Credentials is empty")
   179  	}
   180  	respCredentials := resp.Credentials
   181  	if respCredentials.AccessKeyId == "" || respCredentials.AccessKeySecret == "" || respCredentials.SecurityToken == "" || respCredentials.Expiration == "" {
   182  		return fmt.Errorf("refresh RoleArn sts token err: AccessKeyId: %s, AccessKeySecret: %s, SecurityToken: %s, Expiration: %s", respCredentials.AccessKeyId, respCredentials.AccessKeySecret, respCredentials.SecurityToken, respCredentials.Expiration)
   183  	}
   184  
   185  	expirationTime, err := time.Parse("2006-01-02T15:04:05Z", respCredentials.Expiration)
   186  	r.lastUpdateTimestamp = time.Now().Unix()
   187  	r.credentialExpiration = int(expirationTime.Unix() - time.Now().Unix())
   188  	r.sessionCredential = &sessionCredential{
   189  		AccessKeyId:     respCredentials.AccessKeyId,
   190  		AccessKeySecret: respCredentials.AccessKeySecret,
   191  		SecurityToken:   respCredentials.SecurityToken,
   192  	}
   193  
   194  	return
   195  }
   196  

View as plain text