credential.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518
  1. package credentials
  2. import (
  3. "bufio"
  4. "errors"
  5. "fmt"
  6. "net/http"
  7. "net/url"
  8. "os"
  9. "strings"
  10. "time"
  11. "github.com/alibabacloud-go/debug/debug"
  12. "github.com/alibabacloud-go/tea/tea"
  13. "github.com/aliyun/credentials-go/credentials/internal/utils"
  14. "github.com/aliyun/credentials-go/credentials/providers"
  15. "github.com/aliyun/credentials-go/credentials/request"
  16. "github.com/aliyun/credentials-go/credentials/response"
  17. )
  18. var debuglog = debug.Init("credential")
  19. var hookParse = func(err error) error {
  20. return err
  21. }
  22. // Credential is an interface for getting actual credential
  23. type Credential interface {
  24. // Deprecated: GetAccessKeyId is deprecated, use GetCredential instead of.
  25. GetAccessKeyId() (*string, error)
  26. // Deprecated: GetAccessKeySecret is deprecated, use GetCredential instead of.
  27. GetAccessKeySecret() (*string, error)
  28. // Deprecated: GetSecurityToken is deprecated, use GetCredential instead of.
  29. GetSecurityToken() (*string, error)
  30. GetBearerToken() *string
  31. GetType() *string
  32. GetCredential() (*CredentialModel, error)
  33. }
  34. // Config is important when call NewCredential
  35. type Config struct {
  36. // Credential type, including access_key, sts, bearer, ecs_ram_role, ram_role_arn, rsa_key_pair, oidc_role_arn, credentials_uri
  37. Type *string `json:"type"`
  38. AccessKeyId *string `json:"access_key_id"`
  39. AccessKeySecret *string `json:"access_key_secret"`
  40. SecurityToken *string `json:"security_token"`
  41. BearerToken *string `json:"bearer_token"`
  42. // Used when the type is ram_role_arn or oidc_role_arn
  43. OIDCProviderArn *string `json:"oidc_provider_arn"`
  44. OIDCTokenFilePath *string `json:"oidc_token"`
  45. RoleArn *string `json:"role_arn"`
  46. RoleSessionName *string `json:"role_session_name"`
  47. RoleSessionExpiration *int `json:"role_session_expiration"`
  48. Policy *string `json:"policy"`
  49. ExternalId *string `json:"external_id"`
  50. STSEndpoint *string `json:"sts_endpoint"`
  51. // Used when the type is ecs_ram_role
  52. RoleName *string `json:"role_name"`
  53. // Deprecated
  54. EnableIMDSv2 *bool `json:"enable_imds_v2"`
  55. DisableIMDSv1 *bool `json:"disable_imds_v1"`
  56. // Deprecated
  57. MetadataTokenDuration *int `json:"metadata_token_duration"`
  58. // Used when the type is credentials_uri
  59. Url *string `json:"url"`
  60. // Deprecated
  61. // Used when the type is rsa_key_pair
  62. SessionExpiration *int `json:"session_expiration"`
  63. PublicKeyId *string `json:"public_key_id"`
  64. PrivateKeyFile *string `json:"private_key_file"`
  65. Host *string `json:"host"`
  66. // Read timeout, in milliseconds.
  67. // The default value for ecs_ram_role is 1000ms, the default value for ram_role_arn is 5000ms, and the default value for oidc_role_arn is 5000ms.
  68. Timeout *int `json:"timeout"`
  69. // Connection timeout, in milliseconds.
  70. // The default value for ecs_ram_role is 1000ms, the default value for ram_role_arn is 10000ms, and the default value for oidc_role_arn is 10000ms.
  71. ConnectTimeout *int `json:"connect_timeout"`
  72. Proxy *string `json:"proxy"`
  73. InAdvanceScale *float64 `json:"inAdvanceScale"`
  74. }
  75. func (s Config) String() string {
  76. return tea.Prettify(s)
  77. }
  78. func (s Config) GoString() string {
  79. return s.String()
  80. }
  81. func (s *Config) SetAccessKeyId(v string) *Config {
  82. s.AccessKeyId = &v
  83. return s
  84. }
  85. func (s *Config) SetAccessKeySecret(v string) *Config {
  86. s.AccessKeySecret = &v
  87. return s
  88. }
  89. func (s *Config) SetSecurityToken(v string) *Config {
  90. s.SecurityToken = &v
  91. return s
  92. }
  93. func (s *Config) SetRoleArn(v string) *Config {
  94. s.RoleArn = &v
  95. return s
  96. }
  97. func (s *Config) SetRoleSessionName(v string) *Config {
  98. s.RoleSessionName = &v
  99. return s
  100. }
  101. func (s *Config) SetPublicKeyId(v string) *Config {
  102. s.PublicKeyId = &v
  103. return s
  104. }
  105. func (s *Config) SetRoleName(v string) *Config {
  106. s.RoleName = &v
  107. return s
  108. }
  109. func (s *Config) SetEnableIMDSv2(v bool) *Config {
  110. s.EnableIMDSv2 = &v
  111. return s
  112. }
  113. func (s *Config) SetDisableIMDSv1(v bool) *Config {
  114. s.DisableIMDSv1 = &v
  115. return s
  116. }
  117. func (s *Config) SetMetadataTokenDuration(v int) *Config {
  118. s.MetadataTokenDuration = &v
  119. return s
  120. }
  121. func (s *Config) SetSessionExpiration(v int) *Config {
  122. s.SessionExpiration = &v
  123. return s
  124. }
  125. func (s *Config) SetPrivateKeyFile(v string) *Config {
  126. s.PrivateKeyFile = &v
  127. return s
  128. }
  129. func (s *Config) SetBearerToken(v string) *Config {
  130. s.BearerToken = &v
  131. return s
  132. }
  133. func (s *Config) SetRoleSessionExpiration(v int) *Config {
  134. s.RoleSessionExpiration = &v
  135. return s
  136. }
  137. func (s *Config) SetPolicy(v string) *Config {
  138. s.Policy = &v
  139. return s
  140. }
  141. func (s *Config) SetHost(v string) *Config {
  142. s.Host = &v
  143. return s
  144. }
  145. func (s *Config) SetTimeout(v int) *Config {
  146. s.Timeout = &v
  147. return s
  148. }
  149. func (s *Config) SetConnectTimeout(v int) *Config {
  150. s.ConnectTimeout = &v
  151. return s
  152. }
  153. func (s *Config) SetProxy(v string) *Config {
  154. s.Proxy = &v
  155. return s
  156. }
  157. func (s *Config) SetType(v string) *Config {
  158. s.Type = &v
  159. return s
  160. }
  161. func (s *Config) SetOIDCTokenFilePath(v string) *Config {
  162. s.OIDCTokenFilePath = &v
  163. return s
  164. }
  165. func (s *Config) SetOIDCProviderArn(v string) *Config {
  166. s.OIDCProviderArn = &v
  167. return s
  168. }
  169. func (s *Config) SetURLCredential(v string) *Config {
  170. if v == "" {
  171. v = os.Getenv("ALIBABA_CLOUD_CREDENTIALS_URI")
  172. }
  173. s.Url = &v
  174. return s
  175. }
  176. func (s *Config) SetSTSEndpoint(v string) *Config {
  177. s.STSEndpoint = &v
  178. return s
  179. }
  180. func (s *Config) SetExternalId(v string) *Config {
  181. s.ExternalId = &v
  182. return s
  183. }
  184. // NewCredential return a credential according to the type in config.
  185. // if config is nil, the function will use default provider chain to get credentials.
  186. // please see README.md for detail.
  187. func NewCredential(config *Config) (credential Credential, err error) {
  188. if config == nil {
  189. provider := providers.NewDefaultCredentialsProvider()
  190. credential = FromCredentialsProvider("default", provider)
  191. return
  192. }
  193. switch tea.StringValue(config.Type) {
  194. case "credentials_uri":
  195. provider, err := providers.NewURLCredentialsProviderBuilder().
  196. WithUrl(tea.StringValue(config.Url)).
  197. WithHttpOptions(&providers.HttpOptions{
  198. Proxy: tea.StringValue(config.Proxy),
  199. ReadTimeout: tea.IntValue(config.Timeout),
  200. ConnectTimeout: tea.IntValue(config.ConnectTimeout),
  201. }).
  202. Build()
  203. if err != nil {
  204. return nil, err
  205. }
  206. credential = FromCredentialsProvider("credentials_uri", provider)
  207. case "oidc_role_arn":
  208. provider, err := providers.NewOIDCCredentialsProviderBuilder().
  209. WithRoleArn(tea.StringValue(config.RoleArn)).
  210. WithOIDCTokenFilePath(tea.StringValue(config.OIDCTokenFilePath)).
  211. WithOIDCProviderARN(tea.StringValue(config.OIDCProviderArn)).
  212. WithDurationSeconds(tea.IntValue(config.RoleSessionExpiration)).
  213. WithPolicy(tea.StringValue(config.Policy)).
  214. WithRoleSessionName(tea.StringValue(config.RoleSessionName)).
  215. WithSTSEndpoint(tea.StringValue(config.STSEndpoint)).
  216. WithHttpOptions(&providers.HttpOptions{
  217. Proxy: tea.StringValue(config.Proxy),
  218. ReadTimeout: tea.IntValue(config.Timeout),
  219. ConnectTimeout: tea.IntValue(config.ConnectTimeout),
  220. }).
  221. Build()
  222. if err != nil {
  223. return nil, err
  224. }
  225. credential = FromCredentialsProvider("oidc_role_arn", provider)
  226. case "access_key":
  227. provider, err := providers.NewStaticAKCredentialsProviderBuilder().
  228. WithAccessKeyId(tea.StringValue(config.AccessKeyId)).
  229. WithAccessKeySecret(tea.StringValue(config.AccessKeySecret)).
  230. Build()
  231. if err != nil {
  232. return nil, err
  233. }
  234. credential = FromCredentialsProvider("access_key", provider)
  235. case "sts":
  236. provider, err := providers.NewStaticSTSCredentialsProviderBuilder().
  237. WithAccessKeyId(tea.StringValue(config.AccessKeyId)).
  238. WithAccessKeySecret(tea.StringValue(config.AccessKeySecret)).
  239. WithSecurityToken(tea.StringValue(config.SecurityToken)).
  240. Build()
  241. if err != nil {
  242. return nil, err
  243. }
  244. credential = FromCredentialsProvider("sts", provider)
  245. case "ecs_ram_role":
  246. provider, err := providers.NewECSRAMRoleCredentialsProviderBuilder().
  247. WithRoleName(tea.StringValue(config.RoleName)).
  248. WithDisableIMDSv1(tea.BoolValue(config.DisableIMDSv1)).
  249. Build()
  250. if err != nil {
  251. return nil, err
  252. }
  253. credential = FromCredentialsProvider("ecs_ram_role", provider)
  254. case "ram_role_arn":
  255. var credentialsProvider providers.CredentialsProvider
  256. if config.SecurityToken != nil && *config.SecurityToken != "" {
  257. credentialsProvider, err = providers.NewStaticSTSCredentialsProviderBuilder().
  258. WithAccessKeyId(tea.StringValue(config.AccessKeyId)).
  259. WithAccessKeySecret(tea.StringValue(config.AccessKeySecret)).
  260. WithSecurityToken(tea.StringValue(config.SecurityToken)).
  261. Build()
  262. } else {
  263. credentialsProvider, err = providers.NewStaticAKCredentialsProviderBuilder().
  264. WithAccessKeyId(tea.StringValue(config.AccessKeyId)).
  265. WithAccessKeySecret(tea.StringValue(config.AccessKeySecret)).
  266. Build()
  267. }
  268. if err != nil {
  269. return nil, err
  270. }
  271. provider, err := providers.NewRAMRoleARNCredentialsProviderBuilder().
  272. WithCredentialsProvider(credentialsProvider).
  273. WithRoleArn(tea.StringValue(config.RoleArn)).
  274. WithRoleSessionName(tea.StringValue(config.RoleSessionName)).
  275. WithPolicy(tea.StringValue(config.Policy)).
  276. WithDurationSeconds(tea.IntValue(config.RoleSessionExpiration)).
  277. WithExternalId(tea.StringValue(config.ExternalId)).
  278. WithStsEndpoint(tea.StringValue(config.STSEndpoint)).
  279. WithHttpOptions(&providers.HttpOptions{
  280. Proxy: tea.StringValue(config.Proxy),
  281. ReadTimeout: tea.IntValue(config.Timeout),
  282. ConnectTimeout: tea.IntValue(config.ConnectTimeout),
  283. }).
  284. Build()
  285. if err != nil {
  286. return nil, err
  287. }
  288. credential = FromCredentialsProvider("ram_role_arn", provider)
  289. case "rsa_key_pair":
  290. err = checkRSAKeyPair(config)
  291. if err != nil {
  292. return
  293. }
  294. file, err1 := os.Open(tea.StringValue(config.PrivateKeyFile))
  295. if err1 != nil {
  296. err = fmt.Errorf("InvalidPath: Can not open PrivateKeyFile, err is %s", err1.Error())
  297. return
  298. }
  299. defer file.Close()
  300. var privateKey string
  301. scan := bufio.NewScanner(file)
  302. for scan.Scan() {
  303. if strings.HasPrefix(scan.Text(), "----") {
  304. continue
  305. }
  306. privateKey += scan.Text() + "\n"
  307. }
  308. runtime := &utils.Runtime{
  309. Host: tea.StringValue(config.Host),
  310. Proxy: tea.StringValue(config.Proxy),
  311. ReadTimeout: tea.IntValue(config.Timeout),
  312. ConnectTimeout: tea.IntValue(config.ConnectTimeout),
  313. STSEndpoint: tea.StringValue(config.STSEndpoint),
  314. }
  315. credential = newRsaKeyPairCredential(
  316. privateKey,
  317. tea.StringValue(config.PublicKeyId),
  318. tea.IntValue(config.SessionExpiration),
  319. runtime)
  320. case "bearer":
  321. if tea.StringValue(config.BearerToken) == "" {
  322. err = errors.New("BearerToken cannot be empty")
  323. return
  324. }
  325. credential = newBearerTokenCredential(tea.StringValue(config.BearerToken))
  326. default:
  327. err = errors.New("invalid type option, support: access_key, sts, bearer, ecs_ram_role, ram_role_arn, rsa_key_pair, oidc_role_arn, credentials_uri")
  328. return
  329. }
  330. return credential, nil
  331. }
  332. func checkRSAKeyPair(config *Config) (err error) {
  333. if tea.StringValue(config.PrivateKeyFile) == "" {
  334. err = errors.New("PrivateKeyFile cannot be empty")
  335. return
  336. }
  337. if tea.StringValue(config.PublicKeyId) == "" {
  338. err = errors.New("PublicKeyId cannot be empty")
  339. return
  340. }
  341. return
  342. }
  343. func doAction(request *request.CommonRequest, runtime *utils.Runtime) (content []byte, err error) {
  344. var urlEncoded string
  345. if request.BodyParams != nil {
  346. urlEncoded = utils.GetURLFormedMap(request.BodyParams)
  347. }
  348. httpRequest, err := http.NewRequest(request.Method, request.URL, strings.NewReader(urlEncoded))
  349. if err != nil {
  350. return
  351. }
  352. httpRequest.Proto = "HTTP/1.1"
  353. httpRequest.Host = request.Domain
  354. debuglog("> %s %s %s", httpRequest.Method, httpRequest.URL.RequestURI(), httpRequest.Proto)
  355. debuglog("> Host: %s", httpRequest.Host)
  356. for key, value := range request.Headers {
  357. if value != "" {
  358. debuglog("> %s: %s", key, value)
  359. httpRequest.Header[key] = []string{value}
  360. }
  361. }
  362. debuglog(">")
  363. httpClient := &http.Client{}
  364. httpClient.Timeout = time.Duration(runtime.ReadTimeout) * time.Second
  365. proxy := &url.URL{}
  366. if runtime.Proxy != "" {
  367. proxy, err = url.Parse(runtime.Proxy)
  368. if err != nil {
  369. return
  370. }
  371. }
  372. transport := &http.Transport{}
  373. if proxy != nil && runtime.Proxy != "" {
  374. transport.Proxy = http.ProxyURL(proxy)
  375. }
  376. transport.DialContext = utils.Timeout(time.Duration(runtime.ConnectTimeout) * time.Second)
  377. httpClient.Transport = transport
  378. httpResponse, err := hookDo(httpClient.Do)(httpRequest)
  379. if err != nil {
  380. return
  381. }
  382. debuglog("< %s %s", httpResponse.Proto, httpResponse.Status)
  383. for key, value := range httpResponse.Header {
  384. debuglog("< %s: %v", key, strings.Join(value, ""))
  385. }
  386. debuglog("<")
  387. resp := &response.CommonResponse{}
  388. err = hookParse(resp.ParseFromHTTPResponse(httpResponse))
  389. if err != nil {
  390. return
  391. }
  392. debuglog("%s", resp.GetHTTPContentString())
  393. if resp.GetHTTPStatus() != http.StatusOK {
  394. err = fmt.Errorf("httpStatus: %d, message = %s", resp.GetHTTPStatus(), resp.GetHTTPContentString())
  395. return
  396. }
  397. return resp.GetHTTPContentBytes(), nil
  398. }
  399. type credentialsProviderWrap struct {
  400. typeName string
  401. provider providers.CredentialsProvider
  402. }
  403. // Deprecated: use GetCredential() instead of
  404. func (cp *credentialsProviderWrap) GetAccessKeyId() (accessKeyId *string, err error) {
  405. cc, err := cp.provider.GetCredentials()
  406. if err != nil {
  407. return
  408. }
  409. accessKeyId = &cc.AccessKeyId
  410. return
  411. }
  412. // Deprecated: use GetCredential() instead of
  413. func (cp *credentialsProviderWrap) GetAccessKeySecret() (accessKeySecret *string, err error) {
  414. cc, err := cp.provider.GetCredentials()
  415. if err != nil {
  416. return
  417. }
  418. accessKeySecret = &cc.AccessKeySecret
  419. return
  420. }
  421. // Deprecated: use GetCredential() instead of
  422. func (cp *credentialsProviderWrap) GetSecurityToken() (securityToken *string, err error) {
  423. cc, err := cp.provider.GetCredentials()
  424. if err != nil {
  425. return
  426. }
  427. securityToken = &cc.SecurityToken
  428. return
  429. }
  430. // Deprecated: don't use it
  431. func (cp *credentialsProviderWrap) GetBearerToken() (bearerToken *string) {
  432. return tea.String("")
  433. }
  434. // Get credentials
  435. func (cp *credentialsProviderWrap) GetCredential() (cm *CredentialModel, err error) {
  436. c, err := cp.provider.GetCredentials()
  437. if err != nil {
  438. return
  439. }
  440. cm = &CredentialModel{
  441. AccessKeyId: &c.AccessKeyId,
  442. AccessKeySecret: &c.AccessKeySecret,
  443. SecurityToken: &c.SecurityToken,
  444. Type: &cp.typeName,
  445. ProviderName: &c.ProviderName,
  446. }
  447. return
  448. }
  449. func (cp *credentialsProviderWrap) GetType() *string {
  450. return &cp.typeName
  451. }
  452. func FromCredentialsProvider(typeName string, cp providers.CredentialsProvider) Credential {
  453. return &credentialsProviderWrap{
  454. typeName: typeName,
  455. provider: cp,
  456. }
  457. }