eveseat/installer

View on GitHub
src/Utils/Apache.php

Summary

Maintainability
A
2 hrs
Test Coverage
<?php

/*
 * This file is part of SeAT
 *
 * Copyright (C) 2015 to 2021 Leon Jacobs
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

namespace Seat\Installer\Utils;

use Seat\Installer\Traits\DetectsOperatingSystem;
use Seat\Installer\Traits\DownloadsResources;
use Seat\Installer\Utils\Abstracts\AbstractUtil;
use Seat\Installer\Utils\Interfaces\WebServer;
use Symfony\Component\Filesystem\Filesystem;

/**
 * Class Apache.
 * @package Seat\Installer\Utils
 */
class Apache extends AbstractUtil implements WebServer
{
    use DetectsOperatingSystem, DownloadsResources;

    /**
     * @var array
     */
    protected $vhost_locations = [
        'ubuntu' => '/etc/apache2/sites-enabled/',
        'centos' => '/etc/httpd/conf.d/',
        'debian' => '/etc/apache2/sites-enabled/',
    ];

    /**
     * @var array
     */
    protected $webserver_users = [
        'ubuntu' => [
            '16.04' => 'www-data',
            '18.04' => 'www-data',
            '20.04' => 'www-data',
        ],
        'centos' => [
            '6' => 'apache',
            '7' => 'apache',
        ],
        'debian' => [
            '8' => 'www-data',
            '9' => 'www-data',
        ],
    ];

    /**
     * Install the binaries for Apache.
     */
    public function install()
    {

        $installer = new PackageInstaller($this->io);
        $installer->installPackageGroup('apache');
    }

    /**
     * Configure a SeAT virtual host.
     *
     * @param string $path
     *
     * @return mixed|void
     */
    public function configure(string $path)
    {

        $this->io->text('Writing the Apache Virtual Host configuration');

        // Get the OS that will be used to determine where the config will be
        // written to.
        $os = $this->getOperatingSystem()['os'];
        $version = $this->getOperatingSystem()['version'];

        // Download the config and replace the seatpath
        if ($os == 'ubuntu')
            $vhost = $this->downloadResourceFile('apache-vhost-ubuntu.conf');
        elseif ($os == 'debian')
            $vhost = $this->downloadResourceFile('apache-vhost-debian.conf');
        elseif ($os == 'centos')
            $vhost = $this->downloadResourceFile('apache-vhost-centos.conf');

        $vhost = str_replace(':seatpath', '/var/www/html/seat.local', $vhost);

        // Write the vhost config
        file_put_contents($this->vhost_locations[$os] . '100-seat.local.conf', $vhost);

        // Symlink SeAT public directory to the DocumentRoot/public
        $this->io->text('Symlinking SeATs public directory and the Vhost config');

        // Trim the trailing / if there is one.
        $path = rtrim($path, '/');

        // Do the symlink
        $fs = new Filesystem();
        $fs->symlink($path . '/public', '/var/www/html/seat.local');

        // Enable mod_rewrite if this is a debian based apache
        if ($os == 'ubuntu' || $os == 'debian') {

            $this->io->text('Enabling mod_rewrite');
            $this->runCommand('a2enmod rewrite');
        }

        // Configure SELinux if this is CentOS
        if ($os == 'centos') {

            $this->io->text('Configuring SELinux');
            $this->runCommand('chcon -R --reference=/var/www ' . $path);
            $this->runCommand('setsebool -P httpd_can_network_connect 1');
            $this->runCommand('setsebool -P httpd_unified 1');
        }

        $this->io->text('Configuring permissions');
        $user = $this->webserver_users[$os][$version];
        $this->runCommand('chown -R ' . $user . ':' . $user . ' ' . $path);
        $this->runCommand('chmod -R guo+w ' . $path . '/storage/');

        // Restart Apache
        $this->io->text('Restarting Apache');
        $this->runCommand('apachectl restart');

    }

    /**
     * Harden the Apache Installation.
     */
    public function harden()
    {

        $this->io->text('Hardening Apache');

        $os = $this->getOperatingSystem()['os'];

        if ($os == 'ubuntu' || $os == 'debian')
            $this->hardenDebBased();
        elseif ($os == 'centos')
            $this->hardenCentos();

    }

    /**
     * Harden the Debian Based Apache webserver.
     */
    protected function hardenDebBased()
    {

        // Remove Default Website
        $this->io->text('Removing default website');
        $fs = new Filesystem();
        $fs->remove('/etc/apache2/sites-enabled/000-default.conf');

        // Disable Directory Indexing
        $this->io->text('Disabling directory indexing');
        $apache_conf = file_get_contents('/etc/apache2/apache2.conf');
        $apache_conf = str_replace('Options Indexes FollowSymLinks', 'Options FollowSymLinks', $apache_conf);
        file_put_contents('/etc/apache2/apache2.conf', $apache_conf);

        // Remove ServerSignature and ServerTokens
        $this->io->text('Removing server signature and tokens');
        $security_conf = file_get_contents('/etc/apache2/conf-enabled/security.conf');
        $security_conf = str_replace('ServerTokens OS', 'ServerTokens Prod', $security_conf);
        $security_conf = str_replace('ServerSignature On', 'ServerSignature Off', $security_conf);
        file_put_contents('/etc/apache2/conf-enabled/security.conf', $security_conf);

    }

    /**
     * Harden the CentOS Apache Webserver.
     */
    protected function hardenCentos()
    {

        // Remove Default Website
        $this->io->text('Removing default website');
        $fs = new Filesystem();
        $fs->remove('/etc/httpd/conf.d/welcome.conf');

        // Disable Directory Indexing
        $this->io->text('Disabling directory indexing');
        $apache_conf = file_get_contents('/etc/httpd/conf/httpd.conf');
        $apache_conf = str_replace('Options Indexes FollowSymLinks', 'Options FollowSymLinks', $apache_conf);
        file_put_contents('/etc/httpd/conf/httpd.conf', $apache_conf);

        // Remove ServerSignature and ServerTokens
        $this->io->text('Removing server signature and tokens');
        $security_conf = file_get_contents('/etc/httpd/conf/httpd.conf');
        $security_conf .= PHP_EOL . 'ServerTokens Prod';
        $security_conf .= PHP_EOL . 'ServerSignature Off';
        file_put_contents('/etc/httpd/conf/httpd.conf', $security_conf);

    }

    /**
     * Get the user as which the webserver will run.
     *
     * @return mixed
     */
    public function getuser()
    {

        $os = $this->getOperatingSystem()['os'];
        $ver = $this->getOperatingSystem()['version'];

        if (
            ! array_key_exists($os, $this->webserver_users) ||
            ! array_key_exists($ver, $this->webserver_users[$os])
        )
            return false;

        return $this->webserver_users[$os][$ver];
    }
}