keypair.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package aliyun
  15. import (
  16. "encoding/json"
  17. "fmt"
  18. "strconv"
  19. "strings"
  20. "time"
  21. "github.com/aokoli/goutils"
  22. "golang.org/x/crypto/ssh"
  23. "yunion.io/x/log"
  24. )
  25. type SKeypair struct {
  26. KeyPairFingerPrint string
  27. KeyPairName string
  28. }
  29. func (self *SRegion) GetKeypairs(finger string, name string, offset int, limit int) ([]SKeypair, int, error) {
  30. if limit > 50 || limit <= 0 {
  31. limit = 50
  32. }
  33. params := make(map[string]string)
  34. params["RegionId"] = self.RegionId
  35. params["PageSize"] = fmt.Sprintf("%d", limit)
  36. params["PageNumber"] = fmt.Sprintf("%d", (offset/limit)+1)
  37. if len(finger) > 0 {
  38. params["KeyPairFingerPrint"] = finger
  39. }
  40. if len(name) > 0 {
  41. params["KeyPairName"] = name
  42. }
  43. body, err := self.ecsRequest("DescribeKeyPairs", params)
  44. if err != nil {
  45. log.Errorf("GetKeypairs fail %s", err)
  46. return nil, 0, err
  47. }
  48. keypairs := make([]SKeypair, 0)
  49. err = body.Unmarshal(&keypairs, "KeyPairs", "KeyPair")
  50. if err != nil {
  51. log.Errorf("Unmarshal keypair fail %s", err)
  52. return nil, 0, err
  53. }
  54. total, _ := body.Int("TotalCount")
  55. return keypairs, int(total), nil
  56. }
  57. func (self *SRegion) ImportKeypair(name string, pubKey string) (*SKeypair, error) {
  58. params := make(map[string]string)
  59. params["RegionId"] = self.RegionId
  60. params["PublicKeyBody"] = pubKey
  61. params["KeyPairName"] = name
  62. body, err := self.ecsRequest("ImportKeyPair", params)
  63. if err != nil {
  64. log.Errorf("ImportKeypair fail %s", err)
  65. return nil, err
  66. }
  67. log.Debugf("%s", body)
  68. keypair := SKeypair{}
  69. err = body.Unmarshal(&keypair)
  70. if err != nil {
  71. log.Errorf("Unmarshall keypair fail %s", err)
  72. return nil, err
  73. }
  74. return &keypair, nil
  75. }
  76. func (self *SRegion) AttachKeypair(instanceId string, name string) error {
  77. params := make(map[string]string)
  78. params["RegionId"] = self.RegionId
  79. params["KeyPairName"] = name
  80. instances, _ := json.Marshal(&[...]string{instanceId})
  81. params["InstanceIds"] = string(instances)
  82. _, err := self.ecsRequest("AttachKeyPair", params)
  83. if err != nil {
  84. log.Errorf("AttachKeyPair fail %s", err)
  85. return err
  86. }
  87. return nil
  88. }
  89. func (self *SRegion) DetachKeyPair(instanceId string, name string) error {
  90. params := make(map[string]string)
  91. params["RegionId"] = self.RegionId
  92. params["KeyPairName"] = name
  93. instances, _ := json.Marshal(&[...]string{instanceId})
  94. params["InstanceIds"] = string(instances)
  95. _, err := self.ecsRequest("DetachKeyPair", params)
  96. if err != nil {
  97. log.Errorf("DetachKeyPair fail %s", err)
  98. return err
  99. }
  100. return nil
  101. }
  102. func (self *SRegion) lookUpAliyunKeypair(publicKey string) (string, error) {
  103. pk, _, _, _, err := ssh.ParseAuthorizedKey([]byte(publicKey))
  104. if err != nil {
  105. return "", fmt.Errorf("publicKey error %s", err)
  106. }
  107. fingerprint := strings.Replace(ssh.FingerprintLegacyMD5(pk), ":", "", -1)
  108. ks, total, err := self.GetKeypairs(fingerprint, "*", 0, 1)
  109. if total < 1 {
  110. return "", fmt.Errorf("keypair not found %s", err)
  111. } else {
  112. return ks[0].KeyPairName, nil
  113. }
  114. }
  115. func (self *SRegion) importAliyunKeypair(publicKey string) (string, error) {
  116. prefix, e := goutils.RandomAlphabetic(6)
  117. if e != nil {
  118. return "", fmt.Errorf("publicKey error %s", e)
  119. }
  120. name := prefix + strconv.FormatInt(time.Now().Unix(), 10)
  121. if k, e := self.ImportKeypair(name, publicKey); e != nil {
  122. return "", fmt.Errorf("keypair import error %s", e)
  123. } else {
  124. return k.KeyPairName, nil
  125. }
  126. }
  127. func (self *SRegion) syncKeypair(publicKey string) (string, error) {
  128. name, e := self.lookUpAliyunKeypair(publicKey)
  129. if e == nil {
  130. return name, nil
  131. }
  132. return self.importAliyunKeypair(publicKey)
  133. }