Files
cloudpods/pkg/multicloud/ucloud/securitygroup.go
2021-05-28 20:18:10 +08:00

254 lines
6.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package ucloud
import (
"fmt"
"math/rand"
"strings"
"time"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/util/secrules"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/multicloud"
)
// https://docs.ucloud.cn/api/unet-api/describe_firewall
type SSecurityGroup struct {
multicloud.SSecurityGroup
multicloud.UcloudTags
region *SRegion
vpc *SVPC // 安全组在UCLOUD实际上与VPC是没有直接关联的。这里的vpc字段只是为了统一仅仅是标记是哪个VPC在操作该安全组。
CreateTime int64 `json:"CreateTime"`
FWID string `json:"FWId"`
GroupID string `json:"GroupId"`
Name string `json:"Name"`
Remark string `json:"Remark"`
ResourceCount int `json:"ResourceCount"`
Rule []Rule `json:"Rule"`
Tag string `json:"Tag"`
Type string `json:"Type"`
}
func (self *SSecurityGroup) GetProjectId() string {
return self.region.client.projectId
}
type Rule struct {
DstPort string `json:"DstPort"`
Priority string `json:"Priority"`
ProtocolType string `json:"ProtocolType"`
RuleAction string `json:"RuleAction"`
SrcIP string `json:"SrcIP"`
}
func (self *SSecurityGroup) GetId() string {
return self.FWID
}
func (self *SSecurityGroup) GetName() string {
if len(self.Name) == 0 {
return self.GetId()
}
return self.Name
}
func (self *SSecurityGroup) GetGlobalId() string {
return self.GetId()
}
func (self *SSecurityGroup) GetStatus() string {
return ""
}
func (self *SSecurityGroup) Refresh() error {
if new, err := self.region.GetSecurityGroupById(self.GetId()); err != nil {
return err
} else {
return jsonutils.Update(self, new)
}
}
func (self *SSecurityGroup) IsEmulated() bool {
return false
}
func (self *SSecurityGroup) GetDescription() string {
return self.Remark
}
func (self *SSecurityGroup) UcloudSecRuleToOnecloud(rule Rule) (cloudprovider.SecurityRule, error) {
secrule := cloudprovider.SecurityRule{}
switch rule.Priority {
case "HIGH":
secrule.Priority = 3
case "MEDIUM":
secrule.Priority = 2
case "LOW":
secrule.Priority = 1
default:
secrule.Priority = 1
}
switch rule.RuleAction {
case "ACCEPT":
secrule.Action = secrules.SecurityRuleAllow
case "DROP":
secrule.Action = secrules.SecurityRuleDeny
default:
secrule.Action = secrules.SecurityRuleDeny
}
secrule.ParseCIDR(rule.SrcIP)
secrule.Protocol = strings.ToLower(rule.ProtocolType)
secrule.Direction = secrules.SecurityRuleIngress
err := secrule.ParsePorts(rule.DstPort)
if err != nil {
return secrule, errors.Wrapf(err, "ParsePorts(%s)", rule.DstPort)
}
return secrule, nil
}
// https://docs.ucloud.cn/network/firewall/firewall
// 只有入方向规则
func (self *SSecurityGroup) GetRules() ([]cloudprovider.SecurityRule, error) {
rules := make([]cloudprovider.SecurityRule, 0)
for _, r := range self.Rule {
rule, err := self.UcloudSecRuleToOnecloud(r)
if err != nil {
log.Errorf("failed to convert rule for group %s(%s) error: %v", self.Name, self.GroupID, err)
continue
}
rules = append(rules, rule)
}
return rules, nil
}
func (self *SSecurityGroup) GetVpcId() string {
// 无vpc关联的安全组统一返回normal
return api.NORMAL_VPC_ID
}
func (self *SRegion) GetSecurityGroupById(secGroupId string) (*SSecurityGroup, error) {
secgroups, err := self.GetSecurityGroups(secGroupId, "", "")
if err != nil {
return nil, err
}
if len(secgroups) == 1 {
return &secgroups[0], nil
} else if len(secgroups) == 0 {
return nil, cloudprovider.ErrNotFound
} else {
return nil, fmt.Errorf("GetSecurityGroupById %s %d found", secGroupId, len(secgroups))
}
}
func randomString(prefix string, length int) string {
bytes := []byte("0123456789abcdefghijklmnopqrstuvwxyz")
result := []byte{}
r := rand.New(rand.NewSource(time.Now().UnixNano()))
for i := 0; i < length; i++ {
result = append(result, bytes[r.Intn(len(bytes))])
}
return prefix + string(result)
}
func (self *SRegion) CreateDefaultSecurityGroup(name, description string) (string, error) {
// 减少安全组名称冲突
name = randomString(name, 4)
return self.CreateSecurityGroup(name, description, []string{"TCP|1-65535|0.0.0.0/0|ACCEPT|LOW", "UDP|1-65535|0.0.0.0/0|ACCEPT|LOW", "ICMP||0.0.0.0/0|ACCEPT|LOW"})
}
// https://docs.ucloud.cn/api/unet-api/create_firewall
func (self *SRegion) CreateSecurityGroup(name, description string, rules []string) (string, error) {
params := NewUcloudParams()
params.Set("Name", name)
params.Set("Remark", description)
if len(rules) == 0 {
return "", fmt.Errorf("CreateSecurityGroup required at least one rule")
}
for i, rule := range rules {
params.Set(fmt.Sprintf("Rule.%d", i), rule)
}
type Firewall struct {
FWId string
}
firewall := Firewall{}
err := self.DoAction("CreateFirewall", params, &firewall)
if err != nil {
return "", err
}
return firewall.FWId, nil
}
// https://docs.ucloud.cn/api/unet-api/describe_firewall
func (self *SRegion) GetSecurityGroups(secGroupId string, resourceId string, name string) ([]SSecurityGroup, error) {
secgroups := make([]SSecurityGroup, 0)
params := NewUcloudParams()
if len(secGroupId) > 0 {
params.Set("FWId", secGroupId)
}
if len(resourceId) > 0 {
params.Set("ResourceId", resourceId)
params.Set("ResourceType", "uhost") // 默认只支持"uhost",云主机
}
err := self.DoListAll("DescribeFirewall", params, &secgroups)
if err != nil {
if strings.Contains(err.Error(), "not exist") {
return nil, cloudprovider.ErrNotFound
}
return nil, err
}
result := []SSecurityGroup{}
for i := range secgroups {
if len(name) == 0 || secgroups[i].Name == name {
secgroups[i].region = self
result = append(result, secgroups[i])
}
}
return result, nil
}
func (self *SSecurityGroup) SyncRules(common, inAdds, outAdds, inDels, outDels []cloudprovider.SecurityRule) error {
if len(inAdds) == 0 && len(inDels) == 0 {
return nil
}
rules := append(common, inAdds...)
return self.region.syncSecgroupRules(self.FWID, rules)
}
func (self *SSecurityGroup) Delete() error {
return self.region.DeleteSecurityGroup(self.FWID)
}