-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Egress Network policy fixes #13071
Egress Network policy fixes #13071
Conversation
We also need to drop all egress firewall rules for global namespaces. This requires maintaining namespace to vnid map in the proxy. I will submit this change in a separate pr. @openshift/networking PTAL |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding the rationale comments is definitely a good idea. I should have done that before.
pkg/sdn/plugin/controller.go
Outdated
@@ -384,10 +384,12 @@ func (plugin *OsdnNode) updateEgressNetworkPolicyRules(vnid uint32) { | |||
} else if vnid == 0 { | |||
glog.Errorf("EgressNetworkPolicy in global network namespace is not allowed (%s); ignoring", policyNames(policies)) | |||
} else if len(namespaces) > 1 { | |||
// Rationale: If multiple namespaces have their own egress network policy, it's hard to determine the order of policies to apply. Also it may be wrong to force a network policy on a namespace which only wants to join the network. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mention something about VNIDs or NetNamespaces there since that's the source of the trouble; EgressNetworkPolicies are defined per-Namespace, but are implemented per-NetNamespace.
pkg/sdn/plugin/proxy.go
Outdated
if policy.UID != ref.policyUID { | ||
// We only allow one policy per namespace otherwise it's hard to determine which policy to apply first | ||
glog.Errorf("found multiple egress policies, dropping all firewall rules for namespace: %s", policy.Namespace) | ||
delete(proxy.firewall, policy.Namespace) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm... this isn't right, since it means that the next time an ENP in that namespace gets updated, proxy.firewall[policy.Namespace]
will be unset, and so that ENP will get applied (even if there are also still other ENPs in the namespace too).
We need to remember all the ENPs we've seen, but only apply the policy when there's just one in the Namespace.
277a0c1
to
9aabbd0
Compare
@openshift/networking @danwinship updated, ptal |
9aabbd0
to
7b55356
Compare
Added one more fix (new commit): SDN egress policy should not firewall endpoints from global namespaces. |
[test] |
pkg/sdn/plugin/proxy.go
Outdated
} | ||
|
||
// Add/Update/Delete firwall rules for the namespace |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo "firwall"
pkg/sdn/plugin/proxy.go
Outdated
type proxyFirewallItem struct { | ||
policy osapi.EgressNetworkPolicyRuleType | ||
net *net.IPNet | ||
namespaceFirewalls []policyFirewallItem |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it seems like the code below would be a lot simpler if this was a map[ktypes.UID]policyFirewallItem
rather than a []policyFirewallItem
. (You might even be able to get rid of policyFirewallItem
and just do map[ktypes.UID][]firewallItem
?)
Also, maybe type/field naming would help make the code clearer. It's difficult to keep track of all the different "firewalls" and "items"...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
doing the map looks plausible and would make the code more readable, so +1 from me if it works
pkg/sdn/plugin/proxy.go
Outdated
@@ -98,7 +103,39 @@ func (proxy *OsdnProxy) watchEgressNetworkPolicies() { | |||
}) | |||
} | |||
|
|||
func (proxy *OsdnProxy) watchNetNamespaces() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
blah... we need to abstract out the EgressNetworkPolicy code better so that node and proxy can share more code rather than duplicating. Can you add a TODO comment for that?
pkg/sdn/plugin/proxy.go
Outdated
ignorePolicy := false | ||
func() { | ||
proxy.idLock.Lock() | ||
defer proxy.idLock.Unlock() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would have a slight preference for splitting this out into a real helper function rather than an inline func() but if you really prefer it this way you can keep it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could even do:
if func() bool {
Lock()
defer Unlock()
if global vnid {
log error
return true
}
return false
}() {
return
}
but a helper function is even clearer.
pkg/sdn/plugin/proxy.go
Outdated
@@ -111,7 +148,6 @@ func (proxy *OsdnProxy) updateEgressNetworkPolicy(policy osapi.EgressNetworkPoli | |||
} | |||
|
|||
// Add/Update/Delete firwall rules for the namespace | |||
ns := policy.Namespace |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
doesn't belong in this patch?
7d452cd
to
1c76a3d
Compare
pkg/sdn/plugin/proxy.go
Outdated
updated := false | ||
if ref, ok := proxy.firewall[ns]; ok { | ||
for uid := range ref.namespaceFirewalls { | ||
if uid == policy.UID { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
don't need a loop now that you're using a map; just if _, ok := ref.namespaceFirewalls[policy.UID]; ok {
Although you can get rid of updated
in that case too. Just check if proxy.firewall[ns]
exists, and create it if not, and then set proxy.firewall[ns].namespaceFirewalls[policy.UID]
pkg/sdn/plugin/proxy.go
Outdated
if len(ref.namespaceFirewalls) == 1 { | ||
for uid := range ref.namespaceFirewalls { | ||
ref.activePolicy = &uid | ||
proxy.firewall[ns] = ref |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you made proxy.firewall
be map[string]*proxyFirewallItem
rather than map[string]proxyFirewallItem
then you wouldn't need the reassignment here (and below).
pkg/sdn/plugin/proxy.go
Outdated
} else { | ||
// We only allow one policy per namespace otherwise it's hard to determine which policy to apply first | ||
glog.Errorf("Found multiple egress policies, dropping all firewall rules for namespace: %q", ns) | ||
ref.activePolicy = nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm... this is the opposite of the behavior in controller.go, where having multiple EgressNetworkPolicies means all traffic gets dropped, rather than all traffic being allowed.
- We allow multiple policies to be created per namespace but we only recommend one policy per namespace as per our design. In case of multiple policies per namespace, we drop all corresponding ovs rules because its hard to determine which policy to apply first but currently we keep the latest policy firewall rules in this case. To be consistent with ovs rules behavior, this fix will drop all firewall rules as well. - Renamed proxy.updateNetworkPolicy() to proxy.updateEgressNetworkPolicy() to make it more clear and not to get confused with np.updateNetworkPolicy() in networkpolicy.go
1c76a3d
to
1aaf633
Compare
@danwinship Updated, ptal |
Evaluated for origin test up to 1aaf633 |
continuous-integration/openshift-jenkins/test SUCCESS (https://ci.openshift.redhat.com/jenkins/job/test_pull_request_origin/176/) (Base Commit: 209f100) |
[merge] |
Evaluated for origin merge up to 1aaf633 |
continuous-integration/openshift-jenkins/merge SUCCESS (https://ci.openshift.redhat.com/jenkins/job/merge_pull_request_origin/178/) (Base Commit: e61510a) (Image: devenv-rhel7_6097) |
one policy per namespace as per our design.
In case of multiple policies per namespace, we drop all corresponding ovs rules
because its hard to determine which policy to apply first but currently we keep
the latest policy firewall rules in this case. To be consistent with ovs rules
behavior, this fix will drop all firewall rules as well.
to make it more clear and not to get confused with np.updateNetworkPolicy()
in networkpolicy.go