instance_credentials.go 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. package provider
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "io/ioutil"
  7. "net/http"
  8. "os"
  9. "time"
  10. "github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth"
  11. "github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials"
  12. )
  13. var securityCredURL = "http://100.100.100.200/latest/meta-data/ram/security-credentials/"
  14. type InstanceCredentialsProvider struct{}
  15. var ProviderInstance = new(InstanceCredentialsProvider)
  16. var HookGet = func(fn func(string) (int, []byte, error)) func(string) (int, []byte, error) {
  17. return fn
  18. }
  19. func NewInstanceCredentialsProvider() Provider {
  20. return &InstanceCredentialsProvider{}
  21. }
  22. func (p *InstanceCredentialsProvider) Resolve() (auth.Credential, error) {
  23. roleName, ok := os.LookupEnv(ENVEcsMetadata)
  24. if !ok {
  25. return nil, nil
  26. }
  27. if roleName == "" {
  28. return nil, errors.New("Environmental variable 'ALIBABA_CLOUD_ECS_METADATA' are empty")
  29. }
  30. status, content, err := HookGet(get)(securityCredURL + roleName)
  31. if err != nil {
  32. return nil, err
  33. }
  34. if status != 200 {
  35. if status == 404 {
  36. return nil, fmt.Errorf("The role was not found in the instance")
  37. }
  38. return nil, fmt.Errorf("Received %d when getting security credentials for %s", status, roleName)
  39. }
  40. body := make(map[string]interface{})
  41. if err := json.Unmarshal(content, &body); err != nil {
  42. return nil, err
  43. }
  44. accessKeyID, err := extractString(body, "AccessKeyId")
  45. if err != nil {
  46. return nil, err
  47. }
  48. accessKeySecret, err := extractString(body, "AccessKeySecret")
  49. if err != nil {
  50. return nil, err
  51. }
  52. securityToken, err := extractString(body, "SecurityToken")
  53. if err != nil {
  54. return nil, err
  55. }
  56. return credentials.NewStsTokenCredential(accessKeyID, accessKeySecret, securityToken), nil
  57. }
  58. func get(url string) (status int, content []byte, err error) {
  59. httpClient := http.DefaultClient
  60. httpClient.Timeout = time.Second * 1
  61. resp, err := httpClient.Get(url)
  62. if err != nil {
  63. return
  64. }
  65. defer resp.Body.Close()
  66. content, err = ioutil.ReadAll(resp.Body)
  67. return resp.StatusCode, content, err
  68. }
  69. func extractString(m map[string]interface{}, key string) (string, error) {
  70. raw, ok := m[key]
  71. if !ok {
  72. return "", fmt.Errorf("%s not in map", key)
  73. }
  74. str, ok := raw.(string)
  75. if !ok {
  76. return "", fmt.Errorf("%s is not a string in map", key)
  77. }
  78. return str, nil
  79. }