securitygroup.go 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. // Copyright 2023 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 volcengine
  15. import (
  16. "fmt"
  17. "strings"
  18. "time"
  19. "yunion.io/x/cloudmux/pkg/cloudprovider"
  20. "yunion.io/x/cloudmux/pkg/multicloud"
  21. "yunion.io/x/jsonutils"
  22. "yunion.io/x/log"
  23. "yunion.io/x/pkg/errors"
  24. "yunion.io/x/pkg/util/secrules"
  25. "yunion.io/x/pkg/utils"
  26. )
  27. type SSecurityGroup struct {
  28. multicloud.SSecurityGroup
  29. VolcEngineTags
  30. region *SRegion
  31. Description string
  32. SecurityGroupId string
  33. SecurityGroupName string
  34. VpcId string
  35. CreationTime time.Time
  36. UpdateTime time.Time
  37. Type string
  38. ProjectName string
  39. ServiceManaged bool
  40. Status string
  41. }
  42. func (region *SRegion) CreateSecurityGroup(opts *cloudprovider.SecurityGroupCreateInput) (string, error) {
  43. params := make(map[string]string)
  44. params["VpcId"] = opts.VpcId
  45. params["SecurityGroupName"] = opts.Name
  46. if len(opts.ProjectId) > 0 {
  47. params["ProjectName"] = opts.ProjectId
  48. }
  49. if len(opts.Desc) > 0 {
  50. params["Description"] = opts.Desc
  51. }
  52. params["ClientToken"] = utils.GenRequestId(20)
  53. idx := 1
  54. for k, v := range opts.Tags {
  55. params[fmt.Sprintf("Tags.%d.Key", idx)] = k
  56. params[fmt.Sprintf("Tags.%d.Value", idx)] = v
  57. idx++
  58. }
  59. body, err := region.vpcRequest("CreateSecurityGroup", params)
  60. if err != nil {
  61. return "", errors.Wrap(err, "CreateSecurityGroup")
  62. }
  63. return body.GetString("SecurityGroupId")
  64. }
  65. func (region *SRegion) GetSecurityGroup(secGroupId string) (*SSecurityGroup, error) {
  66. secgroups, _, err := region.GetSecurityGroups("", "", []string{secGroupId}, 1, 1)
  67. if err != nil {
  68. return nil, err
  69. }
  70. for i := range secgroups {
  71. secgroups[i].region = region
  72. if secgroups[i].SecurityGroupId == secGroupId {
  73. return &secgroups[i], nil
  74. }
  75. }
  76. return nil, errors.Wrapf(cloudprovider.ErrNotFound, "%s", secGroupId)
  77. }
  78. func (region *SRegion) GetSecurityGroupRules(secGroupId string) ([]SSecurityGroupRule, error) {
  79. params := make(map[string]string)
  80. params["SecurityGroupId"] = secGroupId
  81. body, err := region.vpcRequest("DescribeSecurityGroupAttributes", params)
  82. if err != nil {
  83. return nil, err
  84. }
  85. ret := []SSecurityGroupRule{}
  86. err = body.Unmarshal(&ret, "Permissions")
  87. if err != nil {
  88. return nil, errors.Wrapf(err, "Unmarshal security group details fail")
  89. }
  90. return ret, nil
  91. }
  92. func (self *SSecurityGroup) CreateRule(opts *cloudprovider.SecurityGroupRuleCreateOptions) (cloudprovider.ISecurityGroupRule, error) {
  93. err := self.region.CreateSecurityGroupRule(self.SecurityGroupId, opts)
  94. if err != nil {
  95. return nil, err
  96. }
  97. rules, err := self.region.GetSecurityGroupRules(self.SecurityGroupId)
  98. if err != nil {
  99. return nil, err
  100. }
  101. for i := range rules {
  102. rules[i].secgroup = self
  103. if rules[i].GetPriority() == opts.Priority &&
  104. rules[i].GetAction() == opts.Action &&
  105. rules[i].GetProtocol() == opts.Protocol &&
  106. rules[i].GetPorts() == opts.Ports &&
  107. strings.Join(rules[i].GetCIDRs(), ",") == opts.CIDR &&
  108. rules[i].GetDirection() == opts.Direction {
  109. return &rules[i], nil
  110. }
  111. }
  112. return nil, errors.Wrapf(cloudprovider.ErrNotFound, "after created")
  113. }
  114. func (region *SRegion) CreateSecurityGroupRule(secGrpId string, opts *cloudprovider.SecurityGroupRuleCreateOptions) error {
  115. params := make(map[string]string)
  116. params["RegionId"] = region.RegionId
  117. params["SecurityGroupId"] = secGrpId
  118. params["Description"] = opts.Desc
  119. params["PortStart"] = "-1"
  120. params["PortEnd"] = "-1"
  121. if len(opts.Ports) > 0 {
  122. params["PortStart"] = opts.Ports
  123. params["PortEnd"] = opts.Ports
  124. if strings.Contains(opts.Ports, "-") {
  125. info := strings.Split(opts.Ports, "-")
  126. if len(info) == 2 {
  127. params["PortStart"] = info[0]
  128. params["PortEnd"] = info[1]
  129. }
  130. }
  131. }
  132. protocol := opts.Protocol
  133. if len(opts.Protocol) == 0 || opts.Protocol == secrules.PROTO_ANY {
  134. protocol = "all"
  135. }
  136. params["Protocol"] = protocol
  137. params["Policy"] = "drop"
  138. if opts.Action == secrules.SecurityRuleAllow {
  139. params["Policy"] = "accept"
  140. }
  141. params["CidrIp"] = "0.0.0.0/0"
  142. if len(opts.CIDR) > 0 {
  143. params["CidrIp"] = opts.CIDR
  144. }
  145. params["Priority"] = fmt.Sprintf("%d", opts.Priority)
  146. action := "AuthorizeSecurityGroupIngress"
  147. if opts.Direction == secrules.DIR_OUT {
  148. action = "AuthorizeSecurityGroupEgress"
  149. }
  150. _, err := region.vpcRequest(action, params)
  151. return err
  152. }
  153. func (region *SRegion) GetSecurityGroups(vpcId, name string, securityGroupIds []string, pageSize int, pageNumber int) ([]SSecurityGroup, int, error) {
  154. if pageSize > 100 || pageSize <= 0 {
  155. pageSize = 100
  156. }
  157. params := make(map[string]string)
  158. params["PageSize"] = fmt.Sprintf("%d", pageSize)
  159. params["PageNumber"] = fmt.Sprintf("%d", pageNumber)
  160. if len(vpcId) > 0 {
  161. params["VpcId"] = vpcId
  162. }
  163. if len(name) > 0 {
  164. params["SecurityGroupName"] = name
  165. }
  166. for i, id := range securityGroupIds {
  167. params[fmt.Sprintf("SecurityGroupIds.%d", i+1)] = id
  168. }
  169. body, err := region.vpcRequest("DescribeSecurityGroups", params)
  170. if err != nil {
  171. log.Errorf("GetSecurityGroups fail %s", err)
  172. return nil, 0, err
  173. }
  174. secgrps := make([]SSecurityGroup, 0)
  175. err = body.Unmarshal(&secgrps, "SecurityGroups")
  176. if err != nil {
  177. log.Errorf("Unmarshal security groups fail %s", err)
  178. return nil, 0, err
  179. }
  180. total, _ := body.Int("TotalCount")
  181. return secgrps, int(total), nil
  182. }
  183. func (secgroup *SSecurityGroup) GetId() string {
  184. return secgroup.SecurityGroupId
  185. }
  186. func (secgroup *SSecurityGroup) GetName() string {
  187. return secgroup.SecurityGroupName
  188. }
  189. func (secgroup *SSecurityGroup) GetGlobalId() string {
  190. return secgroup.GetId()
  191. }
  192. func (secgroup *SSecurityGroup) GetCreatedAt() time.Time {
  193. return secgroup.CreationTime
  194. }
  195. func (secgroup *SSecurityGroup) GetDescription() string {
  196. return secgroup.Description
  197. }
  198. func (secgroup *SSecurityGroup) GetStatus() string {
  199. return secgroup.Status
  200. }
  201. func (secgroup *SSecurityGroup) Refresh() error {
  202. group, err := secgroup.region.GetSecurityGroup(secgroup.GetId())
  203. if err != nil {
  204. return err
  205. }
  206. return jsonutils.Update(secgroup, group)
  207. }
  208. func (secgroup *SSecurityGroup) GetProjectId() string {
  209. return secgroup.ProjectName
  210. }
  211. func (self *SRegion) vpcTagResources(resType string, id string, tags map[string]string) error {
  212. if len(tags) == 0 {
  213. return nil
  214. }
  215. params := map[string]string{
  216. "ResourceType": resType,
  217. "ResourceIds.1": id,
  218. }
  219. idx := 1
  220. for k, v := range tags {
  221. params[fmt.Sprintf("Tags.%d.Key", idx)] = k
  222. params[fmt.Sprintf("Tags.%d.Value", idx)] = v
  223. idx++
  224. }
  225. _, err := self.vpcRequest("TagResources", params)
  226. return err
  227. }
  228. func (self *SRegion) vpcUntagResources(resType string, id string, tags map[string]string) error {
  229. if len(tags) == 0 {
  230. return nil
  231. }
  232. params := map[string]string{
  233. "ResourceType": resType,
  234. "ResourceIds.1": id,
  235. }
  236. idx := 1
  237. for k := range tags {
  238. params[fmt.Sprintf("TagKeys.%d", idx)] = k
  239. idx++
  240. }
  241. _, err := self.vpcRequest("UntagResources", params)
  242. return err
  243. }
  244. func (secgroup *SSecurityGroup) SetTags(tags map[string]string, replace bool) error {
  245. oldTags, err := secgroup.GetTags()
  246. if err != nil {
  247. return errors.Wrapf(err, "GetTags")
  248. }
  249. added, removed := map[string]string{}, map[string]string{}
  250. for k, v := range tags {
  251. oldValue, ok := oldTags[k]
  252. if !ok {
  253. added[k] = v
  254. } else if oldValue != v {
  255. removed[k] = oldValue
  256. added[k] = v
  257. }
  258. }
  259. if replace {
  260. for k, v := range oldTags {
  261. newValue, ok := tags[k]
  262. if !ok {
  263. removed[k] = v
  264. } else if v != newValue {
  265. added[k] = newValue
  266. removed[k] = v
  267. }
  268. }
  269. }
  270. if len(removed) > 0 {
  271. err = secgroup.region.vpcUntagResources("securitygroup", secgroup.SecurityGroupId, removed)
  272. if err != nil {
  273. return errors.Wrapf(err, "DeleteTags %s", removed)
  274. }
  275. }
  276. if len(added) > 0 {
  277. return secgroup.region.vpcTagResources("securitygroup", secgroup.SecurityGroupId, added)
  278. }
  279. return nil
  280. }
  281. func (secgroup *SSecurityGroup) GetRules() ([]cloudprovider.ISecurityGroupRule, error) {
  282. rules, err := secgroup.region.GetSecurityGroupRules(secgroup.SecurityGroupId)
  283. if err != nil {
  284. return nil, err
  285. }
  286. ret := []cloudprovider.ISecurityGroupRule{}
  287. for i := range rules {
  288. rules[i].secgroup = secgroup
  289. ret = append(ret, &rules[i])
  290. }
  291. return ret, nil
  292. }
  293. func (secgroup *SSecurityGroup) GetVpcId() string {
  294. return secgroup.VpcId
  295. }
  296. func (secgroup *SSecurityGroup) GetReferences() ([]cloudprovider.SecurityGroupReference, error) {
  297. ret := []cloudprovider.SecurityGroupReference{}
  298. return ret, errors.Wrapf(errors.ErrNotImplemented, "GetReferences not supported")
  299. }
  300. func (region *SRegion) DeleteSecurityGroup(id string) error {
  301. params := make(map[string]string)
  302. params["SecurityGroupId"] = id
  303. _, err := region.vpcRequest("DeleteSecurityGroup", params)
  304. if err != nil {
  305. return errors.Wrapf(err, "Delete %s", id)
  306. }
  307. return nil
  308. }
  309. func (secgroup *SSecurityGroup) Delete() error {
  310. return secgroup.region.DeleteSecurityGroup(secgroup.SecurityGroupId)
  311. }