view modules/website/manifests/https.pp @ 256:0ebd8efeef04

Merge Puppet divergences and fix SSL chain issues it caused
author IBBoard <dev@ibboard.co.uk>
date Sun, 29 Dec 2019 15:31:28 +0000
parents 4519b727cc4c
children f99974dc0f1a
line wrap: on
line source

# If the SSL cert and key are defined then the definer deals with them existing
# If the SSL cert and key are not defined then we use template file paths and ensure they exist
define website::https(
    $docroot            = undef,
    $ip                 = $website::primary_ip,
    $ssl_cert           = undef,
    $ssl_key            = undef,
    $ssl_ca_chain       = undef,
    $letsencrypt_name   = undef,
    $priority           = undef,
    $docroot_owner      = undef,
    $docroot_group      = undef,
    $serveraliases      = [],
    $ensure             = 'present',
    $custom_fragment    = '',
    $force_no_www       = true,
    $force_no_index     = true,
    $lockdown_requests  = true,
    $csp_override       = undef,
    $csp_report_override = undef,
  ) {

  if ! defined(Class['website']) {
    fail('You must include the website base class before using any website defined resources')
  }

  validate_re($ensure, '^(present|absent)$',
  "${ensure} is not supported for ensure.
  Allowed values are 'present' and 'absent'.")

  $shortname = domain_to_short_name($name)
  $logpart = $shortname
  $shortdomain = domain_to_short_domain($name)
  if $force_no_www {
    $primary_name = $shortdomain
  } else {
    $primary_name = $name
  }

  $csp_string = hash_to_csp($website::csp_base, $csp_override)
  $csp_report_string = hash_to_csp($website::csp_report_base, $csp_report_override)

  $custom_conf0 = template('website/https_core_conf.erb')

  if $force_no_index {
    $custom_conf1 = "$custom_conf0
Include conf.extra/no-index.conf"
  } else {
    $custom_conf1 = $custom_conf0
  }

  if $lockdown_requests {
    $custom_conf2 = "$custom_conf1
Include conf.custom/filter-core.conf"
  } else {
    $custom_conf2 = $custom_conf1
  }

  if $custom_fragment {
    $custom_conf = "$custom_conf2
#Additional custom fragment
$custom_fragment"
  } else {
    $custom_conf = $custom_conf2
  }

  if $docroot == undef {
    $siteroot = "${website::basedir}/${shortname}"
  } else {
    $siteroot = $docroot
  }

# These conditionals use an ugly cludge from
# http://grokbase.com/t/gg/puppet-users/147by1key3/checking-a-variable-is-not-undef#20140713grem6zqsai7qjbgkmd2f4ia3qi
# because if we don't then undef gets auto-cast to the empty string and the empty string matches our special "no CA chain" case
# It'd be nicer to use "=~ Undef" to check types (https://puppet-on-the-edge.blogspot.co.uk/2013/12/lets-talk-about-undef.html),
# but that threw syntax errors.
  if $ssl_cert != undef {
    $sslcert = $ssl_cert
    $sslkey = $ssl_key   
  } elsif $ssl_ca_chain == "" and ("" in [$ssl_ca_chain]) {
    $sslcert = "${website::certdir}/${shortdomain}.crt"
    $sslkey = "${website::certdir}/${shortdomain}.key"
    File {
      mode => '0400',
      owner => 'root',
      group => 'root',
    }
    file { $sslcert:
      source => "puppet:///private/pki/custom/${shortdomain}.crt",
      before => Apache::Vhost[$name],
      notify => Service['httpd'],
      ensure => present;
    }
    file { $sslkey:
      source => "puppet:///private/pki/custom/${shortdomain}.key",
      before => Apache::Vhost[$name],
      notify => Service['httpd'],
      ensure => present;
    }
  } elsif $letsencrypt_name != undef {
    $sslcert = "/etc/letsencrypt/live/${letsencrypt_name}/cert.pem"
    $sslkey = "/etc/letsencrypt/live/${letsencrypt_name}/privkey.pem"
  } else {
    $sslcert = "/etc/letsencrypt/live/${::fqdn}/cert.pem"
    $sslkey = "/etc/letsencrypt/live/${::fqdn}/privkey.pem"
  }

  if $ssl_ca_chain == '' and '' in [$ssl_ca_chain] {
    # Special case where we're directly under the CA and don't want to unnecessarily send the CA cert
    $ssl_chain = undef
  } elsif $ssl_ca_chain != undef {
    $ssl_chain = "/etc/pki/custom/$ssl_ca_chain"
    if ! defined(File[$ssl_chain]) {
      file { $ssl_chain:
        ensure => present,
        source => "puppet:///private/pki/custom/$ssl_ca_chain",
        notify  => Service['httpd'],
      }
    }
  } elsif $letsencrypt_name != undef {
    $ssl_chain = "/etc/letsencrypt/live/${letsencrypt_name}/chain.pem"
  } else {
    $ssl_chain = $website::ca_chain
  }

  if $docroot_owner == undef {
    $owner = $website::docroot_owner
  } else {
    $owner = $docroot_owner
  }

  if $docroot_group == undef {
    $group = $website::docroot_group
  } else {
    $group = $docroot_group
  }

  apache::vhost { $name:
    ip              => $ip,
    port            => '443',
    priority        => $priority,
    docroot         => $siteroot,
    docroot_owner   => $owner,
    docroot_group   => $group,
    docroot_mode    => '2775',
    custom_fragment => $custom_conf,
    logroot         => '/var/log/apache/',
    access_log_file => "access_${logpart}.log",
    access_log_format => "%h %l %u %t \\\"%r\\\" %>s %b \\\"%{Referer}i\\\" \\\"%{User-agent}i\\\" %{Host}i",
    error_log_file  => "error_${logpart}.log",
    serveraliases   => $serveraliases,
    ssl             => true,
    ssl_cert        => $sslcert,
    ssl_key         => $sslkey,
    ssl_chain       => $ssl_chain,
    ensure          => $ensure,
  }

  apache::vhost { "${name}-80":
    servername => $name,
    port => 80,
    docroot => $siteroot,
    redirect_status => 'permanent',
    redirect_dest => "https://$name/",
    serveraliases   => $serveraliases,
    logroot         => '/var/log/apache/',
    access_log_file => "access_${logpart}_nossl.log",
    access_log_format => "%h %l %u %t \\\"%r\\\" %>s %b \\\"%{Referer}i\\\" \\\"%{User-agent}i\\\" %{Host}i",
    error_log_file  => "error_${logpart}_nossl.log",
  }
}