| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 |
- // 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 ovn
- import (
- "fmt"
- "strconv"
- "strings"
- "yunion.io/x/log"
- "yunion.io/x/ovsdb/schema/ovn_nb"
- "yunion.io/x/pkg/errors"
- "yunion.io/x/pkg/util/regutils"
- "yunion.io/x/pkg/util/secrules"
- agentmodels "yunion.io/x/onecloud/pkg/vpcagent/models"
- )
- const (
- errBadSecgroupRule = errors.Error("bad security group rule")
- )
- const (
- aclDirToLport = "to-lport"
- aclDirFromLport = "from-lport"
- )
- func ruleToAcl(lport string, rule *agentmodels.SecurityGroupRule, enableIPv6 bool) (*ovn_nb.ACL, error) {
- var (
- dir string
- action string
- match string
- matches []string
- l3subfn string
- l4subfn string
- errs []error
- )
- switch secrules.TSecurityRuleDirection(rule.Direction) {
- case secrules.SecurityRuleIngress:
- dir = aclDirToLport
- l3subfn = "src"
- l4subfn = "dst"
- matches = append(matches, fmt.Sprintf("outport == %q", lport))
- case secrules.SecurityRuleEgress:
- dir = aclDirFromLport
- l3subfn = "dst"
- l4subfn = "dst"
- matches = append(matches, fmt.Sprintf("inport == %q", lport))
- default:
- return nil, errors.Wrapf(errBadSecgroupRule, "unknown direction %q", rule.Direction)
- }
- switch secrules.TSecurityRuleAction(rule.Action) {
- case secrules.SecurityRuleAllow:
- action = "allow-related"
- case secrules.SecurityRuleDeny:
- action = "drop"
- default:
- return nil, errors.Wrapf(errBadSecgroupRule, "unknown action %q", rule.Action)
- }
- addL3Match := func() {
- if enableIPv6 {
- matches = append(matches, "(ip4 || ip6)")
- } else {
- matches = append(matches, "ip4")
- }
- if cidr := strings.TrimSpace(rule.CIDR); cidr != "" {
- if regutils.MatchCIDR(cidr) {
- matches = append(matches, fmt.Sprintf("ip4.%s == %s", l3subfn, cidr))
- } else if regutils.MatchCIDR6(cidr) {
- matches = append(matches, fmt.Sprintf("ip6.%s == %s", l3subfn, cidr))
- } else {
- log.Debugf("invalid cidr %s, ignore", cidr)
- }
- }
- }
- addL4Match := func(l4proto string) {
- var (
- l4portfn = fmt.Sprintf("%s.%s", l4proto, l4subfn)
- portMatches []string
- )
- parsePort := func(pstr string) (int, error) {
- pn, err := strconv.ParseUint(pstr, 10, 16)
- if err != nil {
- return -1, err
- }
- return int(pn), nil
- }
- for _, pstr := range strings.Split(rule.Ports, ",") {
- pstr = strings.TrimSpace(pstr)
- if pstr == "" {
- continue
- }
- if i := strings.Index(pstr, "-"); i >= 0 {
- spstr := strings.TrimSpace(pstr[:i])
- epstr := strings.TrimSpace(pstr[i+1:])
- if spstr == "" || epstr == "" {
- continue
- }
- spn, err := parsePort(spstr)
- if err != nil {
- errs = append(errs, errors.Wrap(err, "start port"))
- }
- epn, err := parsePort(epstr)
- if err != nil {
- errs = append(errs, errors.Wrap(err, "end port"))
- }
- if spn > epn {
- spn, epn = epn, spn
- }
- if spn < epn {
- portMatches = append(portMatches,
- fmt.Sprintf("( %s >= %d && %s <= %d )",
- l4portfn, spn, l4portfn, epn))
- } else /* spn == epn */ {
- portMatches = append(portMatches,
- fmt.Sprintf("%s == %d", l4portfn, spn))
- }
- } else {
- if pn, err := parsePort(pstr); err != nil {
- errs = append(errs, errors.Wrap(err, "port"))
- } else {
- portMatches = append(portMatches,
- fmt.Sprintf("%s == %d", l4portfn, pn))
- }
- }
- }
- matches = append(matches, l4proto)
- if len(portMatches) > 0 {
- portMatch := strings.Join(portMatches, " || ")
- if len(portMatches) > 1 {
- portMatch = "( " + portMatch + " )"
- }
- matches = append(matches, portMatch)
- }
- }
- switch rule.Protocol {
- case "":
- // noop
- case "arp":
- matches = append(matches, "arp")
- case secrules.PROTO_ANY:
- addL3Match()
- case secrules.PROTO_TCP:
- addL3Match()
- addL4Match("tcp")
- case secrules.PROTO_UDP:
- addL3Match()
- addL4Match("udp")
- case secrules.PROTO_ICMP:
- addL3Match()
- if enableIPv6 {
- matches = append(matches, "(icmp4 || icmp6)")
- } else {
- matches = append(matches, "icmp4")
- }
- default:
- return nil, errors.Wrapf(errBadSecgroupRule, "unknown protocol %q", rule.Protocol)
- }
- if len(errs) > 0 {
- return nil, errors.NewAggregate(errs)
- }
- match = strings.Join(matches, " && ")
- acl := &ovn_nb.ACL{
- Priority: int64(rule.Priority),
- Direction: dir,
- Match: match,
- Action: action,
- }
- return acl, nil
- }
|