Need help with intercepting a 301 redirect

I’m struggling to intercept a redirect from a backend site.

I have a route from
https://example.pomerium.mydomain.com
to
https://test.example.com
Normally, when I access something.example.com, I will be redirected to either

/login
or
/app/ (when I’m already logged in)

But when I access https://example.pomerium.mydomain.com

I get a 301 redirect to https://test.example.com/app/, which puts me “outside” Pomerium again

If I’m not logged in, I’m redirected to /login, which initially doesn’t work, but I got around it with a response header rewrite:

  rewrite_response_headers:
  - header: Location
    prefix: https://test.example.com/login
    value: http://example.pomerium.mydomain.com/login

Now if I access /app directly, everything seems to work:
https://example.pomerium.mydomain.com/app/

But I would like to not have to instruct the users to manually include /app/
I experimented with path_redirect and some other redirects, but while the config doesn’t break ( I can start the application), it also doesn’t seem to work the way I want it to.

What did you expect to happen?

I expected Pomerium to “catch” the redirect and translate it to https://example.pomerium.mydomain.com/app/

What’s your environment like?

  • Pomerium version (retrieve with pomerium --version): 0.20.0-1668445494+9413123c
  • Server Operating System/Architecture/Cloud: RHEL 8.7

What’s your config.yaml?

routes:
- from: https://example.pomerium.mydomain.com
  to: https://test.example.com
  rewrite_response_headers:
  - header: Location
    prefix: https://test.example.com/login
    value: http://example.pomerium.mydomain.com/login
  policy:
  - allow:
      or:
      - domain:
          is: mydomain.com
  redirect:
    path: /
    path_redirect: /app/

What did you see in the logs?

Nothing useful in the logs

Additional context

Are there any examples as to how to configure the redirects? I struggle to make sense of the docs for this feature:

  • path_redirect (string): the incoming path portion of the URL will be swapped with the given value.
    Does this mean that ANY path after the host will be swapped, or can you set a from and to value here (like I’ve tried to do in my config)?

You may set preserve_host_header option so that your app would know the original name of the host. It may not work as your upstream is HTTPS and they’ll come into conflict.

Pomerium does not have conditional rewrite rules currently.

Is this some kind of standard app we can try to look at or it’s something internal ?

1 Like

Thanks for the response

I did try preserve_host_header, but it didn’t work, unfortunately.

The app in question is whip media from mediamorph.com (Buy TV Content Rights, Buy Movie Rights | Whip Media). They use IP whitelisting, so the URL (akin to “mycompany.mediamorph.com”) is only available from some of my company’s predefined IP addresses, so it might be hard for you to test.

If it’s of any use, here are the headers:

Request headers
Request URL: https://mediamorph.pomerium.mycompany.com/
Request Method: GET
Status Code: 301  (from disk cache)
Remote Address: 92.220.230.54:443
Referrer Policy: strict-origin-when-cross-origin
content-length: 243
content-type: text/html; charset=iso-8859-1
date: Mon, 23 Jan 2023 07:52:54 GMT
location: https://mycompany.mediamorph.com/app/
server: envoy
x-envoy-upstream-service-time: 136
x-frame-options: SAMEORIGIN
x-request-id: 2251a9e5-02d2-4faf-124c-a8b6b05c2ba2
x-xss-protection: 1; mode=block
1 Like

Can you use a rule like this so it matches any path?

rewrite_response_headers:
  - header: Location
    prefix: https://test.example.com/
    value: http://example.pomerium.mydomain.com/

Then both /login and /app/ would get redirected. Alternatively you could add two routes:

rewrite_response_headers:
  - header: Location
    prefix: https://test.example.com/login
    value: http://example.pomerium.mydomain.com/login
  - header: Location
    prefix: https://test.example.com/app/
    value: http://example.pomerium.mydomain.com/app/
1 Like

Thanks, @calebdoxsey, your first suggestion seems to work:

routes:
- from: https://mediamorph.pomerium.mydomain.com
  to: https://test.mediamorph.com
  rewrite_response_headers:
  - header: Location
    prefix: https://test.mediamorph.com/
    value: https://mediamorph.pomerium.mydomain.com/

Not sure why this is necessary, though. I would have assumed that this would be covered by the from/to parameters, which are identical, except for the trailing slashes…

The alternative with two rules did not work for me, for some reason.

Anyway, thanks for the assist!

Seems I was a bit too quick to declare this resolved…

Yes, the rewrite_response_headers-fix works for the first URL, but when I try to duplicate the rule for a slightly different one, it doesn’t work:

- from: https://mediamorph-abc.pomerium.mydomain.com
  to: https://test-abc.mediamorph.com
  rewrite_response_headers:
  - header: Location
    prefix: https://test-abc.mediamorph.com/
    value: https://mediamorph-abc.pomerium.mydomain.com/

The only obvious difference between the two is the dash ( - ) in the URL. Is this a known limitation, or have I stumbled upon a bug?

Ok, so I’ve half narrowed down where this goes wrong.

The function replace_prefix in
https://github.com/pomerium/pomerium/blob/main/config/envoyconfig/luascripts/rewrite-headers.lua

function replace_prefix(str, prefix, value)
    return str:gsub("^"..prefix, value)
end

uses gsub. I’m not a lua expert, but apparently the dash/hyphen needs to be escaped for this to work:

If I test the function locally, I see the following behaviour:

Substitution without dash works fine

replace_prefix("https://nodash.domain.com/app/", "https://nodash.domain.com/", "https://rewritten.mydomain.com/")
https://rewritten.mydomain.com/app/	1

Substitution with dash fails ( The original string is returned unaltered)

replace_prefix("https://with-dash.domain.com/app/", "https://with-dash.domain.com/", "https://rewritten.mydomain.com/")
https://with-dash.domain.com/app/	0

But if I escape the dash with a %, it works again

replace_prefix("https://with-dash.domain.com/app/", "https://with%-dash.domain.com/", "https://rewritten.mydomain.com/")
https://rewritten.mydomain.com/app/	1

So in theory, I should be able to escape the dash in my config

  rewrite_response_headers:
  - header: Location
    prefix: https://test%-abc.mediamorph.com/
    value: https://mediamorph-abc.pomerium.mydomain.com/

This doesn’t work however, so maybe the % is being stripped away at some point, before it reaches the replace_prefix function…?

Anyway, perhaps you would consider this solution to get around the issue…?

I believe URLs with dashes are fairly common, so I would imagine this could be helpful for others as well.

I was able to get around this by enclosing the prefix in double quotes and escaping the dash in config.yaml ( single quotes did not work)

    rewrite_response_headers:
      - header: Location
        prefix: "https://test%-abc.mediamorph.com/"
        value: https://mediamorph-abc.pomerium.mydomain.com/

I still think it would be nice if the replace-script had handled this, but at least my setup works now.