profile_credentials.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. package provider
  2. import (
  3. "bufio"
  4. "errors"
  5. "os"
  6. "runtime"
  7. "strings"
  8. "github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth"
  9. "github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials"
  10. ini "gopkg.in/ini.v1"
  11. )
  12. type ProfileProvider struct {
  13. Profile string
  14. }
  15. var ProviderProfile = NewProfileProvider()
  16. // NewProfileProvider receive zero or more parameters,
  17. // when length of name is 0, the value of field Profile will be "default",
  18. // and when there are multiple inputs, the function will take the
  19. // first one and discard the other values.
  20. func NewProfileProvider(name ...string) Provider {
  21. p := new(ProfileProvider)
  22. if len(name) == 0 {
  23. p.Profile = "default"
  24. } else {
  25. p.Profile = name[0]
  26. }
  27. return p
  28. }
  29. // Resolve implements the Provider interface
  30. // when credential type is rsa_key_pair, the content of private_key file
  31. // must be able to be parsed directly into the required string
  32. // that NewRsaKeyPairCredential function needed
  33. func (p *ProfileProvider) Resolve() (auth.Credential, error) {
  34. path, ok := os.LookupEnv(ENVCredentialFile)
  35. if !ok {
  36. var err error
  37. path, err = checkDefaultPath()
  38. if err != nil {
  39. return nil, err
  40. }
  41. if path == "" {
  42. return nil, nil
  43. }
  44. } else if path == "" {
  45. return nil, errors.New("Environment variable '" + ENVCredentialFile + "' cannot be empty")
  46. }
  47. ini, err := ini.Load(path)
  48. if err != nil {
  49. return nil, errors.New("ERROR: Can not open file" + err.Error())
  50. }
  51. section, err := ini.GetSection(p.Profile)
  52. if err != nil {
  53. return nil, errors.New("ERROR: Can not load section" + err.Error())
  54. }
  55. value, err := section.GetKey("type")
  56. if err != nil {
  57. return nil, errors.New("ERROR: Can not find credential type" + err.Error())
  58. }
  59. switch value.String() {
  60. case "access_key":
  61. value1, err1 := section.GetKey("access_key_id")
  62. value2, err2 := section.GetKey("access_key_secret")
  63. if err1 != nil || err2 != nil {
  64. return nil, errors.New("ERROR: Failed to get value")
  65. }
  66. if value1.String() == "" || value2.String() == "" {
  67. return nil, errors.New("ERROR: Value can't be empty")
  68. }
  69. return credentials.NewAccessKeyCredential(value1.String(), value2.String()), nil
  70. case "ecs_ram_role":
  71. value1, err1 := section.GetKey("role_name")
  72. if err1 != nil {
  73. return nil, errors.New("ERROR: Failed to get value")
  74. }
  75. if value1.String() == "" {
  76. return nil, errors.New("ERROR: Value can't be empty")
  77. }
  78. return credentials.NewEcsRamRoleCredential(value1.String()), nil
  79. case "ram_role_arn":
  80. value1, err1 := section.GetKey("access_key_id")
  81. value2, err2 := section.GetKey("access_key_secret")
  82. value3, err3 := section.GetKey("role_arn")
  83. value4, err4 := section.GetKey("role_session_name")
  84. if err1 != nil || err2 != nil || err3 != nil || err4 != nil {
  85. return nil, errors.New("ERROR: Failed to get value")
  86. }
  87. if value1.String() == "" || value2.String() == "" || value3.String() == "" || value4.String() == "" {
  88. return nil, errors.New("ERROR: Value can't be empty")
  89. }
  90. return credentials.NewRamRoleArnCredential(value1.String(), value2.String(), value3.String(), value4.String(), 3600), nil
  91. case "rsa_key_pair":
  92. value1, err1 := section.GetKey("public_key_id")
  93. value2, err2 := section.GetKey("private_key_file")
  94. if err1 != nil || err2 != nil {
  95. return nil, errors.New("ERROR: Failed to get value")
  96. }
  97. if value1.String() == "" || value2.String() == "" {
  98. return nil, errors.New("ERROR: Value can't be empty")
  99. }
  100. file, err := os.Open(value2.String())
  101. if err != nil {
  102. return nil, errors.New("ERROR: Can not get private_key")
  103. }
  104. defer file.Close()
  105. var privateKey string
  106. scan := bufio.NewScanner(file)
  107. var data string
  108. for scan.Scan() {
  109. if strings.HasPrefix(scan.Text(), "----") {
  110. continue
  111. }
  112. data += scan.Text() + "\n"
  113. }
  114. return credentials.NewRsaKeyPairCredential(privateKey, value1.String(), 3600), nil
  115. default:
  116. return nil, errors.New("ERROR: Failed to get credential")
  117. }
  118. }
  119. // GetHomePath return home directory according to the system.
  120. // if the environmental virables does not exist, will return empty
  121. func GetHomePath() string {
  122. if runtime.GOOS == "windows" {
  123. path, ok := os.LookupEnv("USERPROFILE")
  124. if !ok {
  125. return ""
  126. }
  127. return path
  128. }
  129. path, ok := os.LookupEnv("HOME")
  130. if !ok {
  131. return ""
  132. }
  133. return path
  134. }
  135. func checkDefaultPath() (path string, err error) {
  136. path = GetHomePath()
  137. if path == "" {
  138. return "", errors.New("The default credential file path is invalid")
  139. }
  140. path = strings.Replace("~/.alibabacloud/credentials", "~", path, 1)
  141. _, err = os.Stat(path)
  142. if err != nil {
  143. return "", nil
  144. }
  145. return path, nil
  146. }