securitygroup.go 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  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 google
  15. import (
  16. "fmt"
  17. "regexp"
  18. "strings"
  19. "time"
  20. "yunion.io/x/jsonutils"
  21. "yunion.io/x/pkg/errors"
  22. "yunion.io/x/pkg/util/pinyinutils"
  23. "yunion.io/x/pkg/util/secrules"
  24. api "yunion.io/x/cloudmux/pkg/apis/compute"
  25. "yunion.io/x/cloudmux/pkg/cloudprovider"
  26. "yunion.io/x/cloudmux/pkg/multicloud"
  27. )
  28. type SSecurityGroup struct {
  29. multicloud.SSecurityGroup
  30. GoogleTags
  31. gvpc *SGlobalNetwork
  32. Tag string
  33. Rules []SFirewall
  34. }
  35. func (self *SGoogleClient) GetFirewalls(network string, maxResults int, pageToken string) ([]SFirewall, error) {
  36. firewalls := []SFirewall{}
  37. params := map[string]string{"filter": "disabled = false"}
  38. resource := "global/firewalls"
  39. if len(network) > 0 {
  40. params["filter"] = fmt.Sprintf(`(disabled = false) AND (network="%s")`, network)
  41. }
  42. return firewalls, self._ecsListAll("GET", resource, params, &firewalls)
  43. }
  44. func (self *SGoogleClient) GetFirewall(id string) (*SFirewall, error) {
  45. firewall := &SFirewall{}
  46. return firewall, self.ecsGet("global/firewalls", id, firewall)
  47. }
  48. func (secgroup *SSecurityGroup) GetId() string {
  49. return secgroup.Tag
  50. }
  51. func (secgroup *SSecurityGroup) GetGlobalId() string {
  52. return secgroup.Tag
  53. }
  54. func (secgroup *SSecurityGroup) GetDescription() string {
  55. return ""
  56. }
  57. func (self *SSecurityGroup) GetTags() (map[string]string, error) {
  58. return nil, cloudprovider.ErrNotSupported
  59. }
  60. func (secgroup *SSecurityGroup) GetName() string {
  61. return secgroup.Tag
  62. }
  63. func (secgroup *SSecurityGroup) GetStatus() string {
  64. return api.SECGROUP_STATUS_READY
  65. }
  66. func (secgroup *SSecurityGroup) Refresh() error {
  67. rules, err := secgroup.gvpc.client.GetFirewalls(secgroup.gvpc.SelfLink, 0, "")
  68. if err != nil {
  69. return err
  70. }
  71. secgroup.Rules = []SFirewall{}
  72. for i := range rules {
  73. if len(rules[i].TargetTags) > 0 && rules[i].TargetTags[0] == secgroup.Tag {
  74. secgroup.Rules = append(secgroup.Rules, rules[i])
  75. }
  76. }
  77. if len(secgroup.Rules) == 0 {
  78. return cloudprovider.ErrNotFound
  79. }
  80. return nil
  81. }
  82. func (self *SSecurityGroup) Delete() error {
  83. for _, rule := range self.Rules {
  84. err := self.gvpc.client.ecsDelete(rule.SelfLink, nil)
  85. if err != nil {
  86. return errors.Wrapf(err, "delete")
  87. }
  88. }
  89. return nil
  90. }
  91. func (secgroup *SSecurityGroup) GetProjectId() string {
  92. return ""
  93. }
  94. func (secgroup *SSecurityGroup) GetVpcId() string {
  95. return secgroup.gvpc.GetGlobalId()
  96. }
  97. func (self *SSecurityGroup) GetRules() ([]cloudprovider.ISecurityGroupRule, error) {
  98. ret := []cloudprovider.ISecurityGroupRule{}
  99. for i := range self.Rules {
  100. self.Rules[i].secgroup = self
  101. ret = append(ret, &self.Rules[i])
  102. }
  103. return ret, nil
  104. }
  105. func (self *SGoogleClient) CreateSecurityGroupRule(globalnetworkId, tag string, opts *cloudprovider.SecurityGroupRuleCreateOptions) (*SFirewall, error) {
  106. name := fmt.Sprintf("%s-%d-auto-%d", opts.String(), opts.Priority, time.Now().Unix())
  107. body := map[string]interface{}{
  108. "name": normalizeString(name),
  109. "description": opts.Desc,
  110. "priority": opts.Priority,
  111. "network": globalnetworkId,
  112. "direction": "INGRESS",
  113. "targetTags": []string{strings.ToLower(tag)},
  114. }
  115. if len(opts.CIDR) == 0 {
  116. opts.CIDR = "0.0.0.0/0"
  117. }
  118. if opts.Direction == secrules.DIR_OUT {
  119. body["direction"] = "EGRESS"
  120. body["destinationRanges"] = []string{opts.CIDR}
  121. } else {
  122. body["sourceRanges"] = []string{opts.CIDR}
  123. }
  124. protocol := strings.ToLower(opts.Protocol)
  125. if protocol == secrules.PROTO_ANY {
  126. protocol = "all"
  127. }
  128. actionInfo := []struct {
  129. IPProtocol string
  130. Ports []string
  131. }{
  132. {
  133. IPProtocol: protocol,
  134. },
  135. }
  136. if len(opts.Ports) > 0 {
  137. actionInfo[0].Ports = []string{opts.Ports}
  138. }
  139. if opts.Action == secrules.SecurityRuleDeny {
  140. body["denied"] = actionInfo
  141. } else {
  142. body["allowed"] = actionInfo
  143. }
  144. firwall := &SFirewall{}
  145. err := self.Insert("global/firewalls", jsonutils.Marshal(body), firwall)
  146. if err != nil {
  147. return nil, errors.Wrap(err, "region.Insert")
  148. }
  149. return firwall, nil
  150. }
  151. func (self *SSecurityGroup) CreateRule(opts *cloudprovider.SecurityGroupRuleCreateOptions) (cloudprovider.ISecurityGroupRule, error) {
  152. rule, err := self.gvpc.client.CreateSecurityGroupRule(self.gvpc.SelfLink, self.Tag, opts)
  153. if err != nil {
  154. return nil, err
  155. }
  156. rule.secgroup = self
  157. return rule, nil
  158. }
  159. func normalizeString(input string) string {
  160. // 1. 转换为小写
  161. lowerStr := strings.ToLower(input)
  162. lowerStr = strings.Replace(lowerStr, "_", "-", -1)
  163. lowerStr = pinyinutils.Text2Pinyin(lowerStr)
  164. // 2. 移除所有不符合要求的字符(只保留a-z、0-9和-)
  165. reg := regexp.MustCompile(`[^a-z0-9-]`)
  166. cleaned := reg.ReplaceAllString(lowerStr, "")
  167. // 3. 处理开头:如果不以字母开头,添加一个默认字母a
  168. if len(cleaned) == 0 || !regexp.MustCompile(`^[a-z]`).MatchString(cleaned) {
  169. cleaned = "a" + cleaned
  170. }
  171. // 4. 处理结尾:如果以连字符结尾,移除
  172. cleaned = regexp.MustCompile(`-$`).ReplaceAllString(cleaned, "")
  173. // 5. 限制长度为63个字符(域名标签的最大长度)
  174. if len(cleaned) > 63 {
  175. cleaned = cleaned[:63]
  176. // 确保截断后不以连字符结尾
  177. cleaned = regexp.MustCompile(`-$`).ReplaceAllString(cleaned, "")
  178. // 如果截断后为空,添加一个数字1
  179. if len(cleaned) == 0 {
  180. cleaned = "1"
  181. }
  182. }
  183. return cleaned
  184. }
  185. func (self *SGlobalNetwork) CreateISecurityGroup(opts *cloudprovider.SecurityGroupCreateInput) (cloudprovider.ICloudSecurityGroup, error) {
  186. tag := normalizeString(opts.Name)
  187. secgroup := &SSecurityGroup{gvpc: self, Tag: tag}
  188. groups, err := self.GetISecurityGroups()
  189. if err != nil {
  190. return nil, err
  191. }
  192. for i := range groups {
  193. if groups[i].GetGlobalId() == secgroup.GetGlobalId() {
  194. return nil, errors.Wrapf(cloudprovider.ErrDuplicateId, "%s", secgroup.GetGlobalId())
  195. }
  196. }
  197. rule, err := secgroup.gvpc.client.CreateSecurityGroupRule(secgroup.gvpc.SelfLink, secgroup.Tag, &cloudprovider.SecurityGroupRuleCreateOptions{
  198. Desc: "default allow out",
  199. Priority: 65535,
  200. Protocol: secrules.PROTO_ANY,
  201. Direction: secrules.DIR_OUT,
  202. CIDR: "0.0.0.0/0",
  203. Action: secrules.SecurityRuleAllow,
  204. })
  205. if err != nil {
  206. return nil, errors.Wrapf(err, "CreateSecurityGroupRule")
  207. }
  208. secgroup.Rules = []SFirewall{*rule}
  209. return secgroup, nil
  210. }