view modules/website/manifests/https.pp @ 472:73e28468a543

Fix HTTP on IPv6 We don't need the remote IP instruction on both redirects, just on the IPv4-to-6 proxy redirect
author IBBoard <dev@ibboard.co.uk>
date Tue, 21 May 2024 20:15:05 +0100
parents e0147f345e65
children 28d327443c45
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,
    $proxy_4to6_ip      = undef,
    $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    = '',
    Optional[String] $non_proxy_fragment  = '',
    $force_no_www       = true,
    $force_no_index     = true,
    $lockdown_requests  = true,
    $csp                = true,
    $csp_override       = undef,
    $csp_report         = true,
    $csp_report_override = undef,
  ) {

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

  $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
  }

  if $csp {
    $csp_string = hash_to_csp($website::csp_base, $csp_override)
  }
  if $csp_report {
    $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
  }

  $redir_fragment = "
	# Filter before we redirect to HTTPS
	Include conf.custom/filter-core.conf
	Redirect permanent / https://$name/"


  apache::vhost { $name:
    ip              => $ip,
    port            => 443,
    priority        => $priority,
    docroot         => $siteroot,
    docroot_owner   => $owner,
    docroot_group   => $group,
    docroot_mode    => '2775',
    custom_fragment => "$non_proxy_fragment\n$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 %D",
    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,
    ip => $ip,
    port => 80,
    docroot => $siteroot,
    serveraliases   => $serveraliases,
    custom_fragment => $redir_fragment,
    logroot         => '/var/log/apache/',
    access_log_file => "access_${logpart}_80.log",
    access_log_format => "%h %l %u %t \\\"%r\\\" %>s %b \\\"%{Referer}i\\\" \\\"%{User-agent}i\\\" %{Host}i",
    error_log_file  => "error_${logpart}_80.log",
  }

  if ($proxy_4to6_ip != undef) {
    apache::vhost { "$name-PROXY":
      servername      => $name,
      ip              => $proxy_4to6_ip,
      port            => 443,
      priority        => $priority,
      docroot         => $siteroot,
      docroot_owner   => $owner,
      docroot_group   => $group,
      docroot_mode    => '2775',
      custom_fragment => "RemoteIPProxyProtocol On\n$custom_conf",
      logroot         => '/var/log/apache/',
      access_log_file => "access_${logpart}.log",
      access_log_format => "%a %l %u %t \\\"%r\\\" %>s %b \\\"%{Referer}i\\\" \\\"%{User-agent}i\\\" %{Host}i %D",
      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-PROXY":
      servername => $name,
      ip => $proxy_4to6_ip,
      port => 80,
      docroot => $siteroot,
      serveraliases   => $serveraliases,
      custom_fragment => "RemoteIPProxyProtocol On\n$redir_fragment",
      logroot         => '/var/log/apache/',
      access_log_file => "access_${logpart}_80.log",
      access_log_format => "%a %l %u %t \\\"%r\\\" %>s %b \\\"%{Referer}i\\\" \\\"%{User-agent}i\\\" %{Host}i",
      error_log_file  => "error_${logpart}_80.log",
    }
  }
}