securitygroup.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  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 apsara
  15. import (
  16. "fmt"
  17. "time"
  18. "yunion.io/x/jsonutils"
  19. "yunion.io/x/log"
  20. "yunion.io/x/pkg/errors"
  21. "yunion.io/x/pkg/util/secrules"
  22. "yunion.io/x/pkg/utils"
  23. "yunion.io/x/cloudmux/pkg/cloudprovider"
  24. "yunion.io/x/cloudmux/pkg/multicloud"
  25. )
  26. // {"CreationTime":"2017-03-19T13:37:48Z","Description":"System created security group.","SecurityGroupId":"sg-j6cannq0xxj2r9z0yxwl","SecurityGroupName":"sg-j6cannq0xxj2r9z0yxwl","Tags":{"Tag":[]},"VpcId":"vpc-j6c86z3sh8ufhgsxwme0q"}
  27. // {"Description":"System created security group.","InnerAccessPolicy":"Accept","Permissions":{"Permission":[{"CreateTime":"2017-03-19T13:37:54Z","Description":"","DestCidrIp":"","DestGroupId":"","DestGroupName":"","DestGroupOwnerAccount":"","Direction":"ingress","IpProtocol":"ALL","NicType":"intranet","Policy":"Accept","PortRange":"-1/-1","Priority":110,"SourceCidrIp":"0.0.0.0/0","SourceGroupId":"","SourceGroupName":"","SourceGroupOwnerAccount":""},{"CreateTime":"2017-03-19T13:37:55Z","Description":"","DestCidrIp":"0.0.0.0/0","DestGroupId":"","DestGroupName":"","DestGroupOwnerAccount":"","Direction":"egress","IpProtocol":"ALL","NicType":"intranet","Policy":"Accept","PortRange":"-1/-1","Priority":110,"SourceCidrIp":"","SourceGroupId":"","SourceGroupName":"","SourceGroupOwnerAccount":""}]},"RegionId":"cn-hongkong","RequestId":"FBFE0950-5F2D-40DE-8C3C-E5A62AE7F7DA","SecurityGroupId":"sg-j6cannq0xxj2r9z0yxwl","SecurityGroupName":"sg-j6cannq0xxj2r9z0yxwl","VpcId":"vpc-j6c86z3sh8ufhgsxwme0q"}
  28. type SecurityGroupPermissionNicType string
  29. const (
  30. IntranetNicType SecurityGroupPermissionNicType = "intranet"
  31. InternetNicType SecurityGroupPermissionNicType = "internet"
  32. )
  33. type SPermissions struct {
  34. Permission []SPermission
  35. }
  36. type Tags struct {
  37. Tag []Tag
  38. }
  39. type Tag struct {
  40. TagKey string
  41. TagValue string
  42. }
  43. type SSecurityGroup struct {
  44. multicloud.SSecurityGroup
  45. ApsaraTags
  46. region *SRegion
  47. CreationTime time.Time
  48. Description string
  49. SecurityGroupId string
  50. SecurityGroupName string
  51. VpcId string
  52. InnerAccessPolicy string
  53. Permissions SPermissions
  54. RegionId string
  55. Tags Tags
  56. DepartmentInfo
  57. }
  58. func (self *SSecurityGroup) GetVpcId() string {
  59. return self.VpcId
  60. }
  61. func (self *SSecurityGroup) GetTags() (map[string]string, error) {
  62. tags := map[string]string{}
  63. for _, value := range self.Tags.Tag {
  64. tags[value.TagKey] = value.TagValue
  65. }
  66. return tags, nil
  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.Description
  76. }
  77. func (self *SSecurityGroup) GetCreatedAt() time.Time {
  78. return self.CreationTime
  79. }
  80. func (self *SSecurityGroup) GetRules() ([]cloudprovider.ISecurityGroupRule, error) {
  81. ret := make([]cloudprovider.ISecurityGroupRule, 0)
  82. rules, err := self.region.GetSecurityGroupRules(self.SecurityGroupId)
  83. if err != nil {
  84. return nil, err
  85. }
  86. for i := range rules {
  87. rules[i].region = self.region
  88. ret = append(ret, &rules[i])
  89. }
  90. return ret, nil
  91. }
  92. func (self *SSecurityGroup) GetName() string {
  93. if len(self.SecurityGroupName) > 0 {
  94. return self.SecurityGroupName
  95. }
  96. return self.SecurityGroupId
  97. }
  98. func (self *SSecurityGroup) GetStatus() string {
  99. return ""
  100. }
  101. func (self *SSecurityGroup) IsEmulated() bool {
  102. return false
  103. }
  104. func (self *SSecurityGroup) Refresh() error {
  105. group, err := self.region.GetSecurityGroup(self.SecurityGroupId)
  106. if err != nil {
  107. return err
  108. }
  109. return jsonutils.Update(self, group)
  110. }
  111. func (self *SRegion) GetSecurityGroup(id string) (*SSecurityGroup, error) {
  112. groups, _, err := self.GetSecurityGroups("", "", []string{id}, 0, 1)
  113. if err != nil {
  114. return nil, err
  115. }
  116. for i := range groups {
  117. if groups[i].SecurityGroupId == id {
  118. groups[i].region = self
  119. return &groups[i], nil
  120. }
  121. }
  122. return nil, errors.Wrapf(cloudprovider.ErrNotFound, "%s", id)
  123. }
  124. func (self *SRegion) GetSecurityGroups(vpcId, name string, securityGroupIds []string, offset int, limit int) ([]SSecurityGroup, int, error) {
  125. if limit > 50 || limit <= 0 {
  126. limit = 50
  127. }
  128. params := make(map[string]string)
  129. params["RegionId"] = self.RegionId
  130. params["PageSize"] = fmt.Sprintf("%d", limit)
  131. params["PageNumber"] = fmt.Sprintf("%d", (offset/limit)+1)
  132. if len(vpcId) > 0 {
  133. params["VpcId"] = vpcId
  134. }
  135. if len(name) > 0 {
  136. params["SecurityGroupName"] = name
  137. }
  138. if securityGroupIds != nil && len(securityGroupIds) > 0 {
  139. params["SecurityGroupIds"] = jsonutils.Marshal(securityGroupIds).String()
  140. }
  141. body, err := self.ecsRequest("DescribeSecurityGroups", params)
  142. if err != nil {
  143. log.Errorf("GetSecurityGroups fail %s", err)
  144. return nil, 0, err
  145. }
  146. secgrps := make([]SSecurityGroup, 0)
  147. err = body.Unmarshal(&secgrps, "SecurityGroups", "SecurityGroup")
  148. if err != nil {
  149. log.Errorf("Unmarshal security groups fail %s", err)
  150. return nil, 0, err
  151. }
  152. total, _ := body.Int("TotalCount")
  153. return secgrps, int(total), nil
  154. }
  155. func (self *SRegion) GetSecurityGroupRules(id string) ([]SPermission, error) {
  156. params := map[string]string{
  157. "SecurityGroupId": id,
  158. "RegionId": self.RegionId,
  159. }
  160. resp, err := self.ecsRequest("DescribeSecurityGroupAttribute", params)
  161. if err != nil {
  162. return nil, err
  163. }
  164. ret := struct {
  165. Permissions struct {
  166. Permission []SPermission
  167. }
  168. SecurityGroupId string
  169. }{}
  170. err = resp.Unmarshal(&ret)
  171. if err != nil {
  172. return nil, err
  173. }
  174. for i := range ret.Permissions.Permission {
  175. ret.Permissions.Permission[i].SecurityGroupId = ret.SecurityGroupId
  176. }
  177. return ret.Permissions.Permission, nil
  178. }
  179. func (self *SRegion) CreateSecurityGroup(vpcId string, name string, desc, projectId string) (string, error) {
  180. params := make(map[string]string)
  181. if len(vpcId) > 0 {
  182. params["VpcId"] = vpcId
  183. }
  184. if len(projectId) > 0 {
  185. params["ResourceGroupId"] = projectId
  186. }
  187. if len(name) > 0 {
  188. params["SecurityGroupName"] = name
  189. }
  190. if len(desc) > 0 {
  191. params["Description"] = desc
  192. }
  193. params["ClientToken"] = utils.GenRequestId(20)
  194. body, err := self.ecsRequest("CreateSecurityGroup", params)
  195. if err != nil {
  196. return "", errors.Wrap(err, "CreateSecurityGroup")
  197. }
  198. return body.GetString("SecurityGroupId")
  199. }
  200. func (self *SRegion) modifySecurityGroupRule(secGrpId string, rule *secrules.SecurityRule) error {
  201. params := make(map[string]string)
  202. params["RegionId"] = self.RegionId
  203. params["SecurityGroupId"] = secGrpId
  204. params["NicType"] = string(IntranetNicType)
  205. params["Description"] = rule.Description
  206. params["PortRange"] = fmt.Sprintf("%d/%d", rule.PortStart, rule.PortEnd)
  207. protocol := rule.Protocol
  208. if len(rule.Protocol) == 0 || rule.Protocol == secrules.PROTO_ANY {
  209. protocol = "all"
  210. }
  211. params["IpProtocol"] = protocol
  212. if rule.PortStart < 1 && rule.PortEnd < 1 {
  213. if protocol == "udp" || protocol == "tcp" {
  214. params["PortRange"] = "1/65535"
  215. } else {
  216. params["PortRange"] = "-1/-1"
  217. }
  218. }
  219. if rule.Action == secrules.SecurityRuleAllow {
  220. params["Policy"] = "accept"
  221. } else {
  222. params["Policy"] = "drop"
  223. }
  224. params["Priority"] = fmt.Sprintf("%d", rule.Priority)
  225. if rule.Direction == secrules.SecurityRuleIngress {
  226. if rule.IPNet != nil {
  227. params["SourceCidrIp"] = rule.IPNet.String()
  228. } else {
  229. params["SourceCidrIp"] = "0.0.0.0/0"
  230. }
  231. _, err := self.ecsRequest("ModifySecurityGroupRule", params)
  232. return err
  233. } else { // rule.Direction == secrules.SecurityRuleEgress {
  234. //阿里云不支持出方向API接口调用
  235. return nil
  236. // if rule.IPNet != nil {
  237. // params["DestCidrIp"] = rule.IPNet.String()
  238. // } else {
  239. // params["DestCidrIp"] = "0.0.0.0/0"
  240. // }
  241. // _, err := self.ecsRequest("ModifySecurityGroupRule", params)
  242. // return err
  243. }
  244. }
  245. func (self *SRegion) modifySecurityGroup(secGrpId string, name string, desc string) error {
  246. params := make(map[string]string)
  247. params["RegionId"] = self.RegionId
  248. params["SecurityGroupId"] = secGrpId
  249. params["SecurityGroupName"] = name
  250. if len(desc) > 0 {
  251. params["Description"] = desc
  252. }
  253. _, err := self.ecsRequest("ModifySecurityGroupAttribute", params)
  254. return err
  255. }
  256. func (self *SRegion) AddSecurityGroupRules(secGrpId string, rule secrules.SecurityRule) error {
  257. if len(rule.Ports) != 0 {
  258. for _, port := range rule.Ports {
  259. rule.PortStart, rule.PortEnd = port, port
  260. err := self.addSecurityGroupRule(secGrpId, rule)
  261. if err != nil {
  262. return errors.Wrapf(err, "addSecurityGroupRule %s", rule.String())
  263. }
  264. }
  265. return nil
  266. }
  267. return self.addSecurityGroupRule(secGrpId, rule)
  268. }
  269. func (self *SRegion) addSecurityGroupRule(secGrpId string, rule secrules.SecurityRule) error {
  270. params := make(map[string]string)
  271. params["RegionId"] = self.RegionId
  272. params["SecurityGroupId"] = secGrpId
  273. params["NicType"] = string(IntranetNicType)
  274. params["Description"] = rule.Description
  275. params["PortRange"] = fmt.Sprintf("%d/%d", rule.PortStart, rule.PortEnd)
  276. protocol := rule.Protocol
  277. if len(rule.Protocol) == 0 || rule.Protocol == secrules.PROTO_ANY {
  278. protocol = "all"
  279. }
  280. params["IpProtocol"] = protocol
  281. if rule.PortStart < 1 && rule.PortEnd < 1 {
  282. if protocol == "udp" || protocol == "tcp" {
  283. params["PortRange"] = "1/65535"
  284. } else {
  285. params["PortRange"] = "-1/-1"
  286. }
  287. }
  288. if rule.Action == secrules.SecurityRuleAllow {
  289. params["Policy"] = "accept"
  290. } else {
  291. params["Policy"] = "drop"
  292. }
  293. // 忽略地址为0.0.0.0/32这样的阿里云规则
  294. if rule.IPNet.IP.String() == "0.0.0.0" && rule.IPNet.String() != "0.0.0.0/0" {
  295. return nil
  296. }
  297. params["Priority"] = fmt.Sprintf("%d", rule.Priority)
  298. if rule.Direction == secrules.SecurityRuleIngress {
  299. if rule.IPNet != nil {
  300. params["SourceCidrIp"] = rule.IPNet.String()
  301. } else {
  302. params["SourceCidrIp"] = "0.0.0.0/0"
  303. }
  304. _, err := self.ecsRequest("AuthorizeSecurityGroup", params)
  305. return err
  306. } else { // rule.Direction == secrules.SecurityRuleEgress {
  307. if rule.IPNet != nil {
  308. params["DestCidrIp"] = rule.IPNet.String()
  309. } else {
  310. params["DestCidrIp"] = "0.0.0.0/0"
  311. }
  312. _, err := self.ecsRequest("AuthorizeSecurityGroupEgress", params)
  313. return err
  314. }
  315. }
  316. func (self *SRegion) DelSecurityGroupRule(secGrpId string, rule secrules.SecurityRule) error {
  317. params := make(map[string]string)
  318. params["RegionId"] = self.RegionId
  319. params["SecurityGroupId"] = secGrpId
  320. params["NicType"] = string(IntranetNicType)
  321. params["PortRange"] = fmt.Sprintf("%d/%d", rule.PortStart, rule.PortEnd)
  322. protocol := rule.Protocol
  323. if len(rule.Protocol) == 0 || rule.Protocol == secrules.PROTO_ANY {
  324. protocol = "all"
  325. }
  326. params["IpProtocol"] = protocol
  327. if rule.PortStart < 1 && rule.PortEnd < 1 {
  328. if protocol == "udp" || protocol == "tcp" {
  329. params["PortRange"] = "1/65535"
  330. } else {
  331. params["PortRange"] = "-1/-1"
  332. }
  333. }
  334. if rule.Action == secrules.SecurityRuleAllow {
  335. params["Policy"] = "accept"
  336. } else {
  337. params["Policy"] = "drop"
  338. }
  339. params["Priority"] = fmt.Sprintf("%d", rule.Priority)
  340. if rule.Direction == secrules.SecurityRuleIngress {
  341. if rule.IPNet != nil {
  342. params["SourceCidrIp"] = rule.IPNet.String()
  343. } else {
  344. params["SourceCidrIp"] = "0.0.0.0/0"
  345. }
  346. _, err := self.ecsRequest("RevokeSecurityGroup", params)
  347. return err
  348. } else { // rule.Direction == secrules.SecurityRuleEgress {
  349. if rule.IPNet != nil {
  350. params["DestCidrIp"] = rule.IPNet.String()
  351. } else {
  352. params["DestCidrIp"] = "0.0.0.0/0"
  353. }
  354. _, err := self.ecsRequest("RevokeSecurityGroupEgress", params)
  355. return err
  356. }
  357. }
  358. func (self *SRegion) AssignSecurityGroup(secgroupId, instanceId string) error {
  359. return self.SetSecurityGroups([]string{secgroupId}, instanceId)
  360. }
  361. func (self *SRegion) SetSecurityGroups(secgroupIds []string, instanceId string) error {
  362. params := map[string]string{"InstanceId": instanceId}
  363. for _, secgroupId := range secgroupIds {
  364. params["SecurityGroupId"] = secgroupId
  365. if _, err := self.ecsRequest("JoinSecurityGroup", params); err != nil {
  366. return err
  367. }
  368. }
  369. instance, err := self.GetInstance(instanceId)
  370. if err != nil {
  371. return err
  372. }
  373. for _, _secgroupId := range instance.SecurityGroupIds.SecurityGroupId {
  374. if !utils.IsInStringArray(_secgroupId, secgroupIds) {
  375. if err := self.leaveSecurityGroup(_secgroupId, instanceId); err != nil {
  376. return err
  377. }
  378. }
  379. }
  380. return nil
  381. }
  382. func (self *SRegion) leaveSecurityGroup(secgroupId, instanceId string) error {
  383. params := map[string]string{"InstanceId": instanceId, "SecurityGroupId": secgroupId}
  384. _, err := self.ecsRequest("LeaveSecurityGroup", params)
  385. return err
  386. }
  387. func (self *SRegion) DeleteSecurityGroup(secGrpId string) error {
  388. params := make(map[string]string)
  389. params["SecurityGroupId"] = secGrpId
  390. _, err := self.ecsRequest("DeleteSecurityGroup", params)
  391. if err != nil {
  392. log.Errorf("Delete security group fail %s", err)
  393. return err
  394. }
  395. return nil
  396. }
  397. func (self *SSecurityGroup) Delete() error {
  398. return self.region.DeleteSecurityGroup(self.SecurityGroupId)
  399. }