Compare commits
4 Commits
libertacas
...
develop-v1
Author | SHA1 | Date | |
---|---|---|---|
|
86e334a710 | ||
|
84e5328906 | ||
|
ba2368907d | ||
|
9662e8b4ab |
105
Hardening.md
Normal file
105
Hardening.md
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
# Hardening list
|
||||||
|
|
||||||
|
This formula enforce security recommandations from [CIS Benchmarks](https://www.cisecurity.org/cis-benchmarks/) website
|
||||||
|
|
||||||
|
From ***CIS_Apache_HTTP_Server_2.4_Benchmark_v1.4.pdf*** document
|
||||||
|
|
||||||
|
> A scoring status indicates whether compliance with the given recommendation impacts the assessed target's benchmark score.
|
||||||
|
|
||||||
|
> Items in [*level 2*] profile exhibit one or more of the following characteristics:
|
||||||
|
> - are intended for environments or use cases where security is paramount
|
||||||
|
> - acts as defense in depth measure
|
||||||
|
> - may negatively inhibit the utility or performance of the technology
|
||||||
|
|
||||||
|
In this formula we focus on (**Scored**) [*level* ***1***] items
|
||||||
|
|
||||||
|
## List of all items with their CIS references
|
||||||
|
|
||||||
|
## 2. Minimize Apache Modules
|
||||||
|
- [ ] 2.1 Enable Only Necessary Authentication and Authorization Modules (Not Scored)
|
||||||
|
- [X] 2.2 Enable the Log Config Module (**Scored**)
|
||||||
|
- [X] 2.3 Disable WebDAV Modules (**Scored**)
|
||||||
|
- [X] 2.4 Disable Status Module (**Scored**)
|
||||||
|
- [X] 2.5 Disable Autoindex Module (**Scored**)
|
||||||
|
- [ ] 2.6 Disable Proxy Modules (**Scored**)
|
||||||
|
- [X] 2.7 Disable User Directories Modules (**Scored**)
|
||||||
|
- [X] 2.8 Disable Info Module (**Scored**)
|
||||||
|
## 3. Principles, Permissions, and Ownership
|
||||||
|
- [X] 3.1 Run the Apache Web Server as a non-root user (**Scored**)
|
||||||
|
- [X] 3.2 Give the Apache User Account an Invalid Shell (**Scored**)
|
||||||
|
- [ ] 3.3 Lock the Apache User Account (**Scored**)
|
||||||
|
- [X] 3.4 Set Ownership on Apache Directories and Files (**Scored**)
|
||||||
|
- [X] 3.5 Set Group Id on Apache Directories and Files (**Scored**)
|
||||||
|
- [ ] 3.6 Restrict Other Write Access on Apache Directories and Files (**Scored**)
|
||||||
|
- [X] 3.7 Secure Core Dump Directory (**Scored**)
|
||||||
|
- [ ] 3.8 Secure the Lock File (**Scored**)
|
||||||
|
- [X] 3.9 Secure the Pid File (**Scored**)
|
||||||
|
- [X] 3.10 Secure the ScoreBoard File (**Scored**)
|
||||||
|
- [X] 3.11 Restrict Group Write Access for the Apache Directories and Files (**Scored**)
|
||||||
|
- [X] 3.12 Restrict Group Write Access for the Document Root Directories and Files (**Scored**)
|
||||||
|
## 4. Apache Access Control
|
||||||
|
- [X] 4.1 Deny Access to OS Root Directory (**Scored**)
|
||||||
|
- [ ] 4.2 Allow Appropriate Access to Web Content (Not Scored)
|
||||||
|
- [X] 4.3 Restrict Override for the OS Root Directory (**Scored**)
|
||||||
|
- [X] 4.4 Restrict Override for All Directories (**Scored**)
|
||||||
|
## 5. Minimize Features, Content and Options
|
||||||
|
- [X] 5.1 Restrict Options for the OS Root Directory (**Scored**)
|
||||||
|
- [X] 5.2 Restrict Options for the Web Root Directory (**Scored**)
|
||||||
|
- [X] 5.3 Minimize Options for Other Directories (**Scored**)
|
||||||
|
- [X] 5.4 Remove Default HTML Content (**Scored**)
|
||||||
|
- [X] 5.5 Remove Default CGI Content printenv (**Scored**)
|
||||||
|
- [X] 5.6 Remove Default CGI Content test-cgi (**Scored**)
|
||||||
|
- [X] 5.7 Limit HTTP Request Methods (**Scored**)
|
||||||
|
- [X] 5.8 Disable HTTP TRACE Method (**Scored**)
|
||||||
|
- [X] 5.9 Restrict HTTP Protocol Versions (**Scored**)
|
||||||
|
- [X] 5.10 Restrict Access to .ht* files (**Scored**)
|
||||||
|
- [ ] 5.11 Restrict File Extensions [*level 2*] (**Scored**)
|
||||||
|
- [ ] 5.12 Deny IP Address Based Requests [*level 2*] (**Scored**)
|
||||||
|
- [ ] 5.13 Restrict Listen Directive [*level 2*] (**Scored**)
|
||||||
|
- [ ] 5.14 Restrict Browser Frame Options [*level 2*] (**Scored**)
|
||||||
|
## 6. Operations - Logging, Monitoring and Maintenance
|
||||||
|
- [X] 6.1 Configure the Error Log (**Scored**)
|
||||||
|
- [ ] 6.2 Configure a Syslog Facility for Error Logging [*level 2*] (**Scored**)
|
||||||
|
- [X] 6.3 Configure the Access Log (**Scored**)
|
||||||
|
- [X] 6.4 Log Storage and Rotation (**Scored**)
|
||||||
|
- [ ] 6.5 Apply Applicable Patches (**Scored**)
|
||||||
|
- [ ] 6.6 Install and Enable ModSecurity [*level 2*] (**Scored**)
|
||||||
|
- [ ] 6.7 Install and Enable OWASP ModSecurity Core Rule Set [*level 2*] (**Scored**)
|
||||||
|
## 7. SSL/TLS Configuration
|
||||||
|
- [X] 7.1 Install mod_ssl and/or mod_nss (**Scored**)
|
||||||
|
- [ ] 7.2 Install a Valid Trusted Certificate (**Scored**)
|
||||||
|
- [ ] 7.3 Protect the Server's Private Key (**Scored**)
|
||||||
|
- [X] 7.4 Disable the SSL v3.0 Protocol (**Scored**)
|
||||||
|
- [ ] 7.5 Restrict Weak SSL/TLS Ciphers (**Scored**)
|
||||||
|
- [X] 7.6 Disable SSL Insecure Renegotiation (**Scored**)
|
||||||
|
- [X] 7.7 Ensure SSL Compression is not Enabled (**Scored**)
|
||||||
|
- [ ] 7.8 Restrict Medium Strength SSL/TLS Ciphers (**Scored**)
|
||||||
|
- [ ] 7.9 Disable the TLS v1.0 Protocol [*level 2*] (**Scored**)
|
||||||
|
- [ ] 7.10 Enable OCSP Stapling [*level 2*] (**Scored**)
|
||||||
|
- [ ] 7.11 Enable HTTP Strict Transport Security [*level 2*] (**Scored**)
|
||||||
|
## 8. Information Leakage
|
||||||
|
- [X] 8.1 Set ServerToken to 'Prod' (**Scored**)
|
||||||
|
- [X] 8.2 Set ServerSignature to 'Off' (**Scored**)
|
||||||
|
- [ ] 8.3 Information Leakage via Default Apache Content [*level 2*] (**Scored**)
|
||||||
|
- [ ] 8.4 Information Leakage via ETag [*level 2*] (**Scored**)
|
||||||
|
## 9. Denial of Service Mitigations
|
||||||
|
- [X] 9.1 Set TimeOut to 10 or less (**Scored**)
|
||||||
|
- [X] 9.2 Set the KeepAlive directive to On (**Scored**)
|
||||||
|
- [X] 9.3 Set MaxKeepAliveRequests to 100 or greater (**Scored**)
|
||||||
|
- [X] 9.4 Set KeepAliveTimeout Low to Mitigate Denial of Service (**Scored**)
|
||||||
|
- [X] 9.5 Set Timeout Limits for Request Headers (**Scored**)
|
||||||
|
- [X] 9.6 Set Timeout Limits for the Request Body (**Scored**)
|
||||||
|
## 10. Request Limits
|
||||||
|
- [ ] 10.1 Set the LimitRequestLine directive to 512 or less [*level 2*] (**Scored**)
|
||||||
|
- [ ] 10.2 Set the LimitRequestFields directive to 100 or less [*level 2*] (**Scored**)
|
||||||
|
- [ ] 10.3 Set the LimitRequestFieldsize directive to 1024 or less [*level 2*] (**Scored**)
|
||||||
|
- [ ] 10.4 Set the LimitRequestBody directive to 102400 or less [*level 2*] (**Scored**)
|
||||||
|
## 11. Enable SELinux to Restrict Apache Processes
|
||||||
|
- [ ] 11.1 Enable SELinux in Enforcing Mode [*level 2*] (**Scored**)
|
||||||
|
- [ ] 11.2 Run Apache Processes in the httpd_t Confined Context [*level 2*] (**Scored**)
|
||||||
|
- [ ] 11.3 Ensure the httpd_t Type is Not in Permissive Mode [*level 2*] (**Scored**)
|
||||||
|
- [ ] 11.4 Ensure Only the Necessary SELinux Booleans are Enabled [*level 2*] (Not Scored)
|
||||||
|
## 12. Enable AppArmor to Restrict Apache Processes
|
||||||
|
- [ ] 12.1 Enable the AppArmor Framework [*level 2*] (**Scored**)
|
||||||
|
- [ ] 12.2 Customize the Apache AppArmor Profile [*level 2*] (Not Scored)
|
||||||
|
- [ ] 12.3 Ensure Apache AppArmor Profile is in Enforce Mode [*level 2*] (**Scored**)
|
279
README.rst
279
README.rst
@ -4,6 +4,17 @@ apache
|
|||||||
|
|
||||||
Formulas to set up and configure the Apache HTTP server.
|
Formulas to set up and configure the Apache HTTP server.
|
||||||
|
|
||||||
|
This Formula uses the concepts of ``directive`` and ``container`` in pillars
|
||||||
|
|
||||||
|
* ``directive`` is an httpd directive https://httpd.apache.org/docs/2.4/en/mod/directives.html
|
||||||
|
* ``container`` is what described the `configuration sections` https://httpd.apache.org/docs/2.4/en/sections.html
|
||||||
|
|
||||||
|
see examples below for more explanation
|
||||||
|
|
||||||
|
Also it includes and enforce some hardening rules to prevent security issues
|
||||||
|
|
||||||
|
See `<Hardening.md>`_ and `<apache/hardening-values.yaml>`_.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
See the full `Salt Formulas installation and usage instructions
|
See the full `Salt Formulas installation and usage instructions
|
||||||
@ -23,218 +34,116 @@ Installs the Apache package and starts the service.
|
|||||||
``apache.config``
|
``apache.config``
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
Configures apache based on os_family
|
Configures apache server.
|
||||||
|
|
||||||
``apache.certificates``
|
The configuration is done by merging the pillar content with defaults
|
||||||
-----------------
|
present in the state `<apache/defaults/RedHat/defaults-apache-2.4.yaml>`_
|
||||||
|
|
||||||
Deploy SSL certificates from pillars
|
.. code:: yaml
|
||||||
|
|
||||||
``apache.mod_mpm``
|
apache:
|
||||||
------------------
|
server_apache_config:
|
||||||
|
directives:
|
||||||
|
- Timeout: 5
|
||||||
|
containers:
|
||||||
|
IfModule:
|
||||||
|
-
|
||||||
|
item: 'mime_module'
|
||||||
|
directives:
|
||||||
|
- AddType: 'application/x-font-ttf ttc ttf'
|
||||||
|
- AddType: 'application/x-font-opentype otf'
|
||||||
|
- AddType: 'application/x-font-woff woff2'
|
||||||
|
|
||||||
Configures the apache mpm modules on Debian ``mpm_prefork``, ``mpm_worker`` or ``mpm_event`` (Debian Only)
|
|
||||||
|
|
||||||
``apache.modules``
|
``apache.modules``
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
Enables and disables Apache modules.
|
Enables and disables Apache modules.
|
||||||
|
|
||||||
``apache.mod_rewrite``
|
``apache.vhosts.vhost``
|
||||||
----------------------
|
|
||||||
|
|
||||||
Enabled the Apache module mod_rewrite (Debian and FreeBSD only)
|
|
||||||
|
|
||||||
``apache.mod_proxy``
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
Enables the Apache module mod_proxy. (Debian and FreeBSD only)
|
|
||||||
|
|
||||||
``apache.mod_proxy_http``
|
|
||||||
-------------------------
|
|
||||||
|
|
||||||
Enables the Apache module mod_proxy_http and requires the Apache module mod_proxy to be enabled. (Debian Only)
|
|
||||||
|
|
||||||
``apache.mod_proxy_fcgi``
|
|
||||||
-------------------------
|
|
||||||
|
|
||||||
Enables the Apache module mod_proxy_fcgi and requires the Apache module mod_proxy to be enabled. (Debian Only)
|
|
||||||
|
|
||||||
``apache.mod_wsgi``
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
Installs the mod_wsgi package and enables the Apache module.
|
|
||||||
|
|
||||||
``apache.mod_actions``
|
|
||||||
----------------------
|
|
||||||
|
|
||||||
Enables the Apache module mod_actions. (Debian Only)
|
|
||||||
|
|
||||||
``apache.mod_headers``
|
|
||||||
----------------------
|
|
||||||
|
|
||||||
Enables the Apache module mod_headers. (Debian Only)
|
|
||||||
|
|
||||||
``apache.mod_pagespeed``
|
|
||||||
------------------------
|
|
||||||
|
|
||||||
Installs and Enables the mod_pagespeed module. (Debian and RedHat Only)
|
|
||||||
|
|
||||||
``apache.mod_perl2``
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
Installs and enables the mod_perl2 module (Debian and FreeBSD only)
|
|
||||||
|
|
||||||
``apache.mod_geoip``
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
Installs and enables the mod_geoIP (RedHat only)
|
|
||||||
|
|
||||||
``apache.mod_php5``
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
Installs and enables the mod_php5 module
|
|
||||||
|
|
||||||
``apache.mod_cgi``
|
|
||||||
---------------------
|
|
||||||
|
|
||||||
Enables mod_cgi. (FreeBSD only)
|
|
||||||
|
|
||||||
``apache.mod_fcgid``
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
Installs and enables the mod_fcgid module (Debian only)
|
|
||||||
|
|
||||||
``apache.mod_fastcgi``
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
Installs and enables the mod_fastcgi module
|
|
||||||
|
|
||||||
``apache.mod_dav_svn``
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
Installs and enables the mod_dav_svn module (Debian only)
|
|
||||||
|
|
||||||
``apache.mod_security``
|
|
||||||
----------------------
|
|
||||||
|
|
||||||
Installs an enables the `Apache mod_security2 WAF`<http://modsecurity.org/>`_
|
|
||||||
using data from Pillar. (Debian and RedHat Only)
|
|
||||||
|
|
||||||
Allows you to install the basic Core Rules (CRS) and some basic configuration for mod_security2
|
|
||||||
|
|
||||||
``apache.mod_security.rules``
|
|
||||||
-----------------------------
|
|
||||||
|
|
||||||
This state can create symlinks based on basic Core Rules package. (Debian only)
|
|
||||||
Or it can distribute a mod_security rule file and place it /etc/modsecurity/
|
|
||||||
|
|
||||||
``apache.mod_socache_shmcb``
|
|
||||||
---------------------
|
|
||||||
|
|
||||||
Enables mod_socache_shmcb. (FreeBSD only)
|
|
||||||
|
|
||||||
``apache.mod_ssl``
|
|
||||||
----------------------
|
|
||||||
|
|
||||||
Installs and enables the mod_ssl module (Debian, RedHat and FreeBSD only)
|
|
||||||
|
|
||||||
``apache.mod_suexec``
|
|
||||||
---------------------
|
|
||||||
|
|
||||||
Enables mod_suexec. (FreeBSD only)
|
|
||||||
|
|
||||||
``apache.mod_vhost_alias``
|
|
||||||
----------------------
|
|
||||||
|
|
||||||
Enables the Apache module vhost_alias (Debian Only)
|
|
||||||
|
|
||||||
``apache.mod_remoteip``
|
|
||||||
----------------------
|
|
||||||
|
|
||||||
Enables and configures the Apache module mod_remoteip using data from Pillar. (Debian Only)
|
|
||||||
|
|
||||||
``apache.mod_xsendfile``
|
|
||||||
----------------------
|
|
||||||
|
|
||||||
Installs and enables mod_xsendfile module. (Debian Only)
|
|
||||||
|
|
||||||
``apache.own_default_vhost``
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
Replace default vhost with own version. By default, it's 503 code. (Debian Only)
|
|
||||||
|
|
||||||
``apache.no_default_vhost``
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
Remove the default vhost. (Debian Only)
|
|
||||||
|
|
||||||
``apache.vhosts.standard``
|
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
Configures Apache name-based virtual hosts and creates virtual host directories using data from Pillar.
|
Configures Apache name-based virtual hosts and creates virtual host directories using data from Pillar.
|
||||||
|
|
||||||
|
All necessary data must be provided in the pillar
|
||||||
|
|
||||||
|
Exceptions are :
|
||||||
|
|
||||||
|
* ``CustomLog`` default is ``/path/apache/log/ServerName-access.log combined``
|
||||||
|
|
||||||
|
* if ``Logformat`` is defined in pillar, ``CustomLog`` is enforced to ``/path/apache/log/ServerName-access.log Logformat``
|
||||||
|
|
||||||
|
* ``ErrorLog`` is enforced to ``/path/apache/log/ServerName-error.log``
|
||||||
|
|
||||||
Example Pillar:
|
Example Pillar:
|
||||||
|
|
||||||
|
Create two vhosts ``example.com.conf`` and ``test.example.com.conf``
|
||||||
|
|
||||||
.. code:: yaml
|
.. code:: yaml
|
||||||
|
|
||||||
apache:
|
apache:
|
||||||
sites:
|
VirtualHost:
|
||||||
example.com: # must be unique; used as an ID declaration in Salt; also passed to the template context as {{ id }}
|
example.com: # <-- this is an id decalaration used in salt and default ServerName
|
||||||
template_file: salt://apache/vhosts/standard.tmpl
|
item: '*:80'
|
||||||
|
directives:
|
||||||
|
- RewriteEngine: 'on'
|
||||||
|
- Header: 'set Access-Control-Allow-Methods GET,PUT,POST,DELETE,OPTIONS'
|
||||||
|
containers:
|
||||||
|
Location:
|
||||||
|
item: '/test.html'
|
||||||
|
directives:
|
||||||
|
- Require: 'all granted'
|
||||||
|
site_id_declaration:
|
||||||
|
item: '10.10.1.1:8080'
|
||||||
|
directives:
|
||||||
|
- ServerName: 'test.example.com'
|
||||||
|
- LogFormat: '"%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\" %{ms}T"'
|
||||||
|
|
||||||
|
Files produced by these pillars :
|
||||||
|
|
||||||
|
``example.com.conf``
|
||||||
|
|
||||||
|
.. code:: bash
|
||||||
|
|
||||||
|
<VirtualHost *:80>
|
||||||
|
ServerName example.com
|
||||||
|
CustomLog /var/log/httpd/example.com-access.log combined
|
||||||
|
ErrorLog /var/log/httpd/example.com-error.log
|
||||||
|
RewriteEngine on
|
||||||
|
Header set Access-Control-Allow-Methods GET,PUT,POST,DELETE,OPTIONS
|
||||||
|
<Location /test.html>
|
||||||
|
Require all granted
|
||||||
|
</Location>
|
||||||
|
</VirtualHost>
|
||||||
|
|
||||||
|
|
||||||
|
``test.example.com.conf``
|
||||||
|
|
||||||
|
.. code:: bash
|
||||||
|
|
||||||
|
<VirtualHost 10.10.1.1:8080>
|
||||||
|
ServerName test.example.com
|
||||||
|
CustomLog /var/log/httpd/test.example.com-access.log "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\" %{ms}T"
|
||||||
|
ErrorLog /var/log/httpd/test.example.com-error.log
|
||||||
|
</VirtualHost>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
this will delete ``test.example.com.conf``
|
||||||
|
|
||||||
When using the provided templates, one can use a space separated list
|
|
||||||
of interfaces to bind to. For example, to bind both IPv4 and IPv6:
|
|
||||||
|
|
||||||
.. code:: yaml
|
.. code:: yaml
|
||||||
|
|
||||||
apache:
|
apache:
|
||||||
sites:
|
VirtualHost:
|
||||||
example.com:
|
test.example.com:
|
||||||
interface: '1.2.3.4 [2001:abc:def:100::3]'
|
item: '10.10.1.1:8080'
|
||||||
|
absent: True # <-- delete test.example.com.conf
|
||||||
``apache.manage_security``
|
directives:
|
||||||
--------------------------
|
- ServerName: 'test.example.com'
|
||||||
|
|
||||||
Configures Apache's security.conf options by reassinging them using data from Pillar.
|
|
||||||
|
|
||||||
``apache.server_status``
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
Configures Apache's server_status handler for localhost
|
|
||||||
|
|
||||||
``apache.debian_full``
|
|
||||||
----------------------
|
|
||||||
|
|
||||||
Installs and configures Apache on Debian and Ubuntu systems.
|
|
||||||
|
|
||||||
``apache.uninstall``
|
``apache.uninstall``
|
||||||
----------
|
----------
|
||||||
|
|
||||||
Stops the Apache service and uninstalls the package.
|
Stops the Apache service and uninstalls the package.
|
||||||
|
|
||||||
These states are ordered using the ``order`` declaration. Different stages
|
|
||||||
are divided into the following number ranges:
|
|
||||||
|
|
||||||
1) apache will use 1-500 for ordering
|
|
||||||
2) apache will reserve 1 -100 as unused
|
|
||||||
3) apache will reserve 101-150 for pre pkg install
|
|
||||||
4) apache will reserve 151-200 for pkg install
|
|
||||||
5) apache will reserve 201-250 for pkg configure
|
|
||||||
6) apache will reserve 251-300 for downloads, git stuff, load data
|
|
||||||
7) apache will reserve 301-400 for unknown purposes
|
|
||||||
8) apache will reserve 401-450 for service restart-reloads
|
|
||||||
9) apache WILL reserve 451-460 for service.running
|
|
||||||
10) apache will reserve 461-500 for cmd requiring operational services
|
|
||||||
|
|
||||||
Example Pillar:
|
|
||||||
|
|
||||||
.. code:: yaml
|
|
||||||
|
|
||||||
apache:
|
|
||||||
register-site:
|
|
||||||
# any name as an array index, and you can duplicate this section
|
|
||||||
{{UNIQUE}}:
|
|
||||||
name: 'my name'
|
|
||||||
path: 'salt://path/to/sites-available/conf/file'
|
|
||||||
state: 'enabled'
|
|
||||||
|
430
_modules/apache_directives.py
Normal file
430
_modules/apache_directives.py
Normal file
@ -0,0 +1,430 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
'''
|
||||||
|
apache directives
|
||||||
|
:maintainer: "karim Hamza"
|
||||||
|
|
||||||
|
|
||||||
|
'''
|
||||||
|
|
||||||
|
from __future__ import absolute_import, unicode_literals
|
||||||
|
|
||||||
|
# Import python libs
|
||||||
|
import re
|
||||||
|
from copy import deepcopy
|
||||||
|
|
||||||
|
|
||||||
|
from salt.exceptions import CommandExecutionError
|
||||||
|
from salt.ext.six.moves import range
|
||||||
|
|
||||||
|
|
||||||
|
def _get_directive_values(directive, d_list):
|
||||||
|
'''
|
||||||
|
Returns list all values of directive
|
||||||
|
'''
|
||||||
|
values = [item.get(directive) for item in d_list if directive in item]
|
||||||
|
|
||||||
|
return values
|
||||||
|
|
||||||
|
|
||||||
|
def get_directive_single_value(directive, d_list, default=None):
|
||||||
|
'''
|
||||||
|
Returns single value of directive
|
||||||
|
|
||||||
|
default is returned if directive is absent from list
|
||||||
|
'''
|
||||||
|
values = _get_directive_values(directive, d_list)
|
||||||
|
try:
|
||||||
|
return values[0]
|
||||||
|
except IndexError:
|
||||||
|
if default is not None:
|
||||||
|
return default
|
||||||
|
|
||||||
|
error_msg = "invalid Pillar content - " \
|
||||||
|
+ directive + " - is not defined"
|
||||||
|
raise CommandExecutionError(error_msg)
|
||||||
|
|
||||||
|
|
||||||
|
def append_to_container_directives(directive, value, container):
|
||||||
|
'''
|
||||||
|
Append directive to directives list
|
||||||
|
'''
|
||||||
|
try:
|
||||||
|
container['directives'].append({directive: value})
|
||||||
|
except KeyError:
|
||||||
|
container['directives'] = []
|
||||||
|
container['directives'].append({directive: value})
|
||||||
|
|
||||||
|
return container
|
||||||
|
|
||||||
|
|
||||||
|
def _manage_directive_into_containers(directive,
|
||||||
|
value,
|
||||||
|
container,
|
||||||
|
container_name_target,
|
||||||
|
item,
|
||||||
|
enforce_value=False,
|
||||||
|
add_directive=True):
|
||||||
|
'''
|
||||||
|
Enforce value for directive into specific container
|
||||||
|
|
||||||
|
directive
|
||||||
|
directive label (name)
|
||||||
|
|
||||||
|
value
|
||||||
|
value to enforce
|
||||||
|
|
||||||
|
container
|
||||||
|
container to parse
|
||||||
|
|
||||||
|
container_name_target
|
||||||
|
container name target into directive/value have to be enforced
|
||||||
|
|
||||||
|
item
|
||||||
|
name of the item target
|
||||||
|
|
||||||
|
enforce_value : default=False
|
||||||
|
True: enforce value if directive exists, otherwise add it if add_directive=True
|
||||||
|
|
||||||
|
add_directive : default=True
|
||||||
|
Only if enforce_value=False add directive if it is not present
|
||||||
|
'''
|
||||||
|
for n_container, l_containers in container.get('containers', {}).items():
|
||||||
|
for idx, nested_container in enumerate(l_containers):
|
||||||
|
if (n_container == container_name_target
|
||||||
|
and nested_container['item'] == item):
|
||||||
|
if enforce_value:
|
||||||
|
container['containers'][n_container][idx] = \
|
||||||
|
enforce_directive_value(directive,
|
||||||
|
{'value': value, 'add_if_absent': add_directive},
|
||||||
|
n_container,
|
||||||
|
nested_container)
|
||||||
|
else:
|
||||||
|
container['containers'][n_container][idx] = \
|
||||||
|
append_to_container_directives(directive,
|
||||||
|
value,
|
||||||
|
nested_container)
|
||||||
|
|
||||||
|
container['containers'][n_container][idx] = \
|
||||||
|
_manage_directive_into_containers(directive,
|
||||||
|
value,
|
||||||
|
nested_container,
|
||||||
|
container_name_target,
|
||||||
|
item,
|
||||||
|
enforce_value,
|
||||||
|
add_directive)
|
||||||
|
|
||||||
|
return container
|
||||||
|
|
||||||
|
|
||||||
|
def set_vhost_logging_directives(container, servername, logdir):
|
||||||
|
'''
|
||||||
|
set value of CustomLog and LogFormat directives in vhost
|
||||||
|
'''
|
||||||
|
logformat = get_directive_single_value('LogFormat',
|
||||||
|
container.get('directives', []),
|
||||||
|
default='combined')
|
||||||
|
|
||||||
|
enforce_directive_value(
|
||||||
|
directive='CustomLog',
|
||||||
|
enforced_directive_data=
|
||||||
|
{'value': logdir + '/' + servername +'-access.log ' + logformat,
|
||||||
|
'add_if_absent': True},
|
||||||
|
container_name='VirtualHost',
|
||||||
|
container_data=container)
|
||||||
|
enforce_directive_value(
|
||||||
|
directive='ErrorLog',
|
||||||
|
enforced_directive_data=
|
||||||
|
{'value': logdir + '/' + servername +'-error.log ',
|
||||||
|
'add_if_absent': True},
|
||||||
|
container_name='VirtualHost',
|
||||||
|
container_data=container)
|
||||||
|
|
||||||
|
return container
|
||||||
|
|
||||||
|
|
||||||
|
def _container_merge_multiple_directives(container):
|
||||||
|
'''
|
||||||
|
append directives_multiple list into directives
|
||||||
|
'''
|
||||||
|
try:
|
||||||
|
container['directives'].extend(container.get('directives_multiple', []))
|
||||||
|
except KeyError:
|
||||||
|
container['directives'] = []
|
||||||
|
container['directives'] = container.get('directives_multiple', [])
|
||||||
|
|
||||||
|
container.pop('directives_multiple', None)
|
||||||
|
|
||||||
|
for sub_container_name, sub_containers_list in container.get('containers', {}).items():
|
||||||
|
for sub_idx, sub_container in enumerate(sub_containers_list):
|
||||||
|
container['containers'][sub_container_name][sub_idx] = \
|
||||||
|
_container_merge_multiple_directives(sub_container)
|
||||||
|
|
||||||
|
return container
|
||||||
|
|
||||||
|
|
||||||
|
def merge_container_with_additional_data(container_to_update,
|
||||||
|
container_to_import,
|
||||||
|
add_directive=True,
|
||||||
|
add_container=True):
|
||||||
|
'''
|
||||||
|
Merge containers usually to merge default values with pillar content
|
||||||
|
|
||||||
|
container_to_update
|
||||||
|
the default container into which put or modify values with pillar content
|
||||||
|
|
||||||
|
container_to_import
|
||||||
|
usually pillar content
|
||||||
|
|
||||||
|
add_directive : default=True
|
||||||
|
add directive if it is not present
|
||||||
|
|
||||||
|
add_container : default=True
|
||||||
|
add sub_container if it is absent in container_to_update
|
||||||
|
'''
|
||||||
|
merged_container = deepcopy(container_to_update)
|
||||||
|
multiple_directives_to_append = []
|
||||||
|
for mult_directive_item in container_to_update.get('directives_multiple', []):
|
||||||
|
for mult_directive, imp_value in mult_directive_item.items():
|
||||||
|
append_to_container_directives(mult_directive,
|
||||||
|
imp_value,
|
||||||
|
merged_container)
|
||||||
|
if mult_directive not in multiple_directives_to_append:
|
||||||
|
multiple_directives_to_append.append(mult_directive)
|
||||||
|
merged_container.pop('directives_multiple', None)
|
||||||
|
|
||||||
|
for p_directive_item in container_to_import.get('directives', []):
|
||||||
|
for p_directive, p_value in p_directive_item.items():
|
||||||
|
if p_directive in multiple_directives_to_append:
|
||||||
|
append_to_container_directives(p_directive,
|
||||||
|
p_value,
|
||||||
|
merged_container)
|
||||||
|
else:
|
||||||
|
merged_container = enforce_directive_value(
|
||||||
|
p_directive,
|
||||||
|
{'value': p_value, 'add_if_absent': add_directive},
|
||||||
|
'virtual_name_container',
|
||||||
|
merged_container)
|
||||||
|
# containers:
|
||||||
|
sub_containers_to_update = merged_container.get('containers', {})
|
||||||
|
sub_containers_to_import = container_to_import.get('containers', {})
|
||||||
|
if sub_containers_to_update and sub_containers_to_import:
|
||||||
|
# merge directives of sub containers
|
||||||
|
for container_name, u_container_list in sub_containers_to_update.items():
|
||||||
|
to_imp_containers = sub_containers_to_import.get(container_name, [])
|
||||||
|
for container_idx, to_upd_container_data in enumerate(u_container_list):
|
||||||
|
imp_items_containers = [container for container in to_imp_containers
|
||||||
|
if container['item'] == to_upd_container_data['item']]
|
||||||
|
for i_item_container in imp_items_containers:
|
||||||
|
merged_container['containers'][container_name][container_idx] = \
|
||||||
|
merge_container_with_additional_data(
|
||||||
|
merged_container['containers'][container_name][container_idx],
|
||||||
|
i_item_container,
|
||||||
|
add_directive)
|
||||||
|
if add_container:
|
||||||
|
# merge containers not present in default 'container_name' list
|
||||||
|
d_container_items = set([container.get('item') for container
|
||||||
|
in u_container_list])
|
||||||
|
p_container_items = set([container.get('item') for container
|
||||||
|
in to_imp_containers])
|
||||||
|
items_diff = (p_container_items - d_container_items)
|
||||||
|
for item in items_diff:
|
||||||
|
merged_container['containers'][container_name].extend(
|
||||||
|
[container for container in to_imp_containers if
|
||||||
|
container.get('item') == item])
|
||||||
|
|
||||||
|
if add_container:
|
||||||
|
# merge global containers not present in default
|
||||||
|
k_containers_diff = (set(sub_containers_to_import.keys())
|
||||||
|
- set(sub_containers_to_update.keys()))
|
||||||
|
for k_container in k_containers_diff:
|
||||||
|
merged_container['containers'][k_container] = {}
|
||||||
|
merged_container['containers'][k_container] = sub_containers_to_import[k_container]
|
||||||
|
|
||||||
|
elif not sub_containers_to_update \
|
||||||
|
and sub_containers_to_import \
|
||||||
|
and add_container:
|
||||||
|
merged_container['containers'] = {}
|
||||||
|
merged_container['containers'] = sub_containers_to_import
|
||||||
|
elif not sub_containers_to_import:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# move directives_multiple into directives and delete directives_multiple
|
||||||
|
for container_name, containers_list in merged_container.get('containers', {}).items():
|
||||||
|
for container_idx, container_data in enumerate(containers_list):
|
||||||
|
merged_container['containers'][container_name][container_idx] = \
|
||||||
|
_container_merge_multiple_directives(container_data)
|
||||||
|
|
||||||
|
return merged_container
|
||||||
|
|
||||||
|
|
||||||
|
def enforce_security_directives_into_containers(container_to_secure,
|
||||||
|
secured_containers,
|
||||||
|
add_directive=True,
|
||||||
|
add_container=True):
|
||||||
|
'''
|
||||||
|
Merge secured containers into pillar content
|
||||||
|
|
||||||
|
container_to_secure
|
||||||
|
usually pillar content
|
||||||
|
|
||||||
|
secured_containers
|
||||||
|
content of hadened values
|
||||||
|
|
||||||
|
add_directive : default=True
|
||||||
|
add directive if it is not present
|
||||||
|
|
||||||
|
add_container : default=True
|
||||||
|
add sub_container if it is absent in container_to_secure
|
||||||
|
'''
|
||||||
|
i_secured_containers = {}
|
||||||
|
i_secured_containers['containers'] = secured_containers
|
||||||
|
container_to_secure = merge_container_with_additional_data(
|
||||||
|
container_to_secure,
|
||||||
|
i_secured_containers,
|
||||||
|
add_directive=add_directive,
|
||||||
|
add_container=add_container)
|
||||||
|
# search in (sub) nested containers and secure them
|
||||||
|
for secure_container_name, l_s_containers in secured_containers.items():
|
||||||
|
for s_container in l_s_containers:
|
||||||
|
# search into container_to_secure
|
||||||
|
secured_item = s_container.get('item')
|
||||||
|
for s_directive in s_container.get('directives', []):
|
||||||
|
for s_d_label, s_d_value in s_directive.items():
|
||||||
|
container_to_secure = _manage_directive_into_containers(
|
||||||
|
s_d_label,
|
||||||
|
s_d_value,
|
||||||
|
container_to_secure,
|
||||||
|
container_name_target=secure_container_name,
|
||||||
|
item=secured_item,
|
||||||
|
enforce_value=True,
|
||||||
|
add_directive=add_directive)
|
||||||
|
|
||||||
|
return container_to_secure
|
||||||
|
|
||||||
|
|
||||||
|
def _substitute_value(text, enforced_value):
|
||||||
|
'''
|
||||||
|
conditional replace in 'text' with regex and condition
|
||||||
|
|
||||||
|
text
|
||||||
|
string to process
|
||||||
|
|
||||||
|
enforced_value
|
||||||
|
dict :
|
||||||
|
match: regex to match
|
||||||
|
value: value to enforce
|
||||||
|
onlyif_pillar_is: condition on pillar content
|
||||||
|
regex_group_position: number of group to replace in regex
|
||||||
|
'''
|
||||||
|
def my_match_function(m_object):
|
||||||
|
|
||||||
|
return_value = ''.join([m_object.group(idx) for idx in range(1, position)
|
||||||
|
if m_object.group(idx) is not None])
|
||||||
|
if condition == 'greater':
|
||||||
|
return_value = return_value \
|
||||||
|
+ str(min(int(m_object.group(position)), int(enforced_value['value']))) \
|
||||||
|
+ ''.join([m_object.group(idx) for idx in range(position+1, m_object.lastindex+1) if m_object.group(idx) is not None])
|
||||||
|
elif condition == 'lower':
|
||||||
|
return_value = return_value \
|
||||||
|
+ str(max(int(m_object.group(position)), int(enforced_value['value']))) \
|
||||||
|
+ ''.join([m_object.group(idx) for idx in range(position+1, m_object.lastindex+1) if m_object.group(idx) is not None])
|
||||||
|
|
||||||
|
elif condition == 'different' and m_object.group(position) != str(enforced_value['value']):
|
||||||
|
return_value = return_value \
|
||||||
|
+ enforced_value['value'] \
|
||||||
|
+ ''.join([m_object.group(idx) for idx in range(position+1, m_object.lastindex+1) if m_object.group(idx) is not None])
|
||||||
|
else:
|
||||||
|
return_value = m_object.group(0)
|
||||||
|
|
||||||
|
return return_value
|
||||||
|
|
||||||
|
_pattern = re.compile(enforced_value.get('match', r'(\S+(\s+\S+)*)'), re.IGNORECASE)
|
||||||
|
condition = enforced_value.get('onlyif_pillar_is', 'different')
|
||||||
|
position = enforced_value.get('regex_group_position', 1)
|
||||||
|
value = _pattern.sub(my_match_function, str(text))
|
||||||
|
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
def enforce_directive_value(directive,
|
||||||
|
enforced_directive_data,
|
||||||
|
container_name,
|
||||||
|
container_data):
|
||||||
|
'''
|
||||||
|
Enforce value of directive under conditions
|
||||||
|
|
||||||
|
directive
|
||||||
|
directive label (name)
|
||||||
|
|
||||||
|
enforced_directive_data
|
||||||
|
dict containning
|
||||||
|
value to put
|
||||||
|
condition (greater|lower|different)
|
||||||
|
regex match : default= r'(\\w+(\\s+\\w+)*)'
|
||||||
|
regex group position : default=1
|
||||||
|
container : enforce value only on the specified container
|
||||||
|
|
||||||
|
container_name
|
||||||
|
the name of httpd container
|
||||||
|
|
||||||
|
container_data
|
||||||
|
container to parse
|
||||||
|
'''
|
||||||
|
d_is_present = False
|
||||||
|
add_directive = enforced_directive_data.get('add_if_absent', False)
|
||||||
|
enforced_data_values = enforced_directive_data.get('values', [enforced_directive_data])
|
||||||
|
for idx_d, d_item in enumerate(container_data.get('directives', [])):
|
||||||
|
if directive in d_item:
|
||||||
|
d_is_present = True
|
||||||
|
for enforced_data_value in enforced_data_values:
|
||||||
|
if (not enforced_data_value.get('container', '')) \
|
||||||
|
or (enforced_data_value.get('container') == container_name):
|
||||||
|
container_data['directives'][idx_d][directive] = \
|
||||||
|
_substitute_value(container_data['directives'][idx_d][directive],
|
||||||
|
enforced_data_value)
|
||||||
|
if re.match(r'(\s*)?$', container_data['directives'][idx_d][directive]) is not None:
|
||||||
|
# delete directive from list in case of
|
||||||
|
# the value is empty after replacement
|
||||||
|
del container_data['directives'][idx_d]
|
||||||
|
break
|
||||||
|
if add_directive and not d_is_present \
|
||||||
|
and not enforced_directive_data.get('match', '') \
|
||||||
|
and not enforced_directive_data.get('values', ''):
|
||||||
|
append_to_container_directives(directive,
|
||||||
|
enforced_directive_data.get('value'),
|
||||||
|
container_data)
|
||||||
|
|
||||||
|
# directive is not added in subcontainers
|
||||||
|
enforced_directive_data['add_if_absent'] = False
|
||||||
|
|
||||||
|
for sub_container_name, sub_containers in \
|
||||||
|
container_data.get('containers', {}).items():
|
||||||
|
container_to_match = enforced_directive_data.get('container', sub_container_name)
|
||||||
|
if container_to_match == sub_container_name:
|
||||||
|
for idx, nested_container in enumerate(sub_containers):
|
||||||
|
container_data['containers'][sub_container_name][idx] = \
|
||||||
|
enforce_directive_value(directive,
|
||||||
|
enforced_directive_data,
|
||||||
|
sub_container_name,
|
||||||
|
nested_container)
|
||||||
|
|
||||||
|
return container_data
|
||||||
|
|
||||||
|
|
||||||
|
def remove_container(container_data,
|
||||||
|
container_name_to_remove,
|
||||||
|
item_name_to_remove):
|
||||||
|
'''
|
||||||
|
remove container_name/item from container_data
|
||||||
|
'''
|
||||||
|
for idx, container in enumerate(container_data.get('containers', {}).get(container_name_to_remove, [])):
|
||||||
|
if container.get('item') == item_name_to_remove:
|
||||||
|
del container_data['containers'][container_name_to_remove][idx]
|
||||||
|
|
||||||
|
for sub_container_name, sub_containers in \
|
||||||
|
container_data.get('containers', {}).items():
|
||||||
|
for sub_idx, sub_container in enumerate(sub_containers):
|
||||||
|
container_data['containers'][sub_container_name][sub_idx] = \
|
||||||
|
remove_container(sub_container, container_name_to_remove, item_name_to_remove)
|
||||||
|
|
||||||
|
return container_data
|
@ -1,13 +1,61 @@
|
|||||||
{% from "apache/map.jinja" import apache with context %}
|
{% from "apache/map.jinja" import apache with context %}
|
||||||
|
{% import_yaml "apache/hardening-values.yaml" as hardening_values %}
|
||||||
|
{% import_yaml "apache/defaults/" ~ salt['grains.get']('os_family') ~ "/defaults-apache-" ~ apache.version ~ ".yaml" as global_defaults %}
|
||||||
|
|
||||||
include:
|
include:
|
||||||
- apache
|
- apache
|
||||||
|
- apache.mod_ssl
|
||||||
|
- apache.hardening
|
||||||
|
|
||||||
|
{# merge defaults with pillar content #}
|
||||||
|
{% set pillar_server_config = salt['pillar.get']('apache:server_apache_config', {}) %}
|
||||||
|
{% set server_config = salt['apache_directives.merge_container_with_additional_data'](
|
||||||
|
global_defaults.server_apache_config,
|
||||||
|
pillar_server_config) %}
|
||||||
|
|
||||||
|
{# enforce directives values #}
|
||||||
|
{% for directive, directive_data in hardening_values.enforced_directives.items() %}
|
||||||
|
{% set server_config = salt['apache_directives.enforce_directive_value'](directive,
|
||||||
|
directive_data,
|
||||||
|
container_name='server',
|
||||||
|
container_data=server_config) %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{# merge server config with hardened sections #}
|
||||||
|
{% set server_config = salt['apache_directives.enforce_security_directives_into_containers'](
|
||||||
|
server_config,
|
||||||
|
hardening_values.enforced_containers ) %}
|
||||||
|
|
||||||
|
{# remove containers #}
|
||||||
|
{% for container_name_to_remove, items_names in hardening_values.containers_to_remove.items() %}
|
||||||
|
{% for item_name in items_names %}
|
||||||
|
{% set server_config = salt['apache_directives.remove_container'](
|
||||||
|
server_config,
|
||||||
|
container_name_to_remove,
|
||||||
|
item_name) %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{# add supplemental security directives in server configuration #}
|
||||||
|
{% for d_directive in hardening_values.server_supplemental_directives %}
|
||||||
|
{% for directive, value in d_directive.items() %}
|
||||||
|
{% set server_config = salt['apache_directives.append_to_container_directives'](
|
||||||
|
directive,
|
||||||
|
value,
|
||||||
|
server_config) %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{% if grains['os_family']=="RedHat" %}
|
||||||
|
|
||||||
{{ apache.logdir }}:
|
{{ apache.logdir }}:
|
||||||
file.directory:
|
file.directory:
|
||||||
- makedirs: True
|
- makedirs: True
|
||||||
- require:
|
- require:
|
||||||
- pkg: apache
|
- pkg: apache
|
||||||
|
- user: root
|
||||||
|
- group: {{ apache.group }}
|
||||||
|
- dir_mode: 750
|
||||||
- watch_in:
|
- watch_in:
|
||||||
- module: apache-restart
|
- module: apache-restart
|
||||||
- require_in:
|
- require_in:
|
||||||
@ -20,6 +68,9 @@ include:
|
|||||||
- template: jinja
|
- template: jinja
|
||||||
- source:
|
- source:
|
||||||
- salt://apache/files/{{ salt['grains.get']('os_family') }}/apache-{{ apache.version }}.config.jinja
|
- salt://apache/files/{{ salt['grains.get']('os_family') }}/apache-{{ apache.version }}.config.jinja
|
||||||
|
- user: root
|
||||||
|
- group: root
|
||||||
|
- mode: 644
|
||||||
- require:
|
- require:
|
||||||
- pkg: apache
|
- pkg: apache
|
||||||
- watch_in:
|
- watch_in:
|
||||||
@ -29,13 +80,22 @@ include:
|
|||||||
- module: apache-reload
|
- module: apache-reload
|
||||||
- service: apache
|
- service: apache
|
||||||
- context:
|
- context:
|
||||||
apache: {{ apache | json }}
|
apache: {{ apache | json}}
|
||||||
|
server_config: {{ server_config | json }}
|
||||||
|
|
||||||
{{ apache.vhostdir }}:
|
{{ apache.vhostdir }}:
|
||||||
file.directory:
|
file.directory:
|
||||||
- makedirs: True
|
- makedirs: True
|
||||||
- require:
|
- require:
|
||||||
- pkg: apache
|
- pkg: apache
|
||||||
|
- user: root
|
||||||
|
- group: root
|
||||||
|
- dir_mode: 755
|
||||||
|
- file_mode: 644
|
||||||
|
- recurse:
|
||||||
|
- user
|
||||||
|
- group
|
||||||
|
- mode
|
||||||
- watch_in:
|
- watch_in:
|
||||||
- module: apache-restart
|
- module: apache-restart
|
||||||
- require_in:
|
- require_in:
|
||||||
@ -43,98 +103,16 @@ include:
|
|||||||
- module: apache-reload
|
- module: apache-reload
|
||||||
- service: apache
|
- service: apache
|
||||||
|
|
||||||
{% if grains['os_family']=="Debian" %}
|
|
||||||
/etc/apache2/envvars:
|
|
||||||
file.managed:
|
|
||||||
- template: jinja
|
|
||||||
- source:
|
|
||||||
- salt://apache/files/{{ salt['grains.get']('os_family') }}/envvars-{{ apache.version }}.jinja
|
|
||||||
- require:
|
|
||||||
- pkg: apache
|
|
||||||
- watch_in:
|
|
||||||
- module: apache-restart
|
|
||||||
- require_in:
|
|
||||||
- module: apache-restart
|
|
||||||
- module: apache-reload
|
|
||||||
- service: apache
|
|
||||||
|
|
||||||
{{ apache.portsfile }}:
|
|
||||||
file.managed:
|
|
||||||
- template: jinja
|
|
||||||
- source:
|
|
||||||
- salt://apache/files/{{ salt['grains.get']('os_family') }}/ports-{{ apache.version }}.conf.jinja
|
|
||||||
- require:
|
|
||||||
- pkg: apache
|
|
||||||
- watch_in:
|
|
||||||
- module: apache-restart
|
|
||||||
- require_in:
|
|
||||||
- module: apache-restart
|
|
||||||
- module: apache-reload
|
|
||||||
- service: apache
|
|
||||||
- context:
|
|
||||||
apache: {{ apache | json }}
|
|
||||||
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if grains['os_family']=="RedHat" %}
|
|
||||||
{{ apache.confdir }}/welcome.conf:
|
{{ apache.confdir }}/welcome.conf:
|
||||||
file.absent:
|
file.managed:
|
||||||
|
- source:
|
||||||
|
- salt://apache/files/{{ salt['grains.get']('os_family') }}/welcome.conf
|
||||||
|
- user: root
|
||||||
|
- group: root
|
||||||
|
- mode: 644
|
||||||
- require:
|
- require:
|
||||||
- pkg: apache
|
- pkg: apache
|
||||||
- watch_in:
|
- watch_in:
|
||||||
- module: apache-restart
|
|
||||||
- require_in:
|
|
||||||
- module: apache-restart
|
|
||||||
- module: apache-reload
|
|
||||||
- service: apache
|
- service: apache
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if grains['os_family']=="Suse" or salt['grains.get']('os') == 'SUSE' %}
|
|
||||||
/etc/apache2/global.conf:
|
|
||||||
file.managed:
|
|
||||||
- template: jinja
|
|
||||||
- source:
|
|
||||||
- salt://apache/files/{{ salt['grains.get']('os_family') }}/global.config.jinja
|
|
||||||
- require:
|
|
||||||
- pkg: apache
|
|
||||||
- watch_in:
|
|
||||||
- module: apache-restart
|
|
||||||
- require_in:
|
|
||||||
- module: apache-restart
|
|
||||||
- module: apache-reload
|
|
||||||
- service: apache
|
|
||||||
- context:
|
|
||||||
apache: {{ apache | json }}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if grains['os_family']=="FreeBSD" %}
|
|
||||||
/usr/local/etc/{{ apache.service }}/envvars.d/by_salt.env:
|
|
||||||
file.managed:
|
|
||||||
- template: jinja
|
|
||||||
- source:
|
|
||||||
- salt://apache/files/{{ salt['grains.get']('os_family') }}/envvars-{{ apache.version }}.jinja
|
|
||||||
- require:
|
|
||||||
- pkg: apache
|
|
||||||
- watch_in:
|
|
||||||
- module: apache-restart
|
|
||||||
- require_in:
|
|
||||||
- module: apache-restart
|
|
||||||
- module: apache-reload
|
|
||||||
- service: apache
|
|
||||||
|
|
||||||
{{ apache.portsfile }}:
|
|
||||||
file.managed:
|
|
||||||
- template: jinja
|
|
||||||
- source:
|
|
||||||
- salt://apache/files/{{ salt['grains.get']('os_family') }}/ports-{{ apache.version }}.conf.jinja
|
|
||||||
- require:
|
|
||||||
- pkg: apache
|
|
||||||
- watch_in:
|
|
||||||
- module: apache-restart
|
|
||||||
- require_in:
|
|
||||||
- module: apache-restart
|
|
||||||
- module: apache-reload
|
|
||||||
- service: apache
|
|
||||||
- context:
|
|
||||||
apache: {{ apache | json }}
|
|
||||||
{% endif %}
|
|
||||||
|
77
apache/defaults/RedHat/defaults-apache-2.4.yaml
Normal file
77
apache/defaults/RedHat/defaults-apache-2.4.yaml
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
# defaults for httpd.conf
|
||||||
|
|
||||||
|
# The data structure is a little bit different with pillar structure
|
||||||
|
# ``directives_multiple`` list are directives that can be present multiple time in conf file
|
||||||
|
# if the same directive is present in pillar, it will be appended to the defaults ones
|
||||||
|
# there will be no replacement of values
|
||||||
|
server_apache_config:
|
||||||
|
directives:
|
||||||
|
- ServerRoot: '"/etc/httpd"'
|
||||||
|
- AllowEncodedSlashes: 'On'
|
||||||
|
- DocumentRoot: '"/var/www"'
|
||||||
|
- ServerAdmin: 'root@localhost'
|
||||||
|
- EnableSendfile: 'on'
|
||||||
|
- ErrorLog: '"/var/log/httpd/error.log"'
|
||||||
|
- LogLevel: 'warn core:info'
|
||||||
|
- AddDefaultCharset: 'UTF-8'
|
||||||
|
- ServerTokens: 'Prod'
|
||||||
|
|
||||||
|
containers:
|
||||||
|
Directory:
|
||||||
|
-
|
||||||
|
item: '/'
|
||||||
|
directives:
|
||||||
|
- AllowOverride: 'None'
|
||||||
|
- Require: 'all denied'
|
||||||
|
-
|
||||||
|
item: '/var/www'
|
||||||
|
directives:
|
||||||
|
- AllowOverride: 'None'
|
||||||
|
- Require: 'all granted'
|
||||||
|
- Options: 'Indexes FollowSymLinks'
|
||||||
|
-
|
||||||
|
item: '/var/www/cgi-bin'
|
||||||
|
directives:
|
||||||
|
- AllowOverride: 'None'
|
||||||
|
- Options: 'None'
|
||||||
|
- Require: 'all granted'
|
||||||
|
IfModule:
|
||||||
|
-
|
||||||
|
item: 'dir_module'
|
||||||
|
directives:
|
||||||
|
- DirectoryIndex: index.html
|
||||||
|
-
|
||||||
|
item: 'log_config_module'
|
||||||
|
directives:
|
||||||
|
- CustomLog: '"/var/log/httpd/access.log" combined'
|
||||||
|
directives_multiple: # <-- Theses directives are appended as it to pillar content
|
||||||
|
- LogFormat: '"%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined'
|
||||||
|
- LogFormat: '"%h %l %u %t \"%r\" %>s %b" common'
|
||||||
|
containers:
|
||||||
|
IfModule:
|
||||||
|
-
|
||||||
|
item: 'logio_module'
|
||||||
|
directives:
|
||||||
|
- LogFormat: '"%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio'
|
||||||
|
-
|
||||||
|
item: 'alias_module'
|
||||||
|
directives:
|
||||||
|
- ScriptAlias: '/cgi-bin/ "/var/www/cgi-bin/"'
|
||||||
|
-
|
||||||
|
item: 'mime_module'
|
||||||
|
directives:
|
||||||
|
- TypesConfig: '/etc/mime.types'
|
||||||
|
- AddOutputFilter: 'INCLUDES .shtml'
|
||||||
|
directives_multiple:
|
||||||
|
- AddType: 'application/x-compress .Z'
|
||||||
|
- AddType: 'application/x-gzip .gz .tgz'
|
||||||
|
- AddType: 'text/html .shtml'
|
||||||
|
-
|
||||||
|
item: 'mime_magic_module'
|
||||||
|
directives:
|
||||||
|
- MIMEMagicFile: 'conf/magic'
|
||||||
|
FilesMatch:
|
||||||
|
-
|
||||||
|
item: '"^\.ht"'
|
||||||
|
directives:
|
||||||
|
- Require: 'all denied'
|
@ -1,400 +1,42 @@
|
|||||||
#
|
#
|
||||||
# This file is managed by Salt! Do not edit by hand!
|
# This file is managed by Salt! Do not edit by hand!
|
||||||
#
|
#
|
||||||
{% from "apache/map.jinja" import apache with context %}
|
{%- from "apache/map.jinja" import apache with context %}
|
||||||
#
|
{%- import_yaml "apache/hardening-values.yaml" as hardening_values %}
|
||||||
# This is the main Apache HTTP server configuration file. It contains the
|
{%- from "apache/lib.sls" import directives_output, container_output with context %}
|
||||||
# configuration directives that give the server its instructions.
|
|
||||||
# See <URL:http://httpd.apache.org/docs/2.4/> for detailed information.
|
|
||||||
# In particular, see
|
|
||||||
# <URL:http://httpd.apache.org/docs/2.4/mod/directives.html>
|
|
||||||
# for a discussion of each configuration directive.
|
|
||||||
#
|
|
||||||
# Do NOT simply read the instructions in here without understanding
|
|
||||||
# what they do. They're here only as hints or reminders. If you are unsure
|
|
||||||
# consult the online docs. You have been warned.
|
|
||||||
#
|
|
||||||
# Configuration and logfile names: If the filenames you specify for many
|
|
||||||
# of the server's control files begin with "/" (or "drive:/" for Win32), the
|
|
||||||
# server will use that explicit path. If the filenames do *not* begin
|
|
||||||
# with "/", the value of ServerRoot is prepended -- so 'log/access_log'
|
|
||||||
# with ServerRoot set to '/www' will be interpreted by the
|
|
||||||
# server as '/www/log/access_log', where as '/log/access_log' will be
|
|
||||||
# interpreted as '/log/access_log'.
|
|
||||||
|
|
||||||
#
|
{%- set list_interfaces_ports = [] %}
|
||||||
# ServerRoot: The top of the directory tree under which the server's
|
{%- for name, vhost in salt['pillar.get']('apache:VirtualHost', {}).items() %}
|
||||||
# configuration, error, and log files are kept.
|
{%- if not vhost.get('absent', False) %}
|
||||||
#
|
{%- set items = vhost.item.split() %}
|
||||||
# Do not add a slash at the end of the directory path. If you point
|
{%- for item in items if item not in list_interfaces_ports %}
|
||||||
# ServerRoot at a non-local disk, be sure to specify a local disk on the
|
{%- do list_interfaces_ports.append(item) %}
|
||||||
# Mutex directive, if file-based mutexes are used. If you wish to share the
|
{%- endfor %}
|
||||||
# same ServerRoot for multiple httpd daemons, you will need to change at
|
|
||||||
# least PidFile.
|
|
||||||
#
|
|
||||||
ServerRoot "{{ apache.get('serverroot', '/etc/httpd') }}"
|
|
||||||
|
|
||||||
#
|
|
||||||
# Listen: Allows you to bind Apache to specific IP addresses and/or
|
|
||||||
# ports, instead of the default. See also the <VirtualHost>
|
|
||||||
# directive.
|
|
||||||
#
|
|
||||||
# Change this to Listen on specific IP addresses as shown below to
|
|
||||||
# prevent Apache from glomming onto all bound IP addresses.
|
|
||||||
#
|
|
||||||
#Listen 12.34.56.78:80
|
|
||||||
|
|
||||||
{% if salt['pillar.get']('apache:sites') is mapping %}
|
|
||||||
{%- set listen_directives = [] %}
|
|
||||||
{%- for id, site in salt['pillar.get']('apache:sites').items() %}
|
|
||||||
{%- set interfaces = site.get('interface', '*').split() %}
|
|
||||||
{%- set port = site.get('port', 80) %}
|
|
||||||
{%- for interface in interfaces %}
|
|
||||||
{%- if not site.get('exclude_listen_directive', False) and not port == '*' %}
|
|
||||||
{%- set listen_directive = interface ~ ':' ~ port %}
|
|
||||||
{%- if listen_directive not in listen_directives %}
|
|
||||||
{%- do listen_directives.append(listen_directive) %}
|
|
||||||
{%- endif %}
|
|
||||||
{%- endif %}
|
|
||||||
{%- endfor %}
|
|
||||||
{%- endfor %}
|
|
||||||
{%- for listen in listen_directives %}
|
|
||||||
Listen {{ listen }}
|
|
||||||
{%- endfor %}
|
|
||||||
{%- else %}
|
|
||||||
Listen 80
|
|
||||||
|
|
||||||
<IfModule mod_ssl.c>
|
|
||||||
Listen 443
|
|
||||||
</IfModule>
|
|
||||||
|
|
||||||
<IfModule mod_gnutls.c>
|
|
||||||
Listen 443
|
|
||||||
</IfModule>
|
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|
||||||
#
|
|
||||||
# Dynamic Shared Object (DSO) Support
|
|
||||||
#
|
|
||||||
# To be able to use the functionality of a module which was built as a DSO you
|
|
||||||
# have to place corresponding `LoadModule' lines at this location so the
|
|
||||||
# directives contained in it are actually available _before_ they are used.
|
|
||||||
# Statically compiled modules (those listed by `httpd -l') do not need
|
|
||||||
# to be loaded here.
|
|
||||||
#
|
|
||||||
# Example:
|
|
||||||
# LoadModule foo_module modules/mod_foo.so
|
|
||||||
#
|
|
||||||
Include conf.modules.d/*.conf
|
|
||||||
|
|
||||||
#
|
|
||||||
# If you wish httpd to run as a different user or group, you must run
|
|
||||||
# httpd as root initially and it will switch.
|
|
||||||
#
|
|
||||||
# User/Group: The name (or #number) of the user/group to run httpd as.
|
|
||||||
# It is usually good practice to create a dedicated user and group for
|
|
||||||
# running httpd, as with most system services.
|
|
||||||
#
|
|
||||||
User apache
|
|
||||||
Group apache
|
|
||||||
|
|
||||||
# 'Main' server configuration
|
|
||||||
#
|
|
||||||
# The directives in this section set up the values used by the 'main'
|
|
||||||
# server, which responds to any requests that aren't handled by a
|
|
||||||
# <VirtualHost> definition. These values also provide defaults for
|
|
||||||
# any <VirtualHost> containers you may define later in the file.
|
|
||||||
#
|
|
||||||
# All of these directives may appear inside <VirtualHost> containers,
|
|
||||||
# in which case these default settings will be overridden for the
|
|
||||||
# virtual host being defined.
|
|
||||||
#
|
|
||||||
|
|
||||||
#
|
|
||||||
# ServerAdmin: Your address, where problems with the server should be
|
|
||||||
# e-mailed. This address appears on some server-generated pages, such
|
|
||||||
# as error documents. e.g. admin@your-domain.com
|
|
||||||
#
|
|
||||||
ServerAdmin root@localhost
|
|
||||||
|
|
||||||
#
|
|
||||||
# ServerName gives the name and port that the server uses to identify itself.
|
|
||||||
# This can often be determined automatically, but we recommend you specify
|
|
||||||
# it explicitly to prevent problems during startup.
|
|
||||||
#
|
|
||||||
# If your host doesn't have a registered DNS name, enter its IP address here.
|
|
||||||
#
|
|
||||||
#ServerName www.example.com:80
|
|
||||||
|
|
||||||
#
|
|
||||||
# Deny access to the entirety of your server's filesystem. You must
|
|
||||||
# explicitly permit access to web content directories in other
|
|
||||||
# <Directory> blocks below.
|
|
||||||
#
|
|
||||||
<Directory />
|
|
||||||
AllowOverride none
|
|
||||||
Require all denied
|
|
||||||
</Directory>
|
|
||||||
|
|
||||||
#
|
|
||||||
# Note that from this point forward you must specifically allow
|
|
||||||
# particular features to be enabled - so if something's not working as
|
|
||||||
# you might expect, make sure that you have specifically enabled it
|
|
||||||
# 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 "{{ apache.get('docroot', apache.wwwdir + '/html') }}"
|
|
||||||
|
|
||||||
#
|
|
||||||
# Relax access to content within {{ apache.wwwdir }}.
|
|
||||||
#
|
|
||||||
<Directory "{{ apache.wwwdir }}">
|
|
||||||
AllowOverride None
|
|
||||||
# Allow open access:
|
|
||||||
Require all granted
|
|
||||||
</Directory>
|
|
||||||
|
|
||||||
# Further relax access to the default document root:
|
|
||||||
<Directory "{{ apache.get('docroot', apache.wwwdir + '/html') }}">
|
|
||||||
#
|
|
||||||
# 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>
|
|
||||||
|
|
||||||
#
|
|
||||||
# DirectoryIndex: sets the file that Apache will serve if a directory
|
|
||||||
# is requested.
|
|
||||||
#
|
|
||||||
<IfModule dir_module>
|
|
||||||
DirectoryIndex index.html
|
|
||||||
</IfModule>
|
|
||||||
|
|
||||||
#
|
|
||||||
# The following lines prevent .htaccess and .htpasswd files from being
|
|
||||||
# viewed by Web clients.
|
|
||||||
#
|
|
||||||
<Files ".ht*">
|
|
||||||
Require all denied
|
|
||||||
</Files>
|
|
||||||
|
|
||||||
#
|
|
||||||
# ErrorLog: The location of the error log file.
|
|
||||||
# If you do not specify an ErrorLog directive within a <VirtualHost>
|
|
||||||
# container, error messages relating to that virtual host will be
|
|
||||||
# logged here. If you *do* define an error logfile for a <VirtualHost>
|
|
||||||
# container, that host's errors will be logged there and not here.
|
|
||||||
#
|
|
||||||
ErrorLog "{{ apache.logdir }}/error_log"
|
|
||||||
|
|
||||||
#
|
|
||||||
# LogLevel: Control the number of messages logged to the error_log.
|
|
||||||
# Possible values include: debug, info, notice, warn, error, crit,
|
|
||||||
# alert, emerg.
|
|
||||||
#
|
|
||||||
LogLevel warn
|
|
||||||
|
|
||||||
<IfModule log_config_module>
|
|
||||||
#
|
|
||||||
# The following directives define some format nicknames for use with
|
|
||||||
# a CustomLog directive (see below).
|
|
||||||
#
|
|
||||||
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
|
|
||||||
LogFormat "%h %l %u %t \"%r\" %>s %b" common
|
|
||||||
{%- for log_format in salt['pillar.get']('apache:log_formats', []) %}
|
|
||||||
LogFormat {{ log_format }}
|
|
||||||
{%- endfor %}
|
|
||||||
|
|
||||||
<IfModule logio_module>
|
|
||||||
# You need to enable mod_logio.c to use %I and %O
|
|
||||||
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
|
|
||||||
</IfModule>
|
|
||||||
|
|
||||||
#
|
|
||||||
# The location and format of the access logfile (Common Logfile Format).
|
|
||||||
# If you do not define any access logfiles within a <VirtualHost>
|
|
||||||
# container, they will be logged here. Contrariwise, if you *do*
|
|
||||||
# define per-<VirtualHost> access logfiles, transactions will be
|
|
||||||
# logged therein and *not* in this file.
|
|
||||||
#
|
|
||||||
#CustomLog "logs/access_log" common
|
|
||||||
|
|
||||||
#
|
|
||||||
# If you prefer a logfile with access, agent, and referer information
|
|
||||||
# (Combined Logfile Format) you can use the following directive.
|
|
||||||
#
|
|
||||||
CustomLog "{{ apache.logdir }}/access_log" combined
|
|
||||||
</IfModule>
|
|
||||||
|
|
||||||
<IfModule alias_module>
|
|
||||||
#
|
|
||||||
# Redirect: Allows you to tell clients about documents that used to
|
|
||||||
# exist in your server's namespace, but do not anymore. The client
|
|
||||||
# will make a new request for the document at its new location.
|
|
||||||
# Example:
|
|
||||||
# Redirect permanent /foo http://www.example.com/bar
|
|
||||||
|
|
||||||
#
|
|
||||||
# Alias: Maps web paths into filesystem paths and is used to
|
|
||||||
# access content that does not live under the DocumentRoot.
|
|
||||||
# Example:
|
|
||||||
# Alias /webpath /full/filesystem/path
|
|
||||||
#
|
|
||||||
# If you include a trailing / on /webpath then the server will
|
|
||||||
# require it to be present in the URL. You will also likely
|
|
||||||
# need to provide a <Directory> section to allow access to
|
|
||||||
# the filesystem path.
|
|
||||||
|
|
||||||
#
|
|
||||||
# ScriptAlias: This controls which directories contain server scripts.
|
|
||||||
# ScriptAliases are essentially the same as Aliases, except that
|
|
||||||
# documents in the target directory are treated as applications and
|
|
||||||
# run by the server when requested rather than as documents sent to the
|
|
||||||
# client. The same rules about trailing "/" apply to ScriptAlias
|
|
||||||
# directives as to Alias.
|
|
||||||
#
|
|
||||||
ScriptAlias /cgi-bin/ "{{ apache.wwwdir }}/cgi-bin/"
|
|
||||||
|
|
||||||
</IfModule>
|
|
||||||
|
|
||||||
#
|
|
||||||
# "{{ apache.wwwdir }}/cgi-bin/" should be changed to whatever your ScriptAliased
|
|
||||||
# CGI directory exists, if you have that configured.
|
|
||||||
#
|
|
||||||
<Directory "{{ apache.wwwdir }}/cgi-bin/">
|
|
||||||
AllowOverride None
|
|
||||||
Options None
|
|
||||||
Require all granted
|
|
||||||
</Directory>
|
|
||||||
|
|
||||||
<IfModule mime_module>
|
|
||||||
#
|
|
||||||
# TypesConfig points to the file containing the list of mappings from
|
|
||||||
# filename extension to MIME-type.
|
|
||||||
#
|
|
||||||
TypesConfig /etc/mime.types
|
|
||||||
|
|
||||||
#
|
|
||||||
# AddType allows you to add to or override the MIME configuration
|
|
||||||
# file specified in TypesConfig for specific file types.
|
|
||||||
#
|
|
||||||
#AddType application/x-gzip .tgz
|
|
||||||
#
|
|
||||||
# AddEncoding allows you to have certain browsers uncompress
|
|
||||||
# information on the fly. Note: Not all browsers support this.
|
|
||||||
#
|
|
||||||
#AddEncoding x-compress .Z
|
|
||||||
#AddEncoding x-gzip .gz .tgz
|
|
||||||
#
|
|
||||||
# If the AddEncoding directives above are commented-out, then you
|
|
||||||
# probably should define those extensions to indicate media types:
|
|
||||||
#
|
|
||||||
AddType application/x-compress .Z
|
|
||||||
AddType application/x-gzip .gz .tgz
|
|
||||||
|
|
||||||
#
|
|
||||||
# AddHandler allows you to map certain file extensions to "handlers":
|
|
||||||
# actions unrelated to filetype. These can be either built into the server
|
|
||||||
# or added with the Action directive (see below)
|
|
||||||
#
|
|
||||||
# To use CGI scripts outside of ScriptAliased directories:
|
|
||||||
# (You will also need to add "ExecCGI" to the "Options" directive.)
|
|
||||||
#
|
|
||||||
#AddHandler cgi-script .cgi
|
|
||||||
|
|
||||||
# For type maps (negotiated resources):
|
|
||||||
#AddHandler type-map var
|
|
||||||
|
|
||||||
#
|
|
||||||
# Filters allow you to process content before it is sent to the client.
|
|
||||||
#
|
|
||||||
# To parse .shtml files for server-side includes (SSI):
|
|
||||||
# (You will also need to add "Includes" to the "Options" directive.)
|
|
||||||
#
|
|
||||||
AddType text/html .shtml
|
|
||||||
AddOutputFilter INCLUDES .shtml
|
|
||||||
</IfModule>
|
|
||||||
|
|
||||||
#
|
|
||||||
# Specify a default charset for all content served; this enables
|
|
||||||
# interpretation of all content as UTF-8 by default. To use the
|
|
||||||
# default browser choice (ISO-8859-1), or to allow the META tags
|
|
||||||
# in HTML content to override this choice, comment out this
|
|
||||||
# directive:
|
|
||||||
#
|
|
||||||
AddDefaultCharset {{ apache.default_charset }}
|
|
||||||
|
|
||||||
<IfModule mime_magic_module>
|
|
||||||
#
|
|
||||||
# The mod_mime_magic module allows the server to use various hints from the
|
|
||||||
# contents of the file itself to determine its type. The MIMEMagicFile
|
|
||||||
# directive tells the module where the hint definitions are located.
|
|
||||||
#
|
|
||||||
MIMEMagicFile conf/magic
|
|
||||||
</IfModule>
|
|
||||||
|
|
||||||
#
|
|
||||||
# Customizable error responses come in three flavors:
|
|
||||||
# 1) plain text 2) local redirects 3) external redirects
|
|
||||||
#
|
|
||||||
# Some examples:
|
|
||||||
#ErrorDocument 500 "The server made a boo boo."
|
|
||||||
#ErrorDocument 404 /missing.html
|
|
||||||
#ErrorDocument 404 "/cgi-bin/missing_handler.pl"
|
|
||||||
#ErrorDocument 402 http://www.example.com/subscription_info.html
|
|
||||||
#
|
|
||||||
|
|
||||||
#
|
|
||||||
# EnableMMAP and EnableSendfile: On systems that support it,
|
|
||||||
# memory-mapping or the sendfile syscall may be used to deliver
|
|
||||||
# files. This usually improves server performance, but must
|
|
||||||
# be turned off when serving from networked-mounted
|
|
||||||
# filesystems or if support for these functions is otherwise
|
|
||||||
# broken on your system.
|
|
||||||
# Defaults if commented: EnableMMAP On, EnableSendfile Off
|
|
||||||
#
|
|
||||||
#EnableMMAP off
|
|
||||||
EnableSendfile on
|
|
||||||
|
|
||||||
{%- for directive, dvalue in salt['pillar.get']('apache:global', {}).items() %}
|
|
||||||
{{ directive }} {{ dvalue }}
|
|
||||||
{%- endfor %}
|
{%- endfor %}
|
||||||
|
|
||||||
# Supplemental configuration
|
{%- for item in list_interfaces_ports %}
|
||||||
#
|
Listen {{ item }}
|
||||||
# Load config files in the "/etc/httpd/conf.d" directory, if any.
|
{% else %}
|
||||||
IncludeOptional {{ apache.confdir }}/*.conf
|
Listen *:80
|
||||||
{% if apache.vhostdir != apache.confdir %}
|
{%- endfor %}
|
||||||
IncludeOptional {{ apache.vhostdir }}/*.conf
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
# Added for security enhancements
|
{{ directives_output(server_config, 0) }}
|
||||||
TraceEnable off
|
|
||||||
ServerSignature off
|
Include conf.modules.d/*.conf
|
||||||
ServerTokens Prod
|
|
||||||
|
User {{ apache.user }}
|
||||||
|
Group {{ apache.group }}
|
||||||
|
|
||||||
|
|
||||||
|
{%- for container_name, container_data_list in server_config.get('containers', {}).items() %}
|
||||||
|
{%- for container_data in container_data_list %}
|
||||||
|
{{ container_output(container_name, container_data) }}
|
||||||
|
{%- endfor %}
|
||||||
|
{%- endfor %}
|
||||||
|
|
||||||
|
|
||||||
|
IncludeOptional {{ apache.confdir }}/*.conf
|
||||||
|
{%- if apache.vhostdir != apache.confdir %}
|
||||||
|
IncludeOptional {{ apache.vhostdir }}/*.conf
|
||||||
|
{%- endif %}
|
||||||
|
15
apache/files/RedHat/welcome.conf
Normal file
15
apache/files/RedHat/welcome.conf
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#
|
||||||
|
# This file is managed by Salt! Do not edit by hand!
|
||||||
|
#
|
||||||
|
|
||||||
|
# httpd welcome file commented for security reasons
|
||||||
|
|
||||||
|
# This configuration file enables the default ""Welcome""
|
||||||
|
# page if there is no default index page present for
|
||||||
|
# the root URL. To disable the Welcome page, comment
|
||||||
|
# out all the lines below.
|
||||||
|
#
|
||||||
|
##<LocationMatch ""^/+$"">
|
||||||
|
## Options -Indexes
|
||||||
|
## ErrorDocument 403 /error/noindex.html
|
||||||
|
##</LocationMatch>
|
151
apache/hardening-values.yaml
Normal file
151
apache/hardening-values.yaml
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
enforced_directives:
|
||||||
|
# httpd directives enforced in all configuration files and sections
|
||||||
|
# data structure :
|
||||||
|
# directive:
|
||||||
|
# value: numeric or string - value to enforce
|
||||||
|
# add_if_absent: False (default) - True -> add it to server configuration if it is absent from pillar
|
||||||
|
# onlyif_pillar_is: different (default) |greater|lower -> compare numeric values
|
||||||
|
# - greater : enforce value if the pillar content is > value
|
||||||
|
# - lower : enforce value if the pillar content is < value
|
||||||
|
# match : regex
|
||||||
|
# container : enforce only on the specified container
|
||||||
|
# regex_group_position : the position of the group to substitute in regex
|
||||||
|
# values : list of dict - for multiple replacements in the same directive
|
||||||
|
|
||||||
|
# Set TimeOut to 10 or less
|
||||||
|
Timeout:
|
||||||
|
value: 10
|
||||||
|
onlyif_pillar_is: 'greater'
|
||||||
|
add_if_absent: True
|
||||||
|
# Set Timeout Limits for Request Headers
|
||||||
|
RequestReadTimeout:
|
||||||
|
values:
|
||||||
|
-
|
||||||
|
match: '(?<=header=)(\d+-)?(\d+)'
|
||||||
|
value: 40
|
||||||
|
onlyif_pillar_is: 'greater'
|
||||||
|
regex_group_position: 2
|
||||||
|
-
|
||||||
|
match: '(?<=body=)(\d+-)?(\d+)'
|
||||||
|
value: 20
|
||||||
|
onlyif_pillar_is: 'greater'
|
||||||
|
regex_group_position: 2
|
||||||
|
# Disable the SSL v3.0 Protocol
|
||||||
|
SSLProtocol:
|
||||||
|
value: ''
|
||||||
|
match: '(?<!-)((\+)?SSLv3)'
|
||||||
|
regex_group_position: 1
|
||||||
|
# Minimize Options for Directories to NOT have a value of Includes
|
||||||
|
Options:
|
||||||
|
match: '(?<!-)((\+)?Includes)'
|
||||||
|
value: ''
|
||||||
|
regex_group_position: 1
|
||||||
|
container: 'Directory'
|
||||||
|
# Set the KeepAlive directive to On
|
||||||
|
KeepAlive:
|
||||||
|
value: 'On'
|
||||||
|
add_if_absent: True
|
||||||
|
# Set MaxKeepAliveRequests to 100 or greater
|
||||||
|
MaxKeepAliveRequests:
|
||||||
|
value: 100
|
||||||
|
onlyif_pillar_is: 'lower'
|
||||||
|
add_if_absent: True
|
||||||
|
# Set KeepAliveTimeout to 15 or less
|
||||||
|
KeepAliveTimeout:
|
||||||
|
value: 15
|
||||||
|
onlyif_pillar_is: 'greater'
|
||||||
|
add_if_absent: True
|
||||||
|
# Disable HTTP TRACE Method
|
||||||
|
TraceEnable:
|
||||||
|
value: 'off'
|
||||||
|
add_if_absent: True
|
||||||
|
# Set ServerSignature to 'Off'
|
||||||
|
ServerSignature:
|
||||||
|
value: 'off'
|
||||||
|
add_if_absent: True
|
||||||
|
# Set ServerToken to 'Prod'
|
||||||
|
ServerTokens:
|
||||||
|
value: 'Prod'
|
||||||
|
# Secure Core Dump Directory
|
||||||
|
CoreDumpDirectory:
|
||||||
|
value: '/var/log/httpd'
|
||||||
|
# Disable SSL Insecure Renegotiation
|
||||||
|
SSLInsecureRenegotiation:
|
||||||
|
value: 'off'
|
||||||
|
# Ensure SSL Compression is not Enabled
|
||||||
|
SSLCompression:
|
||||||
|
value: 'off'
|
||||||
|
# Restrict Override
|
||||||
|
AllowOverride:
|
||||||
|
value: 'None'
|
||||||
|
AllowOverrideList:
|
||||||
|
value: 'None'
|
||||||
|
PidFile:
|
||||||
|
value: '/etc/httpd/run/httpd.pid'
|
||||||
|
ScoreBoardFile:
|
||||||
|
value: '/var/run/apache_runtime_status'
|
||||||
|
SSLHonorCipherOrder:
|
||||||
|
value: 'On'
|
||||||
|
|
||||||
|
enforced_containers:
|
||||||
|
# httpd sections (containers) enforced in all configuration files and sections
|
||||||
|
Directory:
|
||||||
|
# Restrict Override for the OS Root Directory
|
||||||
|
-
|
||||||
|
item: '/'
|
||||||
|
directives:
|
||||||
|
- AllowOverride: 'None'
|
||||||
|
- Require: 'all denied'
|
||||||
|
- Options: 'None'
|
||||||
|
|
||||||
|
# Limit HTTP Request Methods
|
||||||
|
-
|
||||||
|
item: '/var/www'
|
||||||
|
directives:
|
||||||
|
- Options: 'None'
|
||||||
|
containers:
|
||||||
|
LimitExcept:
|
||||||
|
-
|
||||||
|
item: 'GET POST OPTIONS'
|
||||||
|
directives:
|
||||||
|
- Require: 'all denied'
|
||||||
|
FilesMatch:
|
||||||
|
# Restrict Access to .ht* files
|
||||||
|
-
|
||||||
|
item: '"^\.ht"'
|
||||||
|
directives:
|
||||||
|
- Require: 'all denied'
|
||||||
|
|
||||||
|
containers_to_remove:
|
||||||
|
# Remove Default HTML Content
|
||||||
|
Location:
|
||||||
|
- '/server-info'
|
||||||
|
- '/server-status'
|
||||||
|
- '/perl-status'
|
||||||
|
|
||||||
|
server_supplemental_directives:
|
||||||
|
# httpd directives added as it in httpd.conf
|
||||||
|
# Restrict HTTP protocol versions
|
||||||
|
- RewriteEngine: 'On'
|
||||||
|
- RewriteCond: '%{THE_REQUEST} !HTTP/1\.1$'
|
||||||
|
- RewriteRule: '.* - [F]'
|
||||||
|
|
||||||
|
vhost_supplemental_directives:
|
||||||
|
# httpd directives added as it in vhost config file
|
||||||
|
# Inherit server options
|
||||||
|
- RewriteEngine: 'On'
|
||||||
|
- RewriteOptions: 'Inherit'
|
||||||
|
|
||||||
|
modules:
|
||||||
|
# httpd modules: enforce enabled and disabled
|
||||||
|
enforce_disabled:
|
||||||
|
- "dav"
|
||||||
|
- "dav_fs"
|
||||||
|
- "status"
|
||||||
|
- "autoindex"
|
||||||
|
- "userdir"
|
||||||
|
- "info"
|
||||||
|
enforce_enabled:
|
||||||
|
- "log_config"
|
||||||
|
- "reqtimeout"
|
||||||
|
- "rewrite"
|
67
apache/hardening.sls
Normal file
67
apache/hardening.sls
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
{% from "apache/map.jinja" import apache with context %}
|
||||||
|
|
||||||
|
include:
|
||||||
|
- apache
|
||||||
|
|
||||||
|
nologin_shell_for_apache_user:
|
||||||
|
user.present:
|
||||||
|
- name: {{ apache.user }}
|
||||||
|
- shell: /sbin/nologin
|
||||||
|
- require:
|
||||||
|
- pkg: apache
|
||||||
|
- watch_in:
|
||||||
|
- module: apache-restart
|
||||||
|
- require_in:
|
||||||
|
- module: apache-restart
|
||||||
|
- module: apache-reload
|
||||||
|
- service: apache
|
||||||
|
|
||||||
|
remove_httpd_manual:
|
||||||
|
pkg.removed:
|
||||||
|
- name: httpd-manual
|
||||||
|
- require:
|
||||||
|
- pkg: apache
|
||||||
|
- watch_in:
|
||||||
|
- module: apache-restart
|
||||||
|
- require_in:
|
||||||
|
- module: apache-restart
|
||||||
|
- module: apache-reload
|
||||||
|
- service: apache
|
||||||
|
|
||||||
|
/etc/httpd/conf.d/autoindex.conf:
|
||||||
|
file.managed:
|
||||||
|
- contents: |
|
||||||
|
# File commented with Salt, Do NOT Edit
|
||||||
|
# Do NOT delete because it is contained in the rpm, so it wil re-created on the next upgrade
|
||||||
|
# It is emptied for hardening purpose
|
||||||
|
- require:
|
||||||
|
- pkg: apache
|
||||||
|
- watch_in:
|
||||||
|
- module: apache-restart
|
||||||
|
- require_in:
|
||||||
|
- module: apache-restart
|
||||||
|
- module: apache-reload
|
||||||
|
- service: apache
|
||||||
|
|
||||||
|
|
||||||
|
/etc/httpd/cgi-bin/printenv:
|
||||||
|
file.absent:
|
||||||
|
- require:
|
||||||
|
- pkg: apache
|
||||||
|
- watch_in:
|
||||||
|
- module: apache-restart
|
||||||
|
- require_in:
|
||||||
|
- module: apache-restart
|
||||||
|
- module: apache-reload
|
||||||
|
- service: apache
|
||||||
|
|
||||||
|
/etc/httpd/cgi-bin/test-cgi:
|
||||||
|
file.absent:
|
||||||
|
- require:
|
||||||
|
- pkg: apache
|
||||||
|
- watch_in:
|
||||||
|
- module: apache-restart
|
||||||
|
- require_in:
|
||||||
|
- module: apache-restart
|
||||||
|
- module: apache-reload
|
||||||
|
- service: apache
|
26
apache/lib.sls
Normal file
26
apache/lib.sls
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
# macros for conf Files
|
||||||
|
|
||||||
|
{%- macro output_indented(mytext, indent_value) %}
|
||||||
|
{{ mytext | indent(indent_value, true) }}
|
||||||
|
{%- endmacro %}
|
||||||
|
|
||||||
|
{%- macro directives_output(container, col, default_keys = []) -%}
|
||||||
|
{%- for ordered_directive in container.get('directives', []) -%}
|
||||||
|
{%- for directive, value in ordered_directive.items() if directive not in default_keys| difference(['LogFormat']) -%}
|
||||||
|
{{ output_indented(directive + ' ' + value|string, col) }}
|
||||||
|
{%- endfor %}
|
||||||
|
{%- endfor %}
|
||||||
|
{%- endmacro %}
|
||||||
|
|
||||||
|
{%- macro container_output(container_name, container_data, col=0, default_directives = []) -%}
|
||||||
|
{%- set header_text = '<' ~ container_name ~ ' ' ~ container_data.item ~ '>' -%}
|
||||||
|
{{ output_indented(header_text, col) }}
|
||||||
|
{{ directives_output(container_data, col+4, default_directives ) }}
|
||||||
|
{%- for nested_container_name, nested_containers in container_data.get('containers', {}).items() %}
|
||||||
|
{%- for nested_container in nested_containers %}
|
||||||
|
{{ container_output(nested_container_name, nested_container, col+4) }}
|
||||||
|
{%- endfor %}
|
||||||
|
{%- endfor %}
|
||||||
|
{%- set footer_text = '</' ~ container_name ~ '>' -%}
|
||||||
|
{{ output_indented(footer_text, col) }}
|
||||||
|
{%- endmacro %}
|
@ -1,3 +1,5 @@
|
|||||||
|
{%- import_yaml "apache/hardening-values.yaml" as hardening_values %}
|
||||||
|
|
||||||
{% if grains['os_family']=="Debian" %}
|
{% if grains['os_family']=="Debian" %}
|
||||||
|
|
||||||
include:
|
include:
|
||||||
@ -12,10 +14,6 @@ a2enmod {{ module }}:
|
|||||||
- pkg: apache
|
- pkg: apache
|
||||||
- watch_in:
|
- watch_in:
|
||||||
- module: apache-restart
|
- module: apache-restart
|
||||||
- require_in:
|
|
||||||
- module: apache-restart
|
|
||||||
- module: apache-reload
|
|
||||||
- service: apache
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
{% for module in salt['pillar.get']('apache:modules:disabled', []) %}
|
{% for module in salt['pillar.get']('apache:modules:disabled', []) %}
|
||||||
@ -27,52 +25,62 @@ a2dismod -f {{ module }}:
|
|||||||
- pkg: apache
|
- pkg: apache
|
||||||
- watch_in:
|
- watch_in:
|
||||||
- module: apache-restart
|
- module: apache-restart
|
||||||
- require_in:
|
|
||||||
- module: apache-restart
|
|
||||||
- module: apache-reload
|
|
||||||
- service: apache
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
{% elif grains['os_family']=="RedHat" %}
|
{% elif grains['os_family']=="RedHat" %}
|
||||||
|
|
||||||
include:
|
include:
|
||||||
- apache
|
- apache
|
||||||
|
- apache.config
|
||||||
{% for module in salt['pillar.get']('apache:modules:enabled', []) %}
|
- apache.vhosts.vhost
|
||||||
find /etc/httpd/ -name '*.conf' -type f -exec sed -i -e 's/\(^#\)\(\s*LoadModule.{{ module }}_module\)/\2/g' {} \;:
|
|
||||||
cmd.run:
|
{% set modules_enabled = salt['pillar.get']('apache:modules:enabled', default=hardening_values.modules.enforce_enabled, merge=True) %}
|
||||||
- unless: httpd -M 2> /dev/null | grep "[[:space:]]{{ module }}_module"
|
{% set conf_files = salt['file.find'](path='/etc/httpd/', type='f', name='*.conf') %}
|
||||||
- order: 225
|
|
||||||
|
{% for module in modules_enabled if module not in hardening_values.modules.enforce_disabled %}
|
||||||
|
|
||||||
|
{% for conf_file in conf_files if salt['file.search'](path=conf_file, pattern='LoadModule.' ~ module ) %}
|
||||||
|
|
||||||
|
enable_{{ module }}_{{ conf_file }}:
|
||||||
|
file.uncomment:
|
||||||
|
- name: {{ conf_file }}
|
||||||
|
- regex: LoadModule.{{ module }}
|
||||||
- require:
|
- require:
|
||||||
- pkg: apache
|
- pkg: apache
|
||||||
|
- sls: apache.config
|
||||||
|
- sls: apache.vhosts.vhost
|
||||||
- watch_in:
|
- watch_in:
|
||||||
- module: apache-restart
|
- module: apache-restart
|
||||||
- require_in:
|
|
||||||
- module: apache-restart
|
{% endfor %}
|
||||||
- module: apache-reload
|
|
||||||
- service: apache
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
{% for module in salt['pillar.get']('apache:modules:disabled', []) %}
|
{% set modules_disabled = salt['pillar.get']('apache:modules:disabled', default=hardening_values.modules.enforce_disabled, merge=True) %}
|
||||||
find /etc/httpd/ -name '*.conf' -type f -exec sed -i -e 's/\(^\s*LoadModule.{{ module }}_module\)/#\1/g' {} \;:
|
|
||||||
cmd.run:
|
{% for module in modules_disabled if module not in hardening_values.modules.enforce_enabled %}
|
||||||
- onlyif: httpd -M 2> /dev/null | grep "[[:space:]]{{ module }}_module"
|
{% for conf_file in conf_files if salt['file.search'](path=conf_file, pattern='LoadModule.' ~ module ) %}
|
||||||
- order: 225
|
|
||||||
|
disable_{{ module }}_{{ conf_file }}:
|
||||||
|
file.comment:
|
||||||
|
- name: {{ conf_file }}
|
||||||
|
- regex: LoadModule.{{ module }}
|
||||||
- require:
|
- require:
|
||||||
- pkg: apache
|
- pkg: apache
|
||||||
|
- sls: apache.config
|
||||||
|
- sls: apache.vhosts.vhost
|
||||||
- watch_in:
|
- watch_in:
|
||||||
- module: apache-restart
|
- module: apache-restart
|
||||||
- require_in:
|
|
||||||
- module: apache-restart
|
|
||||||
- module: apache-reload
|
|
||||||
- service: apache
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{% elif salt['grains.get']('os_family') == 'Suse' or salt['grains.get']('os') == 'SUSE' %}
|
{% elif salt['grains.get']('os_family') == 'Suse' or salt['grains.get']('os') == 'SUSE' %}
|
||||||
|
|
||||||
include:
|
include:
|
||||||
- apache
|
- apache
|
||||||
|
|
||||||
{% for module in salt['pillar.get']('apache:modules:enabled', []) %}
|
{% for module in salt['pillar.get']('apache:modules:enabled', []) %}
|
||||||
a2enmod {{ module }}:
|
a2enmod {{ module }}:
|
||||||
cmd.run:
|
cmd.run:
|
||||||
@ -82,10 +90,6 @@ a2enmod {{ module }}:
|
|||||||
- pkg: apache
|
- pkg: apache
|
||||||
- watch_in:
|
- watch_in:
|
||||||
- module: apache-restart
|
- module: apache-restart
|
||||||
- require_in:
|
|
||||||
- module: apache-restart
|
|
||||||
- module: apache-reload
|
|
||||||
- service: apache
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
{% for module in salt['pillar.get']('apache:modules:disabled', []) %}
|
{% for module in salt['pillar.get']('apache:modules:disabled', []) %}
|
||||||
@ -97,10 +101,6 @@ a2dismod -f {{ module }}:
|
|||||||
- pkg: apache
|
- pkg: apache
|
||||||
- watch_in:
|
- watch_in:
|
||||||
- module: apache-restart
|
- module: apache-restart
|
||||||
- require_in:
|
|
||||||
- module: apache-restart
|
|
||||||
- module: apache-reload
|
|
||||||
- service: apache
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -44,7 +44,7 @@ RedHat:
|
|||||||
mod_geoip: mod_geoip
|
mod_geoip: mod_geoip
|
||||||
mod_geoip_database: GeoIP
|
mod_geoip_database: GeoIP
|
||||||
|
|
||||||
vhostdir: /etc/httpd/vhosts.d
|
vhostdir: /etc/httpd/conf.d
|
||||||
confdir: /etc/httpd/conf.d
|
confdir: /etc/httpd/conf.d
|
||||||
confext: .conf
|
confext: .conf
|
||||||
default_site: default
|
default_site: default
|
||||||
@ -111,7 +111,7 @@ FreeBSD:
|
|||||||
modulesdir: /usr/local/etc/apache24/modules.d
|
modulesdir: /usr/local/etc/apache24/modules.d
|
||||||
global_document_root: /usr/local/www/apache24/data
|
global_document_root: /usr/local/www/apache24/data
|
||||||
|
|
||||||
confext:
|
confext:
|
||||||
default_site: default
|
default_site: default
|
||||||
default_site_ssl: default-ssl
|
default_site_ssl: default-ssl
|
||||||
logdir: /var/log/
|
logdir: /var/log/
|
||||||
|
@ -1,41 +0,0 @@
|
|||||||
{% from "apache/map.jinja" import apache with context %}
|
|
||||||
|
|
||||||
include:
|
|
||||||
- apache
|
|
||||||
|
|
||||||
{% if grains.os_family == 'Debian' %}
|
|
||||||
|
|
||||||
{% set dirpath = '/etc/apache2/sites-enabled' %}
|
|
||||||
|
|
||||||
{# Add . and .. to make it easier to not clean those #}
|
|
||||||
{% set valid_sites = ['.', '..', ] %}
|
|
||||||
|
|
||||||
{# Take sites from apache.vhosts.standard #}
|
|
||||||
{% for id, site in salt['pillar.get']('apache:sites', {}).items() %}
|
|
||||||
{% do valid_sites.append('{}{}'.format(id, apache.confext)) %}
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
{# Take sites from apache.register_site #}
|
|
||||||
{% for id, site in salt['pillar.get']('apache:register-site', {}) %}
|
|
||||||
{% do valid_sites.append('{}{}'.format(site.name, apache.confext)) %}
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
|
|
||||||
{% for filename in salt['file.readdir']('/etc/apache2/sites-enabled/') %}
|
|
||||||
{% if filename not in valid_sites %}
|
|
||||||
|
|
||||||
a2dissite {{ filename }}:
|
|
||||||
cmd.run:
|
|
||||||
- onlyif: "test -L {{ dirpath}}/{{ filename }} || test -f {{ dirpath}}/{{ filename }}"
|
|
||||||
- watch_in:
|
|
||||||
- module: apache-reload
|
|
||||||
- require_in:
|
|
||||||
- module: apache-restart
|
|
||||||
- module: apache-reload
|
|
||||||
- service: apache
|
|
||||||
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
|
|
||||||
{% endif %}{# Debian #}
|
|
@ -1,37 +0,0 @@
|
|||||||
#
|
|
||||||
# This file is managed by Salt! Do not edit by hand!
|
|
||||||
#
|
|
||||||
{# Define default values here so the template below can just focus on layout #}
|
|
||||||
{%- set sitename = site.get('ServerName', id) -%}
|
|
||||||
|
|
||||||
{%- set vals = {
|
|
||||||
'interfaces': site.get('interface', '*').split(),
|
|
||||||
'port': site.get('port', '80'),
|
|
||||||
|
|
||||||
'ServerName': sitename,
|
|
||||||
'ServerAlias': site.get('ServerAlias', ''),
|
|
||||||
|
|
||||||
'ServerAdmin': site.get('ServerAdmin', 'webmaster@{0}'.format(sitename)),
|
|
||||||
|
|
||||||
'LogLevel': site.get('LogLevel', 'warn'),
|
|
||||||
'ErrorLog': site.get('ErrorLog', '{0}/{1}-error.log'.format(map.logdir, sitename)),
|
|
||||||
'CustomLog': site.get('CustomLog', '{0}/{1}-access.log'.format(map.logdir, sitename)),
|
|
||||||
'LogFormat': site.get('LogFormat', '"%h %l %u %t \\\"%r\\\" %>s %b"'),
|
|
||||||
|
|
||||||
|
|
||||||
'DocumentRoot': site.get('DocumentRoot', '{0}/{1}'.format(map.wwwdir, sitename))
|
|
||||||
} -%}
|
|
||||||
|
|
||||||
<VirtualHost {% for intf in vals.interfaces %} {{intf}}:{{ vals.port }}{% endfor -%}>
|
|
||||||
ServerName {{ vals.ServerName }}
|
|
||||||
{% if site.get('ServerAlias') != False %}ServerAlias {{ vals.ServerAlias }}{% endif %}
|
|
||||||
{% if site.get('ServerAdmin') != False %}ServerAdmin {{ vals.ServerAdmin }}{% endif %}
|
|
||||||
|
|
||||||
{% if site.get('DocumentRoot') != False -%}DocumentRoot {{ vals.DocumentRoot }}{% endif %}
|
|
||||||
|
|
||||||
{% if site.get('LogLevel') != False -%}LogLevel {{ vals.LogLevel }}{% endif %}
|
|
||||||
{% if site.get('ErrorLog') != False -%}ErrorLog {{ vals.ErrorLog }}{% endif %}
|
|
||||||
{% if site.get('LogFormat') != False -%}LogFormat {{ vals.LogFormat }}{% endif %}
|
|
||||||
{% if site.get('CustomLog') != False -%}LogFormat {{ vals.LogFormat }} {{ sitename }}
|
|
||||||
CustomLog {{ vals.CustomLog }} {{ sitename }}{% endif %}
|
|
||||||
</VirtualHost>
|
|
@ -1,131 +0,0 @@
|
|||||||
#
|
|
||||||
# This file is managed by Salt! Do not edit by hand!
|
|
||||||
#
|
|
||||||
{# Define default values here so the template below can just focus on layout #}
|
|
||||||
{% from "apache/map.jinja" import apache with context %}
|
|
||||||
{% set sitename = site.get('ServerName', id) %}
|
|
||||||
{% set vals = {
|
|
||||||
'interfaces': site.get('interface', '*').split(),
|
|
||||||
'port': site.get('port', '80'),
|
|
||||||
|
|
||||||
'ServerName': sitename,
|
|
||||||
'ServerAlias': site.get('ServerAlias', ''),
|
|
||||||
|
|
||||||
'ServerAdmin': site.get('ServerAdmin', 'webmaster@{0}'.format(sitename)),
|
|
||||||
|
|
||||||
'UseCanonicalName': site.get('UseCanonicalName'),
|
|
||||||
|
|
||||||
'LogLevel': site.get('LogLevel', 'warn'),
|
|
||||||
'ErrorLog': site.get('ErrorLog', '{0}/{1}-error.log'.format(map.logdir, sitename)),
|
|
||||||
'LogFormat': site.get('LogFormat', '"%a %l %u %t \\"%r\\" %>s %O \\"%{Referer}i\\" \\"%{User-Agent}i\\""'),
|
|
||||||
'CustomLog': site.get('CustomLog', '{0}/{1}-access.log'.format(map.logdir, sitename)),
|
|
||||||
|
|
||||||
'ProxyRequests': site.get('ProxyRequests', 'Off'),
|
|
||||||
'ProxyPreserveHost': site.get('ProxyPreserveHost', 'On'),
|
|
||||||
'ProxyRoute': site.get('ProxyRoute', {}),
|
|
||||||
|
|
||||||
'Location': {
|
|
||||||
'Order': 'allow,deny',
|
|
||||||
'Allow': 'from all',
|
|
||||||
'Require': 'all granted',
|
|
||||||
},
|
|
||||||
'LocationMatch': {
|
|
||||||
'Order': 'allow,deny',
|
|
||||||
'Allow': 'from all',
|
|
||||||
'Require': 'all granted',
|
|
||||||
},
|
|
||||||
} %}
|
|
||||||
<VirtualHost {%- for intf in vals.interfaces %} {{intf}}:{{ vals.port }}{% endfor -%}>
|
|
||||||
ServerName {{ vals.ServerName }}
|
|
||||||
{% if site.get('ServerAlias') != False %}ServerAlias {{ vals.ServerAlias }}{% endif %}
|
|
||||||
{% if site.get('ServerAdmin') != False %}ServerAdmin {{ vals.ServerAdmin }}{% endif %}
|
|
||||||
{% if site.get('UseCanonicalName') %}UseCanonicalName {{ vals.UseCanonicalName }}{% endif %}
|
|
||||||
|
|
||||||
{% if site.get('LogLevel') != False %}LogLevel {{ vals.LogLevel }}{% endif %}
|
|
||||||
{% if site.get('ErrorLog') != False %}ErrorLog {{ vals.ErrorLog }}{% endif %}
|
|
||||||
{% if site.get('LogFormat') != False -%}LogFormat {{ vals.LogFormat }}{% endif %}
|
|
||||||
{% if site.get('CustomLog') != False -%}LogFormat {{ vals.LogFormat }} {{ sitename }}
|
|
||||||
CustomLog {{ vals.CustomLog }} {{ sitename }}{% endif %}
|
|
||||||
|
|
||||||
{% if site.get('SSLCertificateFile') %}SSLEngine on
|
|
||||||
SSLCertificateFile {{ site.SSLCertificateFile }}
|
|
||||||
{% if site.get('SSLCertificateKeyFile') %}SSLCertificateKeyFile {{ site.SSLCertificateKeyFile }}{% endif %}
|
|
||||||
{% if site.get('SSLCertificateChainFile') %}SSLCertificateChainFile {{ site.SSLCertificateChainFile}}{% endif %}
|
|
||||||
{% endif %}
|
|
||||||
{% if site.get('Rewrite') %}RewriteEngine on
|
|
||||||
{{ site.Rewrite }}
|
|
||||||
{% endif %}
|
|
||||||
{% if site.get('SSLProxyEngine') %}SSLProxyEngine {{ site.SSLProxyEngine }}{% endif %}
|
|
||||||
ProxyRequests {{ vals.ProxyRequests }}
|
|
||||||
ProxyPreserveHost {{ vals.ProxyPreserveHost }}
|
|
||||||
{% if site.get('ProxyErrorOverride') %}ProxyErrorOverride {{ site.ProxyErrorOverride }} {% endif %}
|
|
||||||
{% if site.get('ProxyErrorDir') %}ProxyPass /{{ site.ProxyErrorDir }}/ ! {% endif %}
|
|
||||||
{% for proxy, proxyargs in vals.ProxyRoute|dictsort|reverse %}
|
|
||||||
{% set proxyvals = {
|
|
||||||
'ProxyPassSource': proxyargs.get('ProxyPassSource', '/'),
|
|
||||||
'ProxyPassTarget': proxyargs.get('ProxyPassTarget', 'https://{0}'.format(sitename)),
|
|
||||||
'ProxyPassTargetOptions': proxyargs.get('ProxyPassTargetOptions', ''),
|
|
||||||
'ProxyPassReverseSource': proxyargs.get('ProxyPassReverseSource', '/'),
|
|
||||||
'ProxyPassReverseTarget': proxyargs.get('ProxyPassReverseTarget', proxyargs.get('ProxyPassTarget', 'https://{0}'.format(sitename))),
|
|
||||||
} %}
|
|
||||||
######### {{proxy}} #########
|
|
||||||
ProxyPass {{ proxyvals.ProxyPassSource }} {{ proxyvals.ProxyPassTarget }} {{ proxyvals.ProxyPassTargetOptions }}
|
|
||||||
ProxyPassReverse {{ proxyvals.ProxyPassReverseSource }} {{ proxyvals.ProxyPassReverseTarget }}
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
{%- for path, loc in site.get('Location', {}).items() %}
|
|
||||||
{%- set lvals = {
|
|
||||||
'Order': loc.get('Order', vals.Location.Order),
|
|
||||||
'Allow': loc.get('Allow', vals.Location.Allow),
|
|
||||||
'Require': loc.get('Require', vals.Location.Require),
|
|
||||||
'Dav': loc.get('Dav', False),
|
|
||||||
} %}
|
|
||||||
<Location "{{ path }}">
|
|
||||||
{% if apache.version == '2.4' %}
|
|
||||||
{%- if lvals.get('Require') != False %}Require {{lvals.Require}}{% endif %}
|
|
||||||
{% else %}
|
|
||||||
{%- if lvals.get('Order') != False %}Order {{ lvals.Order }}{% endif %}
|
|
||||||
{%- if lvals.get('Allow') != False %}Allow {{ lvals.Allow }}{% endif %}
|
|
||||||
{% endif %}
|
|
||||||
{%- if loc.get('Formula_Append') %} {{ loc.Formula_Append|indent(8) }} {% endif %}
|
|
||||||
</Location>
|
|
||||||
{% endfor %}
|
|
||||||
{%- for regpath, locmat in site.get('LocationMatch', {}).items() %}
|
|
||||||
{%- set lmvals = {
|
|
||||||
'Order': locmat.get('Order', vals.LocationMatch.Order),
|
|
||||||
'Allow': locmat.get('Allow', vals.LocationMatch.Allow),
|
|
||||||
'Require': locmat.get('Require', vals.LocationMatch.Require),
|
|
||||||
'Dav': locmat.get('Dav', False),
|
|
||||||
} %}
|
|
||||||
<LocationMatch "{{ regpath }}">
|
|
||||||
{% if apache.version == '2.4' %}
|
|
||||||
{%- if lmvals.get('Require') != False %}Require {{lmvals.Require}}{% endif %}
|
|
||||||
{% else %}
|
|
||||||
{%- if lmvals.get('Order') != False %}Order {{ lmvals.Order }}{% endif %}
|
|
||||||
{%- if lmvals.get('Allow') != False %}Allow {{ lmvals.Allow }}{% endif %}
|
|
||||||
{% endif %}
|
|
||||||
{%- if locmat.get('Formula_Append') %} {{ locmat.Formula_Append|indent(8) }} {% endif %}
|
|
||||||
</LocationMatch>
|
|
||||||
{% endfor %}
|
|
||||||
{%- for proxypath, prox in site.get('Proxy_control', {}).items() %}
|
|
||||||
{%- set proxvals = {
|
|
||||||
'AllowAll': prox.get('AllowAll', vals.AllowAll),
|
|
||||||
'AllowCountry': prox.get('AllowCountry', vals.AllowCountry),
|
|
||||||
'AllowIP': prox.get('AllowIP', vals.AllowIP),
|
|
||||||
} %}
|
|
||||||
<Proxy "{{ proxypath }}">
|
|
||||||
{%- if proxvals.get('AllowAll') != False %}
|
|
||||||
Require all granted
|
|
||||||
{%- else %}
|
|
||||||
{% if proxvals.get('AllowCountry') != False %}{% set country_list = proxvals.get('AllowCountry', {}) %}GeoIPEnable On
|
|
||||||
{% for every_country in country_list %}SetEnvIf GEOIP_COUNTRY_CODE {{ every_country }} AllowCountry
|
|
||||||
{% endfor %}Require env AllowCountry {% endif %}
|
|
||||||
{% if proxvals.get('AllowIP') is defined %} {% set ip_list = proxvals.get('AllowIP', {}) %}
|
|
||||||
Require ip {% for every_ip in ip_list %}{{ every_ip }} {% endfor %} {% endif %}
|
|
||||||
{%- endif %}
|
|
||||||
</Proxy>
|
|
||||||
{%- endfor %}
|
|
||||||
{% if site.get('Formula_Append') %}
|
|
||||||
{{ site.Formula_Append|indent(4) }}
|
|
||||||
{% endif %}
|
|
||||||
</VirtualHost>
|
|
@ -1,51 +0,0 @@
|
|||||||
#
|
|
||||||
# This file is managed by Salt! Do not edit by hand!
|
|
||||||
#
|
|
||||||
{# Define default values here so the template below can just focus on layout #}
|
|
||||||
{%- from "apache/map.jinja" import apache with context %}
|
|
||||||
{%- set sitename = site.get('ServerName', id) %}
|
|
||||||
|
|
||||||
{%- set vals = {
|
|
||||||
'interfaces': site.get('interface', '*').split(),
|
|
||||||
'port': site.get('port', '80'),
|
|
||||||
|
|
||||||
'ServerName': sitename,
|
|
||||||
'ServerAlias': site.get('ServerAlias', ''),
|
|
||||||
|
|
||||||
'ServerAdmin': site.get('ServerAdmin', 'webmaster@{0}'.format(sitename)),
|
|
||||||
|
|
||||||
'UseCanonicalName': site.get('UseCanonicalName'),
|
|
||||||
|
|
||||||
'LogLevel': site.get('LogLevel', 'warn'),
|
|
||||||
'ErrorLog': site.get('ErrorLog', '{0}/{1}-error.log'.format(map.logdir, sitename)),
|
|
||||||
'LogFormat': site.get('LogFormat', '"%h %l %u %t \\\"%r\\\" %>s %O"'),
|
|
||||||
'CustomLog': site.get('CustomLog', '{0}/{1}-access.log'.format(map.logdir, sitename)),
|
|
||||||
|
|
||||||
'RedirectSource': site.get('RedirectSource', '/'),
|
|
||||||
'RedirectTarget': site.get('RedirectTarget', 'https://{0}/'.format(sitename)),
|
|
||||||
} %}
|
|
||||||
|
|
||||||
<VirtualHost {%- for intf in vals.interfaces %} {{intf}}:{{ vals.port }}{% endfor -%}>
|
|
||||||
ServerName {{ vals.ServerName }}
|
|
||||||
{% if site.get('ServerAlias') != False %}ServerAlias {{ vals.ServerAlias }}{% endif %}
|
|
||||||
|
|
||||||
{% if site.get('ServerAdmin') != False %}ServerAdmin {{ vals.ServerAdmin }}{% endif %}
|
|
||||||
|
|
||||||
{% if site.get('UseCanonicalName') %}UseCanonicalName {{ vals.UseCanonicalName }}{% endif %}
|
|
||||||
|
|
||||||
{% if site.get('LogLevel') != False %}LogLevel {{ vals.LogLevel }}{% endif %}
|
|
||||||
{% if site.get('ErrorLog') != False %}ErrorLog {{ vals.ErrorLog }}{% endif %}
|
|
||||||
{% if site.get('LogFormat') != False -%}LogFormat {{ vals.LogFormat }}{% endif %}
|
|
||||||
{% if site.get('CustomLog') != False -%}LogFormat {{ vals.LogFormat }} {{ sitename }}
|
|
||||||
CustomLog {{ vals.CustomLog }} {{ sitename }}{% endif %}
|
|
||||||
|
|
||||||
{% if site.get('RedirectMatch') %}
|
|
||||||
RedirectMatch {{ vals.RedirectSource }} {{ vals.RedirectTarget }}
|
|
||||||
{% else %}
|
|
||||||
Redirect {{ vals.RedirectSource }} {{ vals.RedirectTarget }}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if site.get('Formula_Append') %}
|
|
||||||
{{ site.Formula_Append|indent(4) }}
|
|
||||||
{% endif %}
|
|
||||||
</VirtualHost>
|
|
@ -1,65 +0,0 @@
|
|||||||
{% from "apache/map.jinja" import apache with context %}
|
|
||||||
|
|
||||||
include:
|
|
||||||
- apache
|
|
||||||
|
|
||||||
{% for id, site in salt['pillar.get']('apache:sites', {}).items() %}
|
|
||||||
{% set documentroot = site.get('DocumentRoot', '{0}/{1}'.format(apache.wwwdir, site.get('ServerName', id))) %}
|
|
||||||
|
|
||||||
apache_vhosts_{{ id }}:
|
|
||||||
file.managed:
|
|
||||||
- name: {{ apache.vhostdir }}/{{ id }}{{ apache.confext }}
|
|
||||||
- source: {{ site.get('template_file', 'salt://apache/vhosts/standard.tmpl') }}
|
|
||||||
- template: {{ site.get('template_engine', 'jinja') }}
|
|
||||||
- context:
|
|
||||||
id: {{ id|json }}
|
|
||||||
site: {{ site|json }}
|
|
||||||
map: {{ apache|json }}
|
|
||||||
- require:
|
|
||||||
- pkg: apache
|
|
||||||
- watch_in:
|
|
||||||
- module: apache-reload
|
|
||||||
- require_in:
|
|
||||||
- module: apache-restart
|
|
||||||
- module: apache-reload
|
|
||||||
- service: apache
|
|
||||||
|
|
||||||
{% if site.get('DocumentRoot') != False %}
|
|
||||||
{{ id }}-documentroot:
|
|
||||||
file.directory:
|
|
||||||
- name: {{ documentroot }}
|
|
||||||
- makedirs: True
|
|
||||||
- user: {{ site.get('DocumentRootUser', apache.get('document_root_user'))|json }}
|
|
||||||
- group: {{ site.get('DocumentRootGroup', apache.get('document_root_group'))|json }}
|
|
||||||
- allow_symlink: True
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if grains.os_family == 'Debian' %}
|
|
||||||
{% if site.get('enabled', True) %}
|
|
||||||
a2ensite {{ id }}{{ apache.confext }}:
|
|
||||||
cmd.run:
|
|
||||||
- unless: test -f /etc/apache2/sites-enabled/{{ id }}{{ apache.confext }}
|
|
||||||
- require:
|
|
||||||
- file: /etc/apache2/sites-available/{{ id }}{{ apache.confext }}
|
|
||||||
- watch_in:
|
|
||||||
- module: apache-reload
|
|
||||||
- require_in:
|
|
||||||
- module: apache-restart
|
|
||||||
- module: apache-reload
|
|
||||||
- service: apache
|
|
||||||
{% else %}
|
|
||||||
a2dissite {{ id }}{{ apache.confext }}:
|
|
||||||
cmd.run:
|
|
||||||
- onlyif: test -f /etc/apache2/sites-enabled/{{ id }}{{ apache.confext }}
|
|
||||||
- require:
|
|
||||||
- file: /etc/apache2/sites-available/{{ id }}{{ apache.confext }}
|
|
||||||
- watch_in:
|
|
||||||
- module: apache-reload
|
|
||||||
- require_in:
|
|
||||||
- module: apache-restart
|
|
||||||
- module: apache-reload
|
|
||||||
- service: apache
|
|
||||||
{% endif %}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% endfor %}
|
|
@ -1,136 +0,0 @@
|
|||||||
#
|
|
||||||
# This file is managed by Salt! Do not edit by hand!
|
|
||||||
#
|
|
||||||
{# Define default values here so the template below can just focus on layout #}
|
|
||||||
{%- set sitename = site.get('ServerName', id) -%}
|
|
||||||
|
|
||||||
{%- set vals = {
|
|
||||||
'interfaces': site.get('interface', '*').split(),
|
|
||||||
'port': site.get('port', '80'),
|
|
||||||
|
|
||||||
'ServerName': sitename,
|
|
||||||
'ServerAlias': site.get('ServerAlias', ''),
|
|
||||||
|
|
||||||
'ServerAdmin': site.get('ServerAdmin', 'webmaster@{0}'.format(sitename)),
|
|
||||||
|
|
||||||
'DirectoryIndex': site.get('DirectoryIndex'),
|
|
||||||
'UseCanonicalName': site.get('UseCanonicalName'),
|
|
||||||
'AllowEncodedSlashes': site.get('AllowEncodedSlashes', 'Off'),
|
|
||||||
|
|
||||||
'LogLevel': site.get('LogLevel', 'warn'),
|
|
||||||
'ErrorLog': site.get('ErrorLog', '{0}/{1}-error.log'.format(map.logdir, sitename)),
|
|
||||||
'LogFormat': site.get('LogFormat', '"%h %l %u %t \\\"%r\\\" %>s"'),
|
|
||||||
'CustomLog': site.get('CustomLog', '{0}/{1}-access.log'.format(map.logdir, sitename)),
|
|
||||||
|
|
||||||
'DocumentRoot': site.get('DocumentRoot', '{0}/{1}'.format(map.wwwdir, sitename)),
|
|
||||||
'VirtualDocumentRoot': site.get('VirtualDocumentRoot'),
|
|
||||||
|
|
||||||
'Timeout': site.get('Timeout'),
|
|
||||||
'LimitRequestFields': site.get('LimitRequestFields'),
|
|
||||||
|
|
||||||
'Directory_default': site.get('DocumentRoot', '{0}/{1}'.format(map.wwwdir, sitename)),
|
|
||||||
'Directory': {
|
|
||||||
'Options': '-Indexes +FollowSymLinks',
|
|
||||||
'Order': 'allow,deny',
|
|
||||||
'Allow': 'from all',
|
|
||||||
'Require': 'all granted',
|
|
||||||
'AllowOverride': 'None',
|
|
||||||
},
|
|
||||||
'Location': {
|
|
||||||
'Order': 'allow,deny',
|
|
||||||
'Allow': 'from all',
|
|
||||||
'Require': 'all granted',
|
|
||||||
},
|
|
||||||
} -%}
|
|
||||||
|
|
||||||
<VirtualHost {% for intf in vals.interfaces %} {{intf}}:{{ vals.port }}{% endfor -%}>
|
|
||||||
ServerName {{ vals.ServerName }}
|
|
||||||
{% if site.get('ServerAlias') != False %}ServerAlias {{ vals.ServerAlias }}{% endif %}
|
|
||||||
|
|
||||||
{% if site.get('ServerAdmin') != False %}ServerAdmin {{ vals.ServerAdmin }}{% endif %}
|
|
||||||
|
|
||||||
{% if site.get('DirectoryIndex') -%}DirectoryIndex {{ vals.DirectoryIndex }}{% endif %}
|
|
||||||
{% if site.get('UseCanonicalName') -%}UseCanonicalName {{ vals.UseCanonicalName }}{% endif %}
|
|
||||||
{% if site.get('AllowEncodedSlashes') != False -%}AllowEncodedSlashes {{ vals.AllowEncodedSlashes }}{% endif %}
|
|
||||||
|
|
||||||
{% if site.get('LogLevel') != False -%}LogLevel {{ vals.LogLevel }}{% endif %}
|
|
||||||
{% if site.get('ErrorLog') != False -%}ErrorLog {{ vals.ErrorLog }}{% endif %}
|
|
||||||
{% if site.get('LogFormat') != False -%}LogFormat {{ vals.LogFormat }}{% endif %}
|
|
||||||
{% if site.get('CustomLog') != False -%}CustomLog {{ vals.CustomLog }} {{ vals.LogFormat }}{% endif %}
|
|
||||||
|
|
||||||
{% if site.get('DocumentRoot') != False -%}DocumentRoot {{ vals.DocumentRoot }}{% endif %}
|
|
||||||
{% if site.get('VirtualDocumentRoot') -%}VirtualDocumentRoot {{ vals.VirtualDocumentRoot }}{% endif %}
|
|
||||||
|
|
||||||
{% if site.get('Timeout') != False and site.get('Timeout') != None %}Timeout {{ vals.Timeout }}{% endif %}
|
|
||||||
{% if site.get('LimitRequestFields') %}LimitRequestFields {{ vals.LimitRequestFields }}{% endif %}
|
|
||||||
|
|
||||||
{% if site.get('SSLCertificateFile') %}SSLEngine on
|
|
||||||
SSLCertificateFile {{ site.SSLCertificateFile }}
|
|
||||||
{% if site.get('SSLCertificateKeyFile') %}SSLCertificateKeyFile {{ site.SSLCertificateKeyFile }}{% endif %}
|
|
||||||
{% if site.get('SSLCertificateChainFile') %}SSLCertificateChainFile {{ site.SSLCertificateChainFile}}{% endif %}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if site.get('Rewrite') %}RewriteEngine on
|
|
||||||
{{ site.Rewrite }}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{%- for loc, path in site.get('Alias', {}).items() %}
|
|
||||||
Alias {{ loc }} {{ path }}
|
|
||||||
{%- endfor %}
|
|
||||||
|
|
||||||
{%- for path, dir in site.get('Directory', {}).items() -%}
|
|
||||||
{%- set dvals = {
|
|
||||||
'Options': dir.get('Options', vals.Directory.Options),
|
|
||||||
'Order': dir.get('Order', vals.Directory.Order),
|
|
||||||
'Allow': dir.get('Allow', vals.Directory.Allow),
|
|
||||||
'Require': dir.get('Require', vals.Directory.Require),
|
|
||||||
'AllowOverride': dir.get('AllowOverride', vals.Directory.AllowOverride),
|
|
||||||
'Dav': dir.get('Dav', False),
|
|
||||||
} %}
|
|
||||||
|
|
||||||
{%- if path == 'default' %}{% set path = vals.Directory_default %}{% endif %}
|
|
||||||
|
|
||||||
<Directory "{{ path }}">
|
|
||||||
{% if dvals.get('Options') != False %}Options {{ dvals.Options }}{% endif %}
|
|
||||||
{% if map.version == '2.4' %}
|
|
||||||
{% if dvals.get('Require') != False %}Require {{dvals.Require}}{% endif %}
|
|
||||||
{% else %}
|
|
||||||
{% if dvals.get('Order') != False %}Order {{ dvals.Order }}{% endif %}
|
|
||||||
{% if dvals.get('Allow') != False %}Allow {{ dvals.Allow }}{% endif %}
|
|
||||||
{% endif %}
|
|
||||||
{% if dvals.get('AllowOverride') != False %}AllowOverride {{ dvals.AllowOverride }}{% endif %}
|
|
||||||
{% if dvals.get('Dav') != False %}Dav On{% endif %}
|
|
||||||
|
|
||||||
{% if dir.get('Formula_Append') %}
|
|
||||||
{{ dir.Formula_Append|indent(8) }}
|
|
||||||
{% endif %}
|
|
||||||
</Directory>
|
|
||||||
{%- endfor %}
|
|
||||||
|
|
||||||
{%- for path, loc in site.get('Location', {}).items() %}
|
|
||||||
{%- set lvals = {
|
|
||||||
'Order': loc.get('Order', vals.Location.Order),
|
|
||||||
'Allow': loc.get('Allow', vals.Location.Allow),
|
|
||||||
'Require': loc.get('Require', vals.Location.Require),
|
|
||||||
'Dav': loc.get('Dav', False),
|
|
||||||
} %}
|
|
||||||
|
|
||||||
<Location "{{ path }}">
|
|
||||||
{% if map.version == '2.4' %}
|
|
||||||
{%- if lvals.get('Require') != False %}Require {{lvals.Require}}{% endif %}
|
|
||||||
{% else %}
|
|
||||||
{%- if lvals.get('Order') != False %}Order {{ lvals.Order }}{% endif %}
|
|
||||||
{%- if lvals.get('Allow') != False %}Allow {{ lvals.Allow }}{% endif %}
|
|
||||||
{% endif %}
|
|
||||||
{%- if lvals.get('Dav') != False %}Dav On{% endif %}
|
|
||||||
|
|
||||||
{%- if loc.get('Formula_Append') %}
|
|
||||||
{{ loc.Formula_Append|indent(8) }}
|
|
||||||
{% endif %}
|
|
||||||
</Location>
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
{%- if site.get('Formula_Append') %}
|
|
||||||
{{ site.Formula_Append|indent(4) }}
|
|
||||||
{% endif %}
|
|
||||||
</VirtualHost>
|
|
6
apache/vhosts/vhost.conf.jinja
Normal file
6
apache/vhosts/vhost.conf.jinja
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{% from "apache/lib.sls" import container_output with context %}
|
||||||
|
#
|
||||||
|
# This file is managed by Salt! Do not edit by hand!
|
||||||
|
#
|
||||||
|
|
||||||
|
{{ container_output('VirtualHost', vhost_data, col=0, default_directives = []) }}
|
110
apache/vhosts/vhost.sls
Normal file
110
apache/vhosts/vhost.sls
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
{% from "apache/map.jinja" import apache with context %}
|
||||||
|
{% import_yaml "apache/hardening-values.yaml" as hardening_values %}
|
||||||
|
|
||||||
|
include:
|
||||||
|
- apache
|
||||||
|
|
||||||
|
{% set vhosts = salt['pillar.get']('apache:VirtualHost', {}) %}
|
||||||
|
|
||||||
|
{% for virtual_name, vhost in vhosts.items() %}
|
||||||
|
|
||||||
|
{% set vhost_server_name = salt['apache_directives.get_directive_single_value'](
|
||||||
|
'ServerName',
|
||||||
|
vhost.get('directives'),
|
||||||
|
default=virtual_name) %}
|
||||||
|
{% set vhost = salt['apache_directives.enforce_directive_value'](directive='ServerName',
|
||||||
|
enforced_directive_data={'value': vhost_server_name,
|
||||||
|
'add_if_absent': True},
|
||||||
|
container_name='VirtualHost',
|
||||||
|
container_data=vhost) %}
|
||||||
|
{% set default_documentroot = '{0}/{1}'.format(apache.wwwdir, vhost_server_name) %}
|
||||||
|
{% set documentroot = salt['apache_directives.get_directive_single_value'](
|
||||||
|
'DocumentRoot',
|
||||||
|
vhost.get('directives'),
|
||||||
|
default=default_documentroot) %}
|
||||||
|
{% set vhost = salt['apache_directives.set_vhost_logging_directives'](vhost,
|
||||||
|
vhost_server_name,
|
||||||
|
apache.logdir) %}
|
||||||
|
|
||||||
|
# enforce directives values #
|
||||||
|
|
||||||
|
{% for directive, directive_data in hardening_values.enforced_directives.items() %}
|
||||||
|
{% if 'add_if_absent' in directive_data %}
|
||||||
|
{% do directive_data.update({'add_if_absent': False}) %}
|
||||||
|
{% endif %}
|
||||||
|
{% set vhost = salt['apache_directives.enforce_directive_value'](directive,
|
||||||
|
directive_data,
|
||||||
|
container_name='VirtualHost',
|
||||||
|
container_data=vhost) %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
# merge vhost config with hardened sections #
|
||||||
|
{% set vhost = salt['apache_directives.enforce_security_directives_into_containers'](
|
||||||
|
vhost,
|
||||||
|
hardening_values.enforced_containers,
|
||||||
|
add_container=False ) %}
|
||||||
|
|
||||||
|
# remove containers #
|
||||||
|
{% for container_name_to_remove, items_names in hardening_values.containers_to_remove.items() %}
|
||||||
|
{% for item_name in items_names %}
|
||||||
|
{% set vhost = salt['apache_directives.remove_container'](
|
||||||
|
vhost,
|
||||||
|
container_name_to_remove,
|
||||||
|
item_name) %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
# add supplemental security directives in vhost configuration #
|
||||||
|
{% for d_directive in hardening_values.vhost_supplemental_directives %}
|
||||||
|
{% for directive, value in d_directive.items() %}
|
||||||
|
{% set vhost = salt['apache_directives.append_to_container_directives'](
|
||||||
|
directive,
|
||||||
|
value,
|
||||||
|
vhost) %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{% if vhost.get('absent', False) %}
|
||||||
|
{{ vhost_server_name }}:
|
||||||
|
file.absent:
|
||||||
|
- name: {{ apache.vhostdir }}/{{ vhost_server_name }}{{ apache.confext }}
|
||||||
|
- require:
|
||||||
|
- pkg: apache
|
||||||
|
- watch_in:
|
||||||
|
- module: apache-reload
|
||||||
|
- require_in:
|
||||||
|
- module: apache-restart
|
||||||
|
- module: apache-reload
|
||||||
|
- service: apache
|
||||||
|
|
||||||
|
{% else %}
|
||||||
|
|
||||||
|
|
||||||
|
{{ vhost_server_name }}:
|
||||||
|
file.managed:
|
||||||
|
- name: {{ apache.vhostdir }}/{{ vhost_server_name }}{{ apache.confext }}
|
||||||
|
- source: 'salt://apache/vhosts/vhost.conf.jinja'
|
||||||
|
- template: 'jinja'
|
||||||
|
- user: root
|
||||||
|
- group: root
|
||||||
|
- mode: 644
|
||||||
|
- context:
|
||||||
|
vhost_data: {{ vhost|json }}
|
||||||
|
- require:
|
||||||
|
- pkg: apache
|
||||||
|
- watch_in:
|
||||||
|
- module: apache-reload
|
||||||
|
- require_in:
|
||||||
|
- module: apache-restart
|
||||||
|
- module: apache-reload
|
||||||
|
- service: apache
|
||||||
|
|
||||||
|
|
||||||
|
{{ documentroot }}-documentroot:
|
||||||
|
file.directory:
|
||||||
|
- name: {{ documentroot }}
|
||||||
|
- makedirs: True
|
||||||
|
- allow_symlink: True
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
371
pillar.example
371
pillar.example
@ -1,371 +0,0 @@
|
|||||||
# ``apache`` formula configuration:
|
|
||||||
apache:
|
|
||||||
|
|
||||||
# By default apache restart/reload states run (false skips)
|
|
||||||
manage_service_states: True
|
|
||||||
|
|
||||||
# lookup section overrides ``map.jinja`` values
|
|
||||||
lookup:
|
|
||||||
server: apache2
|
|
||||||
service: apache2
|
|
||||||
user: some_system_user
|
|
||||||
group: some_system_group
|
|
||||||
|
|
||||||
vhostdir: /etc/apache2/sites-available
|
|
||||||
confdir: /etc/apache2/conf.d
|
|
||||||
confext: .conf
|
|
||||||
logdir: /var/log/apache2
|
|
||||||
wwwdir: /srv/apache2
|
|
||||||
|
|
||||||
# apache version (generally '2.2' or '2.4')
|
|
||||||
version: '2.2'
|
|
||||||
|
|
||||||
# ``apache.mod_wsgi`` formula additional configuration:
|
|
||||||
mod_wsgi: mod_wsgi
|
|
||||||
|
|
||||||
# Default value for AddDefaultCharset in RedHat configuration
|
|
||||||
default_charset: 'UTF-8'
|
|
||||||
|
|
||||||
# Should we enforce DocumentRoot user/group?
|
|
||||||
# Default: do not enforce
|
|
||||||
document_root_user: www-data # Force user if specified, leave it default if not
|
|
||||||
document_root_group: null # Do not enforce group
|
|
||||||
|
|
||||||
global:
|
|
||||||
# global apache directives
|
|
||||||
AllowEncodedSlashes: 'On'
|
|
||||||
|
|
||||||
|
|
||||||
name_virtual_hosts:
|
|
||||||
- interface: '*'
|
|
||||||
port: 80
|
|
||||||
- interface: '*'
|
|
||||||
port: 443
|
|
||||||
|
|
||||||
# ``apache.vhosts`` formula additional configuration:
|
|
||||||
sites:
|
|
||||||
example.net:
|
|
||||||
template_file: salt://apache/vhosts/minimal.tmpl
|
|
||||||
|
|
||||||
example.com: # must be unique; used as an ID declaration in Salt.
|
|
||||||
enabled: True
|
|
||||||
template_file: salt://apache/vhosts/standard.tmpl # or minimal.tmpl or redirect.tmpl or proxy.tmpl
|
|
||||||
|
|
||||||
####################### DEFAULT VALUES BELOW ############################
|
|
||||||
# NOTE: the values below are simply default settings that *can* be
|
|
||||||
# overridden and are not required in order to use this formula to create
|
|
||||||
# vhost entries.
|
|
||||||
#
|
|
||||||
# Do not copy the values below into your Pillar unless you intend to
|
|
||||||
# modify these vaules.
|
|
||||||
####################### DEFAULT VALUES BELOW ############################
|
|
||||||
template_engine: jinja
|
|
||||||
|
|
||||||
interface: '*'
|
|
||||||
port: '80'
|
|
||||||
|
|
||||||
exclude_listen_directive: True # Do not add a Listen directive in httpd.conf
|
|
||||||
|
|
||||||
ServerName: example.com # uses the unique ID above unless specified
|
|
||||||
#ServerAlias: www.example.com # Do not add ServerAlias unless defined
|
|
||||||
|
|
||||||
ServerAdmin: webmaster@example.com
|
|
||||||
|
|
||||||
LogLevel: warn
|
|
||||||
ErrorLog: /path/to/logs/example.com-error.log # E.g.: /var/log/apache2/example.com-error.log
|
|
||||||
CustomLog: /path/to/logs/example.com-access.log # E.g.: /var/log/apache2/example.com-access.log
|
|
||||||
|
|
||||||
DocumentRoot: /path/to/www/dir/example.com # E.g., /var/www/example.com
|
|
||||||
DocumentRootUser: null # do not enforce user, defaults to lookup:document_root_user
|
|
||||||
DocumentRootGroup: www-data # Force group, defaults to lookup:document_root_group
|
|
||||||
|
|
||||||
SSLCertificateFile: /etc/ssl/mycert.pem # if ssl is desired
|
|
||||||
SSLCertificateKeyFile: /etc/ssl/mycert.pem.key # if key for cert is needed or in an extra file
|
|
||||||
SSLCertificateChainFile: /etc/ssl/mycert.chain.pem # if you require a chain of server certificates file
|
|
||||||
|
|
||||||
Directory:
|
|
||||||
# "default" is a special case; uses DocumentRoot value
|
|
||||||
# E.g.: /var/www/example.com
|
|
||||||
default:
|
|
||||||
Options: -Indexes +FollowSymLinks
|
|
||||||
Order: allow,deny # For Apache < 2.4
|
|
||||||
Allow: from all # For apache < 2.4
|
|
||||||
Require: all granted # For apache > 2.4.
|
|
||||||
AllowOverride: None
|
|
||||||
Formula_Append: |
|
|
||||||
Additional config as a
|
|
||||||
multi-line string here
|
|
||||||
|
|
||||||
redirectmatch.com:
|
|
||||||
# Use RedirectMatch Directive https://httpd.apache.org/docs/2.4/fr/mod/mod_alias.html#redirectmatch
|
|
||||||
# Require module mod_alias
|
|
||||||
enabled: True
|
|
||||||
template_file: salt://apache/vhosts/redirect.tmpl
|
|
||||||
ServerName: www.redirectmatch.com
|
|
||||||
ServerAlias: www.redirectmatch.com
|
|
||||||
RedirectMatch: true
|
|
||||||
RedirectSource: '^/$'
|
|
||||||
RedirectTarget: '/subdirectory'
|
|
||||||
DocumentRoot: /var/www/html/
|
|
||||||
ErrorLog: ${APACHE_LOG_DIR}/error.log
|
|
||||||
CustomLog: ${APACHE_LOG_DIR}/access.log
|
|
||||||
|
|
||||||
80-proxyexample.com:
|
|
||||||
template_file: salt://apache/vhosts/redirect.tmpl
|
|
||||||
ServerName: www.proxyexample.com
|
|
||||||
ServerAlias: www.proxyexample.com
|
|
||||||
RedirectSource: '/'
|
|
||||||
RedirectTarget: 'https://www.proxyexample.com/'
|
|
||||||
DocumentRoot: /var/www/proxy
|
|
||||||
|
|
||||||
443-proxyexample.com:
|
|
||||||
template_file: salt://apache/vhosts/proxy.tmpl
|
|
||||||
ServerName: www.proxyexample.com
|
|
||||||
ServerAlias: www.proxyexample.com
|
|
||||||
interface: '*'
|
|
||||||
port: '443'
|
|
||||||
DocumentRoot: /var/www/proxy
|
|
||||||
|
|
||||||
Rewrite: |
|
|
||||||
RewriteRule ^/webmail$ /webmail/ [R]
|
|
||||||
RewriteRule ^/webmail(.*) http://mail.example.com$1 [P,L]
|
|
||||||
RewriteRule ^/vicescws(.*) http://svc.example.com:92$1 [P,L]
|
|
||||||
|
|
||||||
SSLCertificateFile: /etc/httpd/ssl/example.com.crt
|
|
||||||
SSLCertificateKeyFile: /etc/httpd/ssl/example.com.key
|
|
||||||
SSLCertificateChainFile: /etc/httpd/ssl/example.com.cer
|
|
||||||
|
|
||||||
SSLCertificateFile_content: |
|
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIICUTCCAfugAwIBAgIBADANBgkqhkiG9w0BAQQFADBXMQswCQYDVQQGEwJDTjEL
|
|
||||||
MAkGA1UECBMCUE4xCzAJBgNVBAcTAkNOMQswCQYDVQQKEwJPTjELMAkGA1UECxMC
|
|
||||||
VU4xFDASBgNVBAMTC0hlcm9uZyBZYW5nMB4XDTA1MDcxNTIxMTk0N1oXDTA1MDgx
|
|
||||||
NDIxMTk0N1owVzELMAkGA1UEBhMCQ04xCzAJBgNVBAgTAlBOMQswCQYDVQQHEwJD
|
|
||||||
TjELMAkGA1UEChMCT04xCzAJBgNVBAsTAlVOMRQwEgYDVQQDEwtIZXJvbmcgWWFu
|
|
||||||
ZzBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQCp5hnG7ogBhtlynpOS21cBewKE/B7j
|
|
||||||
V14qeyslnr26xZUsSVko36ZnhiaO/zbMOoRcKK9vEcgMtcLFuQTWDl3RAgMBAAGj
|
|
||||||
gbEwga4wHQYDVR0OBBYEFFXI70krXeQDxZgbaCQoR4jUDncEMH8GA1UdIwR4MHaA
|
|
||||||
FFXI70krXeQDxZgbaCQoR4jUDncEoVukWTBXMQswCQYDVQQGEwJDTjELMAkGA1UE
|
|
||||||
CBMCUE4xCzAJBgNVBAcTAkNOMQswCQYDVQQKEwJPTjELMAkGA1UECxMCVU4xFDAS
|
|
||||||
BgNVBAMTC0hlcm9uZyBZYW5nggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEE
|
|
||||||
BQADQQA/ugzBrjjK9jcWnDVfGHlk3icNRq0oV7Ri32z/+HQX67aRfgZu7KWdI+Ju
|
|
||||||
Wm7DCfrPNGVwFWUQOmsPue9rZBgO
|
|
||||||
-----END CERTIFICATE-----
|
|
||||||
|
|
||||||
SSLCertificateKeyFile_content: |
|
|
||||||
-----BEGIN PRIVATE KEY-----
|
|
||||||
MIICUTCCAfugAwIBAgIBADANBgkqhkiG9w0BAQQFADBXMQswCQYDVQQGEwJDTjEL
|
|
||||||
MAkGA1UECBMCUE4xCzAJBgNVBAcTAkNOMQswCQYDVQQKEwJPTjELMAkGA1UECxMC
|
|
||||||
VU4xFDASBgNVBAMTC0hlcm9uZyBZYW5nMB4XDTA1MDcxNTIxMTk0N1oXDTA1MDgx
|
|
||||||
NDIxMTk0N1owVzELMAkGA1UEBhMCQ04xCzAJBgNVBAgTAlBOMQswCQYDVQQHEwJD
|
|
||||||
TjELMAkGA1UEChMCT04xCzAJBgNVBAsTAlVOMRQwEgYDVQQDEwtIZXJvbmcgWWFu
|
|
||||||
ZzBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQCp5hnG7ogBhtlynpOS21cBewKE/B7j
|
|
||||||
V14qeyslnr26xZUsSVko36ZnhiaO/zbMOoRcKK9vEcgMtcLFuQTWDl3RAgMBAAGj
|
|
||||||
gbEwga4wHQYDVR0OBBYEFFXI70krXeQDxZgbaCQoR4jUDncEMH8GA1UdIwR4MHaA
|
|
||||||
FFXI70krXeQDxZgbaCQoR4jUDncEoVukWTBXMQswCQYDVQQGEwJDTjELMAkGA1UE
|
|
||||||
CBMCUE4xCzAJBgNVBAcTAkNOMQswCQYDVQQKEwJPTjELMAkGA1UECxMCVU4xFDAS
|
|
||||||
BgNVBAMTC0hlcm9uZyBZYW5nggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEE
|
|
||||||
BQADQQA/ugzBrjjK9jcWnDVfGHlk3icNRq0oV7Ri32z/+HQX67aRfgZu7KWdI+Ju
|
|
||||||
Wm7DCfrPNGVwFWUQOmsPue9rZBgO
|
|
||||||
-----END PRIVATE KEY-----
|
|
||||||
|
|
||||||
SSLCertificateChainFile_content: |
|
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIICUTCCAfugAwIBAgIBADANBgkqhkiG9w0BAQQFADBXMQswCQYDVQQGEwJDTjEL
|
|
||||||
MAkGA1UECBMCUE4xCzAJBgNVBAcTAkNOMQswCQYDVQQKEwJPTjELMAkGA1UECxMC
|
|
||||||
VU4xFDASBgNVBAMTC0hlcm9uZyBZYW5nMB4XDTA1MDcxNTIxMTk0N1oXDTA1MDgx
|
|
||||||
NDIxMTk0N1owVzELMAkGA1UEBhMCQ04xCzAJBgNVBAgTAlBOMQswCQYDVQQHEwJD
|
|
||||||
TjELMAkGA1UEChMCT04xCzAJBgNVBAsTAlVOMRQwEgYDVQQDEwtIZXJvbmcgWWFu
|
|
||||||
ZzBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQCp5hnG7ogBhtlynpOS21cBewKE/B7j
|
|
||||||
V14qeyslnr26xZUsSVko36ZnhiaO/zbMOoRcKK9vEcgMtcLFuQTWDl3RAgMBAAGj
|
|
||||||
gbEwga4wHQYDVR0OBBYEFFXI70krXeQDxZgbaCQoR4jUDncEMH8GA1UdIwR4MHaA
|
|
||||||
FFXI70krXeQDxZgbaCQoR4jUDncEoVukWTBXMQswCQYDVQQGEwJDTjELMAkGA1UE
|
|
||||||
CBMCUE4xCzAJBgNVBAcTAkNOMQswCQYDVQQKEwJPTjELMAkGA1UECxMCVU4xFDAS
|
|
||||||
BgNVBAMTC0hlcm9uZyBZYW5nggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEE
|
|
||||||
BQADQQA/ugzBrjjK9jcWnDVfGHlk3icNRq0oV7Ri32z/+HQX67aRfgZu7KWdI+Ju
|
|
||||||
Wm7DCfrPNGVwFWUQOmsPue9rZBgO
|
|
||||||
-----END CERTIFICATE-----
|
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIICUTCCAfugAwIBAgIBADANBgkqhkiG9w0BAQQFADBXMQswCQYDVQQGEwJDTjEL
|
|
||||||
MAkGA1UECBMCUE4xCzAJBgNVBAcTAkNOMQswCQYDVQQKEwJPTjELMAkGA1UECxMC
|
|
||||||
VU4xFDASBgNVBAMTC0hlcm9uZyBZYW5nMB4XDTA1MDcxNTIxMTk0N1oXDTA1MDgx
|
|
||||||
NDIxMTk0N1owVzELMAkGA1UEBhMCQ04xCzAJBgNVBAgTAlBOMQswCQYDVQQHEwJD
|
|
||||||
TjELMAkGA1UEChMCT04xCzAJBgNVBAsTAlVOMRQwEgYDVQQDEwtIZXJvbmcgWWFu
|
|
||||||
ZzBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQCp5hnG7ogBhtlynpOS21cBewKE/B7j
|
|
||||||
V14qeyslnr26xZUsSVko36ZnhiaO/zbMOoRcKK9vEcgMtcLFuQTWDl3RAgMBAAGj
|
|
||||||
gbEwga4wHQYDVR0OBBYEFFXI70krXeQDxZgbaCQoR4jUDncEMH8GA1UdIwR4MHaA
|
|
||||||
FFXI70krXeQDxZgbaCQoR4jUDncEoVukWTBXMQswCQYDVQQGEwJDTjELMAkGA1UE
|
|
||||||
CBMCUE4xCzAJBgNVBAcTAkNOMQswCQYDVQQKEwJPTjELMAkGA1UECxMCVU4xFDAS
|
|
||||||
BgNVBAMTC0hlcm9uZyBZYW5nggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEE
|
|
||||||
BQADQQA/ugzBrjjK9jcWnDVfGHlk3icNRq0oV7Ri32z/+HQX67aRfgZu7KWdI+Ju
|
|
||||||
Wm7DCfrPNGVwFWUQOmsPue9rZBgO
|
|
||||||
-----END CERTIFICATE-----
|
|
||||||
|
|
||||||
ProxyRequests: 'Off'
|
|
||||||
ProxyPreserveHost: 'On'
|
|
||||||
|
|
||||||
ProxyRoute:
|
|
||||||
example prod proxy route:
|
|
||||||
ProxyPassSource: '/'
|
|
||||||
ProxyPassTarget: 'http://prod.example.com:85/'
|
|
||||||
ProxyPassTargetOptions: 'connectiontimeout=10 timeout=90'
|
|
||||||
ProxyPassReverseSource: '/'
|
|
||||||
ProxyPassReverseTarget: 'http://prod.example.com:85/'
|
|
||||||
|
|
||||||
example webmail proxy route:
|
|
||||||
ProxyPassSource: '/webmail/'
|
|
||||||
ProxyPassTarget: 'http://mail.example.com/'
|
|
||||||
ProxyPassTargetOptions: 'connectiontimeout=10 timeout=90'
|
|
||||||
ProxyPassReverseSource: '/webmail/'
|
|
||||||
ProxyPassReverseTarget: 'http://mail.example.com/'
|
|
||||||
|
|
||||||
example service proxy route:
|
|
||||||
ProxyPassSource: '/svc/'
|
|
||||||
ProxyPassTarget: 'http://svc.example.com:92/'
|
|
||||||
ProxyPassTargetOptions: 'connectiontimeout=10 timeout=90'
|
|
||||||
ProxyPassReverseSource: '/svc/'
|
|
||||||
ProxyPassReverseTarget: 'http://svc.example.com:92/'
|
|
||||||
|
|
||||||
Location:
|
|
||||||
/:
|
|
||||||
Require: False
|
|
||||||
Formula_Append: |
|
|
||||||
SecRuleRemoveById 981231
|
|
||||||
SecRuleRemoveById 981173
|
|
||||||
|
|
||||||
/error:
|
|
||||||
Require: 'all granted'
|
|
||||||
|
|
||||||
/docs:
|
|
||||||
Order: allow,deny # For Apache < 2.4
|
|
||||||
Allow: from all # For apache < 2.4
|
|
||||||
Require: all granted # For apache > 2.4.
|
|
||||||
Formula_Append: |
|
|
||||||
Additional config as a
|
|
||||||
multi-line string here
|
|
||||||
|
|
||||||
LocationMatch:
|
|
||||||
'^[.\\/]+([Ww][Ee][Bb][Mm][Aa][Ii][Ll])[.\\/]':
|
|
||||||
Require: False
|
|
||||||
Formula_Append: |
|
|
||||||
RequestHeader set Host mail.example.com
|
|
||||||
|
|
||||||
'^[.\\/]+([Ss][Vv][Cc])[.\\/]':
|
|
||||||
Require: False
|
|
||||||
Formula_Append: |
|
|
||||||
Require ip 123.123.13.6 84.24.25.74
|
|
||||||
|
|
||||||
Proxy_control:
|
|
||||||
'*':
|
|
||||||
AllowAll: False
|
|
||||||
AllowCountry:
|
|
||||||
- DE
|
|
||||||
AllowIP:
|
|
||||||
- 12.5.25.32
|
|
||||||
- 12.5.25.33
|
|
||||||
|
|
||||||
|
|
||||||
Alias:
|
|
||||||
/docs: /usr/share/docs
|
|
||||||
|
|
||||||
Formula_Append: |
|
|
||||||
Additional config as a
|
|
||||||
multi-line string here
|
|
||||||
|
|
||||||
# ``apache.debian_full`` formula additional configuration:
|
|
||||||
register-site:
|
|
||||||
# any name as an array index, and you can duplicate this section
|
|
||||||
UNIQUE_VALUE_HERE:
|
|
||||||
name: 'my name'
|
|
||||||
path: 'salt://path/to/sites-available/conf/file'
|
|
||||||
state: 'enabled'
|
|
||||||
# Optional - use managed file as Jinja Template
|
|
||||||
#template: true
|
|
||||||
#defaults:
|
|
||||||
# custom_var: "default value"
|
|
||||||
|
|
||||||
modules:
|
|
||||||
enabled: # List modules to enable
|
|
||||||
- ldap
|
|
||||||
- ssl
|
|
||||||
disabled: # List modules to disable
|
|
||||||
- rewrite
|
|
||||||
|
|
||||||
flags:
|
|
||||||
enabled: # List server flags to enable
|
|
||||||
- SSL
|
|
||||||
disabled: # List server flags to disable
|
|
||||||
- status
|
|
||||||
|
|
||||||
# KeepAlive: Whether or not to allow persistent connections (more than
|
|
||||||
# one request per connection). Set to "Off" to deactivate.
|
|
||||||
keepalive: 'On'
|
|
||||||
|
|
||||||
security:
|
|
||||||
# can be Full | OS | Minimal | Minor | Major | Prod
|
|
||||||
# where Full conveys the most information, and Prod the least.
|
|
||||||
ServerTokens: Prod
|
|
||||||
|
|
||||||
# [debian only] configure mod_ssl
|
|
||||||
ssl:
|
|
||||||
SSLCipherSuite: 'HIGH:!aNULL'
|
|
||||||
SSLHonorCipherOrder: 'Off'
|
|
||||||
SSLProtocol: 'all -SSLv3'
|
|
||||||
SSLUseStapling: 'Off'
|
|
||||||
SSLStaplingResponderTimeout: '5'
|
|
||||||
SSLStaplingReturnResponderErrors: 'Off'
|
|
||||||
SSLStaplingCache: 'shmcb:/var/run/ocsp(128000)'
|
|
||||||
|
|
||||||
# ``apache.mod_remoteip`` formula additional configuration:
|
|
||||||
mod_remoteip:
|
|
||||||
RemoteIPHeader: X-Forwarded-For
|
|
||||||
RemoteIPTrustedProxy:
|
|
||||||
- 10.0.8.0/24
|
|
||||||
- 127.0.0.1
|
|
||||||
|
|
||||||
# ``apache.mod_security`` formula additional configuration:
|
|
||||||
mod_security:
|
|
||||||
crs_install: True
|
|
||||||
# If not set, default distro's configuration is installed as is
|
|
||||||
manage_config: True
|
|
||||||
sec_rule_engine: 'On'
|
|
||||||
sec_request_body_access: 'On'
|
|
||||||
sec_request_body_limit: '14000000'
|
|
||||||
sec_request_body_no_files_limit: '114002'
|
|
||||||
sec_request_body_in_memory_limit: '114002'
|
|
||||||
sec_request_body_limit_action: 'Reject'
|
|
||||||
sec_pcre_match_limit: '15000'
|
|
||||||
sec_pcre_match_limit_recursion: '15000'
|
|
||||||
sec_debug_log_level: '3'
|
|
||||||
|
|
||||||
rules:
|
|
||||||
enabled:
|
|
||||||
modsecurity_crs_10_setup.conf:
|
|
||||||
rule_set: ''
|
|
||||||
enabled: True
|
|
||||||
modsecurity_crs_20_protocol_violations.conf:
|
|
||||||
rule_set: 'base_rules'
|
|
||||||
enabled: False
|
|
||||||
|
|
||||||
custom_rule_files:
|
|
||||||
# any name as an array index, and you can duplicate this section
|
|
||||||
UNIQUE_VALUE_HERE:
|
|
||||||
file: 'my name'
|
|
||||||
path: 'salt://path/to/modsecurity/custom/file'
|
|
||||||
enabled: True
|
|
||||||
|
|
||||||
mod_ssl:
|
|
||||||
# set this to True if you want to override your distributions default TLS configuration
|
|
||||||
manage_tls_defaults: False
|
|
||||||
# This stuff is deliberately not configured via map.jinja resp. apache:lookup.
|
|
||||||
# We're unable to know sane defaults for each release of every distribution.
|
|
||||||
# See https://github.com/saltstack-formulas/openssh-formula/issues/102 for a related discussion
|
|
||||||
# Have a look at bettercrypto.org for up-to-date settings.
|
|
||||||
# These are default values:
|
|
||||||
SSLCipherSuite: EDH+CAMELLIA:EDH+aRSA:EECDH+aRSA+AESGCM:EECDH+aRSA+SHA384:EECDH+aRSA+SHA256:EECDH:+CAMELLIA256:+AES256:+CAMELLIA128:+AES128:+SSLv3:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!DSS:!RC4:!SEED:!ECDSA:CAMELLIA256-SHA:AES256-SHA:CAMELLIA128-SHA:AES128-SHA
|
|
||||||
# Mitigate the CRIME attack
|
|
||||||
SSLCompression: Off
|
|
||||||
SSLProtocol: all -SSLv2 -SSLv3 -TLSv1
|
|
||||||
SSLHonorCipherOrder: On
|
|
||||||
SSLOptions: "+StrictRequire"
|
|
||||||
|
|
122
pillar.example.yaml
Normal file
122
pillar.example.yaml
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
# server configuration and any vhost configuration have the same data structure
|
||||||
|
# This data structure is similar to below :
|
||||||
|
#
|
||||||
|
# directives: # list of top level directives/values
|
||||||
|
# - directive_1: value_1
|
||||||
|
# - directive_2: value_2
|
||||||
|
# - directive_3: value_3
|
||||||
|
# containers: # any type of httpd container
|
||||||
|
# container_name_1: # Files|Directory|DirectoryMatch|Proxy|location|locationMatch ...
|
||||||
|
# -
|
||||||
|
# item: 'path/to/1' # label, path or whatever that container applies to
|
||||||
|
# directives: # list of directives into this container
|
||||||
|
# - directive_1: value_1
|
||||||
|
# ...
|
||||||
|
# -
|
||||||
|
# item: '/path/to/2'
|
||||||
|
# direcives:
|
||||||
|
# - ...
|
||||||
|
# containers: # nested containers in /path/to/2
|
||||||
|
# nested_c_1:
|
||||||
|
# - item: '...'
|
||||||
|
# directives:
|
||||||
|
# - ...
|
||||||
|
# container_name_2:
|
||||||
|
# -
|
||||||
|
# item: '...'
|
||||||
|
# ...
|
||||||
|
|
||||||
|
# ``apache`` formula configuration:
|
||||||
|
apache:
|
||||||
|
|
||||||
|
# By default apache restart/reload states run (false skips)
|
||||||
|
manage_service_states: True
|
||||||
|
|
||||||
|
# lookup section overrides ``map.jinja`` values
|
||||||
|
lookup:
|
||||||
|
server: apache2
|
||||||
|
service: apache2
|
||||||
|
user: some_system_user
|
||||||
|
group: some_system_group
|
||||||
|
|
||||||
|
vhostdir: /etc/apache2/sites-available
|
||||||
|
confdir: /etc/apache2/conf.d
|
||||||
|
confext: .conf
|
||||||
|
logdir: /var/log/apache2
|
||||||
|
wwwdir: /srv/apache2
|
||||||
|
|
||||||
|
# apache version (generally '2.2' or '2.4')
|
||||||
|
version: '2.2'
|
||||||
|
|
||||||
|
# ``apache.mod_wsgi`` formula additional configuration:
|
||||||
|
mod_wsgi: mod_wsgi
|
||||||
|
|
||||||
|
# global (server) apache directives
|
||||||
|
server_apache_config: # this content will populate httpd.conf
|
||||||
|
directives:
|
||||||
|
- AllowEncodedSlashes: 'On'
|
||||||
|
- Timeout: 5
|
||||||
|
containers:
|
||||||
|
IfModule:
|
||||||
|
-
|
||||||
|
item: 'mime_module'
|
||||||
|
directives:
|
||||||
|
- AddType: 'application/x-font-ttf ttc ttf'
|
||||||
|
- AddType: 'application/x-font-opentype otf'
|
||||||
|
- AddType: 'application/x-font-woff woff2'
|
||||||
|
|
||||||
|
|
||||||
|
# ``apache.vhosts.vhost-ng`` formula additional configuration:
|
||||||
|
VirtualHost:
|
||||||
|
example.com: # <-- site_name : can be the real ServerName or a virtual name
|
||||||
|
item: '*:8080' # simple example
|
||||||
|
directives:
|
||||||
|
- ServerName: 'example.com' # if not defined default is site_name
|
||||||
|
- ServerAdmin: 'webmaster@example.com'
|
||||||
|
- DocumentRoot: '/path/to/www/dir/example.com'
|
||||||
|
- LogLevel: 'warn'
|
||||||
|
containers:
|
||||||
|
Location:
|
||||||
|
-
|
||||||
|
item: '/test.html'
|
||||||
|
directives:
|
||||||
|
- Require: 'all granted'
|
||||||
|
my_reverse_proxy: # example with a virtual site_name
|
||||||
|
item: '*:80' # vhost with proxypass
|
||||||
|
directives:
|
||||||
|
- ServerName: 'rp-example.com'
|
||||||
|
- ServerAdmin: 'webmaster@example.com'
|
||||||
|
- DocumentRoot: '/path/to/www/dir/rp-example.com'
|
||||||
|
- LogLevel: 'warn'
|
||||||
|
- ProxyPass: '/ balancer://cluster_1'
|
||||||
|
- ProxyPassReverse: '/ balancer://cluster_1'
|
||||||
|
- ProxyPreserveHost: 'On'
|
||||||
|
containers:
|
||||||
|
Proxy:
|
||||||
|
-
|
||||||
|
item: 'balancer://cluster_1'
|
||||||
|
directives:
|
||||||
|
- BalancerMember: 'http://my_backend_1:8081 route=backend-1-8081 timeout=240 retry=120'
|
||||||
|
- BalancerMember: 'http://my_backend_2:8081 route=backend-2-8081 timeout=240 retry=120'
|
||||||
|
- ProxySet: 'stickysession=JSESSIONID|jsessionid nofailover=off maxattempts=1'
|
||||||
|
unused_vhost:
|
||||||
|
item: '*:80'
|
||||||
|
absent: True # Delete this vhost
|
||||||
|
directives:
|
||||||
|
- ServerName: 'to-delete-example.com'
|
||||||
|
- ServerAdmin: 'webmaster@example.com'
|
||||||
|
- DocumentRoot: '/path/to/www/dir/to-delete-example.com'
|
||||||
|
- LogLevel: 'warn'
|
||||||
|
containers:
|
||||||
|
Location:
|
||||||
|
-
|
||||||
|
item: '/test.html'
|
||||||
|
directives:
|
||||||
|
- Require: 'all granted'
|
||||||
|
|
||||||
|
modules:
|
||||||
|
enabled: # List modules to enable
|
||||||
|
- ldap
|
||||||
|
- ssl
|
||||||
|
disabled: # List modules to disable
|
||||||
|
- rewrite
|
Loading…
Reference in New Issue
Block a user