diff --git a/pkg/util/aws/securitygroup.go b/pkg/util/aws/securitygroup.go index 55ac87c49f..592543d1d4 100644 --- a/pkg/util/aws/securitygroup.go +++ b/pkg/util/aws/securitygroup.go @@ -7,35 +7,6 @@ import ( "yunion.io/x/log" ) -type SecurityGroupPermissionNicType string - -const ( - IntranetNicType SecurityGroupPermissionNicType = "intranet" - InternetNicType SecurityGroupPermissionNicType = "internet" -) - -type SPermission struct { - Description string - DestCidrIp string - DestGroupId string - DestGroupName string - DestGroupOwnerAccount string - Direction string - IpProtocol string - NicType SecurityGroupPermissionNicType - Policy string - PortRange string - Priority int - SourceCidrIp string - SourceGroupId string - SourceGroupName string - SourceGroupOwnerAccount string -} - -type SPermissions struct { - Permission []SPermission -} - type Tags struct { Tag []Tag } @@ -53,7 +24,7 @@ type SSecurityGroup struct { SecurityGroupId string Description string SecurityGroupName string - Permissions SPermissions + Permissions []secrules.SecurityRule Tags Tags // CreationTime time.Time @@ -107,25 +78,13 @@ func (self *SSecurityGroup) GetDescription() string { } func (self *SSecurityGroup) GetRules() ([]secrules.SecurityRule, error) { - // todo: implement me rules := make([]secrules.SecurityRule, 0) if secgrp, err := self.vpc.region.GetSecurityGroupDetails(self.SecurityGroupId); err != nil { return rules, err } else { - for _, permission := range secgrp.Permissions.Permission { - if rule, err := secrules.ParseSecurityRule(""); err != nil { - return rules, err - } else { - priority := permission.Priority - if priority > 100 { - priority = 100 - } - rule.Priority = 101 - priority - rule.Description = permission.Description - rules = append(rules, *rule) - } - } + rules = secgrp.Permissions } + return rules, nil } @@ -182,8 +141,31 @@ func (self *SRegion) syncSecgroupRules(secgroupId string, rules []secrules.Secur return nil } -func (self *SRegion) getSecurityGroupsPermissions(ingress []*ec2.IpPermission, egress []*ec2.IpPermission) SPermissions { - return SPermissions{} +func (self *SRegion) getSecRules(ingress []*ec2.IpPermission, egress []*ec2.IpPermission) ([]secrules.SecurityRule) { + rules := []secrules.SecurityRule{} + for _, p := range ingress { + ret, err := AwsIpPermissionToYunion(secrules.SecurityRuleIngress, p) + if err != nil { + log.Debugf(err.Error()) + } + + for _, rule := range ret { + rules = append(rules, rule) + } + } + + for _, p := range egress { + ret, err := AwsIpPermissionToYunion(secrules.SecurityRuleEgress, p) + if err != nil { + log.Debugf(err.Error()) + } + + for _, rule := range ret { + rules = append(rules, rule) + } + } + + return rules } func (self *SRegion) GetSecurityGroups(vpcId string, offset int, limit int) ([]SSecurityGroup, int, error) { @@ -207,10 +189,10 @@ func (self *SRegion) GetSecurityGroups(vpcId string, offset int, limit int) ([]S vpc, err := self.getVpc(*item.VpcId) if err != nil { log.Errorf("vpc %s not found", *item.VpcId) + continue } - permissions := self.getSecurityGroupsPermissions(item.IpPermissions, item.IpPermissionsEgress) - + permissions := self.getSecRules(item.IpPermissions, item.IpPermissionsEgress) group := SSecurityGroup{ vpc: vpc, diff --git a/pkg/util/aws/utils.go b/pkg/util/aws/utils.go index 95657ef942..df8963bc0f 100644 --- a/pkg/util/aws/utils.go +++ b/pkg/util/aws/utils.go @@ -9,6 +9,11 @@ import ( "strings" ) +type portRange struct { + Start int64 + End int64 +} + func AppendFilter(filters []*ec2.Filter, name string, values []string) ([]*ec2.Filter) { f := &ec2.Filter{} v := make([]*string, len(values)) @@ -48,6 +53,14 @@ func ConvertedPointList(list []*string) ([]string) { return result } +func StrVal(s *string) string { + if s != nil { + return *s + } + + return "" +} + func isAwsPermissionAllPorts(p ec2.IpPermission) bool { // 全部端口范围: TCP/UDP (0,65535) 其他:(-1,-1) if (*p.IpProtocol == "tcp" || *p.IpProtocol == "udp") && *p.FromPort == 0 && *p.ToPort == 65535 { @@ -59,6 +72,66 @@ func isAwsPermissionAllPorts(p ec2.IpPermission) bool { } } +func awsProtocolToYunion(p ec2.IpPermission) string { + if *p.IpProtocol == "-1" { + return secrules.PROTO_ANY + } else { + return *p.IpProtocol + } +} + +func isYunionRuleAllPorts(r secrules.SecurityRule) bool { + // 全部端口范围: TCP/UDP (0,65535) 其他:(-1,-1) + if (r.Protocol == "tcp" || r.Protocol == "udp") && r.PortStart == 0 && r.PortEnd == 65535 { + return true + } else if r.PortStart == -1 && r.PortEnd == -1 { + return true + } else { + return false + } +} + +func yunionPortRangeToAws(r secrules.SecurityRule) ([]portRange) { + // port 0 / -1 都代表所有端口 + portranges := []portRange{} + if len(r.Ports) == 0 { + var start, end = 0, 0 + if r.PortStart <= 0 { + if r.Protocol == "tcp" || r.Protocol == "udp" { + start = 0 + } else { + start = -1 + } + } else { + start = r.PortStart + } + + if r.PortEnd <= 0 { + if r.Protocol == "tcp" || r.Protocol == "udp" { + end = 65535 + } else { + end = -1 + } + } else { + end = r.PortEnd + } + + portranges = append(portranges, portRange{int64(start), int64(end)}) + } + + for _, port := range r.Ports { + if port <= 0 && ( r.Protocol == "tcp" || r.Protocol == "udp" ) { + portranges = append(portranges, portRange{0, 65535}) + } else if port <= 0 { + portranges = append(portranges, portRange{-1, -1}) + } else { + portranges = append(portranges, portRange{int64(port), int64(port)}) + } + } + + return portranges +} + // Security Rule Transform func AwsIpPermissionToYunion(direction secrules.TSecurityRuleDirection,p ec2.IpPermission) ([]secrules.SecurityRule, error) { @@ -76,6 +149,7 @@ func AwsIpPermissionToYunion(direction secrules.TSecurityRuleDirection,p ec2.IpP rules := []secrules.SecurityRule{} isAllPorts := isAwsPermissionAllPorts(p) + protocol := awsProtocolToYunion(p) for _, ip := range p.IpRanges { ipNet := strings.Split(*ip.CidrIp, "/") if len(ipNet) != 2 { @@ -88,19 +162,21 @@ func AwsIpPermissionToYunion(direction secrules.TSecurityRuleDirection,p ec2.IpP rule = secrules.SecurityRule{ Action: secrules.SecurityRuleAllow, IPNet: &net.IPNet{net.IP(ipNet[0]), net.IPMask(ipNet[1])}, - Protocol: *p.IpProtocol, + Protocol: protocol, Direction: direction, - Description: "", + Priority: 1, + Description: StrVal(ip.Description), } } else { rule = secrules.SecurityRule{ Action: secrules.SecurityRuleAllow, IPNet: &net.IPNet{net.IP(ipNet[0]), net.IPMask(ipNet[1])}, - Protocol: *p.IpProtocol, + Protocol: protocol, Direction: direction, PortStart: int(*p.FromPort), PortEnd: int(*p.ToPort), - Description: "", + Priority: 1, + Description: StrVal(ip.Description), } } @@ -111,10 +187,30 @@ func AwsIpPermissionToYunion(direction secrules.TSecurityRuleDirection,p ec2.IpP return rules, nil } -func YunionSecRuleToAws(rule secrules.SecurityRule) ec2.IpPermission { - return ec2.IpPermission{} -} +func YunionSecRuleToAws(rule secrules.SecurityRule) ([]ec2.IpPermission, error) { + if rule.Action == secrules.SecurityRuleDeny { + return nil, fmt.Errorf("YunionSecRuleToAws ignored aws not supported deny rule") + } -func DiffIpPermission(permission ec2.IpPermission, rule secrules.SecurityRule) { + iprange := rule.IPNet.String() + if iprange == "" { + return nil, fmt.Errorf("YunionSecRuleToAws ignored ipnet should not be empty") + } + ipranges := []*ec2.IpRange{} + ipranges = append(ipranges, &ec2.IpRange{CidrIp: &iprange, Description: &rule.Description}) + portranges := yunionPortRangeToAws(rule) + permissions := []ec2.IpPermission{} + for _, port := range portranges { + permission := ec2.IpPermission{ + FromPort: &port.Start, + IpProtocol: &rule.Protocol, + IpRanges: ipranges, + ToPort: &port.End, + } + + permissions = append(permissions, permission) + } + + return permissions, nil } \ No newline at end of file