view modules/website/manifests/init.pp @ 284:9431aec4d998

Switch to using IPv6 prefix and IP per site This is because the proxy seems to break SNI, so we need an IP per SSL cert. We're not short of IPv6 addresses, though! Also corrected to "4to6" naming, because we're letting IPv4 access an IPv6 site
author IBBoard <dev@ibboard.co.uk>
date Sun, 16 Feb 2020 12:07:35 +0000
parents af7df930a670
children e765073832d9
line wrap: on
line source

class website(
  Pattern[/^(\/[^\/]+)*$/] $base_dir,
  Pattern[/^(\/[^\/]+)*$/] $cert_dir           = '/etc/pki/custom',
  Stdlib::IP::Address $primary_ip,
  Stdlib::IP::Address::V6 $proxy_4to6_ip_prefix = undef,
  Optional[Integer] $proxy_4to6_mask = undef,
  Array[Stdlib::IP::Address::V6] $proxy_4to6_addresses = [],
  Array $proxy_upstream = undef,
  String $default_owner,
  String $default_group,
  String $default_tld        = 'com',
  Array $default_extra_tlds = []
  ){

  $basedir = $base_dir
  $certdir = $cert_dir
  $docroot_owner = $default_owner
  $docroot_group = $default_group
  $ca_chain = "/etc/letsencrypt/live/${::fqdn}/chain.pem"
  $tld = $default_tld
  $extra_tlds = $default_extra_tlds
  $htmlphpfragment = "Include conf.extra/html-php.conf"
  $filterfragment = "Include conf.custom/filter.conf"
  $cmsfragment = "Include conf.extra/cms_rewrites.conf"

  $csp_base = {"frame-ancestors" => "'none'", "base-uri" => "'none'"}
  $csp_report_base = {
    "default-src" => "'none'",
    "img-src" => "'self'",
    "script-src" => "'self'",
    "style-src" => "'self'",
    "font-src" => "'self'"
  }

  class { 'apache':
    vhost_dir => "/etc/httpd/conf.d/vhosts",
    default_mods => false,
    default_vhost => false,
    mpm_module => false,
  }
  class { 'apache::mod::dir': indexes => [ 'index.html' ] }
  class { 'apache::mod::prefork':
    serverlimit => 45,
    maxclients => 45,
    maxspareservers => 6,
  }
  apache::mod {
    'rewrite':;
    'expires':;
    'env':;
    'setenvif':;
    'headers':;
    'version':;
  }

  # Updating the httpd package puts back some configs that we
  # don't load the relevant modules for, so we'll try to make
  # them blank so that RPM/Yum makes ".rpmnew" files instead
  $unused_default_mods = [
    "${::apache::mod_dir}/autoindex.conf",
    "${::apache::mod_dir}/userdir.conf",
    "${::apache::mod_dir}/welcome.conf",
  ]
  file { $unused_default_mods:
    ensure => file,
    content => '',
    require => Class['apache'],
  }

  file { $base_dir:
    ensure => directory;
  }
  file { '/var/log/apache':
    ensure => directory,
    mode   => '0750',
    group  => 'apache',
  }
  file { '/etc/httpd/conf.extra':
    ensure => directory,
    recurse => true,
    source => "puppet:///modules/website/conf.extra",
    require => Class['apache'],
    notify => Service['httpd'];
  }
  file { '/etc/httpd/conf/mime.types':
    ensure => present,
    source => "puppet:///modules/website/mime.types",
    require => Class['apache'],
    notify => Service['httpd'];
  }
  file { '/etc/php.d/datetime.ini':
    ensure => present,
    source => "puppet:///modules/website/datetime.ini",
    require => Class['apache'],
    notify => Service['httpd'];
  }
  file { '/etc/httpd/conf.d/zzz-custom.conf':
    ensure => absent,
    require => Class['apache'],
    notify => Service['httpd'];
  }
  file { '/etc/httpd/conf.d/zzz-0-custom.conf':
    ensure => present,
    source => "puppet:///modules/website/zzz-0-custom.conf",
    require => Class['apache'],
    notify => Service['httpd'];
  }
  file { '/etc/httpd/conf.d/php.conf':
    ensure => present,
    source => "puppet:///modules/website/php.conf",
    require => Class['apache'],
    notify => Service['httpd'];
  }
  file { '/etc/httpd/conf.custom':
    ensure => directory,
    recurse => true,
    source => "puppet:///private/apache/conf.custom",
    require => Class['apache'],
    notify => Service['httpd']; 
  }
  file { $cert_dir:
    ensure => directory;
  }
  firewall { '100 allow https and http':
    destination => $primary_ip,
    dport => [80, 443],
    proto => tcp,
    action => accept,
  }
  if ($proxy_4to6_ip_prefix != undef) and ($proxy_upstream != undef) {
    $ipv6_secondaries = join($proxy_4to6_addresses, " ")
    augeas {'/etc/sysconfig/network-scripts/ifcfg-eth0':
      context => "/files/etc/sysconfig/network-scripts/ifcfg-eth0",
      changes => "set IPV6ADDR_SECONDARIES '$ipv6_secondaries'",
    }

    apache::mod { "remoteip": }
    $proxy_4to6_ip = "$proxy_4to6_ip_prefix:0000/$proxy_4to6_mask"

    $proxy_upstream.each |String $upstream_addr| {
      firewall { "100 limit PROXY protocol to upstream $upstream_addr":
        source => $upstream_addr,
        destination => $proxy_4to6_ip,
        dport => [80, 443],
        proto => tcp,
        action => accept,
      }
    }
    firewall { "101 block all other PROXY protocol access":
      destination => $proxy_4to6_ip,
      dport => [80, 443],
      proto => tcp,
      action => reject,
    }
  }
  if $operatingsystem == 'CentOS' and versioncmp($operatingsystemrelease, '7') >= 0 {
    exec { 'set_apache_defaults':
      command => 'semanage fcontext -a -t httpd_sys_content_t "/srv/sites(/.*)?"',
      path    => '/bin:/usr/bin/:/sbin:/usr/sbin',
      require => Package['policycoreutils-python'],
      unless  => 'semanage fcontext --list | grep "/srv/sites\\(/\\.\\*\\)\\?"',
    }
    cron { 'letsencrypt-renewal':
      command => '/usr/bin/certbot renew --quiet',
      hour => '*/12',
      minute => '21',
    }
    if versioncmp($operatingsystemrelease, '7') == 0 {
        $certbot_pkg = 'python2-certbot-apache'
    } else {
        $certbot_pkg = 'python3-certbot-apache'
    }
    package { $certbot_pkg:
      ensure => installed,
    }
  }
}