Changeset - 34dffc4a5ea3
[Not reviewed]
0 7 0
Branko Majic (branko) - 5 years ago 2021-01-14 23:50:35
branko@majic.rs
MAR-151: Added support for Debian 10 Buster to web_server role:

- Updated role reference documentaiton.
- Updated role meta information.
- Updated tests.
- Refactor the code around handling of different directories and files
for PHP 7.0 (Debian Stretch) and PHP 7.3 (Debian Buster).
- Separate socket directory tests for WSGI and PHP applications (due
to differences in paths for PHP in Debian Stretch and Debian
Buster).
7 files changed with 114 insertions and 14 deletions:
0 comments (0 inline, 0 general)
docs/rolereference.rst
Show inline comments
 
@@ -1462,24 +1462,25 @@ Parameters
 
  TLS ciphers to enable on the web server. This should be an OpenSSL-compatible
 
  cipher specification. Value should be compatible with Nginx configuration
 
  option ``ssl_ciphers``. Default value allows only TLSv1.2 and strong PFS
 
  ciphers with RSA private keys.
 

	
 

	
 
Distribution compatibility
 
~~~~~~~~~~~~~~~~~~~~~~~~~~
 

	
 
Role is compatible with the following distributions:
 

	
 
- Debian 9 (Stretch)
 
- Debian 10 (Buster)
 

	
 

	
 
Examples
 
~~~~~~~~
 

	
 
Here is an example configuration for setting-up web server:
 

	
 
.. code-block:: yaml
 

	
 
  ---
 

	
 
  default_https_tls_key: "{{ lookup('file', inventory_dir + '/tls/web.example.com_https.key') }}"
roles/web_server/defaults/main.yml
Show inline comments
 
@@ -5,15 +5,23 @@ web_default_message: "You are attempting to access the web server using a wrong
 
web_server_tls_protocols:
 
  - "TLSv1.2"
 
web_server_tls_ciphers: "\
 
DHE-RSA-AES128-GCM-SHA256:\
 
DHE-RSA-AES256-GCM-SHA384:\
 
DHE-RSA-CHACHA20-POLY1305:\
 
ECDHE-RSA-AES128-GCM-SHA256:\
 
ECDHE-RSA-AES256-GCM-SHA384:\
 
ECDHE-RSA-CHACHA20-POLY1305:\
 
!aNULL:!MD5:!EXPORT"
 

	
 
# Internal parameters
 
php_fpm_service_name_per_release:
 
  stretch: "php7.0-fpm"
 
  buster: "php7.3-fpm"
 

	
 
php_base_config_dir_per_release:
 
  stretch: "/etc/php/7.0"
 
  buster: "/etc/php/7.3"
 

	
 
php_fpm_package_name: "php-fpm"
 
php_fpm_service_name: "php7.0-fpm"
 
php_base_config_dir: "/etc/php/7.0"
 
php_fpm_service_name: "{{ php_fpm_service_name_per_release[ansible_distribution_release] }}"
 
php_base_config_dir: "{{ php_base_config_dir_per_release[ansible_distribution_release] }}"
roles/web_server/meta/main.yml
Show inline comments
 
@@ -2,14 +2,14 @@
 

	
 
dependencies:
 
  - common
 

	
 
galaxy_info:
 
  author: Branko Majic
 
  description: Sets-up generic web server
 
  license: BSD
 
  min_ansible_version: 2.9
 
  platforms:
 
    - name: Debian
 
      versions:
 
        - 8
 
        - 9
 
        - 10
roles/web_server/molecule/default/molecule.yml
Show inline comments
 
@@ -44,24 +44,63 @@ platforms:
 
    groups:
 
      - parameters-optional
 
      - stretch
 
    box: debian/contrib-stretch64
 
    memory: 512
 
    cpus: 1
 
    interfaces:
 
      - auto_config: true
 
        ip: 10.31.127.33
 
        network_name: private_network
 
        type: static
 

	
 
  - name: client1-buster
 
    groups:
 
      - client
 
      - buster
 
    box: debian/contrib-buster64
 
    memory: 256
 
    cpus: 1
 
    interfaces:
 
      - auto_config: true
 
        ip: 10.31.127.20
 
        network_name: private_network
 
        type: static
 

	
 
  - name: parameters-mandatory-buster64
 
    groups:
 
      - parameters-mandatory
 
      - buster
 
    box: debian/contrib-buster64
 
    memory: 512
 
    cpus: 1
 
    interfaces:
 
      - auto_config: true
 
        ip: 10.31.127.30
 
        network_name: private_network
 
        type: static
 

	
 
  - name: parameters-optional-buster64
 
    groups:
 
      - parameters-optional
 
      - buster
 
    box: debian/contrib-buster64
 
    memory: 512
 
    cpus: 1
 
    interfaces:
 
      - auto_config: true
 
        ip: 10.31.127.31
 
        network_name: private_network
 
        type: static
 

	
 
provisioner:
 
  name: ansible
 
  playbooks:
 
    cleanup: cleanup.yml
 
  config_options:
 
    defaults:
 
      force_valid_group_names: "ignore"
 
      interpreter_python: "/usr/bin/python3"
 
    ssh_connection:
 
      pipelining: "True"
 
  lint:
 
    name: ansible-lint
roles/web_server/molecule/default/prepare.yml
Show inline comments
 
@@ -18,24 +18,28 @@
 
        chdir: "tests/data/"
 
        creates: ".gimmecert/server/{{ item.name }}.cert.pem"
 
        argv:
 
          - "gimmecert"
 
          - "server"
 
          - "{{ item.name }}"
 
          - "{{ item.fqdn }}"
 
      with_items:
 
        - name: parameters-mandatory-stretch64_https
 
          fqdn: parameters-mandatory
 
        - name: parameters-optional-stretch64_https
 
          fqdn: parameters-optional
 
        - name: parameters-mandatory-buster64_https
 
          fqdn: parameters-mandatory
 
        - name: parameters-optional-buster64_https
 
          fqdn: parameters-optional
 

	
 
    - name: Set-up link to generated X.509 material
 
      file:
 
        src: ".gimmecert"
 
        dest: "tests/data/x509"
 
        state: link
 

	
 
- name: Prepare
 
  hosts: all
 
  gather_facts: false
 
  tasks:
 
    - name: Install python for Ansible
 
@@ -73,24 +77,47 @@
 
        mode: 0644
 
        state: present
 
      with_dict:
 
        10.31.127.21: "client1"
 
        10.31.127.32: "parameters-mandatory"
 
        10.31.127.33: "parameters-optional"
 

	
 
    - name: Install curl for testing redirects and webpage content
 
      apt:
 
        name: curl
 
        state: present
 

	
 
- hosts: buster
 
  become: true
 
  tasks:
 

	
 
    - name: Set-up the hosts file
 
      lineinfile:
 
        path: /etc/hosts
 
        regexp: "^{{ item.key }}"
 
        line: "{{ item.key }} {{ item.value }}"
 
        owner: root
 
        group: root
 
        mode: 0644
 
        state: present
 
      with_dict:
 
        10.31.127.20: "client1"
 
        10.31.127.30: "parameters-mandatory"
 
        10.31.127.31: "parameters-optional"
 

	
 
    - name: Install curl for testing redirects and webpage content
 
      apt:
 
        name: curl
 
        state: present
 

	
 
- hosts: client
 
  become: true
 
  tasks:
 

	
 
    - name: Install tool for testing TCP connectivity
 
      apt:
 
        name: hping3
 
        state: present
 

	
 
    - name: Install console-based web browser for interactive testing
 
      apt:
 
        name: lynx
roles/web_server/molecule/default/tests/conftest.py
Show inline comments
 
from collections import namedtuple
 

	
 
import pytest
 

	
 

	
 
@pytest.fixture
 
def php_info(host):
 
    """
 
    Helper fixture used to define what the expected PHP-FPM package
 
    name, PHP-FPM service name, and PHP base configuration directory
 
    is based on Debian release.
 

	
 
    Currently supports Debian 9 (Stretch).
 
    Currently supports:
 

	
 
    - Debian 9 (Stretch)
 
    - Debian 10 (Buster)
 

	
 
    Resulting information can be accessed through returned named tuple
 
    with the following properties:
 

	
 
    - fpm_package (name of the PHP-FPM package)
 
    - fpm_service (name of the PHP-FPM system service)
 
    - base_config_dir (base configuration directory for PHP)
 
    """
 

	
 
    PHPInfo = namedtuple('PHPInfo', 'fpm_package fpm_service base_config_dir')
 

	
 
    ansible_facts = host.ansible("setup")["ansible_facts"]
 
    ansible_distribution_release = ansible_facts['ansible_distribution_release']
 

	
 
    if ansible_distribution_release == 'stretch':
 
        info = PHPInfo(fpm_package='php-fpm', fpm_service='php7.0-fpm', base_config_dir='/etc/php/7.0')
 
    elif ansible_distribution_release == 'buster':
 
        info = PHPInfo(fpm_package='php-fpm', fpm_service='php7.3-fpm', base_config_dir='/etc/php/7.3')
 
    else:
 
        raise Exception('The php_info pytest fixture does not support Debian release: %s' % ansible_distribution_release)
 

	
 
    return info
roles/web_server/molecule/default/tests/test_default.py
Show inline comments
 
import os
 

	
 
import testinfra.utils.ansible_runner
 

	
 

	
 
import pytest
 
testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
 
    os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('parameters-*')
 

	
 

	
 
def test_installed_packages(host, php_info):
 
    """
 
    Tests if the required packages have been installed.
 
    """
 

	
 
    assert host.package('nginx').is_installed
 
    assert host.package('python-setuptools').is_installed
 
    assert host.package('python3-setuptools').is_installed
 
@@ -155,35 +153,57 @@ def test_services(host, php_info):
 
    assert service.is_running
 

	
 

	
 
def test_sockets(host):
 
    """
 
    Tests if web server is listening on correct ports.
 
    """
 

	
 
    assert host.socket("tcp://80").is_listening
 
    assert host.socket("tcp://443").is_listening
 

	
 

	
 
@pytest.mark.parametrize("application_type, tmpfiles_d_path",
 
                         [("wsgi", "/etc/tmpfiles.d/wsgi.conf"),
 
                          ("php", "/etc/tmpfiles.d/php7.0-fpm.conf")])
 
def test_socket_directories(host, application_type, tmpfiles_d_path):
 
def test_wsgi_socket_directory(host):
 
    """
 
    Tests if directories containing sockets for WSGI and PHP apps are created
 
    correctly.
 
    Tests if directory containing socket for WSGI applications has
 
    been created correctly.
 
    """
 

	
 
    socket_directory = "/run/wsgi"
 
    tmpfiles_d_path = "/etc/tmpfiles.d/wsgi.conf"
 
    tmpfiles_d_content = "d /run/wsgi/ 0750 root www-data - -"
 

	
 
    directory = host.file(socket_directory)
 
    assert directory.is_directory
 
    assert directory.user == 'root'
 
    assert directory.group == 'www-data'
 
    assert directory.mode == 0o750
 

	
 
    config = host.file(tmpfiles_d_path)
 
    assert config.is_file
 
    assert config.user == 'root'
 
    assert config.group == 'root'
 
    assert config.mode == 0o644
 
    assert config.content_string == tmpfiles_d_content
 

	
 

	
 
def test_php_fpm_socket_directory(host, php_info):
 
    """
 
    Tests if directory containing socket for WSGI applications has
 
    been created correctly.
 
    """
 

	
 
    socket_directory = "/run/%s" % application_type
 
    tmpfiles_d_content = "d /run/%s/ 0750 root www-data - -" % application_type
 
    socket_directory = "/run/php"
 
    tmpfiles_d_path = "/etc/tmpfiles.d/%s.conf" % php_info.fpm_service
 
    tmpfiles_d_content = "d /run/php/ 0750 root www-data - -"
 

	
 
    directory = host.file(socket_directory)
 
    assert directory.is_directory
 
    assert directory.user == 'root'
 
    assert directory.group == 'www-data'
 
    assert directory.mode == 0o750
 

	
 
    config = host.file(tmpfiles_d_path)
 
    assert config.is_file
 
    assert config.user == 'root'
 
    assert config.group == 'root'
 
    assert config.mode == 0o644
0 comments (0 inline, 0 general)