securitygroup.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  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 qcloud
  15. import (
  16. "fmt"
  17. "strings"
  18. "time"
  19. "yunion.io/x/jsonutils"
  20. "yunion.io/x/pkg/errors"
  21. "yunion.io/x/pkg/util/netutils"
  22. "yunion.io/x/pkg/util/secrules"
  23. api "yunion.io/x/cloudmux/pkg/apis/compute"
  24. "yunion.io/x/cloudmux/pkg/cloudprovider"
  25. "yunion.io/x/cloudmux/pkg/multicloud"
  26. )
  27. type SSecurityGroup struct {
  28. multicloud.SSecurityGroup
  29. QcloudTags
  30. region *SRegion
  31. SecurityGroupId string // 安全组实例ID,例如:sg-ohuuioma。
  32. SecurityGroupName string // 安全组名称,可任意命名,但不得超过60个字符。
  33. SecurityGroupDesc string // 安全组备注,最多100个字符。
  34. ProjectId string // 项目id,默认0。可在qcloud控制台项目管理页面查询到。
  35. IsDefault bool // 是否是默认安全组,默认安全组不支持删除。
  36. CreatedTime time.Time // 安全组创建时间。
  37. SecurityGroupPolicySet SecurityGroupPolicySet
  38. }
  39. func (self *SRegion) GetSecurityGroups(ids []string, name string, offset int, limit int) ([]SSecurityGroup, int, error) {
  40. if limit > 100 || limit <= 0 {
  41. limit = 100
  42. }
  43. params := make(map[string]string)
  44. params["Limit"] = fmt.Sprintf("%d", limit)
  45. params["Offset"] = fmt.Sprintf("%d", offset)
  46. if len(name) > 0 {
  47. params["Filters.0.Name"] = "security-group-name"
  48. params["Filters.0.Values.0"] = name
  49. }
  50. for idx, id := range ids {
  51. params[fmt.Sprintf("SecurityGroupIds.%d", idx)] = id
  52. }
  53. resp, err := self.vpcRequest("DescribeSecurityGroups", params)
  54. if err != nil {
  55. return nil, 0, errors.Wrapf(err, "DescribeSecurityGroups")
  56. }
  57. secgrps := make([]SSecurityGroup, 0)
  58. err = resp.Unmarshal(&secgrps, "SecurityGroupSet")
  59. if err != nil {
  60. return nil, 0, errors.Wrapf(err, "resp.Unmarshal")
  61. }
  62. total, _ := resp.Float("TotalCount")
  63. return secgrps, int(total), nil
  64. }
  65. func (self *SSecurityGroup) GetVpcId() string {
  66. return ""
  67. }
  68. func (self *SSecurityGroup) GetId() string {
  69. return self.SecurityGroupId
  70. }
  71. func (self *SSecurityGroup) GetGlobalId() string {
  72. return self.SecurityGroupId
  73. }
  74. func (self *SSecurityGroup) GetDescription() string {
  75. return self.SecurityGroupDesc
  76. }
  77. func (self *SSecurityGroup) SetTags(tags map[string]string, replace bool) error {
  78. return self.region.SetResourceTags("cvm", "sg", []string{self.SecurityGroupId}, tags, replace)
  79. }
  80. func (self *SSecurityGroup) GetName() string {
  81. if len(self.SecurityGroupName) > 0 {
  82. return self.SecurityGroupName
  83. }
  84. return self.SecurityGroupId
  85. }
  86. type ReferredSecurityGroup struct {
  87. SecurityGroupId string
  88. ReferredSecurityGroupIds []string
  89. }
  90. func (self *SSecurityGroup) GetReferences() ([]cloudprovider.SecurityGroupReference, error) {
  91. references, err := self.region.DescribeSecurityGroupReferences(self.SecurityGroupId)
  92. if err != nil {
  93. return nil, errors.Wrapf(err, "DescribeSecurityGroupReferences")
  94. }
  95. ret := []cloudprovider.SecurityGroupReference{}
  96. for _, refer := range references {
  97. if refer.SecurityGroupId == self.SecurityGroupId {
  98. for _, id := range refer.ReferredSecurityGroupIds {
  99. ret = append(ret, cloudprovider.SecurityGroupReference{
  100. Id: id,
  101. })
  102. }
  103. }
  104. }
  105. return ret, nil
  106. }
  107. func (self *SRegion) DescribeSecurityGroupReferences(id string) ([]ReferredSecurityGroup, error) {
  108. params := map[string]string{
  109. "Region": self.Region,
  110. "SecurityGroupIds.0": id,
  111. }
  112. resp, err := self.vpcRequest("DescribeSecurityGroupReferences", params)
  113. if err != nil {
  114. return nil, errors.Wrapf(err, "DescribeSecurityGroupReferences")
  115. }
  116. ret := []ReferredSecurityGroup{}
  117. err = resp.Unmarshal(&ret, "ReferredSecurityGroupSet")
  118. if err != nil {
  119. return nil, errors.Wrapf(err, "resp.Unmarshal")
  120. }
  121. return ret, nil
  122. }
  123. func (self *SSecurityGroup) GetRules() ([]cloudprovider.ISecurityGroupRule, error) {
  124. rules, err := self.region.GetSecurityGroupRules(self.SecurityGroupId)
  125. if err != nil {
  126. return nil, errors.Wrapf(err, "GetSecurityGroupRules")
  127. }
  128. ret := []cloudprovider.ISecurityGroupRule{}
  129. for i := range rules {
  130. rules[i].secgroup = self
  131. ret = append(ret, &rules[i])
  132. }
  133. return ret, nil
  134. }
  135. func (self *SSecurityGroup) GetStatus() string {
  136. return api.SECGROUP_STATUS_READY
  137. }
  138. func (self *SSecurityGroup) Refresh() error {
  139. group, err := self.region.GetSecurityGroup(self.SecurityGroupId)
  140. if err != nil {
  141. return err
  142. }
  143. return jsonutils.Update(self, group)
  144. }
  145. func (self *SRegion) GetSecurityGroup(id string) (*SSecurityGroup, error) {
  146. groups, _, err := self.GetSecurityGroups([]string{id}, "", 0, 1)
  147. if err != nil {
  148. return nil, err
  149. }
  150. for i := range groups {
  151. if groups[i].SecurityGroupId == id {
  152. groups[i].region = self
  153. return &groups[i], nil
  154. }
  155. }
  156. return nil, errors.Wrapf(cloudprovider.ErrNotFound, "%s", id)
  157. }
  158. func (self *SRegion) DeleteSecurityGroup(secGroupId string) error {
  159. params := make(map[string]string)
  160. params["Region"] = self.Region
  161. params["SecurityGroupId"] = secGroupId
  162. _, err := self.vpcRequest("DeleteSecurityGroup", params)
  163. return err
  164. }
  165. type AddressTemplate struct {
  166. AddressSet []string
  167. AddressTemplateId string
  168. AddressTemplateName string
  169. CreatedTime time.Time
  170. }
  171. func (self *SRegion) AddressList(addressId, addressName string, offset, limit int) ([]AddressTemplate, int, error) {
  172. params := map[string]string{}
  173. filter := 0
  174. if len(addressId) > 0 {
  175. params[fmt.Sprintf("Filters.%d.Name", filter)] = "address-template-id"
  176. params[fmt.Sprintf("Filters.%d.Values.0", filter)] = addressId
  177. filter++
  178. }
  179. if len(addressName) > 0 {
  180. params[fmt.Sprintf("Filters.%d.Name", filter)] = "address-template-name"
  181. params[fmt.Sprintf("Filters.%d.Values.0", filter)] = addressName
  182. filter++
  183. }
  184. params["Offset"] = fmt.Sprintf("%d", offset)
  185. if limit == 0 {
  186. limit = 20
  187. }
  188. params["Limit"] = fmt.Sprintf("%d", limit)
  189. body, err := self.vpcRequest("DescribeAddressTemplates", params)
  190. if err != nil {
  191. return nil, 0, err
  192. }
  193. addressTemplates := []AddressTemplate{}
  194. err = body.Unmarshal(&addressTemplates, "AddressTemplateSet")
  195. if err != nil {
  196. return nil, 0, err
  197. }
  198. total, _ := body.Float("TotalCount")
  199. return addressTemplates, int(total), nil
  200. }
  201. type AddressTemplateGroup struct {
  202. AddressTemplateIdSet []string
  203. AddressTemplateGroupName string
  204. AddressTemplateGroupId string
  205. CreatedTime time.Time
  206. }
  207. func (self *SRegion) AddressGroupList(groupId, groupName string, offset, limit int) ([]AddressTemplateGroup, int, error) {
  208. params := map[string]string{}
  209. filter := 0
  210. if len(groupId) > 0 {
  211. params[fmt.Sprintf("Filters.%d.Name", filter)] = "address-template-group-id"
  212. params[fmt.Sprintf("Filters.%d.Values.0", filter)] = groupId
  213. filter++
  214. }
  215. if len(groupName) > 0 {
  216. params[fmt.Sprintf("Filters.%d.Name", filter)] = "address-template-group-name"
  217. params[fmt.Sprintf("Filters.%d.Values.0", filter)] = groupName
  218. filter++
  219. }
  220. params["Offset"] = fmt.Sprintf("%d", offset)
  221. if limit == 0 {
  222. limit = 20
  223. }
  224. params["Limit"] = fmt.Sprintf("%d", limit)
  225. body, err := self.vpcRequest("DescribeAddressTemplateGroups", params)
  226. if err != nil {
  227. return nil, 0, err
  228. }
  229. addressTemplateGroups := []AddressTemplateGroup{}
  230. err = body.Unmarshal(&addressTemplateGroups, "AddressTemplateGroupSet")
  231. if err != nil {
  232. return nil, 0, err
  233. }
  234. total, _ := body.Float("TotalCount")
  235. return addressTemplateGroups, int(total), nil
  236. }
  237. func (self *SRegion) CreateSecurityGroup(opts *cloudprovider.SecurityGroupCreateInput) (*SSecurityGroup, error) {
  238. params := make(map[string]string)
  239. params["Region"] = self.Region
  240. params["GroupName"] = opts.Name
  241. params["GroupDescription"] = opts.Desc
  242. if len(opts.ProjectId) > 0 {
  243. params["ProjectId"] = opts.ProjectId
  244. }
  245. idx := 0
  246. for k, v := range opts.Tags {
  247. params[fmt.Sprintf("Tags.%d.Key", idx)] = k
  248. params[fmt.Sprintf("Tags.%d.Value", idx)] = v
  249. idx++
  250. }
  251. secgroup := SSecurityGroup{region: self}
  252. body, err := self.vpcRequest("CreateSecurityGroup", params)
  253. if err != nil {
  254. return nil, errors.Wrap(err, "CreateSecurityGroup")
  255. }
  256. err = body.Unmarshal(&secgroup, "SecurityGroup")
  257. if err != nil {
  258. return nil, errors.Wrap(err, "body.Unmarshal")
  259. }
  260. return &secgroup, nil
  261. }
  262. func (self *SSecurityGroup) CreateRule(opts *cloudprovider.SecurityGroupRuleCreateOptions) (cloudprovider.ISecurityGroupRule, error) {
  263. rules, err := self.region.GetSecurityGroupRules(self.SecurityGroupId)
  264. if err != nil {
  265. return nil, errors.Wrapf(err, "GetSecurityGroupRules")
  266. }
  267. maxPriority := 0
  268. for i := range rules {
  269. if rules[i].GetDirection() == opts.Direction && rules[i].PolicyIndex > maxPriority {
  270. maxPriority = rules[i].PolicyIndex
  271. }
  272. }
  273. if opts.Priority > maxPriority {
  274. opts.Priority = maxPriority
  275. }
  276. err = self.region.CreateSecurityGroupRule(self.SecurityGroupId, opts)
  277. if err != nil {
  278. return nil, errors.Wrapf(err, "CreateSecurityGroupRule")
  279. }
  280. rules, err = self.region.GetSecurityGroupRules(self.SecurityGroupId)
  281. if err != nil {
  282. return nil, errors.Wrapf(err, "GetSecurityGroupRules")
  283. }
  284. for i := range rules {
  285. if rules[i].Direction == opts.Direction && rules[i].GetPriority() == opts.Priority {
  286. rules[i].secgroup = self
  287. return &rules[i], nil
  288. }
  289. }
  290. return nil, errors.Wrapf(cloudprovider.ErrNotFound, "after created")
  291. }
  292. func (self *SRegion) CreateSecurityGroupRule(groupId string, opts *cloudprovider.SecurityGroupRuleCreateOptions) error {
  293. prefix := "SecurityGroupPolicySet.Egress.0."
  294. if opts.Direction == secrules.DIR_IN {
  295. prefix = "SecurityGroupPolicySet.Ingress.0."
  296. }
  297. if opts.Protocol == secrules.PROTO_ANY {
  298. opts.Protocol = "all"
  299. opts.Ports = "all"
  300. }
  301. if len(opts.Ports) == 0 {
  302. opts.Ports = "all"
  303. }
  304. action := "accept"
  305. if opts.Action == secrules.SecurityRuleDeny {
  306. action = "drop"
  307. }
  308. if len(opts.CIDR) == 0 {
  309. opts.CIDR = "0.0.0.0/0"
  310. }
  311. params := map[string]string{
  312. "SecurityGroupId": groupId,
  313. prefix + "PolicyIndex": fmt.Sprintf("%d", opts.Priority),
  314. prefix + "Protocol": strings.ToUpper(opts.Protocol),
  315. prefix + "PolicyDescription": opts.Desc,
  316. prefix + "Action": action,
  317. prefix + "Port": opts.Ports,
  318. prefix + "CidrBlock": opts.CIDR,
  319. }
  320. if _, err := netutils.NewIPV6Prefix(opts.CIDR); err == nil {
  321. params[prefix+"Ipv6CidrBlock"] = opts.CIDR
  322. delete(params, prefix+"CidrBlock")
  323. }
  324. _, err := self.vpcRequest("CreateSecurityGroupPolicies", params)
  325. if err != nil {
  326. return errors.Wrapf(err, "CreateSecurityGroupPolicies")
  327. }
  328. return nil
  329. }
  330. func (self *SSecurityGroup) GetProjectId() string {
  331. return self.ProjectId
  332. }
  333. func (self *SSecurityGroup) Delete() error {
  334. return self.region.DeleteSecurityGroup(self.SecurityGroupId)
  335. }