Skip to content
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

Merged
merged 6 commits into from
Mar 28, 2024

Conversation

liorokman
Copy link
Contributor

Which issue(s) this PR fixes:
Fixes #2963

@liorokman liorokman requested a review from a team as a code owner March 18, 2024 07:21
Copy link

codecov bot commented Mar 18, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 64.55%. Comparing base (a270dd8) to head (4736eb4).
Report is 1 commits behind head on main.

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.
📢 Have feedback on the report? Share it here.

@@ -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 {
Copy link
Contributor

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 {
Copy link
Contributor

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

Copy link
Contributor Author

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.

Copy link
Contributor Author

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
}

Copy link
Contributor

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

Copy link
Contributor Author

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.

Copy link
Member

@zhaohuabing zhaohuabing left a 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

@arkodg
Copy link
Contributor

arkodg commented Mar 18, 2024

@zhaohuabing we still need it for CTP which adds fields like MergeSlashes on the hcm directly, so we have a conflict for http (non https/tls) case

@@ -194,7 +194,7 @@ func (t *Translator) ProcessSecurityPolicies(securityPolicies []*egv1a1.Security
irKey := t.getIRKey(targetedGateway.Gateway)
Copy link
Member

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

Copy link
Contributor Author

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 <lior.okman@sap.com>
Signed-off-by: Lior Okman <lior.okman@sap.com>
another feature.

Signed-off-by: Lior Okman <lior.okman@sap.com>
…SecurityPolicy

Signed-off-by: Lior Okman <lior.okman@sap.com>
Signed-off-by: Lior Okman <lior.okman@sap.com>
@liorokman liorokman force-pushed the reject-non-tls-check branch from 383041e to bc70ce9 Compare March 28, 2024 10:48
} 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, ", "))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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, ", "))

Copy link
Contributor Author

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 ?

Copy link
Contributor

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, ", "))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as below

@arkodg
Copy link
Contributor

arkodg commented Mar 28, 2024

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 <lior.okman@sap.com>
Copy link
Contributor

@arkodg arkodg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM thanks !

@arkodg arkodg requested review from a team March 28, 2024 12:32
@zirain
Copy link
Contributor

zirain commented Mar 28, 2024

/retest

@arkodg
Copy link
Contributor

arkodg commented Mar 28, 2024

all e2e tests consistently seem to be consistently failing @liorokman

@liorokman
Copy link
Contributor Author

/retest

@liorokman
Copy link
Contributor Author

all e2e tests consistently seem to be consistently failing @liorokman

@arkodg all e2e tests have passed.

@arkodg arkodg merged commit f9409e4 into envoyproxy:main Mar 28, 2024
19 checks passed
ShyunnY pushed a commit to ShyunnY/gateway that referenced this pull request Apr 1, 2024
* Fixing the clienttrafficpolicy validation.

Signed-off-by: Lior Okman <lior.okman@sap.com>

* Make SecurityPolicy validate correctly.

Signed-off-by: Lior Okman <lior.okman@sap.com>

* Reverted the SecurityPolicy validation - handled differently via
another feature.

Signed-off-by: Lior Okman <lior.okman@sap.com>

* Updated the tests to reflect that this validation isn't required for SecurityPolicy

Signed-off-by: Lior Okman <lior.okman@sap.com>

* Added some comments to explain the validation being performed.

Signed-off-by: Lior Okman <lior.okman@sap.com>

* Updated the error message as requested in the review.

Signed-off-by: Lior Okman <lior.okman@sap.com>

---------

Signed-off-by: Lior Okman <lior.okman@sap.com>
arkodg pushed a commit to arkodg/gateway that referenced this pull request Apr 8, 2024
* Fixing the clienttrafficpolicy validation.

Signed-off-by: Lior Okman <lior.okman@sap.com>

* Make SecurityPolicy validate correctly.

Signed-off-by: Lior Okman <lior.okman@sap.com>

* Reverted the SecurityPolicy validation - handled differently via
another feature.

Signed-off-by: Lior Okman <lior.okman@sap.com>

* Updated the tests to reflect that this validation isn't required for SecurityPolicy

Signed-off-by: Lior Okman <lior.okman@sap.com>

* Added some comments to explain the validation being performed.

Signed-off-by: Lior Okman <lior.okman@sap.com>

* Updated the error message as requested in the review.

Signed-off-by: Lior Okman <lior.okman@sap.com>

---------

Signed-off-by: Lior Okman <lior.okman@sap.com>
(cherry picked from commit f9409e4)
Signed-off-by: Arko Dasgupta <arko@tetrate.io>
Xunzhuo added a commit that referenced this pull request Apr 8, 2024
* Run certgen when upgrading (#2934)

run certgen when upgrading

Signed-off-by: huabing zhao <zhaohuabing@gmail.com>
(cherry picked from commit 62ecf15)
Signed-off-by: Arko Dasgupta <arko@tetrate.io>

* Fix: nil secret in resourceversiontable (#2982)

* fix nil secret in resourceversiontable

Signed-off-by: huabing zhao <zhaohuabing@gmail.com>

* check secrets in the xds result

Signed-off-by: huabing zhao <zhaohuabing@gmail.com>

---------

Signed-off-by: huabing zhao <zhaohuabing@gmail.com>
(cherry picked from commit e880439)
Signed-off-by: Arko Dasgupta <arko@tetrate.io>

* 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 <zhaohuabing@gmail.com>

* refactor

Signed-off-by: huabing zhao <zhaohuabing@gmail.com>

* fix lint

Signed-off-by: huabing zhao <zhaohuabing@gmail.com>

* add comments

Signed-off-by: huabing zhao <zhaohuabing@gmail.com>

* remove refactor

Signed-off-by: huabing zhao <zhaohuabing@gmail.com>

* remove refactor

Signed-off-by: huabing zhao <zhaohuabing@gmail.com>

* fix gen

Signed-off-by: huabing zhao <zhaohuabing@gmail.com>

* fix lint

Signed-off-by: Huabing Zhao <zhaohuabing@gmail.com>

---------

Signed-off-by: huabing zhao <zhaohuabing@gmail.com>
Signed-off-by: Huabing Zhao <zhaohuabing@gmail.com>
(cherry picked from commit f699edf)
Signed-off-by: Arko Dasgupta <arko@tetrate.io>

* fix: allow websockets in url rewrite (#3022)

allow websockets in url rewrite

Signed-off-by: Jesse Haka <haka.jesse@gmail.com>
Co-authored-by: zirain <zirain2009@gmail.com>
(cherry picked from commit 3d51933)
Signed-off-by: Arko Dasgupta <arko@tetrate.io>

* 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 <lemonlinger@gmail.com>

* fix broken tests

Signed-off-by: lemonlinger <lemonlinger@gmail.com>

* fix health-check test case in xds translation

Signed-off-by: lemonlinger <lemonlinger@gmail.com>

* Simplify code and concise comments

Signed-off-by: lemonlinger <lemonlinger@gmail.com>

---------

Signed-off-by: lemonlinger <lemonlinger@gmail.com>
(cherry picked from commit 8f450a9)
Signed-off-by: Arko Dasgupta <arko@tetrate.io>

* 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 <karol.szwaj@gmail.com>

* remove empty line

Signed-off-by: Karol Szwaj <karol.szwaj@gmail.com>

* skip infra creation on empty listeners and log it

Signed-off-by: Karol Szwaj <karol.szwaj@gmail.com>

---------

Signed-off-by: Karol Szwaj <karol.szwaj@gmail.com>
(cherry picked from commit 36d7141)
Signed-off-by: Arko Dasgupta <arko@tetrate.io>

* Fix: double slashes in redirect URL (#2998)

* fix: double trailing splashs in redirect URL

Signed-off-by: huabing zhao <zhaohuabing@gmail.com>

* add e2e tests

Signed-off-by: huabing zhao <zhaohuabing@gmail.com>

* fix lint

Signed-off-by: huabing zhao <zhaohuabing@gmail.com>

* fix test

Signed-off-by: huabing zhao <zhaohuabing@gmail.com>

* fix test

Signed-off-by: huabing zhao <zhaohuabing@gmail.com>

* fix test

Signed-off-by: huabing zhao <zhaohuabing@gmail.com>

* fix test

Signed-off-by: huabing zhao <zhaohuabing@gmail.com>

* add e2e tests

Signed-off-by: huabing zhao <zhaohuabing@gmail.com>

* fix test

Signed-off-by: huabing zhao <zhaohuabing@gmail.com>

* revert

Signed-off-by: huabing zhao <zhaohuabing@gmail.com>

* use regex rewrite to generate the redirect url

Signed-off-by: huabing zhao <zhaohuabing@gmail.com>

* use regex rewrite to generate the redirect url

Signed-off-by: huabing zhao <zhaohuabing@gmail.com>

* use regex rewrite to generate the redirect url

Signed-off-by: huabing zhao <zhaohuabing@gmail.com>

* remove comments

Signed-off-by: huabing zhao <zhaohuabing@gmail.com>

* extract method

Signed-off-by: huabing zhao <zhaohuabing@gmail.com>

* address comments

Signed-off-by: huabing zhao <zhaohuabing@gmail.com>

---------

Signed-off-by: huabing zhao <zhaohuabing@gmail.com>
(cherry picked from commit ceb697f)
Signed-off-by: Arko Dasgupta <arko@tetrate.io>

* fix: Allow Policy to attach to multiple http listeners  (#2967)

* Fixing the clienttrafficpolicy validation.

Signed-off-by: Lior Okman <lior.okman@sap.com>

* Make SecurityPolicy validate correctly.

Signed-off-by: Lior Okman <lior.okman@sap.com>

* Reverted the SecurityPolicy validation - handled differently via
another feature.

Signed-off-by: Lior Okman <lior.okman@sap.com>

* Updated the tests to reflect that this validation isn't required for SecurityPolicy

Signed-off-by: Lior Okman <lior.okman@sap.com>

* Added some comments to explain the validation being performed.

Signed-off-by: Lior Okman <lior.okman@sap.com>

* Updated the error message as requested in the review.

Signed-off-by: Lior Okman <lior.okman@sap.com>

---------

Signed-off-by: Lior Okman <lior.okman@sap.com>
(cherry picked from commit f9409e4)
Signed-off-by: Arko Dasgupta <arko@tetrate.io>

* fix: set path prefix for http ext auth service (#3018)

Signed-off-by: huabing zhao <zhaohuabing@gmail.com>
(cherry picked from commit 2882b7c)
Signed-off-by: Arko Dasgupta <arko@tetrate.io>

* 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 <stephane.cottin@vixns.com>
(cherry picked from commit 11f56fd)
Signed-off-by: Arko Dasgupta <arko@tetrate.io>

* fix: infraIR duplicate port translation for merged gateways (#3061)

* fix: duplicate port translation for merged gateways

Signed-off-by: Karol Szwaj <karol.szwaj@gmail.com>

* refactor to map

Signed-off-by: Karol Szwaj <karol.szwaj@gmail.com>

* rename map

Signed-off-by: Karol Szwaj <karol.szwaj@gmail.com>

* add seperate testcase

Signed-off-by: Karol Szwaj <karol.szwaj@gmail.com>

---------

Signed-off-by: Karol Szwaj <karol.szwaj@gmail.com>
(cherry picked from commit 29946b0)
Signed-off-by: Arko Dasgupta <arko@tetrate.io>

* translator: set SpawnUpstreamSpan to true (#3102)

* translator: set SpawnUpstreamSpan to true

Signed-off-by: zirain <zirain2009@gmail.com>

* update

Signed-off-by: zirain <zirain2009@gmail.com>

---------

Signed-off-by: zirain <zirain2009@gmail.com>
(cherry picked from commit 635ebfc)
Signed-off-by: Arko Dasgupta <arko@tetrate.io>

* 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 <zhaohuabing@gmail.com>

* add e2e test for rate limit on multiple listeners

Signed-off-by: huabing zhao <zhaohuabing@gmail.com>

* address comments

Signed-off-by: huabing zhao <zhaohuabing@gmail.com>

---------

Signed-off-by: huabing zhao <zhaohuabing@gmail.com>
Co-authored-by: Xunzhuo <bitliu@tencent.com>
(cherry picked from commit a5bedbc)
Signed-off-by: Arko Dasgupta <arko@tetrate.io>

* rerun make testdata

Signed-off-by: Arko Dasgupta <arko@tetrate.io>

---------

Signed-off-by: huabing zhao <zhaohuabing@gmail.com>
Signed-off-by: Arko Dasgupta <arko@tetrate.io>
Signed-off-by: Huabing Zhao <zhaohuabing@gmail.com>
Signed-off-by: Jesse Haka <haka.jesse@gmail.com>
Signed-off-by: lemonlinger <lemonlinger@gmail.com>
Signed-off-by: Karol Szwaj <karol.szwaj@gmail.com>
Signed-off-by: Lior Okman <lior.okman@sap.com>
Signed-off-by: Stéphane Cottin <stephane.cottin@vixns.com>
Signed-off-by: zirain <zirain2009@gmail.com>
Co-authored-by: Huabing Zhao <zhaohuabing@gmail.com>
Co-authored-by: Jesse Haka <haka.jesse@gmail.com>
Co-authored-by: zirain <zirain2009@gmail.com>
Co-authored-by: Meng <lemonlinger@gmail.com>
Co-authored-by: Karol Szwaj <karol.szwaj@gmail.com>
Co-authored-by: Lior Okman <lior.okman@sap.com>
Co-authored-by: vixns <stephane.cottin@vixns.com>
Co-authored-by: Xunzhuo <bitliu@tencent.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

bug: Allow Policy to attach to multiple http listeners
4 participants