#7479 FreeIPA web frontend: Requests to / should not redirect to hard-coded domain
Opened a year ago by bittner. Modified 5 months ago

Request for enhancement

As developer of a free software project, I want FreeIPA not to redirect requests on / to https://domain.tld/ipa/ui (hard-coded) so that it works on any domain, IP address and port out-of-the-box.

Issue

Currently, the domain you use with FreeIPA is hard-coded in /etc/httpd/conf.d/ipa-rewrite.conf (e.g. on CentOS), which attempts to redirect traffic to the SSL version of the service. Unfortunately, this makes it impossible to make FreeIPA run locally, e.g. in a Vagrant box, without additional changes to the infrastructure setup.

Steps to Reproduce

  1. Make the Vagrant setup forward host port 8444 to guest port 443 (which is where the FreeIPA web frontend is running inside the Vagrant box)
  2. Install FreeIPA server in, e.g., a Vagrant box (using, say, Ansible): ipa-server-install --unattended --admin-password={{ ADMIN_PASSWORD }} --ds-password={{ ADMIN_PASSWORD }} --hostname={{ FQDN }} --domain={{ DOMAIN }} --realm={{ DOMAIN|upper }}
  3. Access FreeIPA from the host system, e.g. via https://127.0.0.1:8444/

FILE: Vagrantfile (example setup)

Vagrant.configure("2") do |config|
  config.vm.box = "centos/7"
  config.vm.hostname = "ipa.foo-bar-baz.software"
  config.vm.network :forwarded_port, host: 8444, guest: 443, auto_correct: true
  config.vm.provider :virtualbox do |vb|
    vb.customize ["modifyvm", :id, "--name", "Reproduce freeipa/issue/7479"]
    vb.customize ["modifyvm", :id, "--memory", "1024"]
    vb.customize ["modifyvm", :id, "--vram", "16"]
    vb.customize ["modifyvm", :id, "--ioapic", "on"]
    vb.customize ["modifyvm", :id, "--cpus", "4"]
  end
end

Actual behavior

The httpd service configuration will redirect your browser to https://{{ DOMAIN }}/ipa/ui/

Expected behavior

The browser should be redirected to https://127.0.0.1:8444//ipa/ui/ (i.e. the base URL with /ipa/ui appended)

Version/Release/Distribution

$ rpm -q freeipa-server freeipa-client ipa-server ipa-client 389-ds-base pki-ca krb5-server
package freeipa-server is not installed
package freeipa-client is not installed
ipa-server-4.5.0-22.el7.centos.x86_64
ipa-client-4.5.0-22.el7.centos.x86_64
389-ds-base-1.3.6.1-28.el7_4.x86_64
pki-ca-10.4.1-17.el7_4.noarch
krb5-server-1.15.1-8.el7.x86_64
$ rpm -qa | grep ipa
libipa_hbac-1.15.2-50.el7_4.11.x86_64
python-ipaddress-1.0.16-2.el7.noarch
python2-ipalib-4.5.0-22.el7.centos.noarch
sssd-ipa-1.15.2-50.el7_4.11.x86_64
ipa-common-4.5.0-22.el7.centos.noarch
ipa-client-common-4.5.0-22.el7.centos.noarch
python-libipa_hbac-1.15.2-50.el7_4.11.x86_64
ipa-server-common-4.5.0-22.el7.centos.noarch
python2-ipaclient-4.5.0-22.el7.centos.noarch
python-ipaddr-2.1.11-1.el7.noarch
ipa-server-4.5.0-22.el7.centos.x86_64
python2-ipaserver-4.5.0-22.el7.centos.noarch
python-iniparse-0.4-9.el7.noarch
ipa-client-4.5.0-22.el7.centos.x86_64

Additional info:

FILE: /etc/httpd/conf.d/ipa-rewrite.conf (original state after installation)

# VERSION 6 - DO NOT REMOVE THIS LINE

RewriteEngine on

# By default forward all requests to /ipa. If you don't want IPA
# to be the default on your web server comment this line out.
RewriteRule ^/$ https://ipa.foo-bar-baz.software/ipa/ui [L,NC,R=301]

# Redirect to the fully-qualified hostname. Not redirecting to secure
# port so configuration files can be retrieved without requiring SSL.
RewriteCond %{HTTP_HOST}    !^ipa.foo-bar-baz.software$ [NC]
RewriteRule ^/ipa/(.*)      http://ipa.foo-bar-baz.software/ipa/$1 [L,R=301]

# Redirect to the secure port if not displaying an error or retrieving
# configuration.
RewriteCond %{SERVER_PORT}  !^443$
RewriteCond %{REQUEST_URI}  !^/ipa/(errors|config|crl)
RewriteCond %{REQUEST_URI}  !^/ipa/[^\?]+(\.js|\.css|\.png|\.gif|\.ico|\.woff|\.svg|\.ttf|\.eot)$
RewriteRule ^/ipa/(.*)      https://ipa.foo-bar-baz.software/ipa/$1 [L,R=301,NC]

# Rewrite for plugin index, make it like it's a static file
RewriteRule ^/ipa/ui/js/freeipa/plugins.js$    /ipa/wsgi/plugins.py [PT]

It's sufficient to remove all occurrences of http[s]://ipa.foo-bar-baz.software and the conditions related to port and domain in the configuration above to make the system work as needed.


Couple comments here:

  • ipa-server-install already provides --no-ui-redirect option, documented in the man page and available in the --help.
  • We do not recommend installing additional software on the same machine (instance) as FreeIPA master is installed. You are making your own choice of increasing a potential attack surface to one of corner stones of your infrastructure.

Thanks @abbra for your hints!

ad 1.) The --no-ui-redirect only seems to comment out the first RewriteRule in /etc/httpd/conf.d/ipa-rewrite.conf. It still leaves the domain hard-coded in the configuration file, though. That doesn't solve the problem.
The redirect as such makes a lot of sense. It only needs to be without the domain hard-coded! Regardless of whether users want redirection or not, hard-coding the domain in this configuration file makes things only unnecessarily complicated and is a source of error or confusion.
Is there any serious technical reason why this needs to stay in the setup?

ad 2.) Note that the setup we're working on is for a bootstrapping system; a throw-away system that installs and configures automatically to allow for setting up your definite infrastructure management setup in minutes.
I would really love to keep things separately, ideally based on Docker. It's just a bit hard to do this with the current state of The Foreman and FreeIPA, which seems to be with dedicated systems (virtual or hardware) in mind. For ease of use we're trying to bootstrap everything in a single VM, so the target audience has to worry little.

The other redirects are required so that the name being requested matches the name of the deployment. Otherwise you can get Kerberos and/or HTTPS name mismatches and a poor user experience.

@rcritten The hostname should only be hard-coded in the VirtualHost declaration of the FreeIPA host with the ServerName or ServerAlias directive. There should be no domain hard-coded anywhere else, if it can be avoided.

The redirects work w/o the hard-coded domains. With a little refactoring the configuration could be both beautiful to read and easy to maintain, while retaining the user experience you're referring to.

You are making some rather vague references to the changes needed (for example I assume your use of domain is the FQDN?) Patches are welcome.

My only guess as to what you are suggesting is to use %{SERVER_NAME}.

No, it's not vague. The changes needed are:

  1. Remove all occurrences of the hard-coded FQDN values in the redirect configuration
  2. Set the FQDN in the VirtualHost in question instead (if wanted and needed)

Using %{SERVER_NAME} in the redirect would only reliably work as expected when the ServerName is set correctly in the VirtualHost (though it seems a little more complicated than that for Apache internally). In any case, using the hard-coded value in the specific redirects is unneeded. I would even say, bad style.

I can make the needed PR when we agree which route to take. (That's what this issue is for.)

I still have no idea what you are actually proposing.

If you remove the hostname then what do you propose redirecting TO?

Code would demonstrate what it is you are trying to accomplish. How does removing the FQDN from the redirect rules still actually do redirects for non-fully-qualified names, IP addresses, CNAMEs, whatever?

I still have no idea what you are actually proposing.

A clean separation of concerns.

Code would demonstrate what it is you are trying to accomplish.

I've linked to all code samples above. An example taken from the Apache docs:

Listen 443
<VirtualHost *:443>
    ServerName www.example.com

    # include redirects here
</VirtualHost>

If you remove the hostname then what do you propose redirecting TO?

The redirects to this VirtualHost should be in the default VirtualHost (for both the port HTTP and the SSL host). Other requests, that can be redirected locally (from with inside the same VHost), should be in the redirect configuration, but without any hard-coded value.

Why?

This makes it easier to activate / deactivate the use of a FQDN, or in other words, to use the redirection configuration without having to use a FQDN.

I feel like I'm pulling information out of you little by little. So you want to move the rewrite rules into the VH. It might be possible using augeas. I'm still a bit murky on what the rewrite rules would look like.

This won't work with the non-SSL to SSL redirect unless you tweak the main config as well.

I feel like I'm pulling information out of you little by little

I'm sorry to say, but I would feel a lot less irritated if you would stop with the polemics.

It might be possible using augeas.

I'm looking at the file system of the resulting host after running ipa-server-install. I've made the changes I describe (using Ansible), and the setup works for our local use case (a Vagrant box accessed from the host system via 127.0.0.1:8444).

So, we can fix this ourselves, but I'd rather make the generic solution that the FreeIPA installer generates more suitable for everyone. Can you point to the code that generates the redirect configuration (ipa-rewrite.conf), so I can try to make this more concrete?

In your initial bug report, you wrote

Unfortunately, this makes it impossible to make FreeIPA run locally, e.g. in a Vagrant box, without additional changes to the infrastructure setup.

I have been running FreeIPA in vagrant boxes for years. It works fine without any issues if you set up DNS and host resolution correctly. FreeIPA uses X.509 certificates and Kerberos/GSSAPI. Both depend on correct host names. The port forwarding approach is not compatible with either TLS/SSL or GSSAPI because both rely on correct host names. You can either install FreeIPA with a DNS server and redirect DNS queries with dnsmasq Or you can use vagrant-hostmanager to update /etc/hosts.

We put the redirects to correct ports and hostnames in place to prevent shenanigans with GSSAPI. I don't like the idea to remove them for this broken use case.

It might be clearer if you could provide a patch or at least a diff of the config files so we can see exactly what you are requesting.

The ipa-rewrite.conf template is in /usr/share/ipa/ipa-rewrite.conf

It is generated by a template engine in ipaserver/install/httpinstance.py::__configure_http

Metadata Update from @fbarreto:
- Issue priority set to: low
- Issue set to the milestone: Future Releases

a year ago

Did this ever go any further?

I'm particularly interested in talking to @bittner to understand his configuration?

I've attempted the same steps to configure my server by manually changing the rewrite.conf file however whenever I authenticate against the page I'm presented with the following warning:

IPA Error 911: RefererError
Missing HTTP referer. You have to configure your browser to send HTTP referer header.

This is when I use the IP address of the server in the URL bar of the browser, if I use the hostname correctly then it works no problem.

Am I missing something, or, since this issue was originally posted have there been some changes to IPA that mean this method no longer works?

I've found various posts that show how to make it work behind a reverse proxy e.g. https://www.adelton.com/freeipa/freeipa-behind-proxy-with-different-name

But I want something simpler, just to access it via it's IP (because, for various reasons that I won't go into I can't work around the problem with /etc/hosts or static DNS entries).

Our file looks like this:

# VERSION 6 - DO NOT REMOVE THIS LINE

RewriteEngine on

# By default forward all requests to /ipa. If you don't want IPA
# to be the default on your web server comment this line out.
RewriteRule ^/$ /ipa/ui [L,NC,R=301]

# Redirect to the fully-qualified hostname. Not redirecting to secure
# port so configuration files can be retrieved without requiring SSL.
#RewriteCond %{HTTP_HOST}    !^$
#RewriteRule ^/ipa/(.*)      /ipa/$1 [L,R=301]

# Redirect to the secure port if not displaying an error or retrieving
# configuration.
RewriteCond %{SERVER_PORT}  !^443$
RewriteCond %{REQUEST_URI}  !^/ipa/(errors|config|crl)
RewriteCond %{REQUEST_URI}  !^/ipa/[^\?]+(\.js|\.css|\.png|\.gif|\.ico|\.woff|\.svg|\.ttf|\.eot)$
RewriteRule ^/ipa/(.*)      https://%{HTTP_HOST}/ipa/$1 [L,R=301,NC]

# Rewrite for plugin index, make it like it's a static file
RewriteRule ^/ipa/ui/js/freeipa/plugins.js$    /ipa/wsgi/plugins.py [PT]

Note that we fully comment out the port 80 e.g. HTTP redirect as I believe it's made irrelevant by the 443 entry. Plus, it makes an infinite redirect loop.

Any help would be greatly appreciated.

The referer error is due to a bit of hardcoding in ipaserver/rpcserver.py:

if not environ['HTTP_REFERER'].startswith('https://%s/ipa' % self.api.env.host) and not self.env.in_tree:
    return self.marshal(result, RefererError(referer=environ['HTTP_REFERER']), _id)

You have not disabled the port redirect, that is the condition:

RewriteCond %{SERVER_PORT}  !^443$

Unless you've installed your own web server cert IPA isn't going to have a SAN IPaddr (and there is no way to issue one from IPA today). I can only assume you have it if you've gotten this far.

We "fixed"^H^H^H^H^H^H^Hworked around that issue at last PyCon 9 in Florence.

See github.com/painless-software/groundcontrol (commit 729f689).

Login to comment on this ticket.

Metadata