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

Path is not threated as regex if ingress.kubernetes.io/rewrite-target isn't ending with / #1260

Closed
paalkr opened this issue Aug 29, 2017 · 14 comments
Labels
lifecycle/rotten Denotes an issue or PR that has aged beyond stale and will be auto-closed. nginx

Comments

@paalkr
Copy link
Contributor

paalkr commented Aug 29, 2017

Given the example ingress rule blow
I need the path to be handled as regex for several reasons, one is to support CaMelCase in requests. Another is to get my desired combinations of hosts and paths in the ingress rules to function correctly. Currently we have around 5 hosts and more than 200 paths split in about 50 ingress rules, that all needs to resolve to the correct upstream service.

The problem is that I have to add a trailing / to the ingress.kubernetes.io/rewrite-target, to get the path ending up as regex in the location section of the ingress nginx.conf file.

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: foo
  labels:
    name: foo
  annotations:
    kubernetes.io/ingress.class: "nginx"
    ingress.kubernetes.io/ssl-redirect: "false" 
    ingress.kubernetes.io/secure-backends: "true"    
    ingress.kubernetes.io/rewrite-target: /arcgis/rest/services/Geocache_UTM33_EUREF89/GeocacheBasis/  
spec:
  tls:
  - hosts:
    - foo.geodataonline.no
    secretName: star-gdo-tls-chain
  rules:
  - host: foo.geodataonline.no 
    http: 
      paths:
      - path: /arcgis/rest/services/Geocache_UTM33_EUREF89/GeocacheBasis
        backend:
          serviceName: foo
          servicePort: 6443

Resulting location segment of the nginx.conf file

        location ~* ^/arcgis/rest/services/Geocache_UTM33_EUREF89/GeocacheBasis\/?(?<baseuri>.*) {
            set $proxy_upstream_name "default-geocachebasisutm33euref89-6443";
            port_in_redirect off;
            client_max_body_size                    "1m";
            proxy_set_header Host                   $best_http_host;
            # Pass the extracted client certificate to the backend
            # Allow websocket connections
            proxy_set_header                        Upgrade           $http_upgrade;
            proxy_set_header                        Connection        $connection_upgrade;
            proxy_set_header X-Real-IP              $the_real_ip;
            proxy_set_header X-Forwarded-For        $the_real_ip;
            proxy_set_header X-Forwarded-Host       $best_http_host;
            proxy_set_header X-Forwarded-Port       $pass_port;
            proxy_set_header X-Forwarded-Proto      $pass_access_scheme;
            proxy_set_header X-Original-URI         $request_uri;
            proxy_set_header X-Scheme               $pass_access_scheme;
            # mitigate HTTPoxy Vulnerability
            # https://www.nginx.com/blog/mitigating-the-httpoxy-vulnerability-with-nginx/
            proxy_set_header Proxy                  "";
            # Custom headers to proxied server
            proxy_connect_timeout                   5s;
            proxy_send_timeout                      60s;
            proxy_read_timeout                      60s;
            proxy_redirect                          off;
            proxy_buffering                         off;
            proxy_buffer_size                       "4k";
            proxy_buffers                           4 "4k";
            proxy_http_version                      1.1;
            proxy_cookie_domain                     off;
            proxy_cookie_path                       off;
            # In case of errors try the next upstream server before returning an error
            proxy_next_upstream                     error timeout invalid_header http_502 http_503 http_504;
	rewrite /arcgis/rest/services/Geocache_UTM33_EUREF89/GeocacheBasis/(.*) /arcgis/rest/services/Geocache_UTM33_EUREF89/GeocacheBasis//$1 break;
	proxy_pass https://default-geocachebasisutm33euref89-6443;
	
        }

The problem is that a request like
https://foo.geodataonline.no/arcgis/rest/services/Geocache_UTM33_EUREF89/GeocacheBasis/foo/bar?query=string
are passed to my upstream service as
/arcgis/rest/services/Geocache_UTM33_EUREF89/GeocacheBasis//foo/bar?query=string
notice the // fefore foo

An ideal situation would be to have an option to force the ingress path to be threaded as regex, and to be able to redirect to whatever I want (even without a trailing /).

Desired ingress config

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: foo
  labels:
    name: foo
  annotations:
    kubernetes.io/ingress.class: "nginx"
    ingress.kubernetes.io/ssl-redirect: "false" 
    ingress.kubernetes.io/secure-backends: "true"    
    ingress.kubernetes.io/paths-as-regex: "true"    
    ingress.kubernetes.io/rewrite-target: /foo/bar  
spec:
  tls:
  - hosts:
    - my.host.no
    secretName: star-gdo-tls-chain
  rules:
  - host: my.host.no 
    http: 
      paths:
      - path: /foo/bar
        backend:
          serviceName: foo
          servicePort: 6443

Which then ideally should result in the following being passed to the upstream service

my.host.no/foo/bar -> upstream/foo/bar
my.host.no/fOO/bAr/baz -> upstream/foo/bar/baz
my.host.no/foo/barBaz -> upstream/foo/barBaz
my.host.no/foO/barbecue?request=dinner&location=home -> upstream/foo/barbecue?request=dinner&location=home
@hzxuzhonghu
Copy link
Member

I use 0.9.0-beta.12 , and without a trailing / to the ingress.kubernetes.io/rewrite-target. And it works well, But add trailing / to ingress.kubernetes.io/rewrite-target lead to rewrite /xxx/(.*) /xxx//$1 break;

@paalkr
Copy link
Contributor Author

paalkr commented Sep 5, 2017

I'm using the same version. Rewrite works for me as well without the trailing /. But the problem is that the spec.rules.http.paths.path is not interpreted as regex if the rewrite doesn't end with a /.

@hzxuzhonghu
Copy link
Member

It should not be, please see func buildProxyPass

@paalkr
Copy link
Contributor Author

paalkr commented Sep 5, 2017

I think the problem might be in the buildLocation function (&& location.Rewrite.Target != path), not the buildProxyPass. If the path and the ingress.kubernetes.io/rewrite-target are equal (which they are in my case if not adding a trailing / to the ingress.kubernetes.io/rewrite-targe), the nginx Location is not prefixed with ~* and handled as regex.

	if len(location.Rewrite.Target) > 0 && location.Rewrite.Target != path {
		if path == slash {
			return fmt.Sprintf("~* %s", path)
		}
		// baseuri regex will parse basename from the given location
		baseuri := `(?<baseuri>.*)`
		if !strings.HasSuffix(path, slash) {
			// Not treat the slash after "location path" as a part of baseuri
			baseuri = fmt.Sprintf(`\/?%s`, baseuri)
		}
		return fmt.Sprintf(`~* ^%s%s`, path, baseuri)
	}

return path

I would suggest a directive to specify that the spec.rules.http.paths.path should end up as a regex Location, regardless of what ingress.kubernetes.io/rewrite-target might be (even if it not specified). currently the only way to get the Location to be threatened as regex (added ~*) is to define a ingress.kubernetes.io/rewrite-target that is different from spec.rules.http.paths.path. This is the key issue in my case. I'm actually not even after the rewrite functionality in many cases, but just to get at regex Location.

@paalkr
Copy link
Contributor Author

paalkr commented Sep 10, 2017

After digging around in the issue tracker I can see several related issues. It turns out I'm not the only one who have found the current behavior a little confusing and limiting.

#619
#646
kubernetes-retired/contrib#1884

Are there any plans on how to take this further?

@aledbf
Copy link
Member

aledbf commented Sep 10, 2017

@paalkr before this we need proper e2e tests

@paalkr
Copy link
Contributor Author

paalkr commented Sep 27, 2017

@aledbf , so is that something I can contribute with? Or does it require developer skills?

@fejta-bot
Copy link

Issues go stale after 90d of inactivity.
Mark the issue as fresh with /remove-lifecycle stale.
Stale issues rot after an additional 30d of inactivity and eventually close.

Prevent issues from auto-closing with an /lifecycle frozen comment.

If this issue is safe to close now please do so with /close.

Send feedback to sig-testing, kubernetes/test-infra and/or @fejta.
/lifecycle stale

@k8s-ci-robot k8s-ci-robot added the lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. label Jan 6, 2018
@fejta-bot
Copy link

Stale issues rot after 30d of inactivity.
Mark the issue as fresh with /remove-lifecycle rotten.
Rotten issues close after an additional 30d of inactivity.

If this issue is safe to close now please do so with /close.

Send feedback to sig-testing, kubernetes/test-infra and/or fejta.
/lifecycle rotten
/remove-lifecycle stale

@k8s-ci-robot k8s-ci-robot added lifecycle/rotten Denotes an issue or PR that has aged beyond stale and will be auto-closed. and removed lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. labels Feb 10, 2018
@ananace
Copy link

ananace commented Mar 2, 2018

This is still certainly an issue, even if people seem to have gone silent on it.

Being unable to use regex paths - as the docs state should work - is quite a pain, especially since there doesn't seem to be any notice anywhere about this.

@nullbeck
Copy link

nullbeck commented Mar 7, 2018

This is still certainly an issue, even if people seem to have gone silent on it.

+

@fejta-bot
Copy link

Rotten issues close after 30d of inactivity.
Reopen the issue with /reopen.
Mark the issue as fresh with /remove-lifecycle rotten.

Send feedback to sig-testing, kubernetes/test-infra and/or fejta.
/close

@josuappworks
Copy link

@avezov
Copy link

avezov commented May 24, 2022

/reopen

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
lifecycle/rotten Denotes an issue or PR that has aged beyond stale and will be auto-closed. nginx
Projects
None yet
Development

No branches or pull requests

9 participants