in npm/pkg/controlplane/controllers/v1/translatePolicy.go [226:878]
func translateIngress(ns string, policyName string, targetSelector metav1.LabelSelector, rules []networkingv1.NetworkPolicyIngressRule) ([]string, []string, map[string][]string, [][]string, []*iptm.IptEntry) {
var (
netHashIPsets []string // ipsets with type: net:hash
namedPorts []string // ipsets with type: hash:ip,port
listIPsets map[string][]string // ipsets with type: list:set
ipCidrs [][]string
entries []*iptm.IptEntry
fromRuleEntries []*iptm.IptEntry
addedCidrEntry bool // all cidr entry will be added in one set per from/to rule
addedPortEntry bool // add drop entries at the end of the chain when there are non ALLOW-ALL* rules
)
log.Logf("started parsing ingress rule")
netHashIPsets = append(netHashIPsets, "ns-"+ns)
ipCidrs = make([][]string, len(rules))
listIPsets = make(map[string][]string)
targetSelectorIptEntrySpec, labels, listLabelsWithMembers := craftPartialIptEntrySpecFromSelector(ns, &targetSelector, util.IptablesDstFlag, false)
netHashIPsets = append(netHashIPsets, labels...)
for parsedListName, parsedListMembers := range listLabelsWithMembers {
listIPsets[parsedListName] = append(listIPsets[parsedListName], parsedListMembers...)
}
targetSelectorComment := craftPartialIptablesCommentFromSelector(ns, &targetSelector, false)
for i, rule := range rules {
allowExternal := false
portRuleExists := rule.Ports != nil && len(rule.Ports) > 0
fromRuleExists := false
addedPortEntry = addedPortEntry || portRuleExists
ipCidrs[i] = make([]string, len(rule.From))
if rule.From != nil {
if len(rule.From) == 0 {
fromRuleExists = true
allowExternal = true
}
for _, fromRule := range rule.From {
if fromRule.PodSelector != nil ||
fromRule.NamespaceSelector != nil ||
fromRule.IPBlock != nil {
fromRuleExists = true
break
}
}
} else if !portRuleExists {
allowExternal = true
}
if !portRuleExists && !fromRuleExists && !allowExternal {
entry := &iptm.IptEntry{
Chain: util.IptablesAzureIngressPortChain,
}
entry.Specs = append(
entry.Specs,
util.IptablesModuleFlag,
util.IptablesSetModuleFlag,
util.IptablesMatchSetFlag,
util.GetHashedName(util.KubeAllNamespacesFlag),
util.IptablesSrcFlag,
)
entry.Specs = append(entry.Specs, targetSelectorIptEntrySpec...)
entry.Specs = append(
entry.Specs,
util.IptablesJumpFlag,
util.IptablesMark,
util.IptablesSetMarkFlag,
util.IptablesAzureIngressMarkHex,
util.IptablesModuleFlag,
util.IptablesCommentModuleFlag,
util.IptablesCommentFlag,
"ALLOW-ALL-TO-"+targetSelectorComment+
"-FROM-"+util.KubeAllNamespacesFlag,
)
entries = append(entries, entry)
listIPsets[util.KubeAllNamespacesFlag] = []string{}
continue
}
// Only Ports rules exist
if portRuleExists && !fromRuleExists && !allowExternal {
for _, portRule := range rule.Ports {
switch portCheck := getPortType(portRule); portCheck {
case "namedport":
portName := util.NamedPortIPSetPrefix + portRule.Port.String()
namedPorts = append(namedPorts, portName)
entry := &iptm.IptEntry{
Chain: util.IptablesAzureIngressPortChain,
Specs: append([]string(nil), targetSelectorIptEntrySpec...),
}
if portRule.Protocol != nil {
entry.Specs = append(
entry.Specs,
util.IptablesProtFlag,
string(*portRule.Protocol),
)
}
entry.Specs = append(
entry.Specs,
util.IptablesModuleFlag,
util.IptablesSetModuleFlag,
util.IptablesMatchSetFlag,
util.GetHashedName(portName),
util.IptablesDstFlag+","+util.IptablesDstFlag,
util.IptablesJumpFlag,
util.IptablesMark,
util.IptablesSetMarkFlag,
util.IptablesAzureIngressMarkHex,
util.IptablesModuleFlag,
util.IptablesCommentModuleFlag,
util.IptablesCommentFlag,
"ALLOW-ALL-"+
craftPartialIptablesCommentFromPort(portRule, util.IptablesDstPortFlag)+
"-TO-"+targetSelectorComment,
)
entries = append(entries, entry)
case "validport":
entry := &iptm.IptEntry{
Chain: util.IptablesAzureIngressPortChain,
Specs: craftPartialIptEntrySpecFromPort(portRule, util.IptablesDstPortFlag),
}
entry.Specs = append(entry.Specs, targetSelectorIptEntrySpec...)
entry.Specs = append(
entry.Specs,
util.IptablesJumpFlag,
util.IptablesMark,
util.IptablesSetMarkFlag,
util.IptablesAzureIngressMarkHex,
util.IptablesModuleFlag,
util.IptablesCommentModuleFlag,
util.IptablesCommentFlag,
"ALLOW-ALL-"+
craftPartialIptablesCommentFromPort(portRule, util.IptablesDstPortFlag)+
"-TO-"+targetSelectorComment,
)
entries = append(entries, entry)
default:
log.Logf("Invalid NetworkPolicyPort.")
}
}
continue
}
// fromRuleExists
for j, fromRule := range rule.From {
// Handle IPBlock field of NetworkPolicyPeer
if fromRule.IPBlock != nil {
if len(fromRule.IPBlock.CIDR) > 0 {
ipCidrs[i] = append(ipCidrs[i], fromRule.IPBlock.CIDR)
cidrIpsetName := policyName + "-in-ns-" + ns + "-" + strconv.Itoa(i) + "in"
if len(fromRule.IPBlock.Except) > 0 {
for _, except := range fromRule.IPBlock.Except {
// TODO move IP cidrs rule to allow based only
ipCidrs[i] = append(ipCidrs[i], except+util.IpsetNomatch)
}
}
if j != 0 && addedCidrEntry {
continue
}
if portRuleExists {
for _, portRule := range rule.Ports {
switch portCheck := getPortType(portRule); portCheck {
case "namedport":
portName := util.NamedPortIPSetPrefix + portRule.Port.String()
namedPorts = append(namedPorts, portName)
entry := &iptm.IptEntry{
Chain: util.IptablesAzureIngressPortChain,
Specs: append([]string(nil), targetSelectorIptEntrySpec...),
}
if portRule.Protocol != nil {
entry.Specs = append(
entry.Specs,
util.IptablesProtFlag,
string(*portRule.Protocol),
)
}
entry.Specs = append(
entry.Specs,
util.IptablesModuleFlag,
util.IptablesSetModuleFlag,
util.IptablesMatchSetFlag,
util.GetHashedName(cidrIpsetName),
util.IptablesSrcFlag,
)
entry.Specs = append(
entry.Specs,
util.IptablesModuleFlag,
util.IptablesSetModuleFlag,
util.IptablesMatchSetFlag,
util.GetHashedName(portName),
util.IptablesDstFlag+","+util.IptablesDstFlag,
util.IptablesJumpFlag,
util.IptablesMark,
util.IptablesSetMarkFlag,
util.IptablesAzureIngressMarkHex,
util.IptablesModuleFlag,
util.IptablesCommentModuleFlag,
util.IptablesCommentFlag,
"ALLOW-"+cidrIpsetName+
"-AND-"+craftPartialIptablesCommentFromPort(portRule, util.IptablesDstPortFlag)+
"-TO-"+targetSelectorComment,
)
fromRuleEntries = append(fromRuleEntries, entry)
case "validport":
entry := &iptm.IptEntry{
Chain: util.IptablesAzureIngressPortChain,
Specs: append([]string(nil), targetSelectorIptEntrySpec...),
}
entry.Specs = append(
entry.Specs,
util.IptablesModuleFlag,
util.IptablesSetModuleFlag,
util.IptablesMatchSetFlag,
util.GetHashedName(cidrIpsetName),
util.IptablesSrcFlag,
)
entry.Specs = append(
entry.Specs,
craftPartialIptEntrySpecFromPort(portRule, util.IptablesDstPortFlag)...,
)
entry.Specs = append(
entry.Specs,
util.IptablesJumpFlag,
util.IptablesMark,
util.IptablesSetMarkFlag,
util.IptablesAzureIngressMarkHex,
util.IptablesModuleFlag,
util.IptablesCommentModuleFlag,
util.IptablesCommentFlag,
"ALLOW-"+cidrIpsetName+
"-AND-"+craftPartialIptablesCommentFromPort(portRule, util.IptablesDstPortFlag)+
"-TO-"+targetSelectorComment,
)
fromRuleEntries = append(fromRuleEntries, entry)
default:
log.Logf("Invalid NetworkPolicyPort.")
}
}
} else {
entry := &iptm.IptEntry{
Chain: util.IptablesAzureIngressFromChain,
Specs: append([]string(nil), targetSelectorIptEntrySpec...),
}
entry.Specs = append(
entry.Specs,
util.IptablesModuleFlag,
util.IptablesSetModuleFlag,
util.IptablesMatchSetFlag,
util.GetHashedName(cidrIpsetName),
util.IptablesSrcFlag,
util.IptablesJumpFlag,
util.IptablesMark,
util.IptablesSetMarkFlag,
util.IptablesAzureIngressMarkHex,
util.IptablesModuleFlag,
util.IptablesCommentModuleFlag,
util.IptablesCommentFlag,
"ALLOW-"+cidrIpsetName+
"-TO-"+targetSelectorComment,
)
fromRuleEntries = append(fromRuleEntries, entry)
}
addedCidrEntry = true
}
continue
}
// Handle podSelector and namespaceSelector.
// For PodSelector, use hash:net in ipset.
// For NamespaceSelector, use set:list in ipset.
if fromRule.PodSelector == nil && fromRule.NamespaceSelector == nil {
continue
}
if fromRule.PodSelector == nil && fromRule.NamespaceSelector != nil {
for _, nsSelector := range FlattenNameSpaceSelector(fromRule.NamespaceSelector) {
iptPartialNsSpec, nsLabelsWithoutOps, listLabelsWithMembers := craftPartialIptEntrySpecFromSelector("", &nsSelector, util.IptablesSrcFlag, true)
if len(nsLabelsWithoutOps) == 1 && nsLabelsWithoutOps[0] == "" {
// Empty namespaceSelector. This selects all namespaces
nsLabelsWithoutOps[0] = util.KubeAllNamespacesFlag
if _, ok := listIPsets[nsLabelsWithoutOps[0]]; !ok {
listIPsets[nsLabelsWithoutOps[0]] = nil
}
} else {
for i := range nsLabelsWithoutOps {
// Add namespaces prefix to distinguish namespace ipset lists and pod ipsets
nsLabelsWithoutOps[i] = util.GetNSNameWithPrefix(nsLabelsWithoutOps[i])
if _, ok := listIPsets[nsLabelsWithoutOps[i]]; !ok {
listIPsets[nsLabelsWithoutOps[i]] = nil
}
}
appendSelectorLabelsToLists(listIPsets, listLabelsWithMembers, true)
}
iptPartialNsComment := craftPartialIptablesCommentFromSelector("", &nsSelector, true)
if portRuleExists {
for _, portRule := range rule.Ports {
switch portCheck := getPortType(portRule); portCheck {
case "namedport":
portName := util.NamedPortIPSetPrefix + portRule.Port.String()
namedPorts = append(namedPorts, portName)
entry := &iptm.IptEntry{
Chain: util.IptablesAzureIngressPortChain,
Specs: append([]string(nil), targetSelectorIptEntrySpec...),
}
entry.Specs = append(
entry.Specs,
iptPartialNsSpec...,
)
entry.Specs = append(
entry.Specs,
util.IptablesModuleFlag,
util.IptablesSetModuleFlag,
util.IptablesMatchSetFlag,
util.GetHashedName(portName),
util.IptablesDstFlag+","+util.IptablesDstFlag,
util.IptablesJumpFlag,
util.IptablesMark,
util.IptablesSetMarkFlag,
util.IptablesAzureIngressMarkHex,
util.IptablesModuleFlag,
util.IptablesCommentModuleFlag,
util.IptablesCommentFlag,
"ALLOW-"+iptPartialNsComment+
"-AND-"+craftPartialIptablesCommentFromPort(portRule, util.IptablesDstPortFlag)+
"-TO-"+targetSelectorComment,
)
entries = append(entries, entry)
case "validport":
entry := &iptm.IptEntry{
Chain: util.IptablesAzureIngressPortChain,
Specs: append([]string(nil), targetSelectorIptEntrySpec...),
}
entry.Specs = append(
entry.Specs,
iptPartialNsSpec...,
)
entry.Specs = append(
entry.Specs,
craftPartialIptEntrySpecFromPort(portRule, util.IptablesDstPortFlag)...,
)
entry.Specs = append(
entry.Specs,
util.IptablesJumpFlag,
util.IptablesMark,
util.IptablesSetMarkFlag,
util.IptablesAzureIngressMarkHex,
util.IptablesModuleFlag,
util.IptablesCommentModuleFlag,
util.IptablesCommentFlag,
"ALLOW-"+iptPartialNsComment+
"-AND-"+craftPartialIptablesCommentFromPort(portRule, util.IptablesDstPortFlag)+
"-TO-"+targetSelectorComment,
)
entries = append(entries, entry)
default:
log.Logf("Invalid NetworkPolicyPort.")
}
}
} else {
entry := &iptm.IptEntry{
Chain: util.IptablesAzureIngressFromChain,
Specs: append([]string(nil), iptPartialNsSpec...),
}
entry.Specs = append(
entry.Specs,
targetSelectorIptEntrySpec...,
)
entry.Specs = append(
entry.Specs,
util.IptablesJumpFlag,
util.IptablesMark,
util.IptablesSetMarkFlag,
util.IptablesAzureIngressMarkHex,
util.IptablesModuleFlag,
util.IptablesCommentModuleFlag,
util.IptablesCommentFlag,
"ALLOW-"+iptPartialNsComment+
"-TO-"+targetSelectorComment,
)
entries = append(entries, entry)
}
}
continue
}
if fromRule.PodSelector != nil && fromRule.NamespaceSelector == nil {
// TODO check old code if we need any ns- prefix for pod selectors
iptPartialPodSpec, podLabelsWithoutOps, listPodLabelsWithMembers := craftPartialIptEntrySpecFromSelector(ns, fromRule.PodSelector, util.IptablesSrcFlag, false)
if len(podLabelsWithoutOps) == 1 {
if podLabelsWithoutOps[0] == "" {
podLabelsWithoutOps[0] = util.GetNSNameWithPrefix(ns)
}
}
netHashIPsets = append(netHashIPsets, podLabelsWithoutOps...)
// TODO check this if ns- is needed here.
appendSelectorLabelsToLists(listIPsets, listPodLabelsWithMembers, false)
iptPartialPodComment := craftPartialIptablesCommentFromSelector(ns, fromRule.PodSelector, false)
if portRuleExists {
for _, portRule := range rule.Ports {
switch portCheck := getPortType(portRule); portCheck {
case "namedport":
portName := util.NamedPortIPSetPrefix + portRule.Port.String()
namedPorts = append(namedPorts, portName)
entry := &iptm.IptEntry{
Chain: util.IptablesAzureIngressPortChain,
Specs: append([]string(nil), targetSelectorIptEntrySpec...),
}
if portRule.Protocol != nil {
entry.Specs = append(
entry.Specs,
util.IptablesProtFlag,
string(*portRule.Protocol),
)
}
entry.Specs = append(
entry.Specs,
iptPartialPodSpec...,
)
entry.Specs = append(
entry.Specs,
util.IptablesModuleFlag,
util.IptablesSetModuleFlag,
util.IptablesMatchSetFlag,
util.GetHashedName(portName),
util.IptablesDstFlag+","+util.IptablesDstFlag,
util.IptablesJumpFlag,
util.IptablesMark,
util.IptablesSetMarkFlag,
util.IptablesAzureIngressMarkHex,
util.IptablesModuleFlag,
util.IptablesCommentModuleFlag,
util.IptablesCommentFlag,
"ALLOW-"+iptPartialPodComment+
"-AND-"+craftPartialIptablesCommentFromPort(portRule, util.IptablesDstPortFlag)+
"-TO-"+targetSelectorComment,
)
entries = append(entries, entry)
case "validport":
entry := &iptm.IptEntry{
Chain: util.IptablesAzureIngressPortChain,
Specs: append([]string(nil), targetSelectorIptEntrySpec...),
}
entry.Specs = append(
entry.Specs,
iptPartialPodSpec...,
)
entry.Specs = append(
entry.Specs,
craftPartialIptEntrySpecFromPort(portRule, util.IptablesDstPortFlag)...,
)
entry.Specs = append(
entry.Specs,
util.IptablesJumpFlag,
util.IptablesMark,
util.IptablesSetMarkFlag,
util.IptablesAzureIngressMarkHex,
util.IptablesModuleFlag,
util.IptablesCommentModuleFlag,
util.IptablesCommentFlag,
"ALLOW-"+iptPartialPodComment+
"-AND-"+craftPartialIptablesCommentFromPort(portRule, util.IptablesDstPortFlag)+
"-TO-"+targetSelectorComment,
)
entries = append(entries, entry)
default:
log.Logf("Invalid NetworkPolicyPort.")
}
}
} else {
entry := &iptm.IptEntry{
Chain: util.IptablesAzureIngressFromChain,
Specs: append([]string(nil), iptPartialPodSpec...),
}
entry.Specs = append(
entry.Specs,
targetSelectorIptEntrySpec...,
)
entry.Specs = append(
entry.Specs,
util.IptablesJumpFlag,
util.IptablesMark,
util.IptablesSetMarkFlag,
util.IptablesAzureIngressMarkHex,
util.IptablesModuleFlag,
util.IptablesCommentModuleFlag,
util.IptablesCommentFlag,
"ALLOW-"+iptPartialPodComment+
"-TO-"+targetSelectorComment,
)
entries = append(entries, entry)
}
continue
}
for _, nsSelector := range FlattenNameSpaceSelector(fromRule.NamespaceSelector) {
// we pass empty ns for the podspec and comment here because it's a combo of both selectors and not limited to network policy namespace
iptPartialNsSpec, nsLabelsWithoutOps, listLabelsWithMembers := craftPartialIptEntrySpecFromSelector("", &nsSelector, util.IptablesSrcFlag, true) // Add namespaces prefix to distinguish namespace ipsets and pod ipsets
for i := range nsLabelsWithoutOps {
nsLabelsWithoutOps[i] = util.GetNSNameWithPrefix(nsLabelsWithoutOps[i])
if _, ok := listIPsets[nsLabelsWithoutOps[i]]; !ok {
listIPsets[nsLabelsWithoutOps[i]] = nil
}
}
appendSelectorLabelsToLists(listIPsets, listLabelsWithMembers, true)
iptPartialPodSpec, podLabelsWithoutOps, listPodLabelsWithMembers := craftPartialIptEntrySpecFromSelector("", fromRule.PodSelector, util.IptablesSrcFlag, false)
netHashIPsets = append(netHashIPsets, podLabelsWithoutOps...)
appendSelectorLabelsToLists(listIPsets, listPodLabelsWithMembers, false)
iptPartialNsComment := craftPartialIptablesCommentFromSelector("", &nsSelector, true)
iptPartialPodComment := craftPartialIptablesCommentFromSelector("", fromRule.PodSelector, false)
if portRuleExists {
for _, portRule := range rule.Ports {
switch portCheck := getPortType(portRule); portCheck {
case "namedport":
portName := util.NamedPortIPSetPrefix + portRule.Port.String()
namedPorts = append(namedPorts, portName)
entry := &iptm.IptEntry{
Chain: util.IptablesAzureIngressPortChain,
Specs: append([]string(nil), iptPartialNsSpec...),
}
if portRule.Protocol != nil {
entry.Specs = append(
entry.Specs,
util.IptablesProtFlag,
string(*portRule.Protocol),
)
}
entry.Specs = append(
entry.Specs,
iptPartialPodSpec...,
)
entry.Specs = append(
entry.Specs,
targetSelectorIptEntrySpec...,
)
entry.Specs = append(
entry.Specs,
util.IptablesModuleFlag,
util.IptablesSetModuleFlag,
util.IptablesMatchSetFlag,
util.GetHashedName(portName),
util.IptablesDstFlag+","+util.IptablesDstFlag,
util.IptablesJumpFlag,
util.IptablesMark,
util.IptablesSetMarkFlag,
util.IptablesAzureIngressMarkHex,
util.IptablesModuleFlag,
util.IptablesCommentModuleFlag,
util.IptablesCommentFlag,
"ALLOW-"+iptPartialNsComment+
"-AND-"+iptPartialPodComment+
"-AND-"+craftPartialIptablesCommentFromPort(portRule, util.IptablesDstPortFlag)+
"-TO-"+targetSelectorComment,
)
entries = append(entries, entry)
case "validport":
entry := &iptm.IptEntry{
Chain: util.IptablesAzureIngressPortChain,
Specs: append([]string(nil), iptPartialNsSpec...),
}
entry.Specs = append(
entry.Specs,
iptPartialPodSpec...,
)
entry.Specs = append(
entry.Specs,
targetSelectorIptEntrySpec...,
)
entry.Specs = append(
entry.Specs,
craftPartialIptEntrySpecFromPort(portRule, util.IptablesDstPortFlag)...,
)
entry.Specs = append(
entry.Specs,
util.IptablesJumpFlag,
util.IptablesMark,
util.IptablesSetMarkFlag,
util.IptablesAzureIngressMarkHex,
util.IptablesModuleFlag,
util.IptablesCommentModuleFlag,
util.IptablesCommentFlag,
"ALLOW-"+iptPartialNsComment+
"-AND-"+iptPartialPodComment+
"-AND-"+craftPartialIptablesCommentFromPort(portRule, util.IptablesDstPortFlag)+
"-TO-"+targetSelectorComment,
)
entries = append(entries, entry)
default:
log.Logf("Invalid NetworkPolicyPort.")
}
}
} else {
entry := &iptm.IptEntry{
Chain: util.IptablesAzureIngressFromChain,
Specs: append([]string(nil), targetSelectorIptEntrySpec...),
}
entry.Specs = append(
entry.Specs,
iptPartialNsSpec...,
)
entry.Specs = append(
entry.Specs,
iptPartialPodSpec...,
)
entry.Specs = append(
entry.Specs,
util.IptablesJumpFlag,
util.IptablesMark,
util.IptablesSetMarkFlag,
util.IptablesAzureIngressMarkHex,
util.IptablesModuleFlag,
util.IptablesCommentModuleFlag,
util.IptablesCommentFlag,
"ALLOW-"+iptPartialNsComment+
"-AND-"+iptPartialPodComment+
"-TO-"+targetSelectorComment,
)
entries = append(entries, entry)
}
}
}
if allowExternal {
entry := &iptm.IptEntry{
Chain: util.IptablesAzureIngressPortChain,
Specs: append([]string(nil), targetSelectorIptEntrySpec...),
}
entry.Specs = append(
entry.Specs,
util.IptablesJumpFlag,
util.IptablesMark,
util.IptablesSetMarkFlag,
util.IptablesAzureIngressMarkHex,
util.IptablesModuleFlag,
util.IptablesCommentModuleFlag,
util.IptablesCommentFlag,
"ALLOW-ALL-TO-"+
targetSelectorComment,
)
entries = append(entries, entry)
continue
}
}
// prepending fromRuleEntries (which is in reverse order) so that they will retain correct ordering
// of drop->allow... when the rules are beind prepended to their corresponding chain
if len(fromRuleEntries) > 0 {
entries = append(fromRuleEntries, entries...)
}
log.Logf("finished parsing ingress rule")
return util.DropEmptyFields(netHashIPsets), util.DropEmptyFields(namedPorts), listIPsets, ipCidrs, entries
}