Mercurial > repos > other > Puppet
view manifests/templates.pp @ 476:b0531370e183
Avoid fully controllable rewrite prefix
Apache doesn't guarantee that rewrites are URLs or paths
within the prefix and will process them rather than error,
so close a fully controllable rewrite prefix:
https://blog.orange.tw/2024/08/confusion-attacks-en.html?m=1
author | IBBoard <dev@ibboard.co.uk> |
---|---|
date | Sun, 11 Aug 2024 13:29:59 +0100 |
parents | 9437c6ffa07c |
children | 2c3e745be8d2 |
line wrap: on
line source
# Make sure packages come after their repos File<| tag == 'repo-config' |> -> anchor { 'Repo-config': } -> YumRepo<| |> -> Apt::Source<| |> -> anchor { 'Repos': } -> Package<| |> # Make sure all files are in place before starting services # FIXME: Title matches are to fix a dependency cycle File<| tag != 'post-service' and title != '/etc/sysconfig/ip6tables' and title != '/etc/sysconfig/iptables' |> -> anchor { 'Pre-Service Files': } -> Service<| |> # Set some shortcut variables #$os = $operatingsystem $osver = $operatingsystemmajrelease $server = '' class basenode { include sudo include defaultusers include logwatch file { '/etc/puppet/hiera.yaml': ensure => present, content => " # Let the system set defaults version: 5 ", } service { 'puppet': ensure => stopped, enable => false, } if $operatingsystem == 'Ubuntu' { package { 'locales': ensure => present } -> file { '/etc/locale.gen': ensure => present, content => "en_GB.UTF-8 UTF-8", notify => Exec['Regen locales'] } exec { 'Regen locales': command => 'locale-gen', refreshonly => true } # Don't waste space with Snap and do everything properly with system packages [ 'lxd', 'core18', 'core20', 'snapd'].each |$snap| { exec { "remove $snap snap package": command => "snap remove $snap", onlyif => "which snap && snap list $snap", tag => 'snap', } } Exec<| tag == 'snap' |> -> package { 'snapd': ensure => purged, } } } class basevpsnode ( $primary_ip, $gateway_ip = undef, $proxy_4to6_ip_prefix = undef, $proxy_upstream = undef, $nat64_ranges = [], $mailserver, $imapserver, $mailrelays = [], $firewall_cmd = 'iptables', ) { if $firewall_cmd == 'iptables' { class { 'vpsfirewall': fw_protocol => $primary_ip =~ Stdlib::IP::Address::V6 ? { true => 'IPv6', default => 'IPv4'}, } } #VPS is a self-mastered Puppet machine, so bodge a Hosts file if $primary_ip =~ Stdlib::IP::Address::V6 { $lo_ip = '::1' } else { $lo_ip = '127.0.0.1' } file { '/etc/hosts': ensure => present, content => "${lo_ip} localhost\n${primary_ip} ${fqdn}", } if $proxy_4to6_ip_prefix != undef { # …:1 to …:9 for websites, …:10 for mail # Note: IPv6 is hexadecimal and so 0x10 is not in a /124 netblock with 0x01 to 0x09! $ipv6_addresses = Integer[1, 10].map |$octet| { "$proxy_4to6_ip_prefix:$octet" } if $operatingsystem == 'Ubuntu' { # Ubuntu can't parse the existing file, so we need to brute-force it with a template file { "/etc/network/interfaces.d/eth0": content => epp('privat/eth0.epp', { default_address => $primary_ip, gateway_address => $gateway_ip, } ), notify => Exec["restart_networking"], } # …:1 to …:9 for websites, …:10 for mail Integer[1, 10].each |$octet| { file { "/etc/network/interfaces.d/eth0:$octet": content => epp('privat/eth0-alias.epp', { prefix_address => $proxy_4to6_ip_prefix, octet => $octet, } ), notify => Exec["restart_networking"], } } } else { # …:1 to …:9 for websites, …:10 for mail $ipv6_addresses = Integer[1, 10].map |$octet| { "$proxy_4to6_ip_prefix:$octet" } $ipv6_secondaries = join($ipv6_addresses, " ") augeas {'IPv6 secondary addresses': context => "/files/etc/sysconfig/network-scripts/ifcfg-eth0", changes => "set IPV6ADDR_SECONDARIES '\"$ipv6_secondaries\"'", notify => Exec["restart_networking"], } } Exec { 'restart_networking': command => 'systemctl restart networking', refreshonly => true, } } require repos include basenode include privat include dnsresolver include ::privat::params class { '::ssh': sshd_config_port => $::privat::params::ssh_port[$::fqdn] } include vcs::server include vcs::client class { 'webserver': primary_ip => $primary_ip, proxy_4to6_ip_prefix => $proxy_4to6_ip_prefix, proxy_4to6_mask => 124, proxy_upstream => $proxy_upstream, } include cronjobs include logrotate class { 'fail2ban': firewall_cmd => $firewall_cmd, } include tools class { 'email': mailserver => $mailserver, imapserver => $imapserver, mailserver_ip => $primary_ip, proxy_ip => $proxy_4to6_ip_prefix != undef ? { true => "${proxy_4to6_ip_prefix}:10", default => undef }, proxy_upstream => $proxy_upstream, nat64_ranges => $nat64_ranges, mailrelays => $mailrelays, } } ## Classes to allow facet behaviour using preconfigured setups of classes class vpsfirewall ($fw_protocol) { resources { "firewall": purge => false, } class { "my_fw": ip_version => $fw_protocol, } # Control what does and doesn't get pruned in the main filter chain firewallchain { "INPUT:filter:$fw_protocol": purge => true, ignore => [ '-j f2b-[^ ]+$', '^(:|-A )f2b-', '--comment "Great Firewall of China"', '--comment "Do not purge', ], } include privat::params $ssh_ports = $::privat::params::ssh_port[$::fqdn] firewall { '090 Allow SSH': dport => $ssh_ports - 22, proto => 'tcp', action => 'accept', } if ($fw_protocol != "IPv6") { firewall { '010 Whitelist Googlebot': source => '66.249.64.0/19', dport => [80,443], proto => tcp, action => accept, } # Block a spammer hitting our contact forms (also on StopForumSpam list A LOT) firewall { '099 Blacklist spammers 1': source => '107.181.78.172', dport => [80, 443], proto => tcp, action => 'reject', } firewall { '099 Blacklist IODC bot': # IODC bot makes too many bad requests, and contact form is broken # They don't publish a robots.txt name, so firewall it! source => '86.153.145.149', dport => [ 80, 443 ], proto => tcp, action => 'reject', } firewall { '099 Blacklist Baidu Brazil': #Baidu got a Brazilian netblock and are hitting us hard #Baidu doesn't honour "crawl-delay" in robots.txt #Baidu gets firewalled source => '131.161.8.0/22', dport => [ 80, 443 ], proto => tcp, action => 'reject', } } firewallchain { "GREATFIREWALLOFCHINA:filter:$fw_protocol": ensure => present, } firewall { '050 Check our Great Firewall Against China': chain => 'INPUT', jump => 'GREATFIREWALLOFCHINA', } firewallchain { "Fail2Ban:filter:$fw_protocol": ensure => present, } firewall { '060 Check Fail2Ban': chain => 'INPUT', jump => 'Fail2Ban', } } class dnsresolver { package { 'unbound': ensure => present, } package { 'named': ensure => absent, } service { 'named': ensure => stopped, enable => false, } service { 'unbound': ensure => running, enable => true, } file { '/etc/named.conf': ensure => absent, } file { '/etc/unbound/unbound.conf': ensure => present, source => [ "puppet:///common/unbound.conf-${::hostname}", "puppet:///common/unbound.conf", ], require => Package['unbound'], notify => Service['unbound'], } file { ['/etc/NetworkManager', '/etc/NetworkManager/conf.d']: ensure => directory } file { '/etc/NetworkManager/conf.d/local-dns-resolver.conf': ensure => present, content => "[main] dns=none", } file { '/etc/sysconfig/named': ensure => absent, } file { '/etc/resolv.conf': ensure => file, # "ipaddress" key only exists for machines with IPv4 addresses content => has_key($facts, 'ipaddress') ? { true => "nameserver 127.0.0.1", default => "nameserver ::1" }, require => Service['unbound'], tag => 'post-service', } } class repos { include ::python::params if $operatingsystem == 'CentOS' { yumrepo { 'epel': mirrorlist => 'https://mirrors.fedoraproject.org/metalink?repo=epel-$releasever&arch=$basearch', descr => "Extra Packages for Enterprise Linux", enabled => 1, failovermethod => absent, gpgcheck => 1, gpgkey => "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-$osver", } file { "/etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-$osver": ensure => present, source => "puppet:///common/RPM-GPG-KEY-EPEL-$osver", tag => 'repo-config', } yumrepo { 'ibboard': baseurl => 'https://download.opensuse.org/repositories/home:/IBBoard:/server/CentOS_$releasever/', descr => 'Extra packages from IBBoard', enabled => 1, gpgcheck => 1, gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-ibboard', } file { '/etc/pki/rpm-gpg/RPM-GPG-KEY-ibboard': ensure => present, source => 'puppet:///common/RPM-GPG-KEY-ibboard', tag => 'repo-config', } yumrepo { 'webtatic': ensure => absent, } file { '/etc/pki/rpm-gpg/RPM-GPG-KEY-webtatic-andy': ensure => absent, } file { '/etc/pki/rpm-gpg/RPM-GPG-KEY-webtatic-el7': ensure => absent, } # Python requires the `devel` package on CentOS, but by default the module tries to uninstall it $dev = 'present' } else { # Other distros can take the default devel status $dev = $::python::params::dev # CentOS-like distros have PKI by default. Others need it creating. file { '/etc/pki/': ensure => directory, } file { '/etc/apt/trusted.gpg.d/home_IBBoard_server.gpg': # https://download.opensuse.org/repositories/home:/IBBoard:/server/xUbuntu_22.04/Release.key # Then GPG exported with `cat Release.key | gpg --dearmour -o common/home_IBBoard_server.gpg source => 'puppet:///common/home_IBBoard_server.gpg' } apt::source { 'ibboard': location => 'http://download.opensuse.org/repositories/home:/IBBoard:/server/xUbuntu_22.04/', release => '/', repos => '', keyring => '/etc/apt/trusted.gpg.d/home_IBBoard_server.gpg', } } if $operatingsystem == 'CentOS' and versioncmp($operatingsystemrelease, '8') >= 0 { # The following may possibly work to ensure a CentOS Streams install. # Or it might fail for inexplicable reasons. # FIXME: Should be "centos-release-stream" to migrate (provides repos), but then that gets replaced by centos-stream-release, # which Puppet doesn't recognise as the same and so keeps trying to re-install. May need an "unless" or maybe "allow_virtual" package { 'centos-stream-release': ensure => installed, notify => Exec['migrate to streams']; } exec { 'migrate to streams': command => '/usr/bin/dnf swap centos-linux-repos centos-stream-repos; /usr/bin/dnf distro-sync -y', refreshonly => true } } class { 'python': ensure => 'present', version => 'python3', pip => 'present', use_epel => false, dev => $dev, } } class tools { $packages = [ 'sqlite', 'bash-completion', 'nano', 'zip', 'bzip2', 'mlocate', 'patch', 'tmux', 'wget', 'rsync' ] package { $packages: ensure => installed; } if $osfamily == 'RedHat' { package { 'yum-utils': ensure => installed } } elsif $osfamily == 'Debian' { package { 'dnsutils': ensure => installed } } } class logrotate { package { 'logrotate': ensure => installed; } file { '/etc/logrotate.d/httpd': ensure => present, source => 'puppet:///common/logrotate-httpd', require => Package['logrotate'], } } class logwatch { package { 'logwatch': ensure => installed; } File { ensure => present, require => Package['logwatch'], } file { '/etc/cron.daily/0logwatch': source => 'puppet:///common/0logwatch'; } $logwatch_dirs = [ '/etc/logwatch/', '/etc/logwatch/conf/', '/etc/logwatch/conf/logfiles/', '/etc/logwatch/conf/services/', '/etc/logwatch/scripts/', '/etc/logwatch/scripts/services/', ] file { $logwatch_dirs: ensure => directory, } file { '/etc/logwatch/conf/logwatch.conf': content => 'Detail = Med', } file { '/etc/logwatch/conf/logfiles/http.conf': source => 'puppet:///common/logwatch/logfiles_http.conf', } file { '/etc/logwatch/conf/logfiles/http-error.conf': source => 'puppet:///common/logwatch/logfiles_http-error.conf', } file { '/etc/logwatch/conf/logfiles/mysql.conf': source => 'puppet:///common/logwatch/logfiles_mysql.conf', } file { '/etc/logwatch/conf/logfiles/php.conf': source => 'puppet:///common/logwatch/logfiles_php.conf', } file { '/etc/logwatch/conf/services/php.conf': source => 'puppet:///common/logwatch/services_php.conf', } file { '/etc/logwatch/conf/services/contact-form.conf': source => 'puppet:///common/logwatch/services_contact-form.conf', } file { '/etc/logwatch/scripts/services/dovecot': source => 'puppet:///common/logwatch/dovecot', } file { '/etc/logwatch/scripts/services/postfix': source => 'puppet:///common/logwatch/postfix', } file { '/etc/logwatch/scripts/services/systemd': source => 'puppet:///common/logwatch/systemd', } file { '/etc/logwatch/scripts/services/php': source => 'puppet:///common/logwatch/php', } file { '/etc/logwatch/scripts/services/contact-form': source => 'puppet:///common/logwatch/contact-form', } } #Our web server with our configs, not just a stock one class webserver ( $primary_ip, $proxy_4to6_ip_prefix = undef, $proxy_4to6_mask = undef, $proxy_upstream = undef, ) { #Setup base website parameters class { 'website': base_dir => '/srv/sites', primary_ip => $primary_ip, proxy_4to6_ip_prefix => $proxy_4to6_ip_prefix, proxy_4to6_mask => $proxy_4to6_mask, proxy_upstream => $proxy_upstream, default_owner => $defaultusers::default_user, default_group => $defaultusers::default_user, default_tld => 'co.uk', default_extra_tlds => [ 'com' ], } if $operatingsystem == 'CentOS' { $php_suffix = '' $ini_prefix_20 = '20-' $ini_prefix_30 = '30-' $ini_prefix_40 = '40-' $variant_prefix = 'php-' $extra_prefix = 'pecl-' $extra_extras = { 'posix' => { ini_prefix => '20-', }, # Sodium has been bundled since 7.2, but CentOS packages it separately 'sodium' => { ini_prefix => '20-', }, # JSON is integrated into PHP 8+ and so it's only a plugin in CentOS 'json' => { ini_prefix => '20-', }, } if versioncmp($operatingsystemrelease, '8') >= 0 { yumrepo { 'remirepo-safe': mirrorlist => 'http://cdn.remirepo.net/enterprise/$releasever/safe/$basearch/mirror', descr => "Extra CentOS packages from Remi", enabled => 1, failovermethod => absent, gpgcheck => 1, gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-remi', } yumrepo { 'remirepo-php': mirrorlist => 'http://cdn.remirepo.net/enterprise/8/modular/$basearch/mirror', descr => 'Remi\'s Modular repository for Enterprise Linux 8 - $basearch', enabled => 1, failovermethod => absent, gpgcheck => 1, gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-remi', } file { '/etc/pki/rpm-gpg/RPM-GPG-KEY-remi': ensure => present, source => 'puppet:///common/RPM-GPG-KEY-remi.el8', tag => 'repo-config', } } else { yumrepo { 'remirepo-safe': mirrorlist => 'http://cdn.remirepo.net/enterprise/$releasever/safe/mirror', descr => "Extra CentOS packages from Remi", enabled => 1, failovermethod => absent, gpgcheck => 1, gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-remi', } yumrepo { 'remirepo-php': mirrorlist => 'http://cdn.remirepo.net/enterprise/$releasever/php74/mirror', descr => "PHP7.4 for CentOS from Remi", enabled => 1, failovermethod => absent, gpgcheck => 1, gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-remi', } file { '/etc/pki/rpm-gpg/RPM-GPG-KEY-remi': ensure => present, source => 'puppet:///common/RPM-GPG-KEY-remi', tag => 'repo-config', } } } elsif $operatingsystem == 'Ubuntu' { $php_suffix = '' $ini_prefix_20 = '' $ini_prefix_30 = '' $ini_prefix_40 = '' $variant_prefix = 'php-' $extra_prefix = '' # Work around constant re-install by enabling virtual packages # https://github.com/voxpupuli/puppet-php/issues/387 Package { allow_virtual => true } $extra_extras = { 'xdebug' => { # Occasional profiling retained in case I want to dig into # Wordpress page load inefficiencies any more ensure => absent, # settings => { # "xdebug.mode" => "profile", # "xdebug.start_with_request" => "trigger", # } } } } #Configure the PHP version to use class { 'website::php': suffix => $php_suffix, module => ($operatingsystem == 'CentOS' and versioncmp($operatingsystemrelease, '8') >= 0) ? { true => 'remi-7.4', default => undef }, extras => { 'bcmath' => { ini_prefix => $ini_prefix_20, }, 'curl' => { ini_prefix => $ini_prefix_20, }, 'dom' => { ini_prefix => $ini_prefix_20, }, 'enchant' => { ini_prefix => $ini_prefix_20, }, 'exif' => { ini_prefix => $ini_prefix_20, }, 'fileinfo' => { ini_prefix => $ini_prefix_20, }, 'gmp' => { ini_prefix => $ini_prefix_20, }, 'intl' => { ini_prefix => $ini_prefix_20, }, 'mysqlnd' => { ini_prefix => $ini_prefix_20, }, 'pdo' => { ini_prefix => $ini_prefix_20, }, 'simplexml' => { ini_prefix => $ini_prefix_20, }, 'soap' => { ini_prefix => $ini_prefix_20, }, 'xmlwriter' => { ini_prefix => $ini_prefix_20, }, 'mysqli' => { ini_prefix => $ini_prefix_30, }, 'pdo_mysql' => { ini_prefix => $ini_prefix_30, # Provided by the php-mysql package in CentOS and declared with "Provides" # And Ubuntu is the same but without the "Provides" provider => "none", }, 'xmlreader' => { ini_prefix => $ini_prefix_30, }, 'zip' => { ini_prefix => $ini_prefix_30, package_prefix => "${variant_prefix}${extra_prefix}" }, 'apcu' => { ini_prefix => $ini_prefix_40, package_prefix => "${variant_prefix}${extra_prefix}" }, 'imagick' => { ini_prefix => $ini_prefix_40, package_prefix => "${variant_prefix}${extra_prefix}" }, } + $extra_extras, } #Setup MySQL, using (private) templates to make sure that we set non-std passwords and a default user if $operatingsystem == 'CentOS' { if versioncmp($operatingsystemrelease, '7') >= 0 { $mysqlpackage = 'mariadb' $mysqlsuffix = '' # Required for SELinux rule setting/status checks if versioncmp($operatingsystemrelease, '8') >= 0 { $semanage_package_name = 'policycoreutils-python-utils' } else { $semanage_package_name = 'policycoreutils-python' } package { 'policycoreutils-python': name => $semanage_package_name, ensure => present, } $extra_packages = [ 'perl-Sys-Syslog', #Required for Perl SPF checking ] package { $extra_packages: ensure => installed } } else { $mysqlpackage = 'mysql' $mysqlsuffix = '55w' } $phpmysqlsuffix = 'nd' } elsif $operatingsystem == 'Ubuntu' { $mysqlpackage = 'mariadb' $mysqlsuffix = '' $phpmysqlsuffix = '' } else { fail("No MySQL support for ${operatingsystem}") } include ::defaultusers::params class { 'website::mysql': mysqluser => $::defaultusers::params::mysql_user, mysqlpassword => $::defaultusers::params::mysql_password, mysqlprefix => $mysqlpackage, mysqlsuffix => $mysqlsuffix, phpsuffix => $php_suffix, phpmysqlsuffix => $phpmysqlsuffix } # Additional supporting directories that aren't served as sites file { [ '/srv/sites/errorhandling', '/srv/sites/private', '/srv/cms' ]: ensure => directory, } } class ibboardvpsnode ( $primary_ip, $gateway_ip = undef, $proxy_4to6_ip_prefix = undef, $proxy_upstream = undef, $nat64_ranges = [], $mailserver, $imapserver, $mailrelays = [], $firewall_cmd = 'iptables', ){ class { 'basevpsnode': primary_ip => $primary_ip, gateway_ip => $gateway_ip, proxy_4to6_ip_prefix => $proxy_4to6_ip_prefix, proxy_upstream => $proxy_upstream, nat64_ranges => $nat64_ranges, mailserver => $mailserver, imapserver => $imapserver, mailrelays => $mailrelays, firewall_cmd => $firewall_cmd, } # Set timezone to something sensible file { "/etc/localtime": ensure => 'link', target => '/usr/share/zoneinfo/Europe/London', } file { "${apache::conf_dir}/conf.d/greatfirewallagainstchina.conf": ensure => file, } # Debian doesn't handle sensible depends like module names because of the underscore # So we need to use the package name package { "mod_cspnonce": name => $osfamily == 'Debian' ? { true => "libapache2-mod-cspnonce", default => "mod_cspnonce" }, ensure => installed, } # Common modules used by multiple sites (mod_auth_basic is safe because we HTTPS all the things) $mods = [ 'auth_basic', 'authn_core', 'authn_file', 'authz_user', 'deflate', 'xsendfile', 'cspnonce' ] apache::mod { $mods:; } #Configure our sites, using templates for the custom fragments where the extra content is too long class { "devsite": proxy_4to6_ip => $proxy_4to6_ip_prefix != undef ? { true => "$proxy_4to6_ip_prefix:01", default => undef } } class { "adminsite": proxy_4to6_ip => $proxy_4to6_ip_prefix != undef ? { true => "$proxy_4to6_ip_prefix:02", default => undef } } website::https::multitld { 'www.ibboard': proxy_4to6_ip => $proxy_4to6_ip_prefix != undef ? { true => "$proxy_4to6_ip_prefix:03", default => undef }, custom_fragment => template("privat/apache/ibboard.fragment"), letsencrypt_name => 'ibboard.co.uk', csp_override => { "report-uri" => "https://ibboard.report-uri.com/r/d/csp/enforce", "default-src" => "'none'", "img-src" => "'self' https://live.staticflickr.com/", "script-src" => "'self' https://auth-server.herokuapp.com/proxy https://api.tumblr.com/", "style-src" => "'self'", "font-src" => "'self'", "form-action" => "'self'", "connect-src" => "'self' https://api.tumblr.com/", } } website::https::redir { 'mail.ibboard.co.uk': proxy_4to6_ip => $proxy_4to6_ip_prefix != undef ? { true => "$proxy_4to6_ip_prefix:03", default => undef }, redir => 'https://ibboard.co.uk/', docroot => "${website::basedir}/ibboard", letsencrypt_name => 'ibboard.co.uk', separate_log => true, } website::https::redir { 'imap.ibboard.co.uk': proxy_4to6_ip => $proxy_4to6_ip_prefix != undef ? { true => "$proxy_4to6_ip_prefix:03", default => undef }, redir => 'https://ibboard.co.uk/', docroot => "${website::basedir}/ibboard", letsencrypt_name => 'ibboard.co.uk', separate_log => true, } class { "hiveworldterrasite": proxy_4to6_ip => $proxy_4to6_ip_prefix != undef ? { true => "$proxy_4to6_ip_prefix:04", default => undef } } class { "bdstrikesite": proxy_4to6_ip => $proxy_4to6_ip_prefix != undef ? { true => "$proxy_4to6_ip_prefix:05", default => undef } } website::https::multitld { 'www.abiknight': proxy_4to6_ip => $proxy_4to6_ip_prefix != undef ? { true => "$proxy_4to6_ip_prefix:06", default => undef }, custom_fragment => "$website::htmlphpfragment ErrorDocument 404 /error.php", letsencrypt_name => 'abiknight.co.uk', } class { "webmailpimsite": proxy_4to6_ip_pim => $proxy_4to6_ip_prefix != undef ? { true => "$proxy_4to6_ip_prefix:08", default => undef }, proxy_4to6_ip_webmail => $proxy_4to6_ip_prefix != undef ? { true => "$proxy_4to6_ip_prefix:09", default => undef }, } } class adminsite ($proxy_4to6_ip) { apache::mod { 'info':; 'status':; 'cgi':; } website::https::multitld { 'admin.ibboard': proxy_4to6_ip => $proxy_4to6_ip, force_no_index => false, ssl_ca_chain => '', csp_override => { "report-uri" => "https://ibboard.report-uri.com/r/d/csp/enforce", "img-src" => "'self' data:", }, csp_report_override => { "img-src" => "'self' data:", }, custom_fragment => template("privat/apache/admin.fragment"), } if $osfamily == 'RedHat' { $cron_user = 'apache' } elsif $osfamily == 'Debian' { $cron_user = 'www-data' } cron { 'loadavg': command => '/usr/local/bin/run-loadavg-logger', user => $cron_user, minute => '*/6' } cron { 'awstats': command => '/usr/local/bin/update-awstats > /srv/sites/admin/awstats.log', user => $cron_user, hour => '*/6', minute => '0' } } class hiveworldterrasite ($proxy_4to6_ip) { website::https::multitld { 'www.hiveworldterra': proxy_4to6_ip => $proxy_4to6_ip, force_no_www => false, letsencrypt_name => 'hiveworldterra.co.uk', custom_fragment => template("privat/apache/hwt.fragment"), } website::https::multitld { 'forums.hiveworldterra': proxy_4to6_ip => $proxy_4to6_ip, letsencrypt_name => 'forums.hiveworldterra.co.uk', custom_fragment => template("privat/apache/forums.fragment"), } website::https::multitld { 'skins.hiveworldterra': proxy_4to6_ip => $proxy_4to6_ip, letsencrypt_name => 'skins.hiveworldterra.co.uk', custom_fragment => template("privat/apache/skins.fragment"), } website::https::redir { 'hiveworldterra.ibboard.co.uk': proxy_4to6_ip => $proxy_4to6_ip, redir => 'https://www.hiveworldterra.co.uk/', docroot => "${website::basedir}/hiveworldterra", letsencrypt_name => 'hiveworldterra.ibboard.co.uk', separate_log => true, } } class bdstrikesite ($proxy_4to6_ip) { website::https::multitld { 'www.bdstrike': proxy_4to6_ip => $proxy_4to6_ip, docroot_owner => $defaultusers::secondary_user, docroot_group => 'editors', letsencrypt_name => 'bdstrike.co.uk', custom_fragment => template("privat/apache/bdstrike.fragment"), csp_override => { "report-uri" => "https://ibboard.report-uri.com/r/d/csp/enforce", "font-src" => "'self' https://fonts.gstatic.com/ https://s0.wp.com/i/fonts/inter/ data:", "img-src" => "'self' https://secure.gravatar.com/ https://ps.w.org/ https://s.w.org/ data:", "style-src" => "'self' https://fonts.googleapis.com/ 'unsafe-inline'", "connect-src" => "'self' https://www.sandbox.paypal.com/ https://www.paypal.com/", "frame-ancestors" => "'self'" }, csp_report_override => { "report-uri" => "https://ibboard.report-uri.com/r/d/csp/reportOnly", "font-src" => "'self' https://fonts.gstatic.com/ https://s0.wp.com/i/fonts/inter/ data:", # TODO: What's generating it? "img-src" => "'self' https://secure.gravatar.com/ data:", "style-src" => "'self' https://fonts.googleapis.com/ https://ajax.googleapis.com/ajax/libs/jqueryui/ 'nonce-%{CSP_NONCE}e' 'unsafe-hashes' 'sha256-anQSeQoEnQnBulZOQkDOFf+e6xBIGmqh7M8YFT992co=' 'sha256-zJDyuABAg68wtWDFyIh+RRe+6Vm/r+BLwaNRCGNVyXI=' 'sha256-qMalr/MPLUDW4lX/rq/cGp1Eu/H0cu0Yg98pdu69Jxs=' 'sha256-mshqJ+hidJMRDeNLHknuDAeYLOPg2OTIIA3nZmHgi9U=' 'sha256-YnRUd/QjP/NuFgfjMHhNfMCqXh0RQIGdvQfMCOf6qkw=' 'sha256-EwdiFJgqhefinoeAymrWxOYW4kza2Ekos5MY0PlXYI0=' 'sha256-G4K9vh8e+37+l69S+lHTyX3CfcK95mQUgyxYPCb7uME=' 'sha256-t6oewASd7J1vBg5mQtX4hl8bg8FeegYFM3scKLIhYUc=' 'sha256-mAQYxa3mIYqoLBrm1zLu6sLajr8vUHVFLYNpl6dAakM=' 'sha256-A8foknjCsFBi1PlRehOrHq0pVySigUurqAUgZ2y2U8c=' 'sha256-biLFinpqYMtWHmXfkA1BPeCY0/fNt46SAZ+BBk5YUog=' 'sha256-WzSByVQ8yW/DKrr77TWVt7WEMzueRcfJZImOkjTBKmc=' 'sha256-efof3agGBAL/yN8TplyNbLEgDZ3wIGMK3UMYbe8slkA='", "script-src" => "'self' 'nonce-%{CSP_NONCE}e' 'sha256-hPnbct+H2uwUiwoh3kect6TJt4waDlLPfj47TO58lXc=' 'sha256-80Mr5Xc2f6hVSJwvFRRcNjAI9RMcnuTVAIzr6pIQswI=' 'sha256-zwGmIUR+Z6gWKbwoJ2Z3yGxI/XLETLqDqCRIV0qt/WA='", "connect-src" => "'self' https://www.sandbox.paypal.com/ https://www.paypal.com/", }, } cron { 'wordpress_cron': # Run "php -f wp-cron.php" on a schedule so that we can auto-update # without giving Apache full write access! command => "/usr/local/bin/bdstrike-cron", user => $website::apache_user, minute => '*/15', } } class devsite ($proxy_4to6_ip) { if $operatingsystem == 'CentOS' and versioncmp($operatingsystemrelease, '8') >= 0 { $package_name = 'python3-mod_wsgi' $mod_path = 'mod_wsgi_python3.so' } else { $package_name = undef $mod_path = undef } class { 'apache::mod::wsgi': package_name => $package_name, mod_path => $mod_path, } website::https::multitld { 'dev.ibboard': proxy_4to6_ip => $proxy_4to6_ip, #Make sure we're the first one hit for the tiny fraction of "no support" cases we care about (potentially Python for Mercurial!) # http://en.wikipedia.org/wiki/Server_Name_Indication#No_support priority => 1, letsencrypt_name => 'dev.ibboard.co.uk', custom_fragment => template("privat/apache/dev.fragment"), non_proxy_fragment => template("privat/apache/dev-nonproxy.fragment"), force_no_index => false, } } class webmailpimsite ($proxy_4to6_ip_pim, $proxy_4to6_ip_webmail) { # Webmail and Personal Information Management (PIM) sites website::https { 'webmail.ibboard.co.uk': proxy_4to6_ip => $proxy_4to6_ip_webmail, force_no_index => false, letsencrypt_name => 'webmail.ibboard.co.uk', custom_fragment => template("privat/apache/webmail.fragment"), } include ::apache::params website::https { 'pim.ibboard.co.uk': proxy_4to6_ip => $proxy_4to6_ip_pim, docroot_owner => $apache::params::user, docroot_group => 'editors', force_no_index => false, lockdown_requests => false, letsencrypt_name => 'pim.ibboard.co.uk', csp => false, csp_report => false, custom_fragment => template("privat/apache/pim.fragment"), } cron { 'owncloudcron': command => "/usr/local/bin/owncloud-cron", user => $apache::params::user, minute => '*/15', } } class email ( $mailserver, $imapserver, $mailserver_ip, $proxy_ip = undef, $proxy_upstream = [], $nat64_ranges = [], $mailrelays = [], ){ class { 'postfix': mailserver => $mailserver, mailserver_ip => $mailserver_ip, mailserver_proxy => $proxy_ip, proxy_upstream => $proxy_upstream, mailrelays => $mailrelays, nat64_ranges => $nat64_ranges, protocols => $mailserver_ip =~ Stdlib::IP::Address::V6 ? { true => 'all', default => 'ipv4' }, } class { 'dovecot': imapserver => $imapserver, imapserver_ip => $mailserver_ip, imapserver_proxy => $proxy_ip, proxy_upstream => $proxy_upstream, } # Unspecified SpamAssassin config dependencies that started # showing up as errors in our logs if $osfamily == 'RedHat' { $spamassassin_deps = ['perl-File-MimeInfo'] $spamassassin_dir = '/etc/mail/spamassassin/' $amavis_config = '/etc/amavisd/amavisd.conf' $amavis_rundir = '/var/run/amavisd' $amavis_spooldir = '/var/spool/amavisd' $amavis_quarantinedir = '/var/spool/amavisd/quarantine' $amavis_service = 'amavisd' # CentOS has a Clam service, but we call on demand (Ubuntu doesn't have a service) service { 'clamd@amavisd': ensure => 'stopped', enable=> 'mask', } } elsif $osfamily == 'Debian' { $spamassassin_deps = ['libfile-mimeinfo-perl'] $spamassassin_dir = '/etc/spamassassin/' $amavis_config = '/etc/amavis/conf.d/60-puppeted' $amavis_rundir = '/var/run/amavis' $amavis_spooldir = '/var/lib/amavis' $amavis_quarantinedir = '/var/spool/amavisd/quarantine' $amavis_service = 'amavis' } package { $spamassassin_deps: ensure => installed, } package { [ 'amavisd-new' ]: ensure => installed, tag => 'av', } service { $amavis_service: ensure => 'running', enable => 'true', } file { $amavis_config: ensure => present, content => epp('privat/postfix/amavis.conf.epp', { fqdn => $::fqdn, rundir => $amavis_rundir, spooldir => $amavis_spooldir, quarantinedir => $amavis_quarantinedir, } ), tag => 'av', } file { "${spamassassin_dir}local.cf": ensure => present, source => 'puppet:///private/postfix/spamassassin-local.cf', tag => 'av', } file { "${spamassassin_dir}ole2macro.cf": ensure => present, source => 'puppet:///common/ole2macro.cf', tag => 'av', } file { "${spamassassin_dir}ole2macro.pm": ensure => present, source => 'puppet:///common/spamassassin-vba-macro-master/ole2macro.pm', tag => 'av', } Package<| tag == 'av' |> -> File<| tag == 'av' |> File<| tag == 'av' |> { notify => Service[$amavis_service], } cron { 'Postwhite': command => "/usr/local/bin/postwhite 2>&1| grep -vE '^(Starting|Recursively|Getting|Querying|Removing|Sorting|$)'", user => 'root', weekday => 0, hour => 2, minute => 0, } } class cronjobs { package { 'cron': ensure => installed, name => $operatingsystem == 'Ubuntu' ? { true => 'cron', default => 'cronie' } } # Add Mutt for scripts that send emails, but stop it clogging the disk by keeping copies of emails package { 'mutt': ensure => installed, } file { '/etc/Muttrc.local': content => 'set copy = no', require => Package['mutt'], } # General server-wide cron jobs Cron { user => 'root' } cron { 'backupalldbs': command => "/usr/local/bin/backupalldbs", monthday => "*/2", hour => "4", minute => "9" } # Only run the Great Firewall Against China on IPv4 (since we don't have an IPv6 list # and the PROXY forwards the IPs to services, but not at the network level) cron { 'greatfirewallofchina': command => '/usr/local/bin/update-great-firewall-of-china', ensure => has_key($facts, 'ipaddress') ? { true => "present", default => "absent" }, hour => 3, minute => 30 } cron { 'permissions': command => '/usr/local/bin/set-permissions', hour => 3, minute => 2 } # Since we're only managing the local server, use our script that wraps "puppet apply" instead of PuppetMaster cron { 'puppet': command => '/usr/local/bin/puppet-apply | grep -v "Compiled catalog for\|Finished catalog run in\|Applied catalog in"', hour => '*/6', minute => 5 } cron { 'purgecaches': command => "/usr/local/bin/purge-caches", hour => '4', minute => '15', weekday => '1', } # Notify of uncommitted files cron { 'check-mercurial-committed': command => "/usr/local/bin/check-hg-status", user => $defaultusers::default_user, hour => '4', minute => '20', weekday => '0-6/3', #Sunday, Wednesday and Saturday morning } # Notify of available updates cron { 'check-yum-updates': ensure => absent, } cron { 'check-for-updates': command => '/usr/local/bin/check-updates', hour => '4', minute => '30', weekday => '0-6/3', #Sunday, Wednesday and Saturday morning } # And check whether anything needs restarting cron { 'check-needs-restarting': command => '/usr/local/bin/needs-restarting', hour => '4', minute => '45', weekday => '0-6/3', #Sunday, Wednesday and Saturday morning } }