Web UI redirection policy can invalidate HAProxy and/or TLS setup

Bug #1993618 reported by Samuel Allan
28
This bug affects 5 people
Affects Status Importance Assigned to Milestone
MAAS
Fix Released
Medium
Alberto Donato
3.2
Fix Released
Medium
Anton Troyanov
3.3
Fix Released
Medium
Anton Troyanov

Bug Description

When MAAS is behind haproxy, accessing the web UI is problematic because when it redirects, the protocol and port are lost, replaced with http and port 5240.

It's going to be obvious in the following scenario.

[user] -> [firewall with TCP/80 allowed] -> [haproxy: TCP/80] -> [MAAS TCP/5240]

The initial request with http://<VIP/FQDN>:80/ of HAProxy succeeds and reaches to MAAS, then MAAS returns with a redirection directive to http://<VIP/FQDN>:5240/. It means that MAAS is requesting users to by-pass a reverse proxy such as HAProxy in the middle, and the access is going to be blocked especially when there is a firewall in font of a reverse proxy.

An example to reproduce:

1. deploy maas
2. configure haproxy in front with a VIP, listening on port 80, proxying to regiond on port 5240
3. `curl -i http://<VIP>:80/` and note that the 301 redirect is to `http://<VIP>:5240/MAAS/r/` (which is invalid)
4. note that accessing `http://<VIP>:80/MAAS/r/` works fine

The complete reproduction steps with a realistic scenario is in the comment #2.

This issue is also visible when following the instructions from https://maas.io/docs/how-to-secure-maas#heading--tls and it can redirect HTTPS access to *HTTP* not the other way around.

Related branches

Revision history for this message
Samuel Allan (samuelallan) wrote :

It appears that the problem comes from these redirects in regiond.nginx.conf:

```

    location = / {
        return 301 /MAAS/r/;
    }

    location ~ ^/MAAS/?$ {
        return 301 /MAAS/r/;
    }
```

A potential fix could be to turn off absolute redirects, so that redirects will be automatically interpreted in the context of the requesting url:

```
diff --git a/src/maasserver/templates/http/regiond.nginx.conf.template b/src/maasserver/templates/http/regiond.nginx.conf.template
index b45a7fff9..d9593ccc9 100644
--- a/src/maasserver/templates/http/regiond.nginx.conf.template
+++ b/src/maasserver/templates/http/regiond.nginx.conf.template
@@ -30,6 +30,9 @@ server {
     listen {{http_port}};
     {{endif}}

+ absolute_redirect off;
+ port_in_redirect off;
+
     location = / {
         return 301 /MAAS/r/;
     }
```

description: updated
description: updated
Bill Wear (billwear)
Changed in maas:
status: New → Triaged
importance: Undecided → Medium
Revision history for this message
Samuel Allan (samuelallan) wrote :

Here is a way to reproduce this issue in a lab:

1. create three focal VMs:

```
uvt-simplestreams-libvirt sync release=focal arch=amd64
uvt-kvm create maas1 release=focal --memory 16000 --disk 30
uvt-kvm create maas2 release=focal --memory 16000 --disk 30
uvt-kvm create maas3 release=focal --memory 16000 --disk 30
```

2. retrieve the ip addresses of them:

```
virsh domifaddr maas1
virsh domifaddr maas2
virsh domifaddr maas3
```

We'll refer to the addresses as $IP1, $IP2, and $IP3 below respectively.

3. create an ansible hosts file with the following contents:

```
[maas1]
$IP1

[maas2]
$IP2

[maas3]
$IP3

[maas_postgres_primary:children]
maas1

[maas_postgres_secondary:children]
maas2
maas3

[maas_postgres:children]
maas_postgres_primary
maas_postgres_secondary

[maas_region_controller:children]
maas1

[maas_rack_controller:children]
maas1

[maas_proxy:children]
maas1
```

4. create an ansible variables file with the following contents:

```
maas_version: "3.2"
maas_postgres_password: mypassword
maas_installation_type: snap
maas_url: http://$IP1:5050/MAAS
ansible_user: ubuntu
```

5. clone the new maas-ansible-playbook repository: https://github.com/maas/maas-ansible-playbook . At time of writing, main is at commit db80c9b7ebefd069809e6368e280ed38cd968532 .

6. Run the site.yaml playbook with the above hosts and vars to deploy maas - eg.:

```
ansible-playbook -i hosts --extra-vars "@vars.yaml" ./site.yaml
```

7. now visit http://$IP1:5050/MAAS/r/ in the browser. This is the address that the haproxy instance is listening on. Verify that the maas web ui loads and remains on the same url.

8. now visit http://$IP1:5050/ . Verify that you will be redirected to http://$IP1:5240/MAAS/r/ . Note the changed port number - this is the evidence of the bug here. Now you're directly accessing the url of the maas server, not the haproxy.

When the bug is fixed, it can be confirmed by checking that in step 8, you are redirected to http://$IP1:5050/MAAS/r/ (ie. retaining the correct port - remaining on haproxy).

Revision history for this message
Nobuto Murata (nobuto) wrote :

Subscribing ~field-high.

The invalid redirection policy prevents from setting up a production grade MAAS cluster. And it can be reproduced with the reference Ansible playbook out of the box.

description: updated
summary: - web ui redirects invalid behind haproxy
+ Web UI redirection policy can invalidate HAProxy and/or TLS setup
Changed in maas:
milestone: none → 3.4.0
Revision history for this message
Peter Jose De Sousa (pjds) wrote :

Running into similar issues, but we worked around this by configuring the maas server settings:

sudo maas config
maas_url=http://VIP:80/MAAS
database_host=VIP
database_port=None
database_name=maasdb
database_user=maas
database_pass=(hidden)
debug=True

sudo maas config --maas-url=https://VIP:5443/MAAS

location is now returned in the HTTP headers correctly as 10.66.240.223:5443/MAAS

Alberto Donato (ack)
Changed in maas:
assignee: nobody → Alberto Donato (ack)
Alberto Donato (ack)
Changed in maas:
status: Triaged → In Progress
Changed in maas:
status: In Progress → Fix Committed
Revision history for this message
Nobuto Murata (nobuto) wrote :
Alberto Donato (ack)
Changed in maas:
milestone: 3.4.0 → 3.4.0-beta1
Alberto Donato (ack)
Changed in maas:
status: Fix Committed → Fix Released
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Duplicates of this bug

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.