instance_metadata.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  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 get(url string) (status int, content string, err error) {
  19. resp, err := http.Get(url)
  20. if err != nil {
  21. return
  22. }
  23. defer resp.Body.Close()
  24. bodyBytes, err := ioutil.ReadAll(resp.Body)
  25. return resp.StatusCode, string(bodyBytes), err
  26. }
  27. func (p *InstanceMetadataProvider) GetRoleName() (roleName string, err error) {
  28. // Instances can have only one role name that never changes,
  29. // so attempt to populate it.
  30. // If this call is executed in an environment that doesn't support instance metadata,
  31. // it will time out after 30 seconds and return an err.
  32. status, roleName, err := get(securityCredURL)
  33. if err != nil {
  34. return
  35. }
  36. if status != 200 {
  37. err = fmt.Errorf("received %d getting role name: %s", status, roleName)
  38. return
  39. }
  40. if roleName == "" {
  41. err = errors.New("unable to retrieve role name, it may be unset")
  42. }
  43. return
  44. }
  45. func (p *InstanceMetadataProvider) Retrieve() (auth.Credential, error) {
  46. if p.RoleName == "" {
  47. roleName, err := p.GetRoleName()
  48. if err != nil {
  49. return nil, err
  50. }
  51. p.RoleName = roleName
  52. }
  53. status, content, err := get(securityCredURL + p.RoleName)
  54. if err != nil {
  55. return nil, err
  56. }
  57. if status != 200 {
  58. return nil, fmt.Errorf("received %d getting security credentials for %s", status, p.RoleName)
  59. }
  60. body := make(map[string]interface{})
  61. if err := json.Unmarshal([]byte(content), &body); err != nil {
  62. return nil, err
  63. }
  64. accessKeyID, err := extractString(body, "AccessKeyId")
  65. if err != nil {
  66. return nil, err
  67. }
  68. accessKeySecret, err := extractString(body, "AccessKeySecret")
  69. if err != nil {
  70. return nil, err
  71. }
  72. securityToken, err := extractString(body, "SecurityToken")
  73. if err != nil {
  74. return nil, err
  75. }
  76. return credentials.NewStsTokenCredential(accessKeyID, accessKeySecret, securityToken), nil
  77. }
  78. func extractString(m map[string]interface{}, key string) (string, error) {
  79. raw, ok := m[key]
  80. if !ok {
  81. return "", fmt.Errorf("%s not in map", key)
  82. }
  83. str, ok := raw.(string)
  84. if !ok {
  85. return "", fmt.Errorf("%s is not a string in map", key)
  86. }
  87. return str, nil
  88. }