[NPM] General translation logic for linux and windows (#1055)

* Create generic translation struct and start using it networkPolicyController

* Update ipsm to get more information from NPMCache

* Working on translateIngress part and its UTs

* Done functions of Translate ingress rule (need to add UTs to test its functions and clean up codes)

* Use function for repeated codes

* Cleanup UTs

* Remove all unused codes in this PR except for ingress rules

* Create functions to make codes concise and reorganize ipsets for better readability

* Remove duplicated data for targetPod information in every ACL

* Move translation logics to /pkg/controlplane/translation dir

* Remove redundant codes and resolved some of lint errors

* Resolve lint errors and remove unused codes in parseSelector and its UTs

* Use unique id for acl policy among network policies and add UTs for port rules

* Addresses some comments (will resolve more later)

* Complete namespaceSelector UTs and correct some logics for handling namespaceSelector

* Use consistent variables and variable for flexibility in UTs

* Add more UTs for allowAll and defaultDrop rules and clean-up codes

* Remove unused codes

* Resolve lint errors

* Clean-up and reorganize codes

* Revert "Update ipsm to get more information from NPMCache"

This reverts commit 477bbaf43d56a6535f5cc035dfe15d5b6035647a.

* Address comments

* Resolve part of lint errors

* Add comments for todo things in next PR

* Delete unused file and clean-up code

* Fix Uts

* Remove unnecessary code
This commit is contained in:
JungukCho 2021-11-01 09:03:16 -07:00 коммит произвёл GitHub
Родитель 66453dd20b
Коммит 8434e139d1
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
16 изменённых файлов: 4657 добавлений и 181 удалений

Просмотреть файл

@ -0,0 +1,240 @@
package translation
import (
"github.com/Azure/azure-container-networking/log"
"github.com/Azure/azure-container-networking/npm/util"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// ParseLabel takes a Azure-NPM processed label then returns if it's referring to complement set,
// and if so, returns the original set as well.
func ParseLabel(label string) (string, bool) {
// The input label is guaranteed to have a non-zero length validated by k8s.
// For label definition, see below parseSelector() function.
if label[0:1] == util.IptablesNotFlag {
return label[1:], true
}
return label, false
}
// GetOperatorAndLabel returns the operator associated with the label and the label without operator.
func GetOperatorAndLabel(labelWithOp string) (op, label string) {
// TODO(jungukcho): check whether this is possible
if labelWithOp == "" {
return op, label
}
// in case "!"" Operaror do not exist
if string(labelWithOp[0]) != util.IptablesNotFlag {
label = labelWithOp
return op, label
}
// in case "!"" Operaror exists
op, label = util.IptablesNotFlag, labelWithOp[1:]
return op, label
}
// GetOperatorsAndLabels returns the operators along with the associated labels.
func GetOperatorsAndLabels(labelsWithOps []string) (ops, labelsWithoutOps []string) {
ops = make([]string, len(labelsWithOps))
labelsWithoutOps = make([]string, len(labelsWithOps))
for i, labelWithOp := range labelsWithOps {
op, labelWithoutOp := GetOperatorAndLabel(labelWithOp)
ops[i] = op
labelsWithoutOps[i] = labelWithoutOp
}
return ops, labelsWithoutOps
}
// getSetNameForMultiValueSelector takes in label with multiple values without operator
// and returns a new 2nd level ipset name
func getSetNameForMultiValueSelector(key string, vals []string) string {
newIPSet := key
for _, val := range vals {
newIPSet = util.GetIpSetFromLabelKV(newIPSet, val)
}
return newIPSet
}
// FlattenNameSpaceSelector will help flatten multiple NameSpace selector match Expressions values
// into multiple label selectors helping with the OR condition.
func FlattenNameSpaceSelector(nsSelector *metav1.LabelSelector) []metav1.LabelSelector {
/*
This function helps to create multiple labelSelectors when given a single multivalue nsSelector
Take below example: this nsSelector has 2 values in a matchSelector.
- namespaceSelector:
matchExpressions:
- key: ns
operator: NotIn
values:
- netpol-x
- netpol-y
goal is to convert this single nsSelector into multiple nsSelectors to preserve OR condition
between multiple values of the matchExpr i.e. this function will return
- namespaceSelector:
matchExpressions:
- key: ns
operator: NotIn
values:
- netpol-x
- namespaceSelector:
matchExpressions:
- key: ns
operator: NotIn
values:
- netpol-y
then, translate policy will replicate each of these nsSelectors to add two different rules in iptables,
resulting in OR condition between the values.
Check TestFlattenNameSpaceSelector 2nd subcase for complex scenario
*/
// To avoid any additional length checks, just return a slice of labelSelectors
// with original nsSelector
if nsSelector == nil {
return []metav1.LabelSelector{}
}
if len(nsSelector.MatchExpressions) == 0 {
return []metav1.LabelSelector{*nsSelector}
}
// create a baseSelector which needs to be same across all
// new labelSelectors
baseSelector := &metav1.LabelSelector{
MatchLabels: nsSelector.MatchLabels,
MatchExpressions: []metav1.LabelSelectorRequirement{},
}
multiValuePresent := false
multiValueMatchExprs := []metav1.LabelSelectorRequirement{}
for _, req := range nsSelector.MatchExpressions {
// Only In and NotIn operators of matchExprs have multiple values
// NPM will ignore single value matchExprs of these operators.
// for multiple values, it will create a slice of them to be used for Zipping with baseSelector
// to create multiple nsSelectors to preserve OR condition across all labels and expressions
switch {
case (req.Operator == metav1.LabelSelectorOpIn) || (req.Operator == metav1.LabelSelectorOpNotIn):
if len(req.Values) == 1 {
// for length 1, add the matchExpr to baseSelector
baseSelector.MatchExpressions = append(baseSelector.MatchExpressions, req)
} else {
multiValuePresent = true
multiValueMatchExprs = append(multiValueMatchExprs, req)
}
case (req.Operator == metav1.LabelSelectorOpExists) || (req.Operator == metav1.LabelSelectorOpDoesNotExist):
// since Exists and NotExists do not contain any values, NPM can safely add them to the baseSelector
baseSelector.MatchExpressions = append(baseSelector.MatchExpressions, req)
default:
log.Errorf("Invalid operator [%s] for selector [%v] requirement", req.Operator, *nsSelector)
}
}
// If there are no multiValue NS selector match expressions
// return the original NsSelector
if !multiValuePresent {
return []metav1.LabelSelector{*nsSelector}
}
// Now use the baseSelector and loop over multiValueMatchExprs to create all
// combinations of values
flatNsSelectors := []metav1.LabelSelector{
*baseSelector.DeepCopy(),
}
for _, req := range multiValueMatchExprs {
flatNsSelectors = zipMatchExprs(flatNsSelectors, req)
}
return flatNsSelectors
}
// zipMatchExprs helps with zipping a given matchExpr with given baseLabelSelectors
// this func will loop over each baseSelector in the slice,
// deepCopies each baseSelector, combines with given matchExpr by looping over each value
// and creating a new LabelSelector with given baseSelector and value matchExpr
// then returns a new slice of these zipped LabelSelectors
func zipMatchExprs(baseSelectors []metav1.LabelSelector, matchExpr metav1.LabelSelectorRequirement) []metav1.LabelSelector {
zippedLabelSelectors := []metav1.LabelSelector{}
for _, selector := range baseSelectors {
for _, value := range matchExpr.Values {
tempBaseSelector := selector.DeepCopy()
tempBaseSelector.MatchExpressions = append(
tempBaseSelector.MatchExpressions,
metav1.LabelSelectorRequirement{
Key: matchExpr.Key,
Operator: matchExpr.Operator,
Values: []string{value},
},
)
zippedLabelSelectors = append(zippedLabelSelectors, *tempBaseSelector)
}
}
return zippedLabelSelectors
}
// parseSelector takes a LabelSelector and returns a slice of processed labels, Lists with members as values.
// this function returns a slice of all the label ipsets excluding multivalue matchExprs
// and a map of labelKeys and labelIpsetname for multivalue match exprs
// higher level functions will need to compute what sets or ipsets should be
// used from this map
func parseSelector(selector *metav1.LabelSelector) (labels []string, vals map[string][]string) {
// TODO(jungukcho): check return values
// labels []string and []string{}
if selector == nil {
return labels, vals
}
labels = []string{}
vals = make(map[string][]string)
if len(selector.MatchLabels) == 0 && len(selector.MatchExpressions) == 0 {
labels = append(labels, "")
return labels, vals
}
sortedKeys, sortedVals := util.SortMap(&selector.MatchLabels)
for i := range sortedKeys {
labels = append(labels, sortedKeys[i]+":"+sortedVals[i])
}
for _, req := range selector.MatchExpressions {
var k string
switch op := req.Operator; op {
case metav1.LabelSelectorOpIn:
k = req.Key
if len(req.Values) == 1 {
labels = append(labels, k+":"+req.Values[0])
} else {
// We are not adding the k:v to labels for multiple values, because, labels are used
// to construct partial IptEntries and if these below labels are added then we are inducing
// AND condition on values of a match expression instead of OR
vals[k] = append(vals[k], req.Values...)
}
case metav1.LabelSelectorOpNotIn:
k = util.IptablesNotFlag + req.Key
if len(req.Values) == 1 {
labels = append(labels, k+":"+req.Values[0])
} else {
vals[k] = append(vals[k], req.Values...)
}
// Exists matches pods with req.Key as key
case metav1.LabelSelectorOpExists:
k = req.Key
labels = append(labels, k)
// DoesNotExist matches pods without req.Key as key
case metav1.LabelSelectorOpDoesNotExist:
k = util.IptablesNotFlag + req.Key
labels = append(labels, k)
default:
log.Errorf("Invalid operator [%s] for selector [%v] requirement", op, *selector)
}
}
return labels, vals
}

Просмотреть файл

@ -0,0 +1,763 @@
package translation
import (
"reflect"
"testing"
"github.com/Azure/azure-container-networking/npm/util"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func TestParseLabel(t *testing.T) {
label, isComplementSet := ParseLabel("test:frontend")
expectedLabel := "test:frontend"
if isComplementSet || label != expectedLabel {
t.Errorf("TestParseLabel failed @ label %s", label)
}
label, isComplementSet = ParseLabel("!test:frontend")
expectedLabel = "test:frontend"
if !isComplementSet || label != expectedLabel {
t.Errorf("TestParseLabel failed @ label %s", label)
}
label, isComplementSet = ParseLabel("test")
expectedLabel = "test"
if isComplementSet || label != expectedLabel {
t.Errorf("TestParseLabel failed @ label %s", label)
}
label, isComplementSet = ParseLabel("!test")
expectedLabel = "test"
if !isComplementSet || label != expectedLabel {
t.Errorf("TestParseLabel failed @ label %s", label)
}
label, isComplementSet = ParseLabel("!!test")
expectedLabel = "!test"
if !isComplementSet || label != expectedLabel {
t.Errorf("TestParseLabel failed @ label %s", label)
}
label, isComplementSet = ParseLabel("test:!frontend")
expectedLabel = "test:!frontend"
if isComplementSet || label != expectedLabel {
t.Errorf("TestParseLabel failed @ label %s", label)
}
label, isComplementSet = ParseLabel("!test:!frontend")
expectedLabel = "test:!frontend"
if !isComplementSet || label != expectedLabel {
t.Errorf("TestParseLabel failed @ label %s", label)
}
}
func TestGetOperatorAndLabel(t *testing.T) {
testLabels := []string{
"a",
"k:v",
"",
"!a:b",
"!a",
}
resultOperators, resultLabels := []string{}, []string{}
for _, testLabel := range testLabels {
resultOperator, resultLabel := GetOperatorAndLabel(testLabel)
resultOperators = append(resultOperators, resultOperator)
resultLabels = append(resultLabels, resultLabel)
}
expectedOperators := []string{
"",
"",
"",
util.IptablesNotFlag,
util.IptablesNotFlag,
}
expectedLabels := []string{
"a",
"k:v",
"",
"a:b",
"a",
}
if !reflect.DeepEqual(resultOperators, expectedOperators) {
t.Errorf("TestGetOperatorAndLabel failed @ operator comparison")
}
if !reflect.DeepEqual(resultLabels, expectedLabels) {
t.Errorf("TestGetOperatorAndLabel failed @ label comparison")
}
}
func TestGetOperatorsAndLabels(t *testing.T) {
testLabels := []string{
"k:v",
"",
"!a:b",
}
resultOps, resultLabels := GetOperatorsAndLabels(testLabels)
expectedOps := []string{
"",
"",
"!",
}
expectedLabels := []string{
"k:v",
"",
"a:b",
}
if !reflect.DeepEqual(resultOps, expectedOps) {
t.Errorf("TestGetOperatorsAndLabels failed @ op comparison")
}
if !reflect.DeepEqual(resultLabels, expectedLabels) {
t.Errorf("TestGetOperatorsAndLabels failed @ label comparison")
}
}
// TODO(jungukcho): check UT results.
func TestParseSelector(t *testing.T) {
var selector, expectedSelector *metav1.LabelSelector
selector, expectedSelector = nil, nil
labels, vals := parseSelector(selector)
expectedLabels, expectedVals := []string{}, make(map[string][]string)
if len(labels) != len(expectedLabels) {
t.Errorf("TestparseSelector failed @ labels length comparison")
}
if len(vals) != len(expectedVals) {
t.Errorf("TestparseSelector failed @ vals length comparison")
}
if selector != expectedSelector {
t.Errorf("TestparseSelector failed @ vals length comparison")
}
selector = &metav1.LabelSelector{}
labels, vals = parseSelector(selector)
expectedLabels = []string{""}
if len(labels) != len(expectedLabels) {
t.Errorf("TestparseSelector failed @ labels length comparison")
}
if len(vals) != len(expectedVals) {
t.Errorf("TestparseSelector failed @ vals length comparison")
}
selector = &metav1.LabelSelector{
MatchExpressions: []metav1.LabelSelectorRequirement{
{
Key: "testIn",
Operator: metav1.LabelSelectorOpIn,
Values: []string{
"frontend",
"backend",
},
},
},
}
labels, vals = parseSelector(selector)
expectedLabels = []string{}
expectedVals = map[string][]string{
"testIn": {
"frontend",
"backend",
},
}
if len(labels) != len(expectedLabels) {
t.Errorf("TestparseSelector failed @ labels length comparison")
}
if len(vals) != len(expectedVals) {
t.Errorf("TestparseSelector failed @ vals length comparison")
}
if len(labels) != 0 {
t.Errorf("TestparseSelector failed @ label comparison")
}
if !reflect.DeepEqual(vals, expectedVals) {
t.Errorf("TestparseSelector failed @ value comparison")
}
notIn := metav1.LabelSelectorRequirement{
Key: "testNotIn",
Operator: metav1.LabelSelectorOpNotIn,
Values: []string{
"frontend",
"backend",
},
}
me := &selector.MatchExpressions
*me = append(*me, notIn)
labels, vals = parseSelector(selector)
addedLabels := []string{}
addedVals := map[string][]string{
"!testNotIn": {
"frontend",
"backend",
},
}
expectedLabels = append(expectedLabels, addedLabels...)
for k, v := range addedVals {
expectedVals[k] = append(expectedVals[k], v...)
}
if len(labels) != len(expectedLabels) {
t.Errorf("TestparseSelector failed @ labels length comparison")
}
if len(vals) != len(expectedVals) {
t.Errorf("TestparseSelector failed @ vals length comparison")
}
if len(labels) != 0 {
t.Errorf("TestparseSelector failed @ label comparison")
}
if !reflect.DeepEqual(vals, expectedVals) {
t.Errorf("TestparseSelector failed @ value comparison")
}
exists := metav1.LabelSelectorRequirement{
Key: "testExists",
Operator: metav1.LabelSelectorOpExists,
Values: []string{},
}
*me = append(*me, exists)
labels, vals = parseSelector(selector)
addedLabels = []string{
"testExists",
}
addedVals = map[string][]string{}
expectedLabels = append(expectedLabels, addedLabels...)
for k, v := range addedVals {
expectedVals[k] = append(expectedVals[k], v...)
}
if len(labels) != len(expectedLabels) {
t.Errorf("TestparseSelector failed @ labels length comparison")
}
if len(vals) != len(expectedVals) {
t.Errorf("TestparseSelector failed @ vals length comparison")
}
if !reflect.DeepEqual(labels, expectedLabels) {
t.Errorf("TestparseSelector failed @ label comparison")
}
if !reflect.DeepEqual(vals, expectedVals) {
t.Errorf("TestparseSelector failed @ value comparison")
}
doesNotExist := metav1.LabelSelectorRequirement{
Key: "testDoesNotExist",
Operator: metav1.LabelSelectorOpDoesNotExist,
Values: []string{},
}
*me = append(*me, doesNotExist)
labels, vals = parseSelector(selector)
addedLabels = []string{
"!testDoesNotExist",
}
addedVals = map[string][]string{}
expectedLabels = append(expectedLabels, addedLabels...)
for k, v := range addedVals {
expectedVals[k] = append(expectedVals[k], v...)
}
if len(labels) != len(expectedLabels) {
t.Errorf("TestparseSelector failed @ labels length comparison")
}
if len(vals) != len(expectedVals) {
t.Errorf("TestparseSelector failed @ vals length comparison")
}
if !reflect.DeepEqual(labels, expectedLabels) {
t.Errorf("TestparseSelector failed @ label comparison")
}
if !reflect.DeepEqual(vals, expectedVals) {
t.Errorf("TestparseSelector failed @ value comparison")
}
}
func TestFlattenNameSpaceSelectorCases(t *testing.T) {
firstSelector := &metav1.LabelSelector{}
testSelectors := FlattenNameSpaceSelector(firstSelector)
if len(testSelectors) != 1 {
t.Errorf("TestFlattenNameSpaceSelectorCases failed @ 1st selector length check %+v", testSelectors)
}
var secondSelector *metav1.LabelSelector
testSelectors = FlattenNameSpaceSelector(secondSelector)
if len(testSelectors) > 0 {
t.Errorf("TestFlattenNameSpaceSelectorCases failed @ 1st selector length check %+v", testSelectors)
}
}
func TestFlattenNameSpaceSelector(t *testing.T) {
commonMatchLabel := map[string]string{
"c": "d",
"a": "b",
}
firstSelector := &metav1.LabelSelector{
MatchExpressions: []metav1.LabelSelectorRequirement{
{
Key: "testIn",
Operator: metav1.LabelSelectorOpIn,
Values: []string{
"backend",
},
},
{
Key: "pod",
Operator: metav1.LabelSelectorOpIn,
Values: []string{
"a",
},
},
{
Key: "testExists",
Operator: metav1.LabelSelectorOpExists,
Values: []string{},
},
{
Key: "ns",
Operator: metav1.LabelSelectorOpIn,
Values: []string{
"t",
},
},
},
MatchLabels: commonMatchLabel,
}
testSelectors := FlattenNameSpaceSelector(firstSelector)
if len(testSelectors) != 1 {
t.Errorf("TestFlattenNameSpaceSelector failed @ 1st selector length check %+v", testSelectors)
}
if !reflect.DeepEqual(testSelectors[0], *firstSelector) {
t.Errorf("TestFlattenNameSpaceSelector failed @ 1st selector deepEqual check.\n Expected: %+v \n Actual: %+v", *firstSelector, testSelectors[0])
}
secondSelector := &metav1.LabelSelector{
MatchExpressions: []metav1.LabelSelectorRequirement{
{
Key: "testIn",
Operator: metav1.LabelSelectorOpIn,
Values: []string{
"backend",
"frontend",
},
},
{
Key: "pod",
Operator: metav1.LabelSelectorOpIn,
Values: []string{
"a",
"b",
},
},
{
Key: "testExists",
Operator: metav1.LabelSelectorOpExists,
Values: []string{},
},
{
Key: "ns",
Operator: metav1.LabelSelectorOpIn,
Values: []string{
"t",
"y",
},
},
},
MatchLabels: commonMatchLabel,
}
testSelectors = FlattenNameSpaceSelector(secondSelector)
if len(testSelectors) != 8 {
t.Errorf("TestFlattenNameSpaceSelector failed @ 2nd selector length check %+v", testSelectors)
}
expectedSelectors := []metav1.LabelSelector{
{
MatchExpressions: []metav1.LabelSelectorRequirement{
{
Key: "testExists",
Operator: metav1.LabelSelectorOpExists,
Values: []string{},
},
{
Key: "testIn",
Operator: metav1.LabelSelectorOpIn,
Values: []string{
"backend",
},
},
{
Key: "pod",
Operator: metav1.LabelSelectorOpIn,
Values: []string{
"a",
},
},
{
Key: "ns",
Operator: metav1.LabelSelectorOpIn,
Values: []string{
"t",
},
},
},
MatchLabels: commonMatchLabel,
},
{
MatchExpressions: []metav1.LabelSelectorRequirement{
{
Key: "testExists",
Operator: metav1.LabelSelectorOpExists,
Values: []string{},
},
{
Key: "testIn",
Operator: metav1.LabelSelectorOpIn,
Values: []string{
"backend",
},
},
{
Key: "pod",
Operator: metav1.LabelSelectorOpIn,
Values: []string{
"a",
},
},
{
Key: "ns",
Operator: metav1.LabelSelectorOpIn,
Values: []string{
"y",
},
},
},
MatchLabels: commonMatchLabel,
},
{
MatchExpressions: []metav1.LabelSelectorRequirement{
{
Key: "testExists",
Operator: metav1.LabelSelectorOpExists,
Values: []string{},
},
{
Key: "testIn",
Operator: metav1.LabelSelectorOpIn,
Values: []string{
"backend",
},
},
{
Key: "pod",
Operator: metav1.LabelSelectorOpIn,
Values: []string{
"b",
},
},
{
Key: "ns",
Operator: metav1.LabelSelectorOpIn,
Values: []string{
"t",
},
},
},
MatchLabels: commonMatchLabel,
},
{
MatchExpressions: []metav1.LabelSelectorRequirement{
{
Key: "testExists",
Operator: metav1.LabelSelectorOpExists,
Values: []string{},
},
{
Key: "testIn",
Operator: metav1.LabelSelectorOpIn,
Values: []string{
"backend",
},
},
{
Key: "pod",
Operator: metav1.LabelSelectorOpIn,
Values: []string{
"b",
},
},
{
Key: "ns",
Operator: metav1.LabelSelectorOpIn,
Values: []string{
"y",
},
},
},
MatchLabels: commonMatchLabel,
},
{
MatchExpressions: []metav1.LabelSelectorRequirement{
{
Key: "testExists",
Operator: metav1.LabelSelectorOpExists,
Values: []string{},
},
{
Key: "testIn",
Operator: metav1.LabelSelectorOpIn,
Values: []string{
"frontend",
},
},
{
Key: "pod",
Operator: metav1.LabelSelectorOpIn,
Values: []string{
"a",
},
},
{
Key: "ns",
Operator: metav1.LabelSelectorOpIn,
Values: []string{
"t",
},
},
},
MatchLabels: commonMatchLabel,
},
{
MatchExpressions: []metav1.LabelSelectorRequirement{
{
Key: "testExists",
Operator: metav1.LabelSelectorOpExists,
Values: []string{},
},
{
Key: "testIn",
Operator: metav1.LabelSelectorOpIn,
Values: []string{
"frontend",
},
},
{
Key: "pod",
Operator: metav1.LabelSelectorOpIn,
Values: []string{
"a",
},
},
{
Key: "ns",
Operator: metav1.LabelSelectorOpIn,
Values: []string{
"y",
},
},
},
MatchLabels: commonMatchLabel,
},
{
MatchExpressions: []metav1.LabelSelectorRequirement{
{
Key: "testExists",
Operator: metav1.LabelSelectorOpExists,
Values: []string{},
},
{
Key: "testIn",
Operator: metav1.LabelSelectorOpIn,
Values: []string{
"frontend",
},
},
{
Key: "pod",
Operator: metav1.LabelSelectorOpIn,
Values: []string{
"b",
},
},
{
Key: "ns",
Operator: metav1.LabelSelectorOpIn,
Values: []string{
"t",
},
},
},
MatchLabels: commonMatchLabel,
},
{
MatchExpressions: []metav1.LabelSelectorRequirement{
{
Key: "testExists",
Operator: metav1.LabelSelectorOpExists,
Values: []string{},
},
{
Key: "testIn",
Operator: metav1.LabelSelectorOpIn,
Values: []string{
"frontend",
},
},
{
Key: "pod",
Operator: metav1.LabelSelectorOpIn,
Values: []string{
"b",
},
},
{
Key: "ns",
Operator: metav1.LabelSelectorOpIn,
Values: []string{
"y",
},
},
},
MatchLabels: commonMatchLabel,
},
}
if !reflect.DeepEqual(expectedSelectors, testSelectors) {
t.Errorf("TestFlattenNameSpaceSelector failed @ 2nd selector deepEqual check.\n Expected: %+v \n Actual: %+v", expectedSelectors, testSelectors)
}
}
func TestFlattenNameSpaceSelectorWoMatchLabels(t *testing.T) {
firstSelector := &metav1.LabelSelector{
MatchExpressions: []metav1.LabelSelectorRequirement{
{
Key: "testIn",
Operator: metav1.LabelSelectorOpIn,
Values: []string{
"backend",
},
},
{
Key: "pod",
Operator: metav1.LabelSelectorOpIn,
Values: []string{
"a",
},
},
{
Key: "testExists",
Operator: metav1.LabelSelectorOpExists,
Values: []string{},
},
{
Key: "ns",
Operator: metav1.LabelSelectorOpIn,
Values: []string{
"t",
"y",
},
},
},
}
testSelectors := FlattenNameSpaceSelector(firstSelector)
if len(testSelectors) != 2 {
t.Errorf("TestFlattenNameSpaceSelector failed @ 1st selector length check %+v", testSelectors)
}
expectedSelectors := []metav1.LabelSelector{
{
MatchExpressions: []metav1.LabelSelectorRequirement{
{
Key: "testIn",
Operator: metav1.LabelSelectorOpIn,
Values: []string{
"backend",
},
},
{
Key: "pod",
Operator: metav1.LabelSelectorOpIn,
Values: []string{
"a",
},
},
{
Key: "testExists",
Operator: metav1.LabelSelectorOpExists,
Values: []string{},
},
{
Key: "ns",
Operator: metav1.LabelSelectorOpIn,
Values: []string{
"t",
},
},
},
},
{
MatchExpressions: []metav1.LabelSelectorRequirement{
{
Key: "testIn",
Operator: metav1.LabelSelectorOpIn,
Values: []string{
"backend",
},
},
{
Key: "pod",
Operator: metav1.LabelSelectorOpIn,
Values: []string{
"a",
},
},
{
Key: "testExists",
Operator: metav1.LabelSelectorOpExists,
Values: []string{},
},
{
Key: "ns",
Operator: metav1.LabelSelectorOpIn,
Values: []string{
"y",
},
},
},
},
}
if !reflect.DeepEqual(testSelectors, expectedSelectors) {
t.Errorf("TestFlattenNameSpaceSelector failed @ 1st selector deepEqual check.\n Expected: %+v \n Actual: %+v", expectedSelectors, testSelectors)
}
}

Просмотреть файл

@ -0,0 +1,506 @@
package translation
import (
"errors"
"fmt"
"strings"
"github.com/Azure/azure-container-networking/npm/pkg/dataplane/ipsets"
"github.com/Azure/azure-container-networking/npm/pkg/dataplane/policies"
"github.com/Azure/azure-container-networking/npm/util"
networkingv1 "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/klog"
)
/*
TODO
1. namespace is default in label in K8s. Need to check whether I missed something.
- Targeting a Namespace by its name
(https://kubernetes.io/docs/concepts/services-networking/network-policies/#targeting-a-namespace-by-its-name)
2. Check possible error - first check see how K8s guarantees correctness of the submitted network policy
- Return error and validation
3. Need to handle 0.0.0.0/0 in IPBlock field
- Ipset doesn't allow 0.0.0.0/0 to be added. A general solution is split 0.0.0.0/1 in half which convert to
1.0.0.0/1 and 128.0.0.0/1 in linux
*/
var errUnknownPortType = errors.New("unknown port Type")
type netpolPortType string
const (
numericPortType netpolPortType = "validport"
namedPortType netpolPortType = "namedport"
included bool = true
ipBlocksetNameFormat = "%s-in-ns-%s-%d%s"
onlyKeyLabel = 1
keyValueLabel = 2
)
func portType(portRule networkingv1.NetworkPolicyPort) (netpolPortType, error) {
if portRule.Port == nil || portRule.Port.IntValue() != 0 {
return numericPortType, nil
} else if portRule.Port.IntValue() == 0 && portRule.Port.String() != "" {
return namedPortType, nil
}
// TODO (jungukcho): check whether this can be possible or not.
return "", errUnknownPortType
}
func numericPortRule(portRule *networkingv1.NetworkPolicyPort) (portRuleInfo policies.Ports, protocol string) {
portRuleInfo = policies.Ports{}
protocol = "TCP"
if portRule.Protocol != nil {
protocol = string(*portRule.Protocol)
}
if portRule.Port == nil {
return portRuleInfo, protocol
}
portRuleInfo.Port = int32(portRule.Port.IntValue())
if portRule.EndPort != nil {
portRuleInfo.EndPort = *portRule.EndPort
}
return portRuleInfo, protocol
}
func namedPortRuleInfo(portRule *networkingv1.NetworkPolicyPort) (namedPortIPSet *ipsets.TranslatedIPSet, protocol string) {
if portRule == nil {
return nil, ""
}
protocol = "TCP"
if portRule.Protocol != nil {
protocol = string(*portRule.Protocol)
}
if portRule.Port == nil {
return nil, protocol
}
namedPortIPSet = ipsets.NewTranslatedIPSet(util.NamedPortIPSetPrefix+portRule.Port.String(), ipsets.NamedPorts, []string{})
return namedPortIPSet, protocol
}
func namedPortRule(portRule *networkingv1.NetworkPolicyPort) (*ipsets.TranslatedIPSet, policies.SetInfo, string) {
if portRule == nil {
return nil, policies.SetInfo{}, ""
}
namedPortIPSet, protocol := namedPortRuleInfo(portRule)
setInfo := policies.NewSetInfo(util.NamedPortIPSetPrefix+portRule.Port.String(), ipsets.NamedPorts, included, policies.DstDstMatch)
return namedPortIPSet, setInfo, protocol
}
func portRule(ruleIPSets []*ipsets.TranslatedIPSet, acl *policies.ACLPolicy, portRule *networkingv1.NetworkPolicyPort, portType netpolPortType) []*ipsets.TranslatedIPSet {
if portType == namedPortType {
namedPortIPSet, namedPortRuleDstList, protocol := namedPortRule(portRule)
acl.DstList = append(acl.DstList, namedPortRuleDstList)
acl.Protocol = policies.Protocol(protocol)
ruleIPSets = append(ruleIPSets, namedPortIPSet)
} else if portType == numericPortType {
portInfo, protocol := numericPortRule(portRule)
acl.DstPorts = portInfo
acl.Protocol = policies.Protocol(protocol)
}
return ruleIPSets
}
func ipBlockSetName(policyName, ns string, direction policies.Direction, ipBlockSetIndex int) string {
return fmt.Sprintf(ipBlocksetNameFormat, policyName, ns, ipBlockSetIndex, direction)
}
func ipBlockIPSet(policyName, ns string, direction policies.Direction, ipBlockSetIndex int, ipBlockRule *networkingv1.IPBlock) *ipsets.TranslatedIPSet {
if ipBlockRule == nil || ipBlockRule.CIDR == "" {
return nil
}
members := make([]string, len(ipBlockRule.Except)+1) // except + cidr
cidrIndex := 0
members[cidrIndex] = ipBlockRule.CIDR
for i := 0; i < len(ipBlockRule.Except); i++ {
members[i+1] = ipBlockRule.Except[i] + util.IpsetNomatch
}
ipBlockIPSetName := ipBlockSetName(policyName, ns, direction, ipBlockSetIndex)
ipBlockIPSet := ipsets.NewTranslatedIPSet(ipBlockIPSetName, ipsets.CIDRBlocks, members)
return ipBlockIPSet
}
func ipBlockRule(policyName, ns string, direction policies.Direction, ipBlockSetIndex int, ipBlockRule *networkingv1.IPBlock) (*ipsets.TranslatedIPSet, policies.SetInfo) {
if ipBlockRule == nil || ipBlockRule.CIDR == "" {
return nil, policies.SetInfo{}
}
ipBlockIPSet := ipBlockIPSet(policyName, ns, direction, ipBlockSetIndex, ipBlockRule)
setInfo := policies.NewSetInfo(ipBlockIPSet.Metadata.Name, ipsets.CIDRBlocks, included, policies.SrcMatch)
return ipBlockIPSet, setInfo
}
func podLabelType(label string) ipsets.SetType {
// TODO(jungukcho): this is unnecessary function which has extra computation
// will be removed after optimizing parseSelector function
labels := strings.Split(label, ":")
switch LenOfLabels := len(labels); LenOfLabels {
case onlyKeyLabel:
return ipsets.KeyLabelOfPod
case keyValueLabel:
return ipsets.KeyValueLabelOfPod
default: // in case of nested value (i.e., len(labels) >= 3
return ipsets.NestedLabelOfPod
}
}
// podSelectorRule return srcList for ACL by using ops and labelsForSpec
func podSelectorRule(matchType policies.MatchType, ops, ipSetForACL []string) []policies.SetInfo {
podSelectorList := []policies.SetInfo{}
for i := 0; i < len(ipSetForACL); i++ {
noOp := ops[i] == ""
labelType := podLabelType(ipSetForACL[i])
setInfo := policies.NewSetInfo(ipSetForACL[i], labelType, noOp, matchType)
podSelectorList = append(podSelectorList, setInfo)
}
return podSelectorList
}
func podSelectorIPSets(ipSetForSingleVal []string, ipSetNameForMultiVal map[string][]string) []*ipsets.TranslatedIPSet {
podSelectorIPSets := []*ipsets.TranslatedIPSet{}
for _, hashSetName := range ipSetForSingleVal {
labelType := podLabelType(hashSetName)
ipset := ipsets.NewTranslatedIPSet(hashSetName, labelType, []string{})
podSelectorIPSets = append(podSelectorIPSets, ipset)
}
for listSetName, hashIPSetList := range ipSetNameForMultiVal {
ipset := ipsets.NewTranslatedIPSet(listSetName, ipsets.NestedLabelOfPod, hashIPSetList)
podSelectorIPSets = append(podSelectorIPSets, ipset)
}
return podSelectorIPSets
}
func targetPodSelectorInfo(selector *metav1.LabelSelector) (ops, ipSetForACL, ipSetForSingleVal []string, ipSetNameForMultiVal map[string][]string) {
// TODO(jungukcho) : need to revise parseSelector function to reduce computations and enhance readability
// 1. use better variables to indicate included instead of "".
// 2. Classify type of set in parseSelector to avoid multiple computations
// 3. Resolve makezero lint errors (nozero)
singleValueLabelsWithOps, multiValuesLabelsWithOps := parseSelector(selector)
ops, ipSetForSingleVal = GetOperatorsAndLabels(singleValueLabelsWithOps)
ipSetNameForMultiVal = make(map[string][]string)
LenOfIPSetForACL := len(ipSetForSingleVal) + len(multiValuesLabelsWithOps)
ipSetForACL = make([]string, LenOfIPSetForACL)
IndexOfIPSetForACL := copy(ipSetForACL, ipSetForSingleVal)
for multiValueLabelKeyWithOps, multiValueLabelList := range multiValuesLabelsWithOps {
op, multiValueLabelKey := GetOperatorAndLabel(multiValueLabelKeyWithOps)
ops = append(ops, op) // nozero
ipSetNameForMultiValueLabel := getSetNameForMultiValueSelector(multiValueLabelKey, multiValueLabelList)
ipSetForACL[IndexOfIPSetForACL] = ipSetNameForMultiValueLabel
IndexOfIPSetForACL++
for _, labelValue := range multiValueLabelList {
ipsetName := util.GetIpSetFromLabelKV(multiValueLabelKey, labelValue)
ipSetForSingleVal = append(ipSetForSingleVal, ipsetName) // nozero
ipSetNameForMultiVal[ipSetNameForMultiValueLabel] = append(ipSetNameForMultiVal[ipSetNameForMultiValueLabel], ipsetName)
}
}
return ops, ipSetForACL, ipSetForSingleVal, ipSetNameForMultiVal
}
func allPodsSelectorInNs(ns string, matchType policies.MatchType) ([]*ipsets.TranslatedIPSet, []policies.SetInfo) {
// TODO(jungukcho): important this is common component - double-check whether it has duplicated one or not
ipset := ipsets.NewTranslatedIPSet(ns, ipsets.Namespace, []string{})
podSelectorIPSets := []*ipsets.TranslatedIPSet{ipset}
setInfo := policies.NewSetInfo(ns, ipsets.Namespace, included, matchType)
podSelectorList := []policies.SetInfo{setInfo}
return podSelectorIPSets, podSelectorList
}
func targetPodSelector(ns string, matchType policies.MatchType, selector *metav1.LabelSelector) ([]*ipsets.TranslatedIPSet, []policies.SetInfo) {
// (TODO): some data in singleValueLabels and multiValuesLabels are duplicated
ops, ipSetForACL, ipSetForSingleVal, ipSetNameForMultiVal := targetPodSelectorInfo(selector)
// select all pods in a namespace
if len(ops) == 1 && len(ipSetForSingleVal) == 1 && ops[0] == "" && ipSetForSingleVal[0] == "" {
podSelectorIPSets, podSelectorList := allPodsSelectorInNs(ns, matchType)
return podSelectorIPSets, podSelectorList
}
// TODO(jungukcho): may need to check ordering hashset and listset if ipSetNameForMultiVal exists.
// refer to last test set in TestPodSelectorIPSets
podSelectorIPSets := podSelectorIPSets(ipSetForSingleVal, ipSetNameForMultiVal)
podSelectorList := podSelectorRule(matchType, ops, ipSetForACL)
return podSelectorIPSets, podSelectorList
}
func nsLabelType(label string) ipsets.SetType {
// TODO(jungukcho): this is unnecessary function which has extra computation
// will be removed after optimizing parseSelector function
labels := strings.Split(label, ":")
if len(labels) == onlyKeyLabel {
return ipsets.KeyLabelOfNamespace
} else if len(labels) == keyValueLabel {
return ipsets.KeyValueLabelOfNamespace
}
// (TODO): check whether this is possible
return ipsets.UnknownType
}
func nameSpaceSelectorRule(matchType policies.MatchType, ops, nsSelectorInfo []string) []policies.SetInfo {
nsSelectorList := []policies.SetInfo{}
for i := 0; i < len(nsSelectorInfo); i++ {
noOp := ops[i] == ""
labelType := nsLabelType(nsSelectorInfo[i])
setInfo := policies.NewSetInfo(nsSelectorInfo[i], labelType, noOp, matchType)
nsSelectorList = append(nsSelectorList, setInfo)
}
return nsSelectorList
}
func nameSpaceSelectorIPSets(singleValueLabels []string) []*ipsets.TranslatedIPSet {
nsSelectorIPSets := []*ipsets.TranslatedIPSet{}
for _, listSet := range singleValueLabels {
labelType := nsLabelType(listSet)
translatedIPSet := ipsets.NewTranslatedIPSet(listSet, labelType, []string{})
nsSelectorIPSets = append(nsSelectorIPSets, translatedIPSet)
}
return nsSelectorIPSets
}
func nameSpaceSelectorInfo(selector *metav1.LabelSelector) (ops, singleValueLabels []string) {
// parse namespace label selector.
// Ignore multiple values from parseSelector since Namespace selector does not have multiple values.
// TODO(jungukcho): will revise parseSelector for easy understanding between podSelector and namespaceSelector
singleValueLabelsWithOps, _ := parseSelector(selector)
ops, singleValueLabels = GetOperatorsAndLabels(singleValueLabelsWithOps)
return ops, singleValueLabels
}
func allNameSpaceRule(matchType policies.MatchType) ([]*ipsets.TranslatedIPSet, []policies.SetInfo) {
translatedIPSet := ipsets.NewTranslatedIPSet(util.KubeAllNamespacesFlag, ipsets.Namespace, []string{})
nsSelectorIPSets := []*ipsets.TranslatedIPSet{translatedIPSet}
setInfo := policies.NewSetInfo(util.KubeAllNamespacesFlag, ipsets.Namespace, included, matchType)
nsSelectorList := []policies.SetInfo{setInfo}
return nsSelectorIPSets, nsSelectorList
}
func nameSpaceSelector(matchType policies.MatchType, selector *metav1.LabelSelector) ([]*ipsets.TranslatedIPSet, []policies.SetInfo) {
ops, singleValueLabels := nameSpaceSelectorInfo(selector)
if len(ops) == 1 && len(singleValueLabels) == 1 && ops[0] == "" && singleValueLabels[0] == "" {
nsSelectorIPSets, nsSelectorList := allNameSpaceRule(matchType)
return nsSelectorIPSets, nsSelectorList
}
nsSelectorIPSets := nameSpaceSelectorIPSets(singleValueLabels)
nsSelectorList := nameSpaceSelectorRule(matchType, ops, singleValueLabels)
return nsSelectorIPSets, nsSelectorList
}
func allowAllTraffic(matchType policies.MatchType) (*ipsets.TranslatedIPSet, policies.SetInfo) {
allowAllIPSets := ipsets.NewTranslatedIPSet(util.KubeAllNamespacesFlag, ipsets.Namespace, []string{})
setInfo := policies.NewSetInfo(util.KubeAllNamespacesFlag, ipsets.Namespace, included, matchType)
return allowAllIPSets, setInfo
}
func defaultDropACL(policyNS, policyName string, direction policies.Direction) *policies.ACLPolicy {
dropACL := policies.NewACLPolicy(policyNS, policyName, policies.Dropped, direction)
return dropACL
}
// ruleExists returns type of rules from networkingv1.NetworkPolicyIngressRule or networkingv1.NetworkPolicyEgressRule
func ruleExists(ports []networkingv1.NetworkPolicyPort, peer []networkingv1.NetworkPolicyPeer) (allowExternal, portRuleExists, peerRuleExists bool) {
// TODO(jungukcho): need to clarify and summarize below flags
portRuleExists = len(ports) > 0
if peer != nil {
if len(peer) == 0 {
peerRuleExists = true
allowExternal = true
}
for _, peerRule := range peer {
if peerRule.PodSelector != nil ||
peerRule.NamespaceSelector != nil ||
peerRule.IPBlock != nil {
peerRuleExists = true
break
}
}
} else if !portRuleExists {
allowExternal = true
}
return allowExternal, portRuleExists, peerRuleExists
}
func peerAndPortRule(npmNetPol *policies.NPMNetworkPolicy, ports []networkingv1.NetworkPolicyPort, setInfo []policies.SetInfo) {
if len(ports) == 0 {
acl := policies.NewACLPolicy(npmNetPol.NameSpace, npmNetPol.Name, policies.Allowed, policies.Ingress)
acl.SrcList = setInfo
npmNetPol.ACLs = append(npmNetPol.ACLs, acl)
return
}
for i := range ports {
portKind, err := portType(ports[i])
if err != nil {
// TODO(jungukcho): handle error
klog.Infof("Invalid NetworkPolicyPort %s", err)
continue
}
acl := policies.NewACLPolicy(npmNetPol.NameSpace, npmNetPol.Name, policies.Allowed, policies.Ingress)
acl.SrcList = setInfo
npmNetPol.RuleIPSets = portRule(npmNetPol.RuleIPSets, acl, &ports[i], portKind)
npmNetPol.ACLs = append(npmNetPol.ACLs, acl)
}
}
func translateIngress(npmNetPol *policies.NPMNetworkPolicy, targetSelector *metav1.LabelSelector, rules []networkingv1.NetworkPolicyIngressRule) {
// TODO(jungukcho) : Double-check addedCidrEntry.
var addedCidrEntry bool // all cidr entry will be added in one set per from/to rule
npmNetPol.PodSelectorIPSets, npmNetPol.PodSelectorList = targetPodSelector(npmNetPol.NameSpace, policies.DstMatch, targetSelector)
for i, rule := range rules {
allowExternal, portRuleExists, fromRuleExists := ruleExists(rule.Ports, rule.From)
// #0. TODO(jungukcho): cannot come up when this condition is met.
if !portRuleExists && !fromRuleExists && !allowExternal {
acl := policies.NewACLPolicy(npmNetPol.NameSpace, npmNetPol.Name, policies.Allowed, policies.Ingress)
ruleIPSets, setInfo := allowAllTraffic(policies.SrcMatch)
npmNetPol.RuleIPSets = append(npmNetPol.RuleIPSets, ruleIPSets)
acl.SrcList = append(acl.SrcList, setInfo)
npmNetPol.ACLs = append(npmNetPol.ACLs, acl)
continue
}
// #1. Only Ports fields exist in rule
if portRuleExists && !fromRuleExists && !allowExternal {
for i := range rule.Ports {
portKind, err := portType(rule.Ports[i])
if err != nil {
klog.Infof("Invalid NetworkPolicyPort %s", err)
continue
}
portACL := policies.NewACLPolicy(npmNetPol.NameSpace, npmNetPol.Name, policies.Allowed, policies.Ingress)
npmNetPol.RuleIPSets = portRule(npmNetPol.RuleIPSets, portACL, &rule.Ports[i], portKind)
npmNetPol.ACLs = append(npmNetPol.ACLs, portACL)
}
continue
}
// #2. From fields exist in rule
for j, fromRule := range rule.From {
// #2.1 Handle IPBlock and port if exist
if fromRule.IPBlock != nil {
if len(fromRule.IPBlock.CIDR) > 0 {
// TODO(jungukcho): check this - need UTs
// TODO(jungukcho): need a const for "in"
ipBlockIPSet, ipBlockSetInfo := ipBlockRule(npmNetPol.Name, npmNetPol.NameSpace, policies.Ingress, i, fromRule.IPBlock)
npmNetPol.RuleIPSets = append(npmNetPol.RuleIPSets, ipBlockIPSet)
if j != 0 && addedCidrEntry {
continue
}
peerAndPortRule(npmNetPol, rule.Ports, []policies.SetInfo{ipBlockSetInfo})
addedCidrEntry = true
}
// Do not check further since IPBlock filed is exclusive field.
continue
}
// if there is no podSelector or namespaceSelector in fromRule, no need to check below code.
if fromRule.PodSelector == nil && fromRule.NamespaceSelector == nil {
continue
}
// #2.2 handle nameSpaceSelector and port if exist
if fromRule.PodSelector == nil && fromRule.NamespaceSelector != nil {
flattenNSSelctor := FlattenNameSpaceSelector(fromRule.NamespaceSelector)
for i := range flattenNSSelctor {
nsSelectorIPSets, nsSrcList := nameSpaceSelector(policies.SrcMatch, &flattenNSSelctor[i])
npmNetPol.RuleIPSets = append(npmNetPol.RuleIPSets, nsSelectorIPSets...)
peerAndPortRule(npmNetPol, rule.Ports, nsSrcList)
}
continue
}
// #2.3 handle podSelector and port if exist
if fromRule.PodSelector != nil && fromRule.NamespaceSelector == nil {
// TODO check old code if we need any ns- prefix for pod selectors
podSelectorIPSets, podSelectorSrcList := targetPodSelector(npmNetPol.NameSpace, policies.SrcMatch, fromRule.PodSelector)
npmNetPol.RuleIPSets = append(npmNetPol.RuleIPSets, podSelectorIPSets...)
peerAndPortRule(npmNetPol, rule.Ports, podSelectorSrcList)
continue
}
// fromRule has both namespaceSelector and podSelector set.
// We should match the selected pods in the selected namespaces.
// This allows traffic from podSelector intersects namespaceSelector
// This is only supported in kubernetes version >= 1.11
if !util.IsNewNwPolicyVerFlag {
continue
}
// #2.4 handle namespaceSelector and podSelector and port if exist
podSelectorIPSets, podSelectorSrcList := targetPodSelector(npmNetPol.NameSpace, policies.SrcMatch, fromRule.PodSelector)
npmNetPol.RuleIPSets = append(npmNetPol.RuleIPSets, podSelectorIPSets...)
flattenNSSelctor := FlattenNameSpaceSelector(fromRule.NamespaceSelector)
for i := range flattenNSSelctor {
nsSelectorIPSets, nsSrcList := nameSpaceSelector(policies.SrcMatch, &flattenNSSelctor[i])
npmNetPol.RuleIPSets = append(npmNetPol.RuleIPSets, nsSelectorIPSets...)
nsSrcList = append(nsSrcList, podSelectorSrcList...)
peerAndPortRule(npmNetPol, rule.Ports, nsSrcList)
}
}
// TODO(jungukcho): move this code in entry point of this function?
if allowExternal {
allowExternalACL := policies.NewACLPolicy(npmNetPol.NameSpace, npmNetPol.Name, policies.Allowed, policies.Ingress)
npmNetPol.ACLs = append(npmNetPol.ACLs, allowExternalACL)
}
}
klog.Info("finished parsing ingress rule")
}
func existIngress(npObj *networkingv1.NetworkPolicy) bool { //nolint:unused //it will be called from v2 networkPolicyController which will come in next PR
return !(npObj.Spec.Ingress != nil &&
len(npObj.Spec.Ingress) == 1 &&
len(npObj.Spec.Ingress[0].Ports) == 0 &&
len(npObj.Spec.Ingress[0].From) == 0)
}
func translatePolicy(npObj *networkingv1.NetworkPolicy) *policies.NPMNetworkPolicy { //nolint:deadcode,unused //it will be called from v2 networkPolicyController which will come in next PR
npmNetPol := &policies.NPMNetworkPolicy{
Name: npObj.ObjectMeta.Name,
NameSpace: npObj.ObjectMeta.Namespace,
}
if len(npObj.Spec.PolicyTypes) == 0 {
translateIngress(npmNetPol, &npObj.Spec.PodSelector, npObj.Spec.Ingress)
return npmNetPol
}
for _, ptype := range npObj.Spec.PolicyTypes {
if ptype == networkingv1.PolicyTypeIngress {
translateIngress(npmNetPol, &npObj.Spec.PodSelector, npObj.Spec.Ingress)
}
}
if hasIngress := existIngress(npObj); hasIngress {
dropACL := defaultDropACL(npmNetPol.NameSpace, npmNetPol.Name, policies.Ingress)
npmNetPol.ACLs = append(npmNetPol.ACLs, dropACL)
}
return npmNetPol
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -377,7 +377,7 @@ func (dp *DataPlane) deleteIPSetsAndReferences(sets []*ipsets.TranslatedIPSet, n
return npmerrors.Errorf(npmErrorString, false, fmt.Sprintf("[dataplane] failed to RemoveFromSet in deleteIPSetReferences with err: %s", err.Error()))
}
}
} else if ipsets.GetSetKind(set.Metadata.Type) == ipsets.ListSet && len(set.Members) > 0 {
} else if set.Metadata.GetSetKind() == ipsets.ListSet && len(set.Members) > 0 {
// Delete if any 2nd level IPSets are generated by Controller with members
err := dp.ipsetMgr.RemoveFromList(set.Metadata, getMembersOfTranslatedSets(set.Members))
if err != nil {

Просмотреть файл

@ -10,35 +10,90 @@ import (
npmerrors "github.com/Azure/azure-container-networking/npm/util/errors"
)
type IPSet struct {
Name string
HashedName string
// SetProperties embedding set properties
SetProperties
// IpPodKey is used for setMaps to store Ips and ports as keys
// and podKey as value
IPPodKey map[string]string
// This is used for listMaps to store child IP Sets
MemberIPSets map[string]*IPSet
// Using a map to emulate set and value as struct{} for
// minimal memory consumption
// SelectorReference holds networkpolicy names where this IPSet
// is being used in PodSelector and NameSpace
SelectorReference map[string]struct{}
// NetPolReference holds networkpolicy names where this IPSet
// is being referred as part of rules
NetPolReference map[string]struct{}
// ipsetReferCount keeps track of how many lists in the cache refer to this ipset
ipsetReferCount int
// kernelReferCount keeps track of how many lists in the kernel refer to this ipset
kernelReferCount int
}
type IPSetMetadata struct {
Name string
Type SetType
}
type SetKind string
const (
// ListSet is of kind list with members as other IPSets
ListSet SetKind = "list"
// HashSet is of kind hashset with members as IPs and/or port
HashSet SetKind = "set"
// UnknownKind is returned when kind is unknown
UnknownKind SetKind = "unknown"
)
// NewIPSetMetadata is used for controllers to send in skeleton ipsets to DP
func NewIPSetMetadata(name string, setType SetType) *IPSetMetadata {
set := &IPSetMetadata{
Name: name,
Type: setType,
}
return set
}
func (setMetadata *IPSetMetadata) GetHashedName() string {
// TODO(jungukcho): I think this is unnecessary code.
prefixedName := setMetadata.GetPrefixName()
if prefixedName == Unknown {
return Unknown
}
return util.GetHashedName(prefixedName)
}
func (setMetadata *IPSetMetadata) GetPrefixName() string {
switch setMetadata.Type {
case CIDRBlocks:
return fmt.Sprintf("%s%s", util.CIDRPrefix, setMetadata.Name)
case Namespace:
return fmt.Sprintf("%s%s", util.NamespacePrefix, setMetadata.Name)
case NamedPorts:
return fmt.Sprintf("%s%s", util.NamedPortIPSetPrefix, setMetadata.Name)
case KeyLabelOfPod:
return fmt.Sprintf("%s%s", util.PodLabelPrefix, setMetadata.Name)
case KeyValueLabelOfPod:
return fmt.Sprintf("%s%s", util.PodLabelPrefix, setMetadata.Name)
case KeyLabelOfNamespace:
return fmt.Sprintf("%s%s", util.NamespaceLabelPrefix, setMetadata.Name)
case KeyValueLabelOfNamespace:
return fmt.Sprintf("%s%s", util.NamespaceLabelPrefix, setMetadata.Name)
case NestedLabelOfPod:
return fmt.Sprintf("%s%s", util.NestedLabelPrefix, setMetadata.Name)
case UnknownType: // adding this to appease golint
return Unknown
default:
return Unknown
}
}
func (setMetadata *IPSetMetadata) GetSetKind() SetKind {
switch setMetadata.Type {
case CIDRBlocks:
return HashSet
case Namespace:
return HashSet
case NamedPorts:
return HashSet
case KeyLabelOfPod:
return HashSet
case KeyValueLabelOfPod:
return HashSet
case KeyLabelOfNamespace:
return ListSet
case KeyValueLabelOfNamespace:
return ListSet
case NestedLabelOfPod:
return ListSet
case UnknownType: // adding this to appease golint
return UnknownKind
default:
return UnknownKind
}
}
// TranslatedIPSet is created by translation engine and provides IPSets used in
// network policy. Only 2 types of IPSets are generated with members:
// 1. CIDRBlocks IPSet
@ -52,6 +107,15 @@ type TranslatedIPSet struct {
Members []string
}
// NewTranslatedIPSet creates TranslatedIPSet.
func NewTranslatedIPSet(name string, setType SetType, members []string) *TranslatedIPSet {
translatedIPSet := &TranslatedIPSet{
Metadata: NewIPSetMetadata(name, setType),
Members: members,
}
return translatedIPSet
}
type SetProperties struct {
// Stores type of ip grouping
Type SetType
@ -107,17 +171,6 @@ func (x SetType) String() string {
return setTypeName[x]
}
type SetKind string
const (
// ListSet is of kind list with members as other IPSets
ListSet SetKind = "list"
// HashSet is of kind hashset with members as IPs and/or port
HashSet SetKind = "set"
// UnknownKind is returned when kind is unknown
UnknownKind SetKind = "unknown"
)
// ReferenceType specifies the kind of reference for an IPSet
type ReferenceType string
@ -127,6 +180,30 @@ const (
NetPolType ReferenceType = "NetPol"
)
type IPSet struct {
Name string
HashedName string
// SetProperties embedding set properties
SetProperties
// IpPodKey is used for setMaps to store Ips and ports as keys
// and podKey as value
IPPodKey map[string]string
// This is used for listMaps to store child IP Sets
MemberIPSets map[string]*IPSet
// Using a map to emulate set and value as struct{} for
// minimal memory consumption
// SelectorReference holds networkpolicy names where this IPSet
// is being used in PodSelector and NameSpace
SelectorReference map[string]struct{}
// NetPolReference holds networkpolicy names where this IPSet
// is being referred as part of rules
NetPolReference map[string]struct{}
// ipsetReferCount keeps track of how many lists in the cache refer to this ipset
ipsetReferCount int
// kernelReferCount keeps track of how many lists in the kernel refer to this ipset
kernelReferCount int
}
func NewIPSet(setMetadata *IPSetMetadata) *IPSet {
prefixedName := setMetadata.GetPrefixName()
set := &IPSet{
@ -134,7 +211,7 @@ func NewIPSet(setMetadata *IPSetMetadata) *IPSet {
HashedName: util.GetHashedName(prefixedName),
SetProperties: SetProperties{
Type: setMetadata.Type,
Kind: GetSetKind(setMetadata.Type),
Kind: setMetadata.GetSetKind(),
},
// Map with Key as Network Policy name to to emulate set
// and value as struct{} for minimal memory consumption
@ -153,46 +230,9 @@ func NewIPSet(setMetadata *IPSetMetadata) *IPSet {
return set
}
// NewIPSetMetadata is used for controllers to send in skeleton ipsets to DP
func NewIPSetMetadata(name string, setType SetType) *IPSetMetadata {
set := &IPSetMetadata{
Name: name,
Type: setType,
}
return set
}
func (setMetadata *IPSetMetadata) GetPrefixName() string {
switch setMetadata.Type {
case CIDRBlocks:
return fmt.Sprintf("%s%s", util.CIDRPrefix, setMetadata.Name)
case Namespace:
return fmt.Sprintf("%s%s", util.NamespacePrefix, setMetadata.Name)
case NamedPorts:
return fmt.Sprintf("%s%s", util.NamedPortIPSetPrefix, setMetadata.Name)
case KeyLabelOfPod:
return fmt.Sprintf("%s%s", util.PodLabelPrefix, setMetadata.Name)
case KeyValueLabelOfPod:
return fmt.Sprintf("%s%s", util.PodLabelPrefix, setMetadata.Name)
case KeyLabelOfNamespace:
return fmt.Sprintf("%s%s", util.NamespaceLabelPrefix, setMetadata.Name)
case KeyValueLabelOfNamespace:
return fmt.Sprintf("%s%s", util.NamespaceLabelPrefix, setMetadata.Name)
case NestedLabelOfPod:
return fmt.Sprintf("%s%s", util.NestedLabelPrefix, setMetadata.Name)
case UnknownType: // adding this to appease golint
return Unknown
default:
return Unknown
}
}
func (setMetadata *IPSetMetadata) GetHashedName() string {
prefixedName := setMetadata.GetPrefixName()
if prefixedName == Unknown {
return Unknown
}
return util.GetHashedName(prefixedName)
func (set *IPSet) String() string {
return fmt.Sprintf("Name: %s HashedNamed: %s Type: %s Kind: %s",
set.Name, set.HashedName, setTypeName[set.Type], string(set.Kind))
}
func (set *IPSet) GetSetContents() ([]string, error) {
@ -265,31 +305,6 @@ func (set *IPSet) Compare(newSet *IPSet) bool {
return true
}
func GetSetKind(setType SetType) SetKind {
switch setType {
case CIDRBlocks:
return HashSet
case Namespace:
return HashSet
case NamedPorts:
return HashSet
case KeyLabelOfPod:
return HashSet
case KeyValueLabelOfPod:
return HashSet
case KeyLabelOfNamespace:
return ListSet
case KeyValueLabelOfNamespace:
return ListSet
case NestedLabelOfPod:
return ListSet
case UnknownType: // adding this to appease golint
return UnknownKind
default:
return UnknownKind
}
}
func (set *IPSet) incIPSetReferCount() {
set.ipsetReferCount++
}

Просмотреть файл

@ -174,9 +174,7 @@ func (pMgr *PolicyManager) getCreatorForInitChains() *ioutil.FileCreator {
// add AZURE-NPM chain rules
creator.AddLine("", nil, util.IptablesAppendFlag, util.IptablesAzureChain, util.IptablesJumpFlag, util.IptablesAzureIngressChain)
creator.AddLine("", nil, util.IptablesAppendFlag, util.IptablesAzureChain, util.IptablesJumpFlag, util.IptablesAzureEgressChain)
creator.AddLine("", nil, util.IptablesAppendFlag, util.IptablesAzureChain, util.IptablesJumpFlag, util.IptablesAzureAcceptChain)
// add AZURE-NPM-INGRESS chain rules
@ -190,7 +188,6 @@ func (pMgr *PolicyManager) getCreatorForInitChains() *ioutil.FileCreator {
markIngressAllowSpecs = append(markIngressAllowSpecs, getSetMarkSpecs(util.IptablesAzureIngressAllowMarkHex)...)
markIngressAllowSpecs = append(markIngressAllowSpecs, getCommentSpecs(fmt.Sprintf("SET-INGRESS-ALLOW-MARK-%s", util.IptablesAzureIngressAllowMarkHex))...)
creator.AddLine("", nil, markIngressAllowSpecs...)
creator.AddLine("", nil, util.IptablesAppendFlag, util.IptablesAzureIngressAllowMarkChain, util.IptablesJumpFlag, util.IptablesAzureEgressChain)
// add AZURE-NPM-EGRESS chain rules
@ -209,9 +206,7 @@ func (pMgr *PolicyManager) getCreatorForInitChains() *ioutil.FileCreator {
clearSpecs = append(clearSpecs, getSetMarkSpecs(util.IptablesAzureClearMarkHex)...)
clearSpecs = append(clearSpecs, getCommentSpecs("Clear-AZURE-NPM-MARKS")...)
creator.AddLine("", nil, clearSpecs...)
creator.AddLine("", nil, util.IptablesAppendFlag, util.IptablesAzureAcceptChain, util.IptablesJumpFlag, util.IptablesAccept)
creator.AddLine("", nil, util.IptablesRestoreCommit)
return creator
}

Просмотреть файл

@ -1,27 +1,30 @@
package policies
import (
"fmt"
"strconv"
"github.com/Azure/azure-container-networking/npm/pkg/dataplane/ipsets"
"github.com/Azure/azure-container-networking/npm/util"
networkingv1 "k8s.io/api/networking/v1"
)
type NPMNetworkPolicy struct {
// Netpol Key
Name string
Name string
NameSpace string
// TODO(jungukcho)
// ipsets.IPSetMetadata is common data in both PodSelectorIPSets and PodSelectorList.
// So, they can be one datastructure holding all information without redundancy.
// PodSelectorIPSets holds all the IPSets generated from Pod Selector
PodSelectorIPSets []*ipsets.TranslatedIPSet
// PodSelectorList holds target pod information to avoid duplicatoin in SrcList and DstList fields in ACLs
PodSelectorList []SetInfo
// RuleIPSets holds all IPSets generated from policy's rules
// and not from pod selector IPSets
//
RuleIPSets []*ipsets.TranslatedIPSet
ACLs []*ACLPolicy
// podIP is key and endpoint ID as value
// Will be populated by dataplane and policy manager
PodEndpoints map[string]string
RawNP *networkingv1.NetworkPolicy
}
// ACLPolicy equivalent to a single iptable rule in linux
@ -42,14 +45,31 @@ type ACLPolicy struct {
Target Verdict
// Direction defines the flow of traffic
Direction Direction
// SrcPorts holds the source port information
SrcPorts []Ports
// DstPorts holds the destination port information
DstPorts []Ports
// TODO(jungukcho): It may be better to use pointer to differentiate default value.
DstPorts Ports
// Protocol is the value of traffic protocol
Protocol Protocol
}
const policyIDPrefix = "azure-acl"
// aclPolicyID returns azure-acl-<network policy namespace>-<network policy name> format
// to differentiate ACLs among different network policies,
// but aclPolicy in the same network policy has the same aclPolicyID.
func aclPolicyID(policyNS, policyName string) string {
return fmt.Sprintf("%s-%s-%s", policyIDPrefix, policyNS, policyName)
}
func NewACLPolicy(policyNS, policyName string, target Verdict, direction Direction) *ACLPolicy {
acl := &ACLPolicy{
PolicyID: aclPolicyID(policyNS, policyName),
Target: target,
Direction: direction,
}
return acl
}
func (aclPolicy *ACLPolicy) hasKnownDirection() bool {
return aclPolicy.Direction == Ingress ||
aclPolicy.Direction == Egress ||
@ -77,16 +97,19 @@ func (aclPolicy *ACLPolicy) hasKnownTarget() bool {
}
func (aclPolicy *ACLPolicy) satisifiesPortAndProtocolConstraints() bool {
return aclPolicy.Protocol != AnyProtocol ||
(len(aclPolicy.SrcPorts) == 0 && len(aclPolicy.DstPorts) == 0)
// TODO(jungukcho): need to check second condition
return (aclPolicy.Protocol != AnyProtocol) || (aclPolicy.DstPorts.Port == 0 && aclPolicy.DstPorts.EndPort == 0)
}
// SetInfo helps capture additional details in a matchSet
// example match set in linux:
// ! azure-npm-123 src,src
// "!" this indicates a negative match of an IPset for src,src
// Included flag captures the negative or positive match
// MatchType captures match flags
// SetInfo helps capture additional details in a matchSet.
// Included flag captures the negative or positive match.
// Included is true when match set does not have "!".
// Included is false when match set have "!".
// MatchType captures match direction flags.
// For example match set in linux:
// ! azure-npm-123 src
// "!" this indicates a negative match (Included is false) of an azure-npm-123
// MatchType is "src"
type SetInfo struct {
IPSet *ipsets.IPSetMetadata
Included bool
@ -97,6 +120,15 @@ type SetInfo struct {
// To specify one port, set Port and EndPort to the same value.
// uint16 is used since there are 2^16 - 1 TCP/UDP ports (0 is invalid)
// and 2^16 SCTP ports. ICMP is connectionless and doesn't use ports.
// NewSetInfo creates SetInfo.
func NewSetInfo(name string, setType ipsets.SetType, included bool, matchType MatchType) SetInfo {
return SetInfo{
IPSet: ipsets.NewIPSetMetadata(name, setType),
Included: included,
MatchType: matchType,
}
}
type Ports struct {
Port int32
EndPort int32

Просмотреть файл

@ -96,15 +96,9 @@ func normalizePolicy(networkPolicy *NPMNetworkPolicy) {
if aclPolicy.Protocol == "" {
aclPolicy.Protocol = AnyProtocol
}
for _, portRange := range aclPolicy.SrcPorts {
if portRange.EndPort == 0 {
portRange.EndPort = portRange.Port
}
}
for _, portRange := range aclPolicy.DstPorts {
if portRange.EndPort == 0 {
portRange.EndPort = portRange.Port
}
if aclPolicy.DstPorts.EndPort == 0 {
aclPolicy.DstPorts.EndPort = aclPolicy.DstPorts.Port
}
}
}
@ -128,16 +122,11 @@ func checkForErrors(networkPolicy *NPMNetworkPolicy) error {
string(aclPolicy.Protocol),
))
}
for _, portRange := range aclPolicy.DstPorts {
if !portRange.isValidRange() {
return npmerrors.SimpleError(fmt.Sprintf("ACL policy %s has invalid port range in DstPorts (start: %d, end: %d)", aclPolicy.PolicyID, portRange.Port, portRange.EndPort))
}
}
for _, portRange := range aclPolicy.DstPorts {
if !portRange.isValidRange() {
return npmerrors.SimpleError(fmt.Sprintf("ACL policy %s has invalid port range in SrcPorts (start: %d, end: %d)", aclPolicy.PolicyID, portRange.Port, portRange.EndPort))
}
if !aclPolicy.DstPorts.isValidRange() {
return npmerrors.SimpleError(fmt.Sprintf("ACL policy %s has invalid port range in DstPorts (start: %d, end: %d)", aclPolicy.PolicyID, aclPolicy.DstPorts.Port, aclPolicy.DstPorts.EndPort))
}
for _, setInfo := range aclPolicy.SrcList {
if !setInfo.hasKnownMatchType() {
return npmerrors.SimpleError(fmt.Sprintf("ACL policy %s has set %s in SrcList with unknown Match Type", aclPolicy.PolicyID, setInfo.IPSet.Name))

Просмотреть файл

@ -2,7 +2,6 @@ package policies
import (
"fmt"
"strings"
"github.com/Azure/azure-container-networking/log"
"github.com/Azure/azure-container-networking/npm/pkg/dataplane/ioutil"
@ -114,10 +113,7 @@ func (pMgr *PolicyManager) getNewCreatorWithChains(chainNames []string) *ioutil.
// will make a similar func for on update eventually
func (pMgr *PolicyManager) deleteOldJumpRulesOnRemove(policy *NPMNetworkPolicy) error {
fmt.Println(policy.ACLs[0])
shouldDeleteIngress, shouldDeleteEgress := policy.hasIngressAndEgress()
fmt.Println(shouldDeleteIngress, shouldDeleteEgress)
if shouldDeleteIngress {
if err := pMgr.deleteJumpRule(policy, true); err != nil {
return err
@ -224,8 +220,7 @@ func writeNetworkPolicyRules(creator *ioutil.FileCreator, networkPolicy *NPMNetw
func getIPTablesRuleSpecs(aclPolicy *ACLPolicy) []string {
specs := make([]string, 0)
specs = append(specs, util.IptablesProtFlag, string(aclPolicy.Protocol)) // NOTE: protocol must be ALL instead of nil
specs = append(specs, getPortSpecs(aclPolicy.SrcPorts, false)...)
specs = append(specs, getPortSpecs(aclPolicy.DstPorts, true)...)
specs = append(specs, getPortSpecs([]Ports{aclPolicy.DstPorts})...)
specs = append(specs, getMatchSetSpecsFromSetInfo(aclPolicy.SrcList)...)
specs = append(specs, getMatchSetSpecsFromSetInfo(aclPolicy.DstList)...)
if aclPolicy.Comment != "" {
@ -234,28 +229,18 @@ func getIPTablesRuleSpecs(aclPolicy *ACLPolicy) []string {
return specs
}
func getPortSpecs(portRanges []Ports, isDst bool) []string {
if len(portRanges) == 0 {
func getPortSpecs(portRanges []Ports) []string {
// TODO(jungukcho): do not need to take slices since it can only have one dst port
if len(portRanges) != 1 {
return []string{}
}
if len(portRanges) == 1 {
portFlag := util.IptablesSrcPortFlag
if isDst {
portFlag = util.IptablesDstPortFlag
}
return []string{portFlag, portRanges[0].toIPTablesString()}
// TODO(jungukcho): temporary solution and need to fix it.
if portRanges[0].Port == 0 && portRanges[0].EndPort == 0 {
return []string{}
}
portRangeStrings := make([]string, 0)
for _, portRange := range portRanges {
portRangeStrings = append(portRangeStrings, portRange.toIPTablesString())
}
portFlag := util.IptablesMultiSrcPortFlag
if isDst {
portFlag = util.IptablesMultiDstPortFlag
}
specs := []string{util.IptablesModuleFlag, util.IptablesMultiportFlag, portFlag}
return append(specs, strings.Join(portRangeStrings, ","))
return []string{util.IptablesDstPortFlag, portRanges[0].toIPTablesString()}
}
func getMatchSetSpecsForNetworkPolicy(networkPolicy *NPMNetworkPolicy, matchType MatchType) []string {

Просмотреть файл

@ -24,11 +24,11 @@ var (
testPolicy3EgressJump = fmt.Sprintf("-j %s", testPolicy3EgressChain)
testACLRule1 = fmt.Sprintf(
"-j MARK --set-mark 0x4000 -p tcp --sport 144:255 -m multiport --dports 222:333,456 -m set --match-set %s src -m set ! --match-set %s dst -m comment --comment comment1",
"-j MARK --set-mark 0x4000 -p tcp --dport 222:333 -m set --match-set %s src -m set ! --match-set %s dst -m comment --comment comment1",
ipsets.TestCIDRSet.HashedName,
ipsets.TestKeyPodSet.HashedName,
)
testACLRule2 = fmt.Sprintf("-j AZURE-NPM-EGRESS -p udp --sport 144 -m set --match-set %s src -m comment --comment comment2", ipsets.TestCIDRSet.HashedName)
testACLRule2 = fmt.Sprintf("-j AZURE-NPM-EGRESS -p udp -m set --match-set %s src -m comment --comment comment2", ipsets.TestCIDRSet.HashedName)
testACLRule3 = fmt.Sprintf("-j MARK --set-mark 0x5000 -p udp --dport 144 -m set --match-set %s src -m comment --comment comment3", ipsets.TestCIDRSet.HashedName)
testACLRule4 = fmt.Sprintf("-j AZURE-NPM-ACCEPT -p all -m set --match-set %s src -m comment --comment comment4", ipsets.TestCIDRSet.HashedName)
)

Просмотреть файл

@ -50,12 +50,8 @@ var (
},
Target: Dropped,
Direction: Ingress,
SrcPorts: []Ports{
{144, 255},
},
DstPorts: []Ports{
{222, 333},
{456, 456},
DstPorts: Ports{
222, 333,
},
Protocol: TCP,
},
@ -71,10 +67,7 @@ var (
},
Target: Allowed,
Direction: Ingress,
SrcPorts: []Ports{
{144, 144},
},
Protocol: UDP,
Protocol: UDP,
},
{
PolicyID: "test3",
@ -88,8 +81,8 @@ var (
},
Target: Dropped,
Direction: Egress,
DstPorts: []Ports{
{144, 144},
DstPorts: Ports{
144, 144,
},
Protocol: UDP,
},

Просмотреть файл

@ -0,0 +1,11 @@
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-all-to-in-testnamespace-for-ingress
namespace: testnamespace
spec:
policyTypes:
- Ingress
podSelector: {}
ingress:
- {}

Просмотреть файл

@ -0,0 +1,10 @@
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all-ingress
namespace: testnamespace
spec:
podSelector: {}
policyTypes:
- Ingress

Просмотреть файл

@ -0,0 +1,18 @@
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: only-port
namespace: default
spec:
ingress:
- ports:
# or
- port: 80
protocol: TCP
- port: 100
protocol: UDP
podSelector:
matchLabels:
app: server
policyTypes:
- Ingress

Просмотреть файл

@ -47,6 +47,7 @@ const (
IptablesMark string = "MARK"
IptablesSrcFlag string = "src"
IptablesDstFlag string = "dst"
IptablesNamedPortFlag string = "dst,dst"
IptablesNotFlag string = "!"
IptablesProtFlag string = "-p"
IptablesSFlag string = "-s"
@ -64,8 +65,6 @@ const (
IptablesCtstateModuleFlag string = "conntrack" // state module is obsolete: https://unix.stackexchange.com/questions/108169/what-is-the-difference-between-m-conntrack-ctstate-and-m-state-state
IptablesCtstateFlag string = "--ctstate"
IptablesMultiportFlag string = "multiport"
IptablesMultiDstPortFlag string = "--dports"
IptablesMultiSrcPortFlag string = "--sports"
IptablesRelatedState string = "RELATED"
IptablesEstablishedState string = "ESTABLISHED"
IptablesNewState string = "NEW"