-
Notifications
You must be signed in to change notification settings - Fork 361
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
fix: Allow Policy to attach to multiple http listeners #2967
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #2967 +/- ##
==========================================
+ Coverage 64.49% 64.55% +0.05%
==========================================
Files 121 121
Lines 21388 21397 +9
==========================================
+ Hits 13794 13812 +18
+ Misses 6723 6715 -8
+ Partials 871 870 -1 ☔ View full report in Codecov by Sentry. |
@@ -312,7 +312,7 @@ func resolveCTPolicyTargetRef(policy *egv1a1.ClientTrafficPolicy, gateways map[t | |||
return gateway.GatewayContext, nil | |||
} | |||
|
|||
func validatePortOverlapForClientTrafficPolicy(l *ListenerContext, xds *ir.Xds) error { | |||
func validatePortOverlapForClientTrafficPolicy(l *ListenerContext, xds *ir.Xds, attachedToGateway bool) error { |
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 comments for the new logic would really help
@@ -329,7 +329,20 @@ func validatePortOverlapForClientTrafficPolicy(l *ListenerContext, xds *ir.Xds) | |||
// IR must exist since we're past validation | |||
if httpIR != nil { | |||
if sameListeners := listenersWithSameHTTPPort(xds, httpIR); len(sameListeners) != 0 { | |||
return fmt.Errorf("affects additional listeners: %s", strings.Join(sameListeners, ", ")) | |||
if attachedToGateway { |
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.
this is now O(n^3)
can we instead hold a map containing listener name as the key and policy as the value ?
- if key is missing, add key, and return
- if key is present, policy is same, return
- if key is present, and a different policy, reject
this takes an approach of first policy wins, which imo is better than no policy winning
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.
this takes an approach of first policy wins, which imo is better than no policy winning
"First policy wins" doesn't make sense. It's not a conflict between two policies where one can win and the other can lose, it's that translating a single policy (no other policies existing in the system) would result in it affecting multiple listeners including listeners that should not be affected by the policy.
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.
this is now O(n^3)
Looking closely at the validatePortOverlapForClientTrafficPolicy
method, it seems to me that it's O(n)
where n
is the number of HTTP listeners attached to a Gateway XDS representation.
func validatePortOverlapForClientTrafficPolicy(l *ListenerContext, xds *ir.Xds, attachedToGateway bool) error {
irListenerName := irHTTPListenerName(l)
var httpIR *ir.HTTPListener
// O(n) loop
for _, http := range xds.HTTP {
if http.Name == irListenerName {
httpIR = http
break
}
}
// IR must exist since we're past validation
if httpIR != nil {
// listenersWithSameHTTPPort is O(n) and it is called once.
// This is an 'if' statment, not a 'for' statement.
if sameListeners := listenersWithSameHTTPPort(xds, httpIR); len(sameListeners) != 0 {
if attachedToGateway {
gatewayName := irListenerName[0:strings.LastIndex(irListenerName, "/")]
conflictingListeners := []string{}
// sameListeners is an array with an upper bound of O(n)
for _, currName := range sameListeners {
if strings.Index(currName, gatewayName) != 0 {
conflictingListeners = append(conflictingListeners, currName)
}
}
if len(conflictingListeners) != 0 {
return fmt.Errorf("affects additional listeners: %s", strings.Join(conflictingListeners, ", "))
}
} else {
return fmt.Errorf("affects additional listeners: %s", strings.Join(sameListeners, ", "))
}
}
}
return 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.
@liorokman adding some reasons why we should consider first policy wins
- we already oldest config wins in most places
// Sort based on timestamp - this allows existing traffic to not get interrupted/dropped, ensures that is policy1 targets listener1 at t1 and policy2 targets listener2 at t2, listener1 is not affected
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.
@arkodg The bug occurs when there is exactly one policy. The scenario where there are two policies is out of scope for this issue. There's no way to implement "first policy wins", because "first policy wins" means "reject the policy provided".
Here's a recreation of the bug that this PR is trying to solve.:
apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
name: gateway
spec:
gatewayClassName: envoy-gateway-class
listeners:
- name: http
port: 80
protocol: HTTP
hostname: foo.example.com
allowedRoutes:
namespaces:
from: Same
- name: http2
port: 80
protocol: HTTP
hostname: bar.example.com
allowedRoutes:
namespaces:
from: Same
---
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: ClientTrafficPolicy
metadata:
name: target-gateway
spec:
targetRef:
group: gateway.networking.k8s.io
kind: Gateway
name: gateway
namespace: default
sectionName: http
path:
escapedSlashesAction: RejectRequest
timeout:
http:
requestReceivedTimeout: "5s"
The above single ClientTrafficPolicy
tries to target only one listener - the one called http
- and because both http
and http2
are non-TLS and on the same port, the requestReceivedTimeout
configured for http2
will also be 5s
. Even worse, while http
should have the RejectRequest
action for escaped slashes, http2
should use the default value (UnescapeAndForward
) but will instead be configured to RejectRequest
.
Without this PR the translated IR will be correct - the various settings from the ClientTrafficPolicy
will be set in the correct location - only on http
and not on http2
. The bug occurs because the correct IR is not translatable to valid XDS.
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.
We probably won't need this #2970
@zhaohuabing we still need it for CTP which adds fields like |
@@ -194,7 +194,7 @@ func (t *Translator) ProcessSecurityPolicies(securityPolicies []*egv1a1.Security | |||
irKey := t.getIRKey(targetedGateway.Gateway) |
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.
We don't need this for SecurityPolicy anymore. It's handled in #2970
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 removed the code that validates SecurityPolicy
for this issue.
Signed-off-by: Lior Okman <[email protected]>
Signed-off-by: Lior Okman <[email protected]>
another feature. Signed-off-by: Lior Okman <[email protected]>
…SecurityPolicy Signed-off-by: Lior Okman <[email protected]>
Signed-off-by: Lior Okman <[email protected]>
383041e
to
bc70ce9
Compare
} else { | ||
// If this policy is attached to a specific listener, any other listeners in the list | ||
// would be affected by this policy but should not be, so this policy can't be accepted. | ||
return fmt.Errorf("affects additional listeners: %s", strings.Join(sameListeners, ", ")) |
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.
return fmt.Errorf("affects additional listeners: %s", strings.Join(sameListeners, ", ")) | |
return fmt.Errorf("policy attached to multiple http (non https) listeners %s on the same port is not allowed", strings.Join(sameListeners, ", ")) |
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.
The suggested error message is a bit misleading, since the policy document as applied by the user is explicitly not attached to any other listener.
How about policy would affect additional http (non https) listeners to which it was not attached: %s
?
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.
ah instead of attached
, we could use applied
:)
ClientTrafficPolicy is being applied to multiple http (non https) listeners %s on the same port, which is not allowed
} | ||
} | ||
if len(conflictingListeners) != 0 { | ||
return fmt.Errorf("affects additional listeners: %s", strings.Join(conflictingListeners, ", ")) |
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.
same as below
thanks for adding comments @liorokman, added a minor comment around the error string to make it clearer why the policy was rejected, else LGTM ! |
Signed-off-by: Lior Okman <[email protected]>
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.
LGTM thanks !
/retest |
all e2e tests consistently seem to be consistently failing @liorokman |
/retest |
@arkodg all e2e tests have passed. |
* Fixing the clienttrafficpolicy validation. Signed-off-by: Lior Okman <[email protected]> * Make SecurityPolicy validate correctly. Signed-off-by: Lior Okman <[email protected]> * Reverted the SecurityPolicy validation - handled differently via another feature. Signed-off-by: Lior Okman <[email protected]> * Updated the tests to reflect that this validation isn't required for SecurityPolicy Signed-off-by: Lior Okman <[email protected]> * Added some comments to explain the validation being performed. Signed-off-by: Lior Okman <[email protected]> * Updated the error message as requested in the review. Signed-off-by: Lior Okman <[email protected]> --------- Signed-off-by: Lior Okman <[email protected]>
* Fixing the clienttrafficpolicy validation. Signed-off-by: Lior Okman <[email protected]> * Make SecurityPolicy validate correctly. Signed-off-by: Lior Okman <[email protected]> * Reverted the SecurityPolicy validation - handled differently via another feature. Signed-off-by: Lior Okman <[email protected]> * Updated the tests to reflect that this validation isn't required for SecurityPolicy Signed-off-by: Lior Okman <[email protected]> * Added some comments to explain the validation being performed. Signed-off-by: Lior Okman <[email protected]> * Updated the error message as requested in the review. Signed-off-by: Lior Okman <[email protected]> --------- Signed-off-by: Lior Okman <[email protected]> (cherry picked from commit f9409e4) Signed-off-by: Arko Dasgupta <[email protected]>
* Run certgen when upgrading (#2934) run certgen when upgrading Signed-off-by: huabing zhao <[email protected]> (cherry picked from commit 62ecf15) Signed-off-by: Arko Dasgupta <[email protected]> * Fix: nil secret in resourceversiontable (#2982) * fix nil secret in resourceversiontable Signed-off-by: huabing zhao <[email protected]> * check secrets in the xds result Signed-off-by: huabing zhao <[email protected]> --------- Signed-off-by: huabing zhao <[email protected]> (cherry picked from commit e880439) Signed-off-by: Arko Dasgupta <[email protected]> * fix: add missing http filters to the http filter chain (#2970) * fix: add missing http filters to the http filter chain Signed-off-by: huabing zhao <[email protected]> * refactor Signed-off-by: huabing zhao <[email protected]> * fix lint Signed-off-by: huabing zhao <[email protected]> * add comments Signed-off-by: huabing zhao <[email protected]> * remove refactor Signed-off-by: huabing zhao <[email protected]> * remove refactor Signed-off-by: huabing zhao <[email protected]> * fix gen Signed-off-by: huabing zhao <[email protected]> * fix lint Signed-off-by: Huabing Zhao <[email protected]> --------- Signed-off-by: huabing zhao <[email protected]> Signed-off-by: Huabing Zhao <[email protected]> (cherry picked from commit f699edf) Signed-off-by: Arko Dasgupta <[email protected]> * fix: allow websockets in url rewrite (#3022) allow websockets in url rewrite Signed-off-by: Jesse Haka <[email protected]> Co-authored-by: zirain <[email protected]> (cherry picked from commit 3d51933) Signed-off-by: Arko Dasgupta <[email protected]> * Set host for http health checker explicitly to avoid using the cluster name as host header for http health checking request. (#3057) * Set host for http health checker explictly to avoid using the cluster name as host header for http health checking request Signed-off-by: lemonlinger <[email protected]> * fix broken tests Signed-off-by: lemonlinger <[email protected]> * fix health-check test case in xds translation Signed-off-by: lemonlinger <[email protected]> * Simplify code and concise comments Signed-off-by: lemonlinger <[email protected]> --------- Signed-off-by: lemonlinger <[email protected]> (cherry picked from commit 8f450a9) Signed-off-by: Arko Dasgupta <[email protected]> * fix: do not create infra resources when missing translated listeners (#3043) * fix: do not create infra resources when missing translated listeners Signed-off-by: Karol Szwaj <[email protected]> * remove empty line Signed-off-by: Karol Szwaj <[email protected]> * skip infra creation on empty listeners and log it Signed-off-by: Karol Szwaj <[email protected]> --------- Signed-off-by: Karol Szwaj <[email protected]> (cherry picked from commit 36d7141) Signed-off-by: Arko Dasgupta <[email protected]> * Fix: double slashes in redirect URL (#2998) * fix: double trailing splashs in redirect URL Signed-off-by: huabing zhao <[email protected]> * add e2e tests Signed-off-by: huabing zhao <[email protected]> * fix lint Signed-off-by: huabing zhao <[email protected]> * fix test Signed-off-by: huabing zhao <[email protected]> * fix test Signed-off-by: huabing zhao <[email protected]> * fix test Signed-off-by: huabing zhao <[email protected]> * fix test Signed-off-by: huabing zhao <[email protected]> * add e2e tests Signed-off-by: huabing zhao <[email protected]> * fix test Signed-off-by: huabing zhao <[email protected]> * revert Signed-off-by: huabing zhao <[email protected]> * use regex rewrite to generate the redirect url Signed-off-by: huabing zhao <[email protected]> * use regex rewrite to generate the redirect url Signed-off-by: huabing zhao <[email protected]> * use regex rewrite to generate the redirect url Signed-off-by: huabing zhao <[email protected]> * remove comments Signed-off-by: huabing zhao <[email protected]> * extract method Signed-off-by: huabing zhao <[email protected]> * address comments Signed-off-by: huabing zhao <[email protected]> --------- Signed-off-by: huabing zhao <[email protected]> (cherry picked from commit ceb697f) Signed-off-by: Arko Dasgupta <[email protected]> * fix: Allow Policy to attach to multiple http listeners (#2967) * Fixing the clienttrafficpolicy validation. Signed-off-by: Lior Okman <[email protected]> * Make SecurityPolicy validate correctly. Signed-off-by: Lior Okman <[email protected]> * Reverted the SecurityPolicy validation - handled differently via another feature. Signed-off-by: Lior Okman <[email protected]> * Updated the tests to reflect that this validation isn't required for SecurityPolicy Signed-off-by: Lior Okman <[email protected]> * Added some comments to explain the validation being performed. Signed-off-by: Lior Okman <[email protected]> * Updated the error message as requested in the review. Signed-off-by: Lior Okman <[email protected]> --------- Signed-off-by: Lior Okman <[email protected]> (cherry picked from commit f9409e4) Signed-off-by: Arko Dasgupta <[email protected]> * fix: set path prefix for http ext auth service (#3018) Signed-off-by: huabing zhao <[email protected]> (cherry picked from commit 2882b7c) Signed-off-by: Arko Dasgupta <[email protected]> * Change route sorting order to Exact > RegularExpression > PathPrefix (#2579) * Change route sorting order to Exact > RegularExpression > PathPrefix kubernetes-sigs/gateway-api#1770 kubernetes-sigs/gateway-api#1855 Signed-off-by: Stéphane Cottin <[email protected]> (cherry picked from commit 11f56fd) Signed-off-by: Arko Dasgupta <[email protected]> * fix: infraIR duplicate port translation for merged gateways (#3061) * fix: duplicate port translation for merged gateways Signed-off-by: Karol Szwaj <[email protected]> * refactor to map Signed-off-by: Karol Szwaj <[email protected]> * rename map Signed-off-by: Karol Szwaj <[email protected]> * add seperate testcase Signed-off-by: Karol Szwaj <[email protected]> --------- Signed-off-by: Karol Szwaj <[email protected]> (cherry picked from commit 29946b0) Signed-off-by: Arko Dasgupta <[email protected]> * translator: set SpawnUpstreamSpan to true (#3102) * translator: set SpawnUpstreamSpan to true Signed-off-by: zirain <[email protected]> * update Signed-off-by: zirain <[email protected]> --------- Signed-off-by: zirain <[email protected]> (cherry picked from commit 635ebfc) Signed-off-by: Arko Dasgupta <[email protected]> * fix: rate limit doesn't work with two(and more) listeners (#3085) * fix: rate limit doesn't work with two listeners Signed-off-by: huabing zhao <[email protected]> * add e2e test for rate limit on multiple listeners Signed-off-by: huabing zhao <[email protected]> * address comments Signed-off-by: huabing zhao <[email protected]> --------- Signed-off-by: huabing zhao <[email protected]> Co-authored-by: Xunzhuo <[email protected]> (cherry picked from commit a5bedbc) Signed-off-by: Arko Dasgupta <[email protected]> * rerun make testdata Signed-off-by: Arko Dasgupta <[email protected]> --------- Signed-off-by: huabing zhao <[email protected]> Signed-off-by: Arko Dasgupta <[email protected]> Signed-off-by: Huabing Zhao <[email protected]> Signed-off-by: Jesse Haka <[email protected]> Signed-off-by: lemonlinger <[email protected]> Signed-off-by: Karol Szwaj <[email protected]> Signed-off-by: Lior Okman <[email protected]> Signed-off-by: Stéphane Cottin <[email protected]> Signed-off-by: zirain <[email protected]> Co-authored-by: Huabing Zhao <[email protected]> Co-authored-by: Jesse Haka <[email protected]> Co-authored-by: zirain <[email protected]> Co-authored-by: Meng <[email protected]> Co-authored-by: Karol Szwaj <[email protected]> Co-authored-by: Lior Okman <[email protected]> Co-authored-by: vixns <[email protected]> Co-authored-by: Xunzhuo <[email protected]>
Which issue(s) this PR fixes:
Fixes #2963