instance_metadata.go 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. package providers
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "io/ioutil"
  7. "net/http"
  8. "github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth"
  9. "github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials"
  10. )
  11. var securityCredURL = "http://100.100.100.200/latest/meta-data/ram/security-credentials/"
  12. func NewInstanceMetadataProvider() Provider {
  13. return &InstanceMetadataProvider{}
  14. }
  15. type InstanceMetadataProvider struct {
  16. RoleName string
  17. }
  18. func (p *InstanceMetadataProvider) Retrieve() (auth.Credential, error) {
  19. if p.RoleName == "" {
  20. // Instances can have only one role name that never changes,
  21. // so attempt to populate it.
  22. // If this call is executed in an environment that doesn't support instance metadata,
  23. // it will time out after 30 seconds and return an err.
  24. resp, err := http.Get(securityCredURL)
  25. if err != nil {
  26. return nil, err
  27. }
  28. defer resp.Body.Close()
  29. bodyBytes, _ := ioutil.ReadAll(resp.Body)
  30. if resp.StatusCode != 200 {
  31. return nil, fmt.Errorf("received %d getting role name: %s", resp.StatusCode, bodyBytes)
  32. }
  33. roleName := string(bodyBytes)
  34. if roleName == "" {
  35. return nil, errors.New("unable to retrieve role name, it may be unset")
  36. }
  37. p.RoleName = roleName
  38. }
  39. resp, err := http.Get(securityCredURL + p.RoleName)
  40. if err != nil {
  41. return nil, err
  42. }
  43. defer resp.Body.Close()
  44. if resp.StatusCode != 200 {
  45. return nil, fmt.Errorf("received %d getting security credentials for %s", resp.StatusCode, p.RoleName)
  46. }
  47. body := make(map[string]interface{})
  48. if err := json.NewDecoder(resp.Body).Decode(&body); err != nil {
  49. return nil, err
  50. }
  51. accessKeyID, err := extractString(body, "AccessKeyId")
  52. if err != nil {
  53. return nil, err
  54. }
  55. accessKeySecret, err := extractString(body, "AccessKeySecret")
  56. if err != nil {
  57. return nil, err
  58. }
  59. securityToken, err := extractString(body, "SecurityToken")
  60. if err != nil {
  61. return nil, err
  62. }
  63. return credentials.NewStsTokenCredential(accessKeyID, accessKeySecret, securityToken), nil
  64. }
  65. func extractString(m map[string]interface{}, key string) (string, error) {
  66. raw, ok := m[key]
  67. if !ok {
  68. return "", fmt.Errorf("%s not in %+v", key, m)
  69. }
  70. str, ok := raw.(string)
  71. if !ok {
  72. return "", fmt.Errorf("%s is not a string in %+v", key, m)
  73. }
  74. return str, nil
  75. }