105 lines
2.6 KiB
Go
105 lines
2.6 KiB
Go
package npc
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"k8s.io/apimachinery/pkg/types"
|
|
|
|
"github.com/weaveworks/weave/common"
|
|
"github.com/weaveworks/weave/npc/iptables"
|
|
)
|
|
|
|
type ruleType byte
|
|
|
|
const (
|
|
ingress ruleType = iota
|
|
egress
|
|
)
|
|
|
|
type ruleSpec struct {
|
|
key string
|
|
args []string
|
|
ruleType ruleType
|
|
}
|
|
|
|
func newRuleSpec(ruleType ruleType, proto *string, srcHost *selectorSpec, dstHost *selectorSpec, dstPort *string) *ruleSpec {
|
|
args := []string{}
|
|
if proto != nil {
|
|
args = append(args, "-p", *proto)
|
|
}
|
|
srcComment := "anywhere"
|
|
if srcHost != nil {
|
|
args = append(args, "-m", "set", "--match-set", string(srcHost.ipsetName), "src")
|
|
if srcHost.nsName != "" {
|
|
srcComment = fmt.Sprintf("pods: namespace: %s, selector: %s", srcHost.nsName, srcHost.key)
|
|
} else {
|
|
srcComment = fmt.Sprintf("namespaces: selector: %s", srcHost.key)
|
|
}
|
|
}
|
|
dstComment := "anywhere"
|
|
if dstHost != nil {
|
|
args = append(args, "-m", "set", "--match-set", string(dstHost.ipsetName), "dst")
|
|
dstComment = fmt.Sprintf("pods: namespace: %s, selector: %s", dstHost.nsName, dstHost.key)
|
|
}
|
|
if dstPort != nil {
|
|
args = append(args, "--dport", *dstPort)
|
|
}
|
|
args = append(args, "-j", "ACCEPT")
|
|
args = append(args, "-m", "comment", "--comment", fmt.Sprintf("%s -> %s", srcComment, dstComment))
|
|
key := strings.Join(args, " ")
|
|
|
|
return &ruleSpec{key, args, ruleType}
|
|
}
|
|
|
|
type ruleSet struct {
|
|
ipt iptables.Interface
|
|
users map[string]map[types.UID]struct{}
|
|
}
|
|
|
|
func newRuleSet(ipt iptables.Interface) *ruleSet {
|
|
return &ruleSet{ipt, make(map[string]map[types.UID]struct{})}
|
|
}
|
|
|
|
func (rs *ruleSet) deprovision(user types.UID, current, desired map[string]*ruleSpec) error {
|
|
for key, spec := range current {
|
|
if _, found := desired[key]; !found {
|
|
delete(rs.users[key], user)
|
|
if len(rs.users[key]) == 0 {
|
|
chain := IngressChain
|
|
if spec.ruleType == egress {
|
|
chain = EgressCustomChain
|
|
}
|
|
common.Log.Infof("deleting rule %v from %q chain", spec.args, chain)
|
|
if err := rs.ipt.Delete(TableFilter, chain, spec.args...); err != nil {
|
|
return err
|
|
}
|
|
delete(rs.users, key)
|
|
}
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (rs *ruleSet) provision(user types.UID, current, desired map[string]*ruleSpec) error {
|
|
for key, spec := range desired {
|
|
if _, found := current[key]; !found {
|
|
if _, found := rs.users[key]; !found {
|
|
chain := IngressChain
|
|
if spec.ruleType == egress {
|
|
chain = EgressCustomChain
|
|
}
|
|
common.Log.Infof("adding rule %v to %q chain", spec.args, chain)
|
|
if err := rs.ipt.Append(TableFilter, chain, spec.args...); err != nil {
|
|
return err
|
|
}
|
|
rs.users[key] = make(map[types.UID]struct{})
|
|
}
|
|
rs.users[key][user] = struct{}{}
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|