# Apache 2.4 access control

A customer has an AWS EC2 server running two websites on Apache 2.4: a static public HTML for corporate website and a Ruby on Rails app meant for internal use. These two are configured using Apache `VirtualHost` with the RoR running using [Passenger](https://www.phusionpassenger.com/library/deploy/apache/deploy/ruby/).

There are two issues that the customer would like us to fix:
- The static public HTML site has directory listing enabled although they had not enabled it in the `VirtualHost` directive.
- The RoR app is accessible from public and they would like to restrict it to certain IP ranges.

This was the original configuration in the `conf.d/vhost.conf` file:
```
<IfModule mod_ssl.c>
<VirtualHost *:443>
    ServerName app.example.com
    DocumentRoot /var/www/railsapp/public
    PassengerRuby /usr/bin/ruby

    <Directory /var/www/railsapp/public>
        Allow from all
        Options -MultiViews
        Require all granted
        RailsEnv production
    </Directory>
    ...
</VirtualHost>

<VirtualHost *:443>
    ServerName www.example.com    
    DocumentRoot /var/www/static

    <Directory "/var/www/static">
        AllowOverride All
        Require all granted
    </Directory>
    ...
</VirtualHost>
</IfModule>
```

## Why directory listing was enabled
According to [documentation](https://httpd.apache.org/docs/2.4/mod/core.html#options) the default for `Options` is `FollowSymlinks` if the directive is not set, and the directory listing should not be enabled.

On checking, I found that the customer has edited `conf/httpd.conf` as below:
```
#
# DocumentRoot: The directory out of which you will serve your
# documents. By default, all requests are taken from this directory, but
# symbolic links and aliases may be used to point to other locations.
#
DocumentRoot "/var/www/static"

#
# Relax access to content within /var/www/static.
#
<Directory "/var/www/static">
    AllowOverride None
    # Allow open access:
    Require all granted
</Directory>

# Further relax access to the default document root:
<Directory "/var/www/static">
    #
    # Possible values for the Options directive are "None", "All",
    # or any combination of:
    #   Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews
    #
    # Note that "MultiViews" must be named *explicitly* --- "Options All"
    # doesn't give it to you.
    #
    # The Options directive is both complicated and important.  Please see
    # http://httpd.apache.org/docs/2.4/mod/core.html#options
    # for more information.
    #
    Options Indexes FollowSymLinks

    #
    # AllowOverride controls what directives may be placed in .htaccess files.
    # It can be "All", "None", or any combination of the keywords:
    #   Options FileInfo AuthConfig Limit
    #
    AllowOverride None

    #
    # Controls who can get stuff from this server.
    #
    Require all granted
</Directory>
``` 

Thus the problem is that `Options` was actually specified in `conf/httpd.conf`. This comes from the default configuration when installing Apache. The customer had merely edited the `Directory` path. This could be an easy fix by just commenting the `Options` line but I find the entire chunk above necessary. This is because both `VirtualHost` directives are already using wildcard (*) IP matching which means it will definitely match one of them. As per the [documentation](https://httpd.apache.org/docs/2.4/vhosts/name-based.html), the match will be the first listed virtual host if there are no matching `ServerName` or `ServerAlias`. Hence I removed the entire chunk in `conf/httpd.conf` and moved the `VirtualHost` section of static website above the RoR instead.

## Apache 2.2 versus 2.4 access control
I also reviewed the directives in the VirtualHost configurations and found that there are some unnecessary directives:
- The first is that `Allow from all` is from Apache 2.2 and deprecated in Apache 2.4. The replacement is `Require all granted`.
- Next is the line `Options -MultiViews`. It is unnecessary because the `Options` directive default is set to `FollowSymLinks` from 2.3.11 onwards. Furthermore `MultiViews` must be explicitly enabled. There is no need to disable it if it wasn't enabled anywhere.
- Lastly I removed `AllowOverride All` since there is no `.htaccess` file in the static website.

## Restricting Ruby on Rails access by IP
To limit access to RoR by IP addresses, I used the `AllowOverrideList` as it is more specific. The directive `AllowOverride` is set to `None` by default in version 2.3.9 onwards and therefore not necessary to include in the configuration. 

The edited `conf.d/vhost.conf` is as below:

```
<IfModule mod_ssl.c>
<VirtualHost *:443>
    ServerName www.example.com    
    DocumentRoot /var/www/static

    <Directory "/var/www/static">
        Require all granted
    </Directory>
    ...
</VirtualHost>

<VirtualHost *:443>
    ServerName app.example.com
    DocumentRoot /var/www/railsapp/public
    PassengerRuby /usr/bin/ruby

    <Directory /var/www/railsapp/public>
        AllowOverrideList Require
        Require all granted
        RailsEnv production
    </Directory>
    ...
</VirtualHost>
</IfModule>
```

And all that is needed now is `.htaccess` to be placed in the `public` folder of the RoR app:
```
Require ip x.y.z.0/24
```
