diff options
Diffstat (limited to 'puppet/modules')
185 files changed, 3972 insertions, 752 deletions
diff --git a/puppet/modules/apt b/puppet/modules/apt -Subproject 1a72a99693c1d77bfe891546408f88264fca98e +Subproject 64fb988c0e37d64fb3e241dc95f156072e43bf2 diff --git a/puppet/modules/backupninja b/puppet/modules/backupninja new file mode 160000 +Subproject daeb1a1f112a4dbf6b39565f0dea461e46a6468 diff --git a/puppet/modules/check_mk b/puppet/modules/check_mk new file mode 160000 +Subproject 5c11597a055858b5ddc1ce8f7f8db249f5f1b33 diff --git a/puppet/modules/couchdb b/puppet/modules/couchdb -Subproject 20deb0652ccfe105eddec6ba2ad32b8d633705f +Subproject c8f5443e0998d3d3d43505ff5a6fdf8c438d6c2 diff --git a/puppet/modules/git b/puppet/modules/git -Subproject 497a1034489e0dc3cab5dab2fb0a85778576973 +Subproject ba5dd8d5c8e09d521ff49f1ebc753601e449f82 diff --git a/puppet/modules/leap_mx/manifests/init.pp b/puppet/modules/leap_mx/manifests/init.pp new file mode 100644 index 00000000..b59eac01 --- /dev/null +++ b/puppet/modules/leap_mx/manifests/init.pp @@ -0,0 +1,62 @@ +class leap_mx { + + $leap_mx = hiera('couchdb_leap_mx_user') + $couchdb_user = $leap_mx['username'] + $couchdb_password = $leap_mx['password'] + + $couchdb_host = 'localhost' + $couchdb_port = '4096' + + include soledad::common + include site_apt::preferences::twisted + + # + # USER AND GROUP + # + + group { 'leap-mx': + ensure => present, + allowdupe => false; + } + + user { 'leap-mx': + ensure => present, + allowdupe => false, + gid => 'leap-mx', + home => '/etc/leap', + require => Group['leap-mx']; + } + + # + # LEAP-MX CONFIG + # + + file { '/etc/leap/mx.conf': + content => template('leap_mx/mx.conf.erb'), + owner => 'leap-mx', + group => 'leap-mx', + mode => '0600', + notify => Service['leap-mx']; + } + + # + # LEAP-MX CODE + # + + package { 'leap-mx': + ensure => installed, + require => Class['site_apt::preferences::twisted'] + } + + # + # LEAP-MX DAEMON + # + + service { 'leap-mx': + ensure => running, + enable => true, + hasstatus => true, + hasrestart => true, + require => [ Package['leap-mx'] ]; + } +} diff --git a/puppet/modules/leap_mx/templates/mx.conf.erb b/puppet/modules/leap_mx/templates/mx.conf.erb new file mode 100644 index 00000000..e05bc150 --- /dev/null +++ b/puppet/modules/leap_mx/templates/mx.conf.erb @@ -0,0 +1,15 @@ +[mail1] +path=/var/mail/vmail/Maildir +recursive=True + +[couchdb] +user=<%= @couchdb_user %> +password=<%= @couchdb_password %> +server=<%= @couchdb_host %> +port=<%= @couchdb_port %> + +[alias map] +port=4242 + +[check recipient] +port=2244 diff --git a/puppet/modules/postfix b/puppet/modules/postfix new file mode 160000 +Subproject 1103a73ab4253712c6446bba7a443619fe51671 diff --git a/puppet/modules/rsyslog b/puppet/modules/rsyslog new file mode 160000 +Subproject 20fbda6b91472e656331a9c64630fb207e9f578 diff --git a/puppet/modules/rubygems b/puppet/modules/rubygems -Subproject 1e5ed3dbef9381bb9d5e2a7b4957bb3f5288d6a +Subproject ef820cfec3321d17be99ef814318adb4e3cc1e9 diff --git a/puppet/modules/site_apache/files/conf.d/security b/puppet/modules/site_apache/files/conf.d/security new file mode 100644 index 00000000..a5ae5bdc --- /dev/null +++ b/puppet/modules/site_apache/files/conf.d/security @@ -0,0 +1,55 @@ +# +# Disable access to the entire file system except for the directories that +# are explicitly allowed later. +# +# This currently breaks the configurations that come with some web application +# Debian packages. It will be made the default for the release after lenny. +# +#<Directory /> +# AllowOverride None +# Order Deny,Allow +# Deny from all +#</Directory> + + +# Changing the following options will not really affect the security of the +# server, but might make attacks slightly more difficult in some cases. + +# +# ServerTokens +# This directive configures what you return as the Server HTTP response +# Header. The default is 'Full' which sends information about the OS-Type +# and compiled in modules. +# Set to one of: Full | OS | Minimal | Minor | Major | Prod +# where Full conveys the most information, and Prod the least. +# +#ServerTokens Minimal +ServerTokens Prod + +# +# Optionally add a line containing the server version and virtual host +# name to server-generated pages (internal error documents, FTP directory +# listings, mod_status and mod_info output etc., but not CGI generated +# documents or custom error documents). +# Set to "EMail" to also include a mailto: link to the ServerAdmin. +# Set to one of: On | Off | EMail +# +#ServerSignature Off +ServerSignature Off + +# +# Allow TRACE method +# +# Set to "extended" to also reflect the request body (only for testing and +# diagnostic purposes). +# +# Set to one of: On | Off | extended +# +#TraceEnable Off +TraceEnable On + +# Setting this header will prevent other sites from embedding pages from this +# site as frames. This defends against clickjacking attacks. +# Requires mod_headers to be enabled. +# +Header set X-Frame-Options: "DENY" diff --git a/puppet/modules/site_apache/manifests/common.pp b/puppet/modules/site_apache/manifests/common.pp new file mode 100644 index 00000000..72f24838 --- /dev/null +++ b/puppet/modules/site_apache/manifests/common.pp @@ -0,0 +1,26 @@ +class site_apache::common { + # installs x509 cert + key and common config + # that both nagios + leap webapp use + + $web_domain = hiera('domain') + $domain_name = $web_domain['name'] + + include x509::variables + include site_config::x509::commercial::cert + include site_config::x509::commercial::key + include site_config::x509::commercial::ca + + Class['Site_config::X509::Commercial::Key'] ~> Service[apache] + Class['Site_config::X509::Commercial::Cert'] ~> Service[apache] + Class['Site_config::X509::Commercial::Ca'] ~> Service[apache] + + include site_apache::module::rewrite + + class { '::apache': no_default_site => true, ssl => true } + + apache::vhost::file { + 'common': + content => template('site_apache/vhosts.d/common.conf.erb') + } + +} diff --git a/puppet/modules/site_apache/manifests/module/alias.pp b/puppet/modules/site_apache/manifests/module/alias.pp new file mode 100644 index 00000000..c1f5e185 --- /dev/null +++ b/puppet/modules/site_apache/manifests/module/alias.pp @@ -0,0 +1,5 @@ +class site_apache::module::alias ( $ensure = present ) +{ + + apache::module { 'alias': ensure => $ensure } +} diff --git a/puppet/modules/site_apache/manifests/module/expires.pp b/puppet/modules/site_apache/manifests/module/expires.pp new file mode 100644 index 00000000..f73a5607 --- /dev/null +++ b/puppet/modules/site_apache/manifests/module/expires.pp @@ -0,0 +1,4 @@ +class site_apache::module::expires ( $ensure = present ) +{ + apache::module { 'expires': ensure => $ensure } +} diff --git a/puppet/modules/site_apache/manifests/module/headers.pp b/puppet/modules/site_apache/manifests/module/headers.pp new file mode 100644 index 00000000..f7caa28c --- /dev/null +++ b/puppet/modules/site_apache/manifests/module/headers.pp @@ -0,0 +1,5 @@ +class site_apache::module::headers ( $ensure = present ) +{ + + apache::module {'headers': ensure => $ensure } +} diff --git a/puppet/modules/site_apache/manifests/module/removeip.pp b/puppet/modules/site_apache/manifests/module/removeip.pp new file mode 100644 index 00000000..f106167a --- /dev/null +++ b/puppet/modules/site_apache/manifests/module/removeip.pp @@ -0,0 +1,5 @@ +class site_apache::module::removeip ( $ensure = present ) +{ + package { 'libapache2-mod-removeip': ensure => $ensure } + apache::module { 'removeip': ensure => $ensure } +} diff --git a/puppet/modules/site_apache/manifests/module/rewrite.pp b/puppet/modules/site_apache/manifests/module/rewrite.pp new file mode 100644 index 00000000..7ad00a0c --- /dev/null +++ b/puppet/modules/site_apache/manifests/module/rewrite.pp @@ -0,0 +1,5 @@ +class site_apache::module::rewrite ( $ensure = present ) +{ + + apache::module { 'rewrite': ensure => $ensure } +} diff --git a/puppet/modules/site_apache/templates/vhosts.d/api.conf.erb b/puppet/modules/site_apache/templates/vhosts.d/api.conf.erb index ae894cd4..3360ac59 100644 --- a/puppet/modules/site_apache/templates/vhosts.d/api.conf.erb +++ b/puppet/modules/site_apache/templates/vhosts.d/api.conf.erb @@ -10,17 +10,26 @@ Listen 0.0.0.0:<%= api_port %> ServerName <%= api_domain %> SSLEngine on - SSLProtocol -all +SSLv3 +TLSv1 - SSLCipherSuite HIGH:MEDIUM:!aNULL:!SSLv2:!MD5:@STRENGTH + SSLProtocol all -SSLv2 SSLHonorCipherOrder on + SSLCompression off + SSLCipherSuite "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:ECDHE-RSA-RC4-SHA:ECDHE-ECDSA-RC4-SHA:AES128:AES256:RC4-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK" SSLCACertificatePath /etc/ssl/certs - SSLCertificateChainFile /etc/ssl/certs/leap_api.pem - SSLCertificateKeyFile /etc/x509/keys/leap_api.key - SSLCertificateFile /etc/x509/certs/leap_api.crt + SSLCertificateChainFile <%= scope.lookupvar('x509::variables::local_CAs') %>/<%= scope.lookupvar('site_config::params::ca_name') %>.crt + SSLCertificateKeyFile <%= scope.lookupvar('x509::variables::keys') %>/<%= scope.lookupvar('site_config::params::cert_name') %>.key + SSLCertificateFile <%= scope.lookupvar('x509::variables::certs') %>/<%= scope.lookupvar('site_config::params::cert_name') %>.crt RequestHeader set X_FORWARDED_PROTO 'https' + <IfModule mod_headers.c> +<% if @webapp['secure'] -%> + Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains" +<% end -%> + Header always unset X-Powered-By + Header always unset X-Runtime + </IfModule> + DocumentRoot /srv/leap/webapp/public # Check for maintenance file and redirect all requests diff --git a/puppet/modules/site_apache/templates/vhosts.d/common.conf.erb b/puppet/modules/site_apache/templates/vhosts.d/common.conf.erb new file mode 100644 index 00000000..ed430510 --- /dev/null +++ b/puppet/modules/site_apache/templates/vhosts.d/common.conf.erb @@ -0,0 +1,73 @@ +<VirtualHost *:80> + ServerName <%= domain %> + ServerAlias www.<%= domain %> + RewriteEngine On + RewriteRule ^.*$ https://<%= domain -%>%{REQUEST_URI} [R=permanent,L] +</VirtualHost> + +<VirtualHost *:443> + ServerName <%= domain_name %> + ServerAlias <%= domain %> + ServerAlias www.<%= domain %> + + SSLEngine on + SSLProtocol all -SSLv2 + SSLHonorCipherOrder on + SSLCompression off + SSLCipherSuite "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:ECDHE-RSA-RC4-SHA:ECDHE-ECDSA-RC4-SHA:AES128:AES256:RC4-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK" + + SSLCACertificatePath /etc/ssl/certs + SSLCertificateChainFile <%= scope.lookupvar('x509::variables::local_CAs') %>/<%= scope.lookupvar('site_config::params::commercial_ca_name') %>.crt + SSLCertificateKeyFile <%= scope.lookupvar('x509::variables::keys') %>/<%= scope.lookupvar('site_config::params::commercial_cert_name') %>.key + SSLCertificateFile <%= scope.lookupvar('x509::variables::certs') %>/<%= scope.lookupvar('site_config::params::commercial_cert_name') %>.crt + + RequestHeader set X_FORWARDED_PROTO 'https' + + <IfModule mod_headers.c> +<% if (defined? @services) and (@services.include? 'webapp') and (@webapp['secure']) -%> + Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains" +<% end -%> + Header always unset X-Powered-By + Header always unset X-Runtime + </IfModule> + +<% if (defined? @services) and (@services.include? 'webapp') -%> + DocumentRoot /srv/leap/webapp/public + + RewriteEngine On + # Check for maintenance file and redirect all requests + RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f + RewriteCond %{SCRIPT_FILENAME} !maintenance.html + RewriteCond %{REQUEST_URI} !/images/maintenance.jpg + RewriteRule ^.*$ %{DOCUMENT_ROOT}/system/maintenance.html [L] + + # http://www.modrails.com/documentation/Users%20guide%20Apache.html#_passengerallowencodedslashes_lt_on_off_gt + AllowEncodedSlashes on + PassengerAllowEncodedSlashes on + PassengerFriendlyErrorPages off + SetEnv TMPDIR /var/tmp + + # Allow rails assets to be cached for a very long time (since the URLs change whenever the content changes) + <Location /assets/> + Header unset ETag + FileETag None + ExpiresActive On + ExpiresDefault "access plus 1 year" + </Location> +<% end -%> + + +<% if (defined? @services) and (@services.include? 'monitor') -%> + <DirectoryMatch (/usr/share/nagios3/htdocs|/usr/lib/cgi-bin/nagios3|/etc/nagios3/stylesheets)> + <% if (defined? @services) and (@services.include? 'webapp') -%> + PassengerEnabled off + <% end -%> + AllowOverride all + # Nagios won't work with setting this option to "DENY", + # as set in conf.d/security (#4169). Therefor we allow + # it here, only for nagios. + Header set X-Frame-Options: "ALLOW" + </DirectoryMatch> +<% end -%> +</VirtualHost> + diff --git a/puppet/modules/site_apache/templates/vhosts.d/leap_webapp.conf.erb b/puppet/modules/site_apache/templates/vhosts.d/leap_webapp.conf.erb deleted file mode 100644 index 4b051699..00000000 --- a/puppet/modules/site_apache/templates/vhosts.d/leap_webapp.conf.erb +++ /dev/null @@ -1,46 +0,0 @@ -<VirtualHost *:80> - ServerName <%= domain %> - ServerAlias www.<%= domain %> - RewriteEngine On - RewriteRule ^.*$ https://<%= domain -%>%{REQUEST_URI} [R=permanent,L] -</VirtualHost> - -<VirtualHost *:443> - ServerName <%= domain %> - ServerAlias www.<%= domain %> - - SSLEngine on - SSLProtocol -all +SSLv3 +TLSv1 - SSLCipherSuite HIGH:MEDIUM:!aNULL:!SSLv2:!MD5:@STRENGTH - SSLHonorCipherOrder on - - SSLCACertificatePath /etc/ssl/certs - SSLCertificateChainFile /etc/ssl/certs/leap_webapp.pem - SSLCertificateKeyFile /etc/x509/keys/leap_webapp.key - SSLCertificateFile /etc/x509/certs/leap_webapp.crt - - RequestHeader set X_FORWARDED_PROTO 'https' - - DocumentRoot /srv/leap/webapp/public - - RewriteEngine On - # Check for maintenance file and redirect all requests - RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f - RewriteCond %{SCRIPT_FILENAME} !maintenance.html - RewriteCond %{REQUEST_URI} !/images/maintenance.jpg - RewriteRule ^.*$ %{DOCUMENT_ROOT}/system/maintenance.html [L] - - # http://www.modrails.com/documentation/Users%20guide%20Apache.html#_passengerallowencodedslashes_lt_on_off_gt - AllowEncodedSlashes on - PassengerAllowEncodedSlashes on - PassengerFriendlyErrorPages off - SetEnv TMPDIR /var/tmp - - <% if (defined? @services) and (@services.include? 'monitor') -%> - <DirectoryMatch (/usr/share/nagios3/htdocs|/usr/lib/cgi-bin/nagios3|/etc/nagios3/stylesheets)> - PassengerEnabled off - AllowOverride all - </DirectoryMatch> - <% end -%> -</VirtualHost> - diff --git a/puppet/modules/site_apt/files/keys/cloudant-key.asc b/puppet/modules/site_apt/files/keys/cloudant-key.asc deleted file mode 100644 index 99716a3c..00000000 --- a/puppet/modules/site_apt/files/keys/cloudant-key.asc +++ /dev/null @@ -1,52 +0,0 @@ ------BEGIN PGP PUBLIC KEY BLOCK----- -Version: GnuPG v1.4.11 (GNU/Linux) - -mQINBFE7fhIBEACrDREcODnhdugNozMeBawOm2irpNCP54yMljST/DOXx1uo3gQw -HnVcQ4lL7lXhbfL6Tp0WhrNYTWbbWHO0DaQbW0GQMHa2BGG0Xm0HPrjr3j55tAcM -NPr0ArDuplq4Py2pwviZiEtQkkn+biH9oV+N3jNO+8+zVHLVU7pHaX6Yd7HAxFM8 -XX+7SeVtplZ7nvSxUREiMNxQb9o0kYNRPS+b0UjiIXHrFO9afl7lTdg/I8AhKWa0 -3jJoY/IRvVopJblISQNGFipR11Lpu5sOHghgz4V8mk/in7JLMmoqSl5DP5VhRII8 -OyADBjaUJD2mkv5cGaevqpB4AId78X9+Y62gFJrGkIHY9uBxIUkRe+leYI4Zz4Bm -D9qBIbEY/kKkblTlC1G7u3qbGQcsbCRVIOnhruCih7vifcP40YwGUk5NmDA5AE78 -OovCGYGp4zMepDTSJxGT3sJOTEbzN09so6C7fQWBeQiiG5Uepp1q+VnaGpT1L4rc -Y6yRbu9dOFj6WzY4W5HtnbalzTIEYy+SIGZqRkJt6jREYLiFfyrpSFIgGoJAs0yx -9M0McXfeOod69TPufB1PeppnBwFcTmYNYxakusQxAebRDPEBZqoEgl0gMmxWbAdI -nxGMWWnSsN/Dj0dXRf1MG/5akOhX2zQcUzBOE2m/Xr5kjDPYFtFxVJDGzQARAQAB -tDNDbG91ZGFudCBQYWNrYWdlIFNpZ25pbmcgS2V5IDxzdXBwb3J0QGNsb3VkYW50 -LmNvbT6JAj4EEwECACgFAlE7fhICGwMFCQHhM4AGCwkIBwMCBhUIAgkKCwQWAgMB -Ah4BAheAAAoJEFngH70Vvo4mciIP/AlqHA/LDtSYfrFwdXifY2ImCMyzYvH40Ko2 -DHCw2qDjvK5UXn1iWuzXidT7DrxOfYoZpzySRP7VGyHxa3VPhOtzLDZSvTpk9ELo -2x2IczUwLC17M0Iis4CpqlxSFIBYGX78pMzvsEyC4TFqUDfXRlye3apjD0iwK0hE -kdP1+TPdJjhWImJm+3TLu45zTw3Ph5dnf5pLQPNhKfBSdku+vRrd35N5hHso9S1y -Z3NrxcQlWnXuqkLIA14gM7qbBFD+el9Y+tZ7ERGYg3s5uNDQRTb0QC8zg/um2+zW -4hHmuRcWY3n8IgHcYUruC1VyrrsFIWWMyLv7SZkAAoSY+jKyESDfYpJQ8jtZ4EF9 -2/gYm4FgZR8j4gWkzHSLGVt/4EIykJZb0yIg/QEovmmHqpy8xYri3goMSl4h7tfF -TOCZLTzTyQ7xONdyEsrvQPhmdtXEgvSo5S7ZU9kkx32OjCoshLLjhtqAipBgEXqb -hElFo1oSyOVoGc7UNh7KNBjWfeP8dNdCbIbIYPMeM0/CVjD60kW5ZEVDuYglT+Rz -enJJvS4Hs+fq8cFNxMB+l64qE7iS+I6RP2bPeQM2aBa2UZNWxUIbXF7bb3zLrCGn -GT8GF1AFRoW3GiDzB7QnLVp8BhIaqFUzbDim+5mFFG8wguxHTiz4snDdQXq2Es6V -UETFsNsluQINBFE7fhIBEADIyLHyBh8AKJKQHksFAPHOyA48ocxgQDpQnqYlQcAK -D8eUbRXciIz4ePBmvjaQmz8wJgWULc04u4i9jK8Jd/Ks+VhEz3AjRBfjvkBaVMog -FMPKaoDn9LVMBSZJ3fcC1DVck1oO8LnFIdktt0zhvzG+pV5b/UTRsVZmwNh1p2dM -4cJswxlksJXYnI9tFA74qiomDCPYM0zpv7TEjX23PZTLqTSHP5aWctx+MIEtdoqp -EsEDL6npvYBRz/tuL41cUWs7CItH131Hyuizo4vGrxgWPnoXIxLmLOOZCMk/kbx0 -XCSvengqYwNgAOlIjewtTw+WJm1gtNQQeKmaXBX7njf2Wz7LI/0KVxttEpKT5/5y -embOGn7My9i7zOc1frMCDivIOTQDBZTzR9o7/6wUJ69DIoFLMlO8UcCK3R7o5VUI -ezx+XYsOAD7D2vKoiD8Se65Vnax2rfFlLP7OQqdem5l2lkHpJzP3lA8qmA2MfJ7V -jsk7eDSyJQjG5c6KBoaFlYGhp/E2kR82cAKVaFIbW3euMM4XK6Mgzy3+DVKfk8mu -AEuHub7plfxM+65yjLNAK6l6IKtY1HfM7F4GFyNSd3mNNcWN7ceIHh8Ur4DeD2Tp -7r3XcWd6/czLYNsw2BAHeVUxnMTCeGN99UZTtHgVq9IJMOCDOPwMSzHFfZ6sNaYL -qQARAQABiQIlBBgBAgAPBQJRO34SAhsMBQkB4TOAAAoJEFngH70Vvo4mpokP/jJJ -2mXdhMVqZCtZhwphJfdxg8nBERzrd6ebXxKbTq1MmSN/fDwLknPabFHUpzk1ADCf -6mh2o0HB+67yMzo1UVtyfPOaHgCE/pWer5ultJM8gOdpBfSWL8jRwU8ZQ4fDu3z8 -AC6zTNq7znOVLEzZPy8U7q5Rt5/6QdQYoTLe6DwlLmkflzWP5VWi/mTGvtu/t5OV -tGZkzBYQ5QAXRXXkKswqkJpQFuW6d1vlYm9+x/+Q1+2kGT+CKbRAkqkf77qVcyJR -1M2JQSs4ko+rLMZzr01sYA+EBD17nxqV8vUdYebNc9Qnk8Aphid1zarUbySgAdnJ -5SLAjLe/6N6IEE9F3uKsPEs87gJrnwrYHRrmu0wAPwA0cMmtgD4Bz7Iiz4CLYPFW -rHpQCA313K+rS/LLfLBL66wIRKcPuYIFR9N03jX9eGR6qtk0b5Zb3YjWOo4V9Q1r -o+g6IB0Us5vH6ISuokq7Bv+8cXhEMVoctL9A8xWN1KDkweZ+7dNWCGV8lUWKy3Hw -ig6hENH6H7J57U8H2v2aZTeUo6e7VDP9gddNKPSEEeoBKfVnWYGoG8mVPQ2PzTgZ -ZO2vwp4c3Ix/kIV3xe+/Opcq1lxYhD7HSre1MB7HOeFmis6tBBjMJPaatZVfzj1v -6Uhz5oUCwcPol8rsp69DvGVUPSHfDwBxurDX71oG -=lEm7 ------END PGP PUBLIC KEY BLOCK----- diff --git a/puppet/modules/site_apt/files/keys/leap_key.asc b/puppet/modules/site_apt/files/keys/leap_key.asc index b69251f0..b6b5077b 100644 --- a/puppet/modules/site_apt/files/keys/leap_key.asc +++ b/puppet/modules/site_apt/files/keys/leap_key.asc @@ -1,5 +1,5 @@ -----BEGIN PGP PUBLIC KEY BLOCK----- -Version: GnuPG v1.4.11 (GNU/Linux) +Version: GnuPG v1.4.14 (GNU/Linux) mQINBFESwt0BEAC2CR+XgW04DVwT427v2T4+qz+O/xGOwQcalVaSOUuguYgf29en Apb6mUqROOTuJWN1nw1lvXiA6iFxg6DjDUhsp6j54X7GAAAjZ9QuavPgcsractsJ @@ -36,7 +36,19 @@ y9k8peFB7wwf0sW3Eg78XFsfy4gyV619VnBR+PbfOpKqFFXAodF1mFiIrPeefaVp F9fiQ5Owt0sJjDaJnYT83ksAO2Aj+VsY3UjnDrGFaiV8Neit9y/8W8DqmZ3EZEF/ M3iS0yDjqqt9ACFD+jkGlKYsyHv7gbpTq0yi6u/kRXHUTIvVwFL9M6Z6AUcG8gzo qbKhXGfWKEq0lN5HAjJ//V9ro3DekFd0A+NQOlFV6XtspZwphVdtW1WS078HmVlw -F5dbD8pcfT/RjbkCDQRREsLdARAA3Frw+j6H9McEIi/gjiGwvxnIdGc8McWchnFp +F5dbD8pcfT/RjYkCPQQTAQoAJwIbAwULCQgHAwUVCgkICwUWAgMBAAIeAQIXgAUC +UvT9ZgUJA8NuBQAKCRAeNKGCjiB5AXB+D/9k/BzZdAczQ3/v7hKrN9y3/D8kOEYK +rF8HdcBOH522sN6mqvm7wGkf3RmNSi731m6vzlbBSonrAT5KDMpj+THOmUcY29V5 +a1YOgFCCkToOfl+LmlLiuqfrGCJyE28MKMrsi2zMBKhsSxhvcI0EhJkQpPBu8gUs +XW1GSHuh5CYzwf/i8eNDpVrhHjRF0AVCOWIq52LTR62QchR+6ci/wVDHWd9Ase5X +8rxNnt2/pCbgATklQbmRcQS6efTVk3oXk1DZ8M46vayJ1g2BFuIi7pohiekLAAAt +MCwRKHTHvtPkGAUAEXExPGS78qHxLHIau2VCtSBxm+bQX+ZyCMANDpI+ZTFp1APJ +9SpbtGozuQOpWFjWY1rERunrbyWHIb2DuVVNKGiHlkMJB76zzysvbIPYWx1RqD6s +KFJBkjrM0xn8H+D6qzwzGfmX1Yaw12oYA6pcai4aK5sO7KHt+THAxYAcVF7qxGU7 +lnDifM56hrH/DbE5InlDC8OUqDysj0cHacRee+ZYtj7TiEykWfP5RrZCLQ7L6Jd/ +HtgQti/9TVUaFkIlQCfvF+l4BYZQYvnhx3MVK7ChKLmy6AVQLWnDrBrDvl07HLvW +6pslRzVHfWyIYng0pZ0HvK+MpQztCoUcDK470mjlpAtjNHuyKh6r6TtaiVK8MgbR +Sx/NMHb1/PXQJrkCDQRREsLdARAA3Frw+j6H9McEIi/gjiGwvxnIdGc8McWchnFp OWvdhTW9056v+y22DoKbULjT8k+8GzuRQ0xp4VwCC1rX3UExwceczzGs+tSKuIGm g1ELygsaOZHdQBNLGPvn+TZNGlaYXPlQo7m8YhXGHwgQrdKyjcFD5xnOHxe981LT q+IQ6jVYhho7/Qik9rVE1XHxoOfYvnNZJD0cFdf9OcX47YoqmM4sZYPMoOmKoVQT @@ -59,5 +71,5 @@ Dxix2FBXQU/4pVpGHjXTQP6RqeTrAedXvpgCHWP1UIlswIQecGmQcJ/hRZjd+0vl cjfCYhZHr7N96Da6Cy8v2fZiZHaSAt7T2oIZ9X3gEh/kOlLDcuIdvMHUfojn0MrP Ce1AqOHyQQqhkVylvZpS0PdE0VW3PmJ98uKfX2FVAOTUD4Rw3n9Ew7bfM249HuP4 JOXi/Skp4sBB/xgrtV1u+E+BW0SS/BOiwfrI4xUy+MrWuw== -=4STg +=Om8x -----END PGP PUBLIC KEY BLOCK----- diff --git a/puppet/modules/site_apt/manifests/init.pp b/puppet/modules/site_apt/manifests/init.pp index 8821c110..9facf4cc 100644 --- a/puppet/modules/site_apt/manifests/init.pp +++ b/puppet/modules/site_apt/manifests/init.pp @@ -1,15 +1,6 @@ class site_apt { - # on couchdb we need to include squeeze in apt preferences, - # so the cloudant package can pull some packages from squeeze - # template() must be unquoted ! - if 'couchdb' in $::services { - $custom_preferences = template("site_apt/preferences.include_squeeze") - } else { - $custom_preferences = '' - } class { 'apt': - custom_preferences => $custom_preferences, custom_key_dir => 'puppet:///modules/site_apt/keys' } @@ -37,6 +28,6 @@ class site_apt { # The creation of sources.list depends on the lsb package File['/etc/apt/preferences'] -> - Exec['refresh_apt'] - Package <| ( title != 'lsb' ) |> + Exec['refresh_apt'] -> + Package <| ( title != 'lsb' ) |> } diff --git a/puppet/modules/site_apt/manifests/preferences/check_mk.pp b/puppet/modules/site_apt/manifests/preferences/check_mk.pp new file mode 100644 index 00000000..580e0d3f --- /dev/null +++ b/puppet/modules/site_apt/manifests/preferences/check_mk.pp @@ -0,0 +1,9 @@ +class site_apt::preferences::check_mk { + + apt::preferences_snippet { 'check-mk': + package => 'check-mk-*', + release => "${::lsbdistcodename}-backports", + priority => 999; + } + +} diff --git a/puppet/modules/site_apt/manifests/preferences/twisted.pp b/puppet/modules/site_apt/manifests/preferences/twisted.pp new file mode 100644 index 00000000..abff6838 --- /dev/null +++ b/puppet/modules/site_apt/manifests/preferences/twisted.pp @@ -0,0 +1,9 @@ +class site_apt::preferences::twisted { + + apt::preferences_snippet { 'python-twisted': + package => 'python-twisted*', + release => "${::lsbdistcodename}-backports", + priority => 999; + } + +} diff --git a/puppet/modules/site_apt/templates/wheezy/postfix.seeds b/puppet/modules/site_apt/templates/wheezy/postfix.seeds new file mode 100644 index 00000000..1a878ccc --- /dev/null +++ b/puppet/modules/site_apt/templates/wheezy/postfix.seeds @@ -0,0 +1 @@ +postfix postfix/main_mailer_type select No configuration diff --git a/puppet/modules/site_check_mk/files/agent/local_checks/all_hosts/run_node_tests.sh b/puppet/modules/site_check_mk/files/agent/local_checks/all_hosts/run_node_tests.sh new file mode 100644 index 00000000..1dd0afc9 --- /dev/null +++ b/puppet/modules/site_check_mk/files/agent/local_checks/all_hosts/run_node_tests.sh @@ -0,0 +1,5 @@ +#!/bin/sh +# +# runs node tests + +/srv/leap/bin/run_tests --checkmk diff --git a/puppet/modules/site_check_mk/files/agent/local_checks/mx/check_leap_mx.sh b/puppet/modules/site_check_mk/files/agent/local_checks/mx/check_leap_mx.sh new file mode 100755 index 00000000..b8687c9a --- /dev/null +++ b/puppet/modules/site_check_mk/files/agent/local_checks/mx/check_leap_mx.sh @@ -0,0 +1,33 @@ +#!/bin/bash + + +WARN=1 +CRIT=5 + +# in minutes +MAXAGE=10 + +STATUS[0]='OK' +STATUS[1]='Warning' +STATUS[2]='Critical' +CHECKNAME='Leap_MX_Queue' + +WATCHDIR='/var/mail/vmail/Maildir/new/' + + +total=`find $WATCHDIR -type f -mmin +$MAXAGE | wc -l` + +if [ $total -lt $WARN ] +then + exitcode=0 +else + if [ $total -le $CRIT ] + then + exitcode=1 + else + exitcode=2 + fi +fi + +echo "${exitcode} ${CHECKNAME} stale_files=${total} ${STATUS[exitcode]}: ${total} stale files (>=${MAXAGE} min) in ${WATCHDIR}." + diff --git a/puppet/modules/site_check_mk/files/agent/logwatch/bigcouch.cfg b/puppet/modules/site_check_mk/files/agent/logwatch/bigcouch.cfg new file mode 100644 index 00000000..28f333b0 --- /dev/null +++ b/puppet/modules/site_check_mk/files/agent/logwatch/bigcouch.cfg @@ -0,0 +1,20 @@ +/opt/bigcouch/var/log/bigcouch.log nocontext=1 +# ignore requests that are fine + I undefined - -.*200$ + I undefined - -.*201$ + I 127.0.0.1 undefined.* ok + I 127.0.0.1 localhost:5984 .* ok + # https://leap.se/code/issues/5246 + I Shutting down group server + # ignore "Uncaught error in HTTP request: {exit, normal}" error + # it's suppressed in later versions of bigcouch anhow + # see https://leap.se/code/issues/5226 + I Uncaught error in HTTP request: {exit,normal} + I Uncaught error in HTTP request: {exit, + C Uncaught error in HTTP request: {error, + C Response abnormally terminated: {nodedown, + C rexi_DOWN,noproc + C rexi_DOWN,noconnection + C error + C Connection attempt from disallowed node + W Apache CouchDB has started diff --git a/puppet/modules/site_check_mk/files/agent/logwatch/leap_mx.cfg b/puppet/modules/site_check_mk/files/agent/logwatch/leap_mx.cfg new file mode 100644 index 00000000..c71c5392 --- /dev/null +++ b/puppet/modules/site_check_mk/files/agent/logwatch/leap_mx.cfg @@ -0,0 +1,4 @@ +/var/log/leap_mx.log + W Don't know how to deliver mail + W No public key, stopping the processing chain + diff --git a/puppet/modules/site_check_mk/files/agent/logwatch/logwatch.cfg b/puppet/modules/site_check_mk/files/agent/logwatch/logwatch.cfg new file mode 100644 index 00000000..4f16d1bd --- /dev/null +++ b/puppet/modules/site_check_mk/files/agent/logwatch/logwatch.cfg @@ -0,0 +1,31 @@ +# This file is managed by Puppet. DO NOT EDIT. + +# logwatch.cfg +# This file configures mk_logwatch. Define your logfiles +# and patterns to be looked for here. + +# Name one or more logfiles +/var/log/messages +# Patterns are indented with one space are prefixed with: +# C: Critical messages +# W: Warning messages +# I: ignore these lines (OK) +# The first match decided. Lines that do not match any pattern +# are ignored + C Fail event detected on md device + I mdadm.*: Rebuild.*event detected + W mdadm\[ + W ata.*hard resetting link + W ata.*soft reset failed (.*FIS failed) + W device-mapper: thin:.*reached low water mark + C device-mapper: thin:.*no free space + +/var/log/auth.log + W sshd.*Corrupted MAC on input + +/var/log/kern.log + C panic + C Oops + W generic protection rip + W .*Unrecovered read error - auto reallocate failed + diff --git a/puppet/modules/site_check_mk/files/agent/logwatch/soledad.cfg b/puppet/modules/site_check_mk/files/agent/logwatch/soledad.cfg new file mode 100644 index 00000000..623d1e46 --- /dev/null +++ b/puppet/modules/site_check_mk/files/agent/logwatch/soledad.cfg @@ -0,0 +1,5 @@ +/var/log/soledad.log + C WSGI application error + C Error + C error + W Timing out client: diff --git a/puppet/modules/site_check_mk/files/agent/logwatch/syslog/couchdb.cfg b/puppet/modules/site_check_mk/files/agent/logwatch/syslog/couchdb.cfg new file mode 100644 index 00000000..f546135a --- /dev/null +++ b/puppet/modules/site_check_mk/files/agent/logwatch/syslog/couchdb.cfg @@ -0,0 +1,7 @@ + C /usr/local/bin/couch-doc-update.*failed + C /usr/local/bin/couch-doc-update.*ERROR +# on one-node bigcouch setups, we'll get this msg +# a lot, so we ignore it here until we fix +# https://leap.se/code/issues/5244 + I epmd: got partial packet only on file descriptor + diff --git a/puppet/modules/site_check_mk/files/agent/logwatch/syslog/openvpn.cfg b/puppet/modules/site_check_mk/files/agent/logwatch/syslog/openvpn.cfg new file mode 100644 index 00000000..d58e876d --- /dev/null +++ b/puppet/modules/site_check_mk/files/agent/logwatch/syslog/openvpn.cfg @@ -0,0 +1,7 @@ +# ignore openvpn TLS initialization errors when clients +# suddenly hangup before properly establishing +# a tls connection + I ovpn-.*TLS Error: Unroutable control packet received from + I ovpn-.*TLS Error: TLS key negotiation failed to occur within 60 seconds (check your network connectivity) + I ovpn-.*TLS Error: TLS handshake failed + diff --git a/puppet/modules/site_check_mk/files/agent/logwatch/syslog/stunnel.cfg b/puppet/modules/site_check_mk/files/agent/logwatch/syslog/stunnel.cfg new file mode 100644 index 00000000..eb3131f2 --- /dev/null +++ b/puppet/modules/site_check_mk/files/agent/logwatch/syslog/stunnel.cfg @@ -0,0 +1,9 @@ +# check for stunnel failures +# +# these are temporary failures and happen very often, so we +# ignore them until we tuned stunnel timeouts/logging, +# see https://leap.se/code/issues/5218 + I stunnel:.*Connection reset by peer + I stunnel:.*Peer suddenly disconnected + I stunnel:.*Connection refused + diff --git a/puppet/modules/site_check_mk/files/agent/logwatch/syslog/tapicero.cfg b/puppet/modules/site_check_mk/files/agent/logwatch/syslog/tapicero.cfg new file mode 100644 index 00000000..93ce0311 --- /dev/null +++ b/puppet/modules/site_check_mk/files/agent/logwatch/syslog/tapicero.cfg @@ -0,0 +1,8 @@ + C tapicero.*RestClient::InternalServerError: +# possible race condition between multiple tapicero +# instances, so we ignore it +# see https://leap.se/code/issues/5168 + I tapicero.*RestClient::PreconditionFailed: + C tapicero.*Creating database.*failed due to: + C tapicero.*failed + W tapicero.*Couch stream ended unexpectedly. diff --git a/puppet/modules/site_check_mk/files/agent/logwatch/syslog/webapp.cfg b/puppet/modules/site_check_mk/files/agent/logwatch/syslog/webapp.cfg new file mode 100644 index 00000000..00f9c7fd --- /dev/null +++ b/puppet/modules/site_check_mk/files/agent/logwatch/syslog/webapp.cfg @@ -0,0 +1,5 @@ +# check for webapp errors + C webapp.*Could not connect to couch database messages due to 401 Unauthorized: {"error":"unauthorized","reason":"You are not a server admin."} +# ignore RoutingErrors that rails throw when it can't handle a url +# see https://leap.se/code/issues/5173 + I webapp.*ActionController::RoutingError diff --git a/puppet/modules/site_check_mk/files/agent/logwatch/syslog_header.cfg b/puppet/modules/site_check_mk/files/agent/logwatch/syslog_header.cfg new file mode 100644 index 00000000..f60d752b --- /dev/null +++ b/puppet/modules/site_check_mk/files/agent/logwatch/syslog_header.cfg @@ -0,0 +1 @@ +/var/log/syslog diff --git a/puppet/modules/site_check_mk/files/agent/logwatch/syslog_tail.cfg b/puppet/modules/site_check_mk/files/agent/logwatch/syslog_tail.cfg new file mode 100644 index 00000000..450b9e90 --- /dev/null +++ b/puppet/modules/site_check_mk/files/agent/logwatch/syslog_tail.cfg @@ -0,0 +1,11 @@ +# some general patterns + C panic + C Oops + I Error: Driver 'pcspkr' is already registered, aborting... + C Error + C error + W generic protection rip + W .*Unrecovered read error - auto reallocate failed +# 401 Unauthorized error logged by webapp and possible other +# applications + C Unauthorized diff --git a/puppet/modules/site_check_mk/files/agent/nagios_plugins/check_unix_open_fds.pl b/puppet/modules/site_check_mk/files/agent/nagios_plugins/check_unix_open_fds.pl new file mode 100755 index 00000000..06163d49 --- /dev/null +++ b/puppet/modules/site_check_mk/files/agent/nagios_plugins/check_unix_open_fds.pl @@ -0,0 +1,322 @@ +#!/usr/bin/perl -w + +# check_unix_open_fds Nagios Plugin +# +# TComm - Carlos Peris Pla +# +# This nagios plugin is free software, and comes with ABSOLUTELY +# NO WARRANTY. It may be used, redistributed and/or modified under +# the terms of the GNU General Public Licence (see +# http://www.fsf.org/licensing/licenses/gpl.txt). + + +# MODULE DECLARATION + +use strict; +use Nagios::Plugin; + + +# FUNCTION DECLARATION + +sub CreateNagiosManager (); +sub CheckArguments (); +sub PerformCheck (); + + +# CONSTANT DEFINITION + +use constant NAME => 'check_unix_open_fds'; +use constant VERSION => '0.1b'; +use constant USAGE => "Usage:\ncheck_unix_open_fds -w <process_threshold,application_threshold> -c <process_threshold,application_threshold>\n". + "\t\t[-V <version>]\n"; +use constant BLURB => "This plugin checks, in UNIX systems with the command lsof installed and with its SUID bit activated, the number\n". + "of file descriptors opened by an application and its processes.\n"; +use constant LICENSE => "This nagios plugin is free software, and comes with ABSOLUTELY\n". + "no WARRANTY. It may be used, redistributed and/or modified under\n". + "the terms of the GNU General Public Licence\n". + "(see http://www.fsf.org/licensing/licenses/gpl.txt).\n"; +use constant EXAMPLE => "\n\n". + "Example:\n". + "\n". + "check_unix_open_fds -a /usr/local/nagios/bin/ndo2db -w 20,75 -c 25,85\n". + "\n". + "It returns CRITICAL if number of file descriptors opened by ndo2db is higher than 85,\n". + "if not it returns WARNING if number of file descriptors opened by ndo2db is higher \n". + "than 75, if not it returns CRITICAL if number of file descriptors opened by any process\n". + "of ndo2db is higher than 25, if not it returns WARNING if number of file descriptors \n". + "opened by any process of ndo2db is higher than 20.\n". + "In other cases it returns OK if check has been performed succesfully.\n\n"; + + +# VARIABLE DEFINITION + +my $Nagios; +my $Error; +my $PluginResult; +my $PluginOutput; +my @WVRange; +my @CVRange; + + +# MAIN FUNCTION + +# Get command line arguments +$Nagios = &CreateNagiosManager(USAGE, VERSION, BLURB, LICENSE, NAME, EXAMPLE); +eval {$Nagios->getopts}; + +if (!$@) { + # Command line parsed + if (&CheckArguments($Nagios, \$Error, \@WVRange, \@CVRange)) { + # Argument checking passed + $PluginResult = &PerformCheck($Nagios, \$PluginOutput, \@WVRange, \@CVRange) + } + else { + # Error checking arguments + $PluginOutput = $Error; + $PluginResult = UNKNOWN; + } + $Nagios->nagios_exit($PluginResult,$PluginOutput); +} +else { + # Error parsing command line + $Nagios->nagios_exit(UNKNOWN,$@); +} + + + +# FUNCTION DEFINITIONS + +# Creates and configures a Nagios plugin object +# Input: strings (usage, version, blurb, license, name and example) to configure argument parsing functionality +# Return value: reference to a Nagios plugin object + +sub CreateNagiosManager() { + # Create GetOpt object + my $Nagios = Nagios::Plugin->new(usage => $_[0], version => $_[1], blurb => $_[2], license => $_[3], plugin => $_[4], extra => $_[5]); + + # Add argument units + $Nagios->add_arg(spec => 'application|a=s', + help => 'Application path for which you want to check the number of open file descriptors', + required => 1); + + # Add argument warning + $Nagios->add_arg(spec => 'warning|w=s', + help => "Warning thresholds. Format: <process_threshold,application_threshold>", + required => 1); + # Add argument critical + $Nagios->add_arg(spec => 'critical|c=s', + help => "Critical thresholds. Format: <process_threshold,application_threshold>", + required => 1); + + # Return value + return $Nagios; +} + + +# Checks argument values and sets some default values +# Input: Nagios Plugin object +# Output: reference to Error description string, Memory Unit, Swap Unit, reference to WVRange ($_[4]), reference to CVRange ($_[5]) +# Return value: True if arguments ok, false if not + +sub CheckArguments() { + my ($Nagios, $Error, $WVRange, $CVRange) = @_; + my $commas; + my $units; + my $i; + my $firstpos; + my $secondpos; + + # Check Warning thresholds list + $commas = $Nagios->opts->warning =~ tr/,//; + if ($commas !=1){ + ${$Error} = "Invalid Warning list format. One comma is expected."; + return 0; + } + else{ + $i=0; + $firstpos=0; + my $warning=$Nagios->opts->warning; + while ($warning =~ /[,]/g) { + $secondpos=pos $warning; + if ($secondpos - $firstpos==1){ + @{$WVRange}[$i] = "~:"; + } + else{ + @{$WVRange}[$i] = substr $Nagios->opts->warning, $firstpos, ($secondpos-$firstpos-1); + } + $firstpos=$secondpos; + $i++ + } + if (length($Nagios->opts->warning) - $firstpos==0){#La coma es el ultimo elemento del string + @{$WVRange}[$i] = "~:"; + } + else{ + @{$WVRange}[$i] = substr $Nagios->opts->warning, $firstpos, (length($Nagios->opts->warning)-$firstpos); + } + + if (@{$WVRange}[0] !~/^(@?(\d+|(\d+|~):(\d+)?))?$/){ + ${$Error} = "Invalid Process Warning threshold in ${$WVRange[0]}"; + return 0; + }if (@{$WVRange}[1] !~/^(@?(\d+|(\d+|~):(\d+)?))?$/){ + ${$Error} = "Invalid Application Warning threshold in ${$WVRange[1]}"; + return 0; + } + } + + # Check Critical thresholds list + $commas = $Nagios->opts->critical =~ tr/,//; + if ($commas !=1){ + ${$Error} = "Invalid Critical list format. One comma is expected."; + return 0; + } + else{ + $i=0; + $firstpos=0; + my $critical=$Nagios->opts->critical; + while ($critical =~ /[,]/g) { + $secondpos=pos $critical ; + if ($secondpos - $firstpos==1){ + @{$CVRange}[$i] = "~:"; + } + else{ + @{$CVRange}[$i] =substr $Nagios->opts->critical, $firstpos, ($secondpos-$firstpos-1); + } + $firstpos=$secondpos; + $i++ + } + if (length($Nagios->opts->critical) - $firstpos==0){#La coma es el ultimo elemento del string + @{$CVRange}[$i] = "~:"; + } + else{ + @{$CVRange}[$i] = substr $Nagios->opts->critical, $firstpos, (length($Nagios->opts->critical)-$firstpos); + } + + if (@{$CVRange}[0] !~/^(@?(\d+|(\d+|~):(\d+)?))?$/) { + ${$Error} = "Invalid Process Critical threshold in @{$CVRange}[0]"; + return 0; + } + if (@{$CVRange}[1] !~/^(@?(\d+|(\d+|~):(\d+)?))?$/) { + ${$Error} = "Invalid Application Critical threshold in @{$CVRange}[1]"; + return 0; + } + } + + return 1; +} + + +# Performs whole check: +# Input: Nagios Plugin object, reference to Plugin output string, Application, referece to WVRange, reference to CVRange +# Output: Plugin output string +# Return value: Plugin return value + +sub PerformCheck() { + my ($Nagios, $PluginOutput, $WVRange, $CVRange) = @_; + my $Application; + my @AppNameSplitted; + my $ApplicationName; + my $PsCommand; + my $PsResult; + my @PsResultLines; + my $ProcLine; + my $ProcPid; + my $LsofCommand; + my $LsofResult; + my $ProcCount = 0; + my $FDCount = 0; + my $ProcFDAvg = 0; + my $PerProcMaxFD = 0; + my $ProcOKFlag = 0; + my $ProcWarningFlag = 0; + my $ProcCriticalFlag = 0; + my $OKFlag = 0; + my $WarningFlag = 0; + my $CriticalFlag = 0; + my $LastWarningProcFDs = 0; + my $LastWarningProc = -1; + my $LastCriticalProcFDs = 0; + my $LastCriticalProc = -1; + my $ProcPluginReturnValue = UNKNOWN; + my $AppPluginReturnValue = UNKNOWN; + my $PluginReturnValue = UNKNOWN; + my $PerformanceData = ""; + my $PerfdataUnit = "FDs"; + + $Application = $Nagios->opts->application; + $PsCommand = "ps -eaf | grep $Application"; + $PsResult = `$PsCommand`; + @AppNameSplitted = split(/\//, $Application); + $ApplicationName = $AppNameSplitted[$#AppNameSplitted]; + @PsResultLines = split(/\n/, $PsResult); + if ( $#PsResultLines > 1 ) { + foreach my $Proc (split(/\n/, $PsResult)) { + if ($Proc !~ /check_unix_open_fds/ && $Proc !~ / grep /) { + $ProcCount += 1; + $ProcPid = (split(/\s+/, $Proc))[1]; + $LsofCommand = "lsof -p $ProcPid | wc -l"; + $LsofResult = `$LsofCommand`; + $LsofResult = ($LsofResult > 0 ) ? ($LsofResult - 1) : 0; + $FDCount += $LsofResult; + if ($LsofResult >= $PerProcMaxFD) { $PerProcMaxFD = $LsofResult; } + $ProcPluginReturnValue = $Nagios->check_threshold(check => $LsofResult,warning => @{$WVRange}[0],critical => @{$CVRange}[0]); + if ($ProcPluginReturnValue eq OK) { + $ProcOKFlag = 1; + } + elsif ($ProcPluginReturnValue eq WARNING) { + $ProcWarningFlag = 1; + if ($LsofResult >= $LastWarningProcFDs) { + $LastWarningProcFDs = $LsofResult; + $LastWarningProc = $ProcPid; + } + } + #if ($LsofResult >= $PCT) { + elsif ($ProcPluginReturnValue eq CRITICAL) { + $ProcCriticalFlag = 1; + if ($LsofResult >= $LastCriticalProcFDs) { + $LastCriticalProcFDs = $LsofResult; + $LastCriticalProc = $ProcPid; + } + } + } + } + if ($ProcCount) { $ProcFDAvg = int($FDCount / $ProcCount); } + $AppPluginReturnValue = $Nagios->check_threshold(check => $FDCount,warning => @{$WVRange}[1],critical => @{$CVRange}[1]); + #if ($FDCount >= $TWT) { + if ($AppPluginReturnValue eq OK) { $OKFlag = 1; } + elsif ($AppPluginReturnValue eq WARNING) { $WarningFlag = 1; } + elsif ($AppPluginReturnValue eq CRITICAL) { $CriticalFlag = 1; } + + # PluginReturnValue and PluginOutput + if ($CriticalFlag) { + $PluginReturnValue = CRITICAL; + ${$PluginOutput} .= "$ApplicationName handling $FDCount files (critical threshold set to @{$CVRange}[1])"; + } + elsif ($WarningFlag) { + $PluginReturnValue = WARNING; + ${$PluginOutput} .= "$ApplicationName handling $FDCount files (warning threshold set to @{$WVRange}[1])"; + } + elsif ($ProcCriticalFlag) { + $PluginReturnValue = CRITICAL; + ${$PluginOutput} .= "Process ID $LastCriticalProc handling $LastCriticalProcFDs files (critical threshold set to @{$CVRange}[0])"; + } + elsif ($ProcWarningFlag) { + $PluginReturnValue = WARNING; + ${$PluginOutput} .= "Process ID $LastWarningProc handling $LastWarningProcFDs files (warning threshold set to @{$WVRange}[0])"; + } + elsif ($OKFlag && $ProcOKFlag) { + $PluginReturnValue = OK; + ${$PluginOutput} .= "$ApplicationName handling $FDCount files"; + } + } + else { + ${$PluginOutput} .= "No existe la aplicacion $ApplicationName"; + } + + + $PerformanceData .= "ProcCount=$ProcCount$PerfdataUnit FDCount=$FDCount$PerfdataUnit ProcFDAvg=$ProcFDAvg$PerfdataUnit PerProcMaxFD=$PerProcMaxFD$PerfdataUnit"; + + # Output with performance data: + ${$PluginOutput} .= " | $PerformanceData"; + + return $PluginReturnValue; +} diff --git a/puppet/modules/site_check_mk/files/agent/plugins/mk_logwatch.1.2.4 b/puppet/modules/site_check_mk/files/agent/plugins/mk_logwatch.1.2.4 new file mode 100755 index 00000000..3dbca322 --- /dev/null +++ b/puppet/modules/site_check_mk/files/agent/plugins/mk_logwatch.1.2.4 @@ -0,0 +1,374 @@ +#!/usr/bin/python +# -*- encoding: utf-8; py-indent-offset: 4 -*- +# +------------------------------------------------------------------+ +# | ____ _ _ __ __ _ __ | +# | / ___| |__ ___ ___| | __ | \/ | |/ / | +# | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / | +# | | |___| | | | __/ (__| < | | | | . \ | +# | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ | +# | | +# | Copyright Mathias Kettner 2010 mk@mathias-kettner.de | +# +------------------------------------------------------------------+ +# +# This file is part of Check_MK. +# The official homepage is at http://mathias-kettner.de/check_mk. +# +# check_mk is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation in version 2. check_mk is distributed +# in the hope that it will be useful, but WITHOUT ANY WARRANTY; with- +# out even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. See the GNU General Public License for more de- +# ails. You should have received a copy of the GNU General Public +# License along with GNU Make; see the file COPYING. If not, write +# to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, +# Boston, MA 02110-1301 USA. + +# Call with -d for debug mode: colored output, no saving of status + +import sys, os, re, time +import glob + +if '-d' in sys.argv[1:] or '--debug' in sys.argv[1:]: + tty_red = '\033[1;31m' + tty_green = '\033[1;32m' + tty_yellow = '\033[1;33m' + tty_blue = '\033[1;34m' + tty_normal = '\033[0m' + debug = True +else: + tty_red = '' + tty_green = '' + tty_yellow = '' + tty_blue = '' + tty_normal = '' + debug = False + +# The configuration file and status file are searched +# in the directory named by the environment variable +# LOGWATCH_DIR. If that is not set, MK_CONFDIR is used. +# If that is not set either, the current directory ist +# used. +logwatch_dir = os.getenv("LOGWATCH_DIR") +if not logwatch_dir: + logwatch_dir = os.getenv("MK_CONFDIR") + if not logwatch_dir: + logwatch_dir = "." + +print "<<<logwatch>>>" + +config_filename = logwatch_dir + "/logwatch.cfg" +status_filename = logwatch_dir + "/logwatch.state" +config_dir = logwatch_dir + "/logwatch.d/*.cfg" + +def is_not_comment(line): + if line.lstrip().startswith('#') or \ + line.strip() == '': + return False + return True + +def parse_filenames(line): + return line.split() + +def parse_pattern(level, pattern): + if level not in [ 'C', 'W', 'I', 'O' ]: + raise(Exception("Invalid pattern line '%s'" % line)) + try: + compiled = re.compile(pattern) + except: + raise(Exception("Invalid regular expression in line '%s'" % line)) + return (level, compiled) + +def read_config(): + config_lines = [ line.rstrip() for line in filter(is_not_comment, file(config_filename).readlines()) ] + # Add config from a logwatch.d folder + for config_file in glob.glob(config_dir): + config_lines += [ line.rstrip() for line in filter(is_not_comment, file(config_file).readlines()) ] + + have_filenames = False + config = [] + + for line in config_lines: + rewrite = False + if line[0].isspace(): # pattern line + if not have_filenames: + raise Exception("Missing logfile names") + level, pattern = line.split(None, 1) + if level == 'A': + cont_list.append(parse_cont_pattern(pattern)) + elif level == 'R': + rewrite_list.append(pattern) + else: + level, compiled = parse_pattern(level, pattern) + cont_list = [] # List of continuation patterns + rewrite_list = [] # List of rewrite patterns + patterns.append((level, compiled, cont_list, rewrite_list)) + else: # filename line + patterns = [] + config.append((parse_filenames(line), patterns)) + have_filenames = True + return config + +def parse_cont_pattern(pattern): + try: + return int(pattern) + except: + try: + return re.compile(pattern) + except: + if debug: + raise + raise Exception("Invalid regular expression in line '%s'" % pattern) + +# structure of statusfile +# # LOGFILE OFFSET INODE +# /var/log/messages|7767698|32455445 +# /var/test/x12134.log|12345|32444355 +def read_status(): + if debug: + return {} + + status = {} + for line in file(status_filename): + # TODO: Remove variants with spaces. rsplit is + # not portable. split fails if logfilename contains + # spaces + inode = -1 + try: + parts = line.split('|') + filename = parts[0] + offset = parts[1] + if len(parts) >= 3: + inode = parts[2] + + except: + try: + filename, offset = line.rsplit(None, 1) + except: + filename, offset = line.split(None, 1) + status[filename] = int(offset), int(inode) + return status + +def save_status(status): + f = file(status_filename, "w") + for filename, (offset, inode) in status.items(): + f.write("%s|%d|%d\n" % (filename, offset, inode)) + +pushed_back_line = None +def next_line(f): + global pushed_back_line + if pushed_back_line != None: + line = pushed_back_line + pushed_back_line = None + return line + else: + try: + line = f.next() + return line + except: + return None + + +def process_logfile(logfile, patterns): + global pushed_back_line + + # Look at which file offset we have finished scanning + # the logfile last time. If we have never seen this file + # before, we set the offset to -1 + offset, prev_inode = status.get(logfile, (-1, -1)) + try: + fl = os.open(logfile, os.O_RDONLY) + inode = os.fstat(fl)[1] # 1 = st_ino + except: + if debug: + raise + print "[[[%s:cannotopen]]]" % logfile + return + + print "[[[%s]]]" % logfile + + # Seek to the current end in order to determine file size + current_end = os.lseek(fl, 0, 2) # os.SEEK_END not available in Python 2.4 + status[logfile] = current_end, inode + + # If we have never seen this file before, we just set the + # current pointer to the file end. We do not want to make + # a fuss about ancient log messages... + if offset == -1: + if not debug: + return + else: + offset = 0 + + + # If the inode of the logfile has changed it has appearently + # been started from new (logfile rotation). At least we must + # assume that. In some rare cases (restore of a backup, etc) + # we are wrong and resend old log messages + if prev_inode >= 0 and inode != prev_inode: + offset = 0 + + # Our previously stored offset is the current end -> + # no new lines in this file + if offset == current_end: + return # nothing new + + # If our offset is beyond the current end, the logfile has been + # truncated or wrapped while keeping the same inode. We assume + # that it contains all new data in that case and restart from + # offset 0. + if offset > current_end: + offset = 0 + + # now seek to offset where interesting data begins + os.lseek(fl, offset, 0) # os.SEEK_SET not available in Python 2.4 + f = os.fdopen(fl) + worst = -1 + outputtxt = "" + lines_parsed = 0 + start_time = time.time() + + while True: + line = next_line(f) + if line == None: + break # End of file + + lines_parsed += 1 + # Check if maximum number of new log messages is exceeded + if opt_maxlines != None and lines_parsed > opt_maxlines: + outputtxt += "%s Maximum number (%d) of new log messages exceeded.\n" % ( + opt_overflow, opt_maxlines) + worst = max(worst, opt_overflow_level) + os.lseek(fl, 0, 2) # Seek to end of file, skip all other messages + break + + # Check if maximum processing time (per file) is exceeded. Check only + # every 100'th line in order to save system calls + if opt_maxtime != None and lines_parsed % 100 == 10 \ + and time.time() - start_time > opt_maxtime: + outputtxt += "%s Maximum parsing time (%.1f sec) of this log file exceeded.\n" % ( + opt_overflow, opt_maxtime) + worst = max(worst, opt_overflow_level) + os.lseek(fl, 0, 2) # Seek to end of file, skip all other messages + break + + level = "." + for lev, pattern, cont_patterns, replacements in patterns: + matches = pattern.search(line[:-1]) + if matches: + level = lev + levelint = {'C': 2, 'W': 1, 'O': 0, 'I': -1, '.': -1}[lev] + worst = max(levelint, worst) + + # Check for continuation lines + for cont_pattern in cont_patterns: + if type(cont_pattern) == int: # add that many lines + for x in range(cont_pattern): + cont_line = next_line(f) + if cont_line == None: # end of file + break + line = line[:-1] + "\1" + cont_line + + else: # pattern is regex + while True: + cont_line = next_line(f) + if cont_line == None: # end of file + break + elif cont_pattern.search(cont_line[:-1]): + line = line[:-1] + "\1" + cont_line + else: + pushed_back_line = cont_line # sorry for stealing this line + break + + # Replacement + for replace in replacements: + line = replace.replace('\\0', line) + "\n" + for nr, group in enumerate(matches.groups()): + line = line.replace('\\%d' % (nr+1), group) + + break # matching rule found and executed + + color = {'C': tty_red, 'W': tty_yellow, 'O': tty_green, 'I': tty_blue, '.': ''}[level] + if debug: + line = line.replace("\1", "\nCONT:") + if level == "I": + level = "." + if opt_nocontext and level == '.': + continue + outputtxt += "%s%s %s%s\n" % (color, level, line[:-1], tty_normal) + + new_offset = os.lseek(fl, 0, 1) # os.SEEK_CUR not available in Python 2.4 + status[logfile] = new_offset, inode + + # output all lines if at least one warning, error or ok has been found + if worst > -1: + sys.stdout.write(outputtxt) + sys.stdout.flush() + +try: + config = read_config() +except Exception, e: + if debug: + raise + print "CANNOT READ CONFIG FILE: %s" % e + sys.exit(1) + +# Simply ignore errors in the status file. In case of a corrupted status file we simply begin +# with an empty status. That keeps the monitoring up and running - even if we might loose a +# message in the extreme case of a corrupted status file. +try: + status = read_status() +except Exception, e: + status = {} + + +# The filename line may contain options like 'maxlines=100' or 'maxtime=10' +for filenames, patterns in config: + # Initialize options with default values + opt_maxlines = None + opt_maxtime = None + opt_regex = None + opt_overflow = 'C' + opt_overflow_level = 2 + opt_nocontext = False + try: + options = [ o.split('=', 1) for o in filenames if '=' in o ] + for key, value in options: + if key == 'maxlines': + opt_maxlines = int(value) + elif key == 'maxtime': + opt_maxtime = float(value) + elif key == 'overflow': + if value not in [ 'C', 'I', 'W', 'O' ]: + raise Exception("Invalid value %s for overflow. Allowed are C, I, O and W" % value) + opt_overflow = value + opt_overflow_level = {'C':2, 'W':1, 'O':0, 'I':0}[value] + elif key == 'regex': + opt_regex = re.compile(value) + elif key == 'iregex': + opt_regex = re.compile(value, re.I) + elif key == 'nocontext': + opt_nocontext = True + else: + raise Exception("Invalid option %s" % key) + except Exception, e: + if debug: + raise + print "INVALID CONFIGURATION: %s" % e + sys.exit(1) + + + for glob in filenames: + if '=' in glob: + continue + logfiles = [ l.strip() for l in os.popen("ls %s 2>/dev/null" % glob).readlines() ] + if opt_regex: + logfiles = [ f for f in logfiles if opt_regex.search(f) ] + if len(logfiles) == 0: + print '[[[%s:missing]]]' % glob + else: + for logfile in logfiles: + process_logfile(logfile, patterns) + +if not debug: + save_status(status) diff --git a/puppet/modules/site_check_mk/manifests/agent.pp b/puppet/modules/site_check_mk/manifests/agent.pp new file mode 100644 index 00000000..589041eb --- /dev/null +++ b/puppet/modules/site_check_mk/manifests/agent.pp @@ -0,0 +1,28 @@ +class site_check_mk::agent { + + $ssh_hash = hiera('ssh') + $pubkey = $ssh_hash['authorized_keys']['monitor']['key'] + $type = $ssh_hash['authorized_keys']['monitor']['type'] + + class { 'site_apt::preferences::check_mk': } -> + + class { 'check_mk::agent': + agent_package_name => 'check-mk-agent', + agent_logwatch_package_name => 'check-mk-agent-logwatch', + method => 'ssh', + homedir => '/etc/nagios/check_mk', + register_agent => false + } -> + + class { 'site_check_mk::agent::mrpe': } -> + class { 'site_check_mk::agent::logwatch': } -> + + file { + [ '/srv/leap/nagios', '/srv/leap/nagios/plugins' ]: + ensure => directory; + '/usr/lib/check_mk_agent/local/run_node_tests.sh': + source => 'puppet:///modules/site_check_mk/agent/local_checks/all_hosts/run_node_tests.sh', + mode => '0755'; + } + +} diff --git a/puppet/modules/site_check_mk/manifests/agent/couchdb.pp b/puppet/modules/site_check_mk/manifests/agent/couchdb.pp new file mode 100644 index 00000000..01e2b886 --- /dev/null +++ b/puppet/modules/site_check_mk/manifests/agent/couchdb.pp @@ -0,0 +1,36 @@ +class site_check_mk::agent::couchdb { + + # watch logs + file { '/etc/check_mk/logwatch.d/bigcouch.cfg': + source => 'puppet:///modules/site_check_mk/agent/logwatch/bigcouch.cfg', + } + concat::fragment { 'syslog_couchdb': + source => 'puppet:///modules/site_check_mk/agent/logwatch/syslog/couchdb.cfg', + target => '/etc/check_mk/logwatch.d/syslog.cfg', + order => '02'; + } + + + # check bigcouch processes + file_line { + 'Bigcouch_epmd_procs': + line => 'Bigcouch_epmd_procs /usr/lib/nagios/plugins/check_procs -w 1:1 -c 1:1 -a /opt/bigcouch/erts-5.9.1/bin/epmd', + path => '/etc/check_mk/mrpe.cfg'; + 'Bigcouch_beam_procs': + line => 'Bigcouch_beam_procs /usr/lib/nagios/plugins/check_procs -w 1:1 -c 1:1 -a /opt/bigcouch/erts-5.9.1/bin/beam', + path => '/etc/check_mk/mrpe.cfg'; + } + + # check open files for bigcouch proc + include site_check_mk::agent::package::perl_plugin + file { '/srv/leap/nagios/plugins/check_unix_open_fds.pl': + source => 'puppet:///modules/site_check_mk/agent/nagios_plugins/check_unix_open_fds.pl', + mode => '0755' + } + file_line { + 'Bigcouch_open_files': + line => 'Bigcouch_open_files /srv/leap/nagios/plugins/check_unix_open_fds.pl -a beam -w 750,750 -c 1000,1000', + path => '/etc/check_mk/mrpe.cfg'; + } + +} diff --git a/puppet/modules/site_check_mk/manifests/agent/haproxy.pp b/puppet/modules/site_check_mk/manifests/agent/haproxy.pp new file mode 100644 index 00000000..e7986db1 --- /dev/null +++ b/puppet/modules/site_check_mk/manifests/agent/haproxy.pp @@ -0,0 +1,12 @@ +class site_check_mk::agent::haproxy { + + include site_check_mk::agent::package::nagios_plugins_contrib + + # local nagios plugin checks via mrpe + file_line { + 'haproxy': + line => 'Haproxy /usr/lib/nagios/plugins/check_haproxy -u "http://localhost:8000/haproxy;csv"', + path => '/etc/check_mk/mrpe.cfg'; + } + +} diff --git a/puppet/modules/site_check_mk/manifests/agent/logwatch.pp b/puppet/modules/site_check_mk/manifests/agent/logwatch.pp new file mode 100644 index 00000000..423cace2 --- /dev/null +++ b/puppet/modules/site_check_mk/manifests/agent/logwatch.pp @@ -0,0 +1,36 @@ +class site_check_mk::agent::logwatch { + # Deploy mk_logwatch 1.2.4 so we can split the config + # into multiple config files in /etc/check_mk/logwatch.d + # see https://leap.se/code/issues/5135 + + file { '/usr/lib/check_mk_agent/plugins/mk_logwatch': + source => 'puppet:///modules/site_check_mk/agent/plugins/mk_logwatch.1.2.4', + mode => '0755', + require => Package['check-mk-agent-logwatch'] + } + + # only config files that watch a distinct logfile should go in logwatch.d/ + file { '/etc/check_mk/logwatch.d': + ensure => directory, + recurse => true, + purge => true, + require => Package['check-mk-agent-logwatch'] + } + + # service that share a common logfile (i.e. /var/log/syslog) need to get + # concanated in one file, otherwise the last file sourced will override + # the config before + # see mk_logwatch: "logwatch.cfg overwrites config files in logwatch.d", + # https://leap.se/code/issues/5155 + + # first, we need to deploy a custom logwatch.cfg that doesn't include + # a section about /var/log/syslog + + file { '/etc/check_mk/logwatch.cfg': + source => 'puppet:///modules/site_check_mk/agent/logwatch/logwatch.cfg', + require => Package['check_mk-agent-logwatch'] + } + + include concat::setup + include site_check_mk::agent::logwatch::syslog +} diff --git a/puppet/modules/site_check_mk/manifests/agent/logwatch/syslog.pp b/puppet/modules/site_check_mk/manifests/agent/logwatch/syslog.pp new file mode 100644 index 00000000..c927780d --- /dev/null +++ b/puppet/modules/site_check_mk/manifests/agent/logwatch/syslog.pp @@ -0,0 +1,18 @@ +class site_check_mk::agent::logwatch::syslog { + + concat { '/etc/check_mk/logwatch.d/syslog.cfg': + warn => true + } + + concat::fragment { 'syslog_header': + source => 'puppet:///modules/site_check_mk/agent/logwatch/syslog_header.cfg', + target => '/etc/check_mk/logwatch.d/syslog.cfg', + order => '01'; + } + concat::fragment { 'syslog_tail': + source => 'puppet:///modules/site_check_mk/agent/logwatch/syslog_tail.cfg', + target => '/etc/check_mk/logwatch.d/syslog.cfg', + order => '99'; + } + +} diff --git a/puppet/modules/site_check_mk/manifests/agent/mrpe.pp b/puppet/modules/site_check_mk/manifests/agent/mrpe.pp new file mode 100644 index 00000000..6921574f --- /dev/null +++ b/puppet/modules/site_check_mk/manifests/agent/mrpe.pp @@ -0,0 +1,18 @@ +class site_check_mk::agent::mrpe { + # check_mk can use standard nagios plugins using + # a wrapper called mrpe + # see http://mathias-kettner.de/checkmk_mrpe.html + + package { 'nagios-plugins-basic': + ensure => latest, + } + + file { '/etc/check_mk/mrpe.cfg': + ensure => present, + require => Package['check-mk-agent'] + } -> + file_line { 'Apt': + line => 'APT /usr/lib/nagios/plugins/check_apt', + path => '/etc/check_mk/mrpe.cfg', + } +} diff --git a/puppet/modules/site_check_mk/manifests/agent/mx.pp b/puppet/modules/site_check_mk/manifests/agent/mx.pp new file mode 100644 index 00000000..35a4e9a5 --- /dev/null +++ b/puppet/modules/site_check_mk/manifests/agent/mx.pp @@ -0,0 +1,23 @@ +class site_check_mk::agent::mx { + + # watch logs + file { '/etc/check_mk/logwatch.d/leap_mx.cfg': + source => 'puppet:///modules/site_check_mk/agent/logwatch/leap_mx.cfg', + } + + # local nagios plugin checks via mrpe + file_line { + 'Leap_MX_Procs': + line => 'Leap_MX_Procs /usr/lib/nagios/plugins/check_procs -w 1:1 -c 1:1 -a leap_mx', + path => '/etc/check_mk/mrpe.cfg'; + } + + + # check stale files in queue dir + file { '/usr/lib/check_mk_agent/local/check_leap_mx.sh': + source => 'puppet:///modules/site_check_mk/agent/local_checks/mx/check_leap_mx.sh', + mode => '0755', + require => Package['check_mk-agent'] + } + +} diff --git a/puppet/modules/site_check_mk/manifests/agent/openvpn.pp b/puppet/modules/site_check_mk/manifests/agent/openvpn.pp new file mode 100644 index 00000000..919a408d --- /dev/null +++ b/puppet/modules/site_check_mk/manifests/agent/openvpn.pp @@ -0,0 +1,10 @@ +class site_check_mk::agent::openvpn { + + # check syslog + concat::fragment { 'syslog_openpvn': + source => 'puppet:///modules/site_check_mk/agent/logwatch/syslog/openvpn.cfg', + target => '/etc/check_mk/logwatch.d/syslog.cfg', + order => '02'; + } + +} diff --git a/puppet/modules/site_check_mk/manifests/agent/package/nagios_plugins_contrib.pp b/puppet/modules/site_check_mk/manifests/agent/package/nagios_plugins_contrib.pp new file mode 100644 index 00000000..95a60d17 --- /dev/null +++ b/puppet/modules/site_check_mk/manifests/agent/package/nagios_plugins_contrib.pp @@ -0,0 +1,5 @@ +class site_check_mk::agent::package::nagios_plugins_contrib { + package { 'nagios-plugins-contrib': + ensure => installed, + } +} diff --git a/puppet/modules/site_check_mk/manifests/agent/package/perl_plugin.pp b/puppet/modules/site_check_mk/manifests/agent/package/perl_plugin.pp new file mode 100644 index 00000000..4feda375 --- /dev/null +++ b/puppet/modules/site_check_mk/manifests/agent/package/perl_plugin.pp @@ -0,0 +1,5 @@ +class site_check_mk::agent::package::perl_plugin { + package { 'libnagios-plugin-perl': + ensure => installed, + } +} diff --git a/puppet/modules/site_check_mk/manifests/agent/soledad.pp b/puppet/modules/site_check_mk/manifests/agent/soledad.pp new file mode 100644 index 00000000..cbae81fe --- /dev/null +++ b/puppet/modules/site_check_mk/manifests/agent/soledad.pp @@ -0,0 +1,14 @@ +class site_check_mk::agent::soledad { + + file { '/etc/check_mk/logwatch.d/soledad.cfg': + source => 'puppet:///modules/site_check_mk/agent/logwatch/soledad.cfg', + } + + # local nagios plugin checks via mrpe + file_line { + 'Soledad_Procs': + line => 'Soledad_Procs /usr/lib/nagios/plugins/check_procs -w 1:1 -c 1:1 -a soledad', + path => '/etc/check_mk/mrpe.cfg'; + } + +} diff --git a/puppet/modules/site_check_mk/manifests/agent/stunnel.pp b/puppet/modules/site_check_mk/manifests/agent/stunnel.pp new file mode 100644 index 00000000..64022824 --- /dev/null +++ b/puppet/modules/site_check_mk/manifests/agent/stunnel.pp @@ -0,0 +1,9 @@ +class site_check_mk::agent::stunnel { + + concat::fragment { 'syslog_stunnel': + source => 'puppet:///modules/site_check_mk/agent/logwatch/syslog/stunnel.cfg', + target => '/etc/check_mk/logwatch.d/syslog.cfg', + order => '02'; + } + +} diff --git a/puppet/modules/site_check_mk/manifests/agent/tapicero.pp b/puppet/modules/site_check_mk/manifests/agent/tapicero.pp new file mode 100644 index 00000000..369ed00b --- /dev/null +++ b/puppet/modules/site_check_mk/manifests/agent/tapicero.pp @@ -0,0 +1,16 @@ +class site_check_mk::agent::tapicero { + + concat::fragment { 'syslog_tapicero': + source => 'puppet:///modules/site_check_mk/agent/logwatch/syslog/tapicero.cfg', + target => '/etc/check_mk/logwatch.d/syslog.cfg', + order => '02'; + } + + # local nagios plugin checks via mrpe + file_line { + 'Tapicero_Procs': + line => 'Tapicero_Procs /usr/lib/nagios/plugins/check_procs -w 1:1 -c 1:1 -a tapicero', + path => '/etc/check_mk/mrpe.cfg'; + } + +} diff --git a/puppet/modules/site_check_mk/manifests/agent/webapp.pp b/puppet/modules/site_check_mk/manifests/agent/webapp.pp new file mode 100644 index 00000000..64f5ea6d --- /dev/null +++ b/puppet/modules/site_check_mk/manifests/agent/webapp.pp @@ -0,0 +1,26 @@ +class site_check_mk::agent::webapp { + + # check webapp login + soledad sync + package { [ 'python-srp', 'python-requests', 'python-yaml', 'python-u1db' ]: + ensure => installed + } + file { '/usr/lib/check_mk_agent/local/nagios-webapp_login.py': + ensure => link, + target => '/srv/leap/webapp/test/nagios/webapp_login.py', + require => Package['check_mk-agent'] + } + file { '/usr/lib/check_mk_agent/local/soledad_sync.py': + ensure => link, + target => '/srv/leap/webapp/test/nagios/soledad_sync.py', + require => Package['check_mk-agent'] + } + + + # check syslog + concat::fragment { 'syslog_webapp': + source => 'puppet:///modules/site_check_mk/agent/logwatch/syslog/webapp.cfg', + target => '/etc/check_mk/logwatch.d/syslog.cfg', + order => '02'; + } + +} diff --git a/puppet/modules/site_check_mk/manifests/server.pp b/puppet/modules/site_check_mk/manifests/server.pp new file mode 100644 index 00000000..e544ef0d --- /dev/null +++ b/puppet/modules/site_check_mk/manifests/server.pp @@ -0,0 +1,64 @@ +class site_check_mk::server { + + $ssh_hash = hiera('ssh') + $pubkey = $ssh_hash['authorized_keys']['monitor']['key'] + $type = $ssh_hash['authorized_keys']['monitor']['type'] + $seckey = $ssh_hash['monitor']['private_key'] + + $nagios_hiera = hiera_hash('nagios') + $nagios_hosts = $nagios_hiera['hosts'] + + $hosts = hiera_hash('hosts') + $all_hosts = inline_template ('<% @hosts.keys.sort.each do |key| -%>"<%= @hosts[key]["domain_internal"] %>", <% end -%>') + + package { 'check-mk-server': + ensure => installed, + } + + # override paths to use the system check_mk rather than OMD + class { 'check_mk::config': + site => '', + etc_dir => '/etc', + nagios_subdir => 'nagios3', + bin_dir => '/usr/bin', + host_groups => undef, + use_storedconfigs => false, + require => Package['check-mk-server'] + } + + Exec['check_mk-reload'] -> + Exec['check_mk-refresh-inventory-daily'] -> + Service['nagios'] + + file { + '/etc/check_mk/conf.d/use_ssh.mk': + content => template('site_check_mk/use_ssh.mk'), + notify => Exec['check_mk-refresh'], + require => Package['check-mk-server']; + '/etc/check_mk/all_hosts_static': + content => $all_hosts, + notify => Exec['check_mk-refresh'], + require => Package['check-mk-server']; + '/etc/check_mk/.ssh': + ensure => directory, + require => Package['check-mk-server']; + '/etc/check_mk/.ssh/id_rsa': + content => $seckey, + owner => 'nagios', + mode => '0600', + require => Package['check-mk-server']; + '/etc/check_mk/.ssh/id_rsa.pub': + content => "${type} ${pubkey} monitor", + owner => 'nagios', + mode => '0644', + require => Package['check-mk-server']; + # check_icmp must be suid root or called by sudo + # see https://leap.se/code/issues/5171 + '/usr/lib/nagios/plugins/check_icmp': + mode => '4755', + require => Package['nagios-plugins-basic']; + } + + + include check_mk::agent::local_checks +} diff --git a/puppet/modules/site_check_mk/templates/use_ssh.mk b/puppet/modules/site_check_mk/templates/use_ssh.mk new file mode 100644 index 00000000..0bebebcf --- /dev/null +++ b/puppet/modules/site_check_mk/templates/use_ssh.mk @@ -0,0 +1,6 @@ +# http://mathias-kettner.de/checkmk_datasource_programs.html +datasource_programs = [ +<% nagios_hosts.sort.each do |name,config| %> + ( "ssh -l root -i /etc/check_mk/.ssh/id_rsa -p <%=config['ssh_port']%> <%=config['domain_internal']%> check_mk_agent", [ "<%=config['domain_internal']%>" ], ),<%- end -%> + +] diff --git a/puppet/modules/site_config/manifests/caching_resolver.pp b/puppet/modules/site_config/manifests/caching_resolver.pp index 922c394f..3d7b9206 100644 --- a/puppet/modules/site_config/manifests/caching_resolver.pp +++ b/puppet/modules/site_config/manifests/caching_resolver.pp @@ -1,4 +1,5 @@ class site_config::caching_resolver { + tag 'leap_base' # Setup a conf.d directory to place additional unbound configuration files. # There must be at least one file in the directory, or unbound will not start, diff --git a/puppet/modules/site_config/manifests/default.pp b/puppet/modules/site_config/manifests/default.pp index 00eee9d0..7e421a21 100644 --- a/puppet/modules/site_config/manifests/default.pp +++ b/puppet/modules/site_config/manifests/default.pp @@ -2,19 +2,27 @@ class site_config::default { tag 'leap_base' $domain_hash = hiera('domain') + include site_config::params - include concat::setup + # make sure apt is updated before any packages are installed + include apt::update + Package { require => Exec['apt_updated'] } + + include site_config::slow # default class, used by all hosts include lsb, git - # configure apt - include site_apt + # configure sysctl parameters + include site_config::sysctl # configure ssh and include ssh-keys include site_config::sshd + # include classes for special environments + # i.e. openstack/aws nodes, vagrant nodes + # fix dhclient from changing resolver information if $::ec2_instance_id { include site_config::dhclient @@ -26,13 +34,11 @@ class site_config::default { # configure caching, local resolver include site_config::caching_resolver - # configure /etc/hosts - class { 'site_config::hosts': - stage => setup, - } + # install/configure syslog + include site_config::syslog # install/remove base packages - include site_config::base_packages + include site_config::packages::base # include basic shorewall config include site_shorewall::defaults @@ -41,4 +47,19 @@ class site_config::default { # include basic shell config include site_config::shell + + # set up core leap files and directories + include site_config::files + + if $::services !~ /\bmx\b/ { + include site_postfix::satellite + } + + # if class site_custom exists, include it. + # possibility for users to define custom puppet recipes + if defined( '::site_custom') { + include ::site_custom + } + + include site_check_mk::agent } diff --git a/puppet/modules/site_config/manifests/files.pp b/puppet/modules/site_config/manifests/files.pp new file mode 100644 index 00000000..684d3ad0 --- /dev/null +++ b/puppet/modules/site_config/manifests/files.pp @@ -0,0 +1,23 @@ +class site_config::files { + + file { + '/srv/leap': + ensure => directory, + owner => 'root', + group => 'root', + mode => '0711'; + + '/var/lib/leap': + ensure => directory, + owner => root, + group => 'root', + mode => '0755'; + + '/var/log/leap': + ensure => directory, + owner => root, + group => 'adm', + mode => '0750'; + } + +} diff --git a/puppet/modules/site_config/manifests/hosts.pp b/puppet/modules/site_config/manifests/hosts.pp index ccedf036..e5d4dd70 100644 --- a/puppet/modules/site_config/manifests/hosts.pp +++ b/puppet/modules/site_config/manifests/hosts.pp @@ -1,8 +1,9 @@ class site_config::hosts() { - $hosts = hiera('hosts','') + $hosts = hiera('hosts', false) $hostname = hiera('name') $domain_hash = hiera('domain') $domain_public = $domain_hash['full_suffix'] + $api = hiera('api', '') file { '/etc/hostname': ensure => present, diff --git a/puppet/modules/site_config/manifests/initial_firewall.pp b/puppet/modules/site_config/manifests/initial_firewall.pp new file mode 100644 index 00000000..51cceb31 --- /dev/null +++ b/puppet/modules/site_config/manifests/initial_firewall.pp @@ -0,0 +1,62 @@ +class site_config::initial_firewall { + + # This class is intended to setup an initial firewall, before shorewall is + # configured. The purpose of this is for the rare case where shorewall fails + # to start, we should not expose services to the public. + + $ssh_config = hiera('ssh') + $ssh_port = $ssh_config['port'] + + package { 'iptables': + ensure => present + } + + file { + # This firewall enables ssh access, dns lookups and web lookups (for + # package installation) but otherwise restricts all outgoing and incoming + # ports + '/etc/network/ipv4firewall_up.rules': + content => template('site_config/ipv4firewall_up.rules.erb'), + owner => root, + group => 0, + mode => '0644'; + + # This firewall denys all ipv6 traffic - we will need to change this + # when we begin to support ipv6 + '/etc/network/ipv6firewall_up.rules': + content => template('site_config/ipv6firewall_up.rules.erb'), + owner => root, + group => 0, + mode => '0644'; + + # Run the iptables-restore in if-pre-up so that the network is locked down + # until the correct interfaces and ips are connected + '/etc/network/if-pre-up.d/ipv4tables': + content => "#!/bin/sh\n/sbin/iptables-restore < /etc/network/ipv4firewall_up.rules\n", + owner => root, + group => 0, + mode => '0744'; + + # Same as above for IPv6 + '/etc/network/if-pre-up.d/ipv6tables': + content => "#!/bin/sh\n/sbin/ip6tables-restore < /etc/network/ipv6firewall_up.rules\n", + owner => root, + group => 0, + mode => '0744'; + } + + # Immediately setup these firewall rules, but only if shorewall is not running + exec { + 'default_ipv4_firewall': + command => '/sbin/iptables-restore < /etc/network/ipv4firewall_up.rules', + logoutput => true, + unless => 'test -x /etc/init.d/shorewall && /etc/init.d/shorewall status', + require => File['/etc/network/ipv4firewall_up.rules']; + + 'default_ipv6_firewall': + command => '/sbin/ip6tables-restore < /etc/network/ipv6firewall_up.rules', + logoutput => true, + unless => 'test -x /etc/init.d/shorewall && /etc/init.d/shorewall status', + require => File['/etc/network/ipv6firewall_up.rules']; + } +} diff --git a/puppet/modules/site_config/manifests/base_packages.pp b/puppet/modules/site_config/manifests/packages/base.pp index 3d40f7a2..ae47963c 100644 --- a/puppet/modules/site_config/manifests/base_packages.pp +++ b/puppet/modules/site_config/manifests/packages/base.pp @@ -1,12 +1,13 @@ -class site_config::base_packages { +class site_config::packages::base { + # base set of packages that we want to have installed everywhere - package { [ 'etckeeper', 'screen', 'less' ]: + package { [ 'etckeeper', 'screen', 'less', 'ntp' ]: ensure => installed, } # base set of packages that we want to remove everywhere - package { [ 'acpi', 'acpid', 'acpi-support-base', 'eject', 'ftp', + package { [ 'acpi', 'acpid', 'acpi-support-base', 'eject', 'ftp', 'fontconfig-config', 'laptop-detect', 'lpr', 'nfs-common', 'nfs-kernel-server', 'portmap', 'pppconfig', 'pppoe', 'pump', 'qstat', 'rpcbind', 'samba-common', 'samba-common-bin', 'smbclient', 'tcl8.5', @@ -14,15 +15,4 @@ class site_config::base_packages { 'x11-utils', 'xterm' ]: ensure => absent; } - - if $::virtual == 'virtualbox' { - $virtualbox_ensure = present - } else { - $virtualbox_ensure = absent - } - - package { [ 'build-essential', 'fontconfig-config', 'g++', 'g++-4.7', 'gcc', - 'gcc-4.6', 'gcc-4.7', 'cpp', 'cpp-4.6', 'cpp-4.7', 'libc6-dev' ]: - ensure => $virtualbox_ensure - } } diff --git a/puppet/modules/site_config/manifests/packages/build_essential.pp b/puppet/modules/site_config/manifests/packages/build_essential.pp new file mode 100644 index 00000000..7dfb8b03 --- /dev/null +++ b/puppet/modules/site_config/manifests/packages/build_essential.pp @@ -0,0 +1,11 @@ +# +# include this whenever you want to ensure build-essential package and related compilers are installed. +# +class site_config::packages::build_essential { + if !defined(Package['build-essential']) { + package { + ['build-essential', 'g++', 'g++-4.7', 'gcc', 'gcc-4.6', 'gcc-4.7', 'cpp', 'cpp-4.6', 'cpp-4.7', 'libc6-dev']: + ensure => present + } + } +}
\ No newline at end of file diff --git a/puppet/modules/site_config/manifests/packages/gnutls.pp b/puppet/modules/site_config/manifests/packages/gnutls.pp new file mode 100644 index 00000000..b1f17480 --- /dev/null +++ b/puppet/modules/site_config/manifests/packages/gnutls.pp @@ -0,0 +1,5 @@ +class site_config::packages::gnutls { + + package { 'gnutls-bin': ensure => installed } + +} diff --git a/puppet/modules/site_config/manifests/packages/uninstall.pp b/puppet/modules/site_config/manifests/packages/uninstall.pp new file mode 100644 index 00000000..12f527d9 --- /dev/null +++ b/puppet/modules/site_config/manifests/packages/uninstall.pp @@ -0,0 +1,16 @@ +# +# Uninstall build-essential and compilers, unless they have been explicitly installed elsewhere. +# +class site_config::packages::uninstall { + tag 'leap_base' + + # generally, dev packages are needed for installing ruby gems with native extensions. + # (nickserver, webapp, etc) + + if !defined(Package['build-essential']) { + package { + ['build-essential', 'g++', 'g++-4.7', 'gcc', 'gcc-4.6', 'gcc-4.7', 'cpp', 'cpp-4.6', 'cpp-4.7', 'libc6-dev']: + ensure => purged + } + } +}
\ No newline at end of file diff --git a/puppet/modules/site_config/manifests/params.pp b/puppet/modules/site_config/manifests/params.pp index 237ee454..012b3ce0 100644 --- a/puppet/modules/site_config/manifests/params.pp +++ b/puppet/modules/site_config/manifests/params.pp @@ -3,9 +3,12 @@ class site_config::params { $ip_address = hiera('ip_address') $ip_address_interface = getvar("interface_${ip_address}") $ec2_local_ipv4_interface = getvar("interface_${::ec2_local_ipv4}") + $environment = hiera('environment', undef) - if $::virtual == 'virtualbox' { - $interface = [ 'eth0', 'eth1' ] + + if $environment == 'local' { + $interface = 'eth1' + include site_config::packages::build_essential } elsif hiera('interface','') != '' { $interface = hiera('interface') @@ -17,9 +20,16 @@ class site_config::params { $interface = $ec2_local_ipv4_interface } elsif $::interfaces =~ /eth0/ { - $interface = eth0 + $interface = 'eth0' } else { fail("unable to determine a valid interface, please set a valid interface for this node in nodes/${::hostname}.json") } + + $ca_name = 'leap_ca' + $client_ca_name = 'leap_client_ca' + $ca_bundle_name = 'leap_ca_bundle' + $cert_name = 'leap' + $commercial_ca_name = 'leap_commercial_ca' + $commercial_cert_name = 'leap_commercial' } diff --git a/puppet/modules/site_config/manifests/resolvconf.pp b/puppet/modules/site_config/manifests/resolvconf.pp index 271c5043..05990c67 100644 --- a/puppet/modules/site_config/manifests/resolvconf.pp +++ b/puppet/modules/site_config/manifests/resolvconf.pp @@ -2,12 +2,13 @@ class site_config::resolvconf { $domain_public = $site_config::default::domain_hash['full_suffix'] - # 127.0.0.1: caching-only local bind - # 87.118.100.175: http://server.privacyfoundation.de - # 62.141.58.13: http://www.privacyfoundation.ch/de/service/server.html class { '::resolvconf': domain => $domain_public, search => $domain_public, - nameservers => [ '127.0.0.1', '87.118.100.175', '62.141.58.13' ] + nameservers => [ + '127.0.0.1 # local caching-only, unbound', + '85.214.20.141 # Digitalcourage, a german privacy organisation: (https://en.wikipedia.org/wiki/Digitalcourage)', + '77.109.138.45 # Swiss privacy Foundation (http://www.privacyfoundation.ch/de/service/server.html)' + ] } } diff --git a/puppet/modules/site_config/manifests/ruby/dev.pp b/puppet/modules/site_config/manifests/ruby/dev.pp new file mode 100644 index 00000000..3ea6ca96 --- /dev/null +++ b/puppet/modules/site_config/manifests/ruby/dev.pp @@ -0,0 +1,8 @@ +class site_config::ruby::dev inherits site_config::ruby { + Class['::ruby'] { + ruby_version => '1.9.3', + install_dev => true + } + # building gems locally probably requires build-essential and gcc: + include site_config::packages::build_essential +} diff --git a/puppet/modules/site_config/manifests/setup.pp b/puppet/modules/site_config/manifests/setup.pp new file mode 100644 index 00000000..6d89be86 --- /dev/null +++ b/puppet/modules/site_config/manifests/setup.pp @@ -0,0 +1,50 @@ +class site_config::setup { + tag 'leap_base' + + # + # this is applied before each run of site.pp + # + #$services = '' + + Exec { path => '/usr/bin:/usr/sbin/:/bin:/sbin:/usr/local/bin:/usr/local/sbin' } + + include site_config::params + + include concat::setup + include stdlib + + # configure /etc/hosts + class { 'site_config::hosts': + stage => setup, + } + + include site_config::initial_firewall + + include site_apt + + package { 'facter': + ensure => latest, + require => Exec['refresh_apt'] + } + + # if squid_deb_proxy_client is set to true, install and configure + # squid_deb_proxy_client for apt caching + if hiera('squid_deb_proxy_client', false) { + include site_squid_deb_proxy::client + } + + # shorewall is installed/half-configured during setup.pp (Bug #3871) + # we need to include shorewall::interface{eth0} in setup.pp so + # packages can be installed during main puppetrun, even before shorewall + # is configured completly + if ( $::site_config::params::environment == 'local' ) { + include site_config::vagrant + } + + # if class site_custom::setup exists, include it. + # possibility for users to define custom puppet recipes + if defined( '::site_custom::setup') { + include ::site_custom::setup + } + +} diff --git a/puppet/modules/site_config/manifests/sysctl.pp b/puppet/modules/site_config/manifests/sysctl.pp new file mode 100644 index 00000000..99f75123 --- /dev/null +++ b/puppet/modules/site_config/manifests/sysctl.pp @@ -0,0 +1,8 @@ +class site_config::sysctl { + + sysctl::config { + 'net.ipv4.ip_nonlocal_bind': + value => 1, + comment => 'Allow applications to bind to an address when link is down (see https://leap.se/code/issues/4506)' + } +} diff --git a/puppet/modules/site_config/manifests/syslog.pp b/puppet/modules/site_config/manifests/syslog.pp new file mode 100644 index 00000000..d3abeca1 --- /dev/null +++ b/puppet/modules/site_config/manifests/syslog.pp @@ -0,0 +1,28 @@ +class site_config::syslog { + + # we need to pull in rsyslog from the leap repository until it is availbale in + # wheezy-backports + apt::preferences_snippet { 'fixed_rsyslog_anon_package': + package => 'rsyslog*', + priority => '999', + pin => 'release o=leap.se', + before => Class['rsyslog::install'] + } + + apt::preferences_snippet { 'rsyslog_anon_depends': + package => 'libestr0 librelp0', + priority => '999', + pin => 'release a=wheezy-backports', + before => Class['rsyslog::install'] + } + + class { 'rsyslog::client': + log_remote => false, + log_local => true + } + + rsyslog::snippet { '00-anonymize_logs': + content => '$ModLoad mmanon +action(type="mmanon" ipv4.bits="32" mode="rewrite")' + } +} diff --git a/puppet/modules/site_config/manifests/vagrant.pp b/puppet/modules/site_config/manifests/vagrant.pp new file mode 100644 index 00000000..8f50b305 --- /dev/null +++ b/puppet/modules/site_config/manifests/vagrant.pp @@ -0,0 +1,11 @@ +class site_config::vagrant { + # class for vagrant nodes + + include site_shorewall::defaults + # eth0 on vagrant nodes is the uplink if + shorewall::interface { 'eth0': + zone => 'net', + options => 'tcpflags,blacklist,nosmurfs'; + } + +} diff --git a/puppet/modules/site_config/manifests/x509/ca.pp b/puppet/modules/site_config/manifests/x509/ca.pp new file mode 100644 index 00000000..b16d0eeb --- /dev/null +++ b/puppet/modules/site_config/manifests/x509/ca.pp @@ -0,0 +1,9 @@ +class site_config::x509::ca { + + $x509 = hiera('x509') + $ca = $x509['ca_cert'] + + x509::ca { $site_config::params::ca_name: + content => $ca + } +} diff --git a/puppet/modules/site_config/manifests/x509/ca_bundle.pp b/puppet/modules/site_config/manifests/x509/ca_bundle.pp new file mode 100644 index 00000000..4cbe574a --- /dev/null +++ b/puppet/modules/site_config/manifests/x509/ca_bundle.pp @@ -0,0 +1,16 @@ +class site_config::x509::ca_bundle { + + # CA bundle -- we want to have the possibility of allowing multiple CAs. + # For now, the reason is to transition to using client CA. In the future, + # we will want to be able to smoothly phase out one CA and phase in another. + # I tried "--capath" for this, but it did not work. + + + $x509 = hiera('x509') + $ca = $x509['ca_cert'] + $client_ca = $x509['client_ca_cert'] + + x509::ca { $site_config::params::ca_bundle_name: + content => "${ca}${client_ca}" + } +} diff --git a/puppet/modules/site_config/manifests/x509/cert.pp b/puppet/modules/site_config/manifests/x509/cert.pp new file mode 100644 index 00000000..7ed42959 --- /dev/null +++ b/puppet/modules/site_config/manifests/x509/cert.pp @@ -0,0 +1,10 @@ +class site_config::x509::cert { + + $x509 = hiera('x509') + $cert = $x509['cert'] + + x509::cert { $site_config::params::cert_name: + content => $cert + } + +} diff --git a/puppet/modules/site_config/manifests/x509/client_ca/ca.pp b/puppet/modules/site_config/manifests/x509/client_ca/ca.pp new file mode 100644 index 00000000..0f313898 --- /dev/null +++ b/puppet/modules/site_config/manifests/x509/client_ca/ca.pp @@ -0,0 +1,14 @@ +class site_config::x509::client_ca::ca { + + ## + ## This is for the special CA that is used exclusively for generating + ## client certificates by the webapp. + ## + + $x509 = hiera('x509') + $cert = $x509['client_ca_cert'] + + x509::ca { $site_config::params::client_ca_name: + content => $cert + } +} diff --git a/puppet/modules/site_config/manifests/x509/client_ca/key.pp b/puppet/modules/site_config/manifests/x509/client_ca/key.pp new file mode 100644 index 00000000..f9ef3f52 --- /dev/null +++ b/puppet/modules/site_config/manifests/x509/client_ca/key.pp @@ -0,0 +1,14 @@ +class site_config::x509::client_ca::key { + + ## + ## This is for the special CA that is used exclusively for generating + ## client certificates by the webapp. + ## + + $x509 = hiera('x509') + $key = $x509['client_ca_key'] + + x509::key { $site_config::params::client_ca_name: + content => $key + } +} diff --git a/puppet/modules/site_config/manifests/x509/commercial/ca.pp b/puppet/modules/site_config/manifests/x509/commercial/ca.pp new file mode 100644 index 00000000..8f35759f --- /dev/null +++ b/puppet/modules/site_config/manifests/x509/commercial/ca.pp @@ -0,0 +1,9 @@ +class site_config::x509::commercial::ca { + + $x509 = hiera('x509') + $ca = $x509['commercial_ca_cert'] + + x509::ca { $site_config::params::commercial_ca_name: + content => $ca + } +} diff --git a/puppet/modules/site_config/manifests/x509/commercial/cert.pp b/puppet/modules/site_config/manifests/x509/commercial/cert.pp new file mode 100644 index 00000000..0c71a705 --- /dev/null +++ b/puppet/modules/site_config/manifests/x509/commercial/cert.pp @@ -0,0 +1,10 @@ +class site_config::x509::commercial::cert { + + $x509 = hiera('x509') + $cert = $x509['commercial_cert'] + + x509::cert { $site_config::params::commercial_cert_name: + content => $cert + } + +} diff --git a/puppet/modules/site_config/manifests/x509/commercial/key.pp b/puppet/modules/site_config/manifests/x509/commercial/key.pp new file mode 100644 index 00000000..d32e85ef --- /dev/null +++ b/puppet/modules/site_config/manifests/x509/commercial/key.pp @@ -0,0 +1,9 @@ +class site_config::x509::commercial::key { + + $x509 = hiera('x509') + $key = $x509['commercial_key'] + + x509::key { $site_config::params::commercial_cert_name: + content => $key + } +} diff --git a/puppet/modules/site_config/manifests/x509/key.pp b/puppet/modules/site_config/manifests/x509/key.pp new file mode 100644 index 00000000..32b59726 --- /dev/null +++ b/puppet/modules/site_config/manifests/x509/key.pp @@ -0,0 +1,9 @@ +class site_config::x509::key { + + $x509 = hiera('x509') + $key = $x509['key'] + + x509::key { $site_config::params::cert_name: + content => $key + } +} diff --git a/puppet/modules/site_config/templates/hosts b/puppet/modules/site_config/templates/hosts index 2c784b05..bfcabaa5 100644 --- a/puppet/modules/site_config/templates/hosts +++ b/puppet/modules/site_config/templates/hosts @@ -1,10 +1,12 @@ # This file is managed by puppet, any changes will be overwritten! 127.0.0.1 localhost -127.0.1.1 <%= @hostname %>.<%= @domain_public %> <%= @hostname %> +127.0.1.1 <%= @hostname %>.<%= @domain_public %> <%= @hostname %> <% if (defined? @services) and (@services.include? 'webapp') -%><%= @domain_public %> <%= @api['domain'] %><% end -%> + <%- if @hosts then -%> -<% @hosts.each do |name, props| -%> +<% @hosts.keys.sort.each do |name| -%> +<%- props = @hosts[name] -%> <%= props["ip_address"] %> <%= props["domain_full"] %> <%= props["domain_internal"] %> <%= name %> <% end -%> <% end -%> diff --git a/puppet/modules/site_config/templates/ipv4firewall_up.rules.erb b/puppet/modules/site_config/templates/ipv4firewall_up.rules.erb new file mode 100644 index 00000000..524ae308 --- /dev/null +++ b/puppet/modules/site_config/templates/ipv4firewall_up.rules.erb @@ -0,0 +1,22 @@ +# Generated by iptables-save v1.4.14 on Tue Aug 20 14:40:40 2013 +*filter +:INPUT DROP [0:0] +:FORWARD DROP [0:0] +:OUTPUT DROP [0:0] +-A INPUT -i lo -j ACCEPT +-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT +-A INPUT -p tcp -m state --state NEW,ESTABLISHED --dport <%= @ssh_port %> -j ACCEPT +-A INPUT -p udp -m udp --sport 53 -j ACCEPT +-A INPUT -p icmp -m icmp --icmp-type 8 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT +-A INPUT -p icmp -m icmp --icmp-type 0 -m state --state RELATED,ESTABLISHED -j ACCEPT +-A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7 +-A OUTPUT -o lo -j ACCEPT +-A OUTPUT -p icmp -m icmp --icmp-type 0 -m state --state RELATED,ESTABLISHED -j ACCEPT +-A OUTPUT -p icmp -m icmp --icmp-type 8 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT +-A OUTPUT -p tcp -m state --state NEW,ESTABLISHED --sport <%= @ssh_port %> -j ACCEPT +-A OUTPUT -p tcp -m state --state NEW,ESTABLISHED --dport 80 -j ACCEPT +-A OUTPUT -p tcp -m state --state NEW,ESTABLISHED --dport 443 -j ACCEPT +-A OUTPUT -p udp -m udp --dport 53 -j ACCEPT +-A OUTPUT -p udp -m udp --dport 123 -j ACCEPT +-A OUTPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7 +COMMIT diff --git a/puppet/modules/site_config/templates/ipv6firewall_up.rules.erb b/puppet/modules/site_config/templates/ipv6firewall_up.rules.erb new file mode 100644 index 00000000..e7fae52e --- /dev/null +++ b/puppet/modules/site_config/templates/ipv6firewall_up.rules.erb @@ -0,0 +1,7 @@ +# Generated by ip6tables-save v1.4.20 on Tue Aug 20 12:19:43 2013 +*filter +:INPUT DROP [24:1980] +:FORWARD DROP [0:0] +:OUTPUT DROP [14:8030] +COMMIT +# Completed on Tue Aug 20 12:19:43 2013 diff --git a/puppet/modules/site_couchdb/files/couchdb_scripts_defaults.conf b/puppet/modules/site_couchdb/files/couchdb_scripts_defaults.conf new file mode 100644 index 00000000..1565e1a1 --- /dev/null +++ b/puppet/modules/site_couchdb/files/couchdb_scripts_defaults.conf @@ -0,0 +1,4 @@ +# space separated list of excluded DBs for dumping +# sourced by couchdb_dumpall.sh +EXCLUDE_DBS='sessions tokens' + diff --git a/puppet/modules/site_couchdb/files/designs/Readme.md b/puppet/modules/site_couchdb/files/designs/Readme.md new file mode 100644 index 00000000..983f629f --- /dev/null +++ b/puppet/modules/site_couchdb/files/designs/Readme.md @@ -0,0 +1,14 @@ +This directory contains design documents for the leap platform. + +They need to be uploaded to the couch database in order to query the +database in certain ways. + +Each subdirectory corresponds to a couch database and contains the design +documents that need to be added to that particular database. + +Here's an example of how to upload the users design document: +```bash +HOST="http://localhost:5984" +curl -X PUT $HOST/users/_design/User --data @users/User.json + +``` diff --git a/puppet/modules/site_couchdb/files/designs/customers/Customer.json b/puppet/modules/site_couchdb/files/designs/customers/Customer.json new file mode 100644 index 00000000..1b4bbddd --- /dev/null +++ b/puppet/modules/site_couchdb/files/designs/customers/Customer.json @@ -0,0 +1,18 @@ +{ + "_id": "_design/Customer", + "language": "javascript", + "views": { + "by_user_id": { + "map": " function(doc) {\n if ((doc['type'] == 'Customer') && (doc['user_id'] != null)) {\n emit(doc['user_id'], 1);\n }\n }\n", + "reduce": "_sum" + }, + "by_braintree_customer_id": { + "map": " function(doc) {\n if ((doc['type'] == 'Customer') && (doc['braintree_customer_id'] != null)) {\n emit(doc['braintree_customer_id'], 1);\n }\n }\n", + "reduce": "_sum" + }, + "all": { + "map": " function(doc) {\n if (doc['type'] == 'Customer') {\n emit(doc._id, null);\n }\n }\n" + } + }, + "couchrest-hash": "688c401ec0230b75625c176a88fc4a02" +}
\ No newline at end of file diff --git a/puppet/modules/site_couchdb/files/designs/identities/Identity.json b/puppet/modules/site_couchdb/files/designs/identities/Identity.json new file mode 100644 index 00000000..2ac092ab --- /dev/null +++ b/puppet/modules/site_couchdb/files/designs/identities/Identity.json @@ -0,0 +1,28 @@ +{ + "_id": "_design/Identity", + "language": "javascript", + "views": { + "by_user_id": { + "map": " function(doc) {\n if ((doc['type'] == 'Identity') && (doc['user_id'] != null)) {\n emit(doc['user_id'], 1);\n }\n }\n", + "reduce": "_sum" + }, + "by_address_and_destination": { + "map": " function(doc) {\n if ((doc['type'] == 'Identity') && (doc['address'] != null) && (doc['destination'] != null)) {\n emit([doc['address'], doc['destination']], 1);\n }\n }\n", + "reduce": "_sum" + }, + "by_address": { + "map": " function(doc) {\n if ((doc['type'] == 'Identity') && (doc['address'] != null)) {\n emit(doc['address'], 1);\n }\n }\n", + "reduce": "_sum" + }, + "pgp_key_by_email": { + "map": " function(doc) {\n if (doc.type != 'Identity') {\n return;\n }\n if (typeof doc.keys === \"object\") {\n emit(doc.address, doc.keys[\"pgp\"]);\n }\n }\n" + }, + "disabled": { + "map": " function(doc) {\n if (doc.type != 'Identity') {\n return;\n }\n if (typeof doc.user_id === \"undefined\") {\n emit(doc._id, 1);\n }\n }\n" + }, + "all": { + "map": " function(doc) {\n if (doc['type'] == 'Identity') {\n emit(doc._id, null);\n }\n }\n" + } + }, + "couchrest-hash": "e9004d70e26770c621a9667536429a68" +}
\ No newline at end of file diff --git a/puppet/modules/site_couchdb/files/designs/messages/Message.json b/puppet/modules/site_couchdb/files/designs/messages/Message.json new file mode 100644 index 00000000..7bcd74c7 --- /dev/null +++ b/puppet/modules/site_couchdb/files/designs/messages/Message.json @@ -0,0 +1,18 @@ +{ + "_id": "_design/Message", + "language": "javascript", + "views": { + "by_user_ids_to_show_and_created_at": { + "map": "// not using at moment\n// call with something like Message.by_user_ids_to_show_and_created_at.startkey([user_id, start_date]).endkey([user_id,end_date])\nfunction (doc) {\n if (doc.type === 'Message' && doc.user_ids_to_show && Array.isArray(doc.user_ids_to_show)) {\n doc.user_ids_to_show.forEach(function (userId) {\n emit([userId, doc.created_at], 1);\n });\n }\n}\n", + "reduce": "function(key, values, rereduce) { return sum(values); }" + }, + "by_user_ids_to_show": { + "map": "function (doc) {\n if (doc.type === 'Message' && doc.user_ids_to_show && Array.isArray(doc.user_ids_to_show)) {\n doc.user_ids_to_show.forEach(function (userId) {\n emit(userId, 1);\n });\n }\n}\n", + "reduce": "function(key, values, rereduce) { return sum(values); }" + }, + "all": { + "map": " function(doc) {\n if (doc['type'] == 'Message') {\n emit(doc._id, null);\n }\n }\n" + } + }, + "couchrest-hash": "0967e7cc5bb1e61edc1c085f6f0cecbf" +}
\ No newline at end of file diff --git a/puppet/modules/site_couchdb/files/designs/sessions/Session.json b/puppet/modules/site_couchdb/files/designs/sessions/Session.json new file mode 100644 index 00000000..70202780 --- /dev/null +++ b/puppet/modules/site_couchdb/files/designs/sessions/Session.json @@ -0,0 +1,8 @@ +{ + "views": { + "by_expires": { + "reduce": "_sum", + "map": "function(doc) {\n if(typeof doc.expires !== \"undefined\") {\n emit(doc.expires, 1);\n }\n}\n" + } + } +} diff --git a/puppet/modules/site_couchdb/files/designs/shared/docs.json b/puppet/modules/site_couchdb/files/designs/shared/docs.json new file mode 100644 index 00000000..004180cd --- /dev/null +++ b/puppet/modules/site_couchdb/files/designs/shared/docs.json @@ -0,0 +1,8 @@ +{ + "_id": "_design/docs", + "views": { + "get": { + "map": "function(doc) {\n if (doc.u1db_rev) {\n var is_tombstone = true;\n var has_conflicts = false;\n if (doc._attachments) {\n if (doc._attachments.u1db_content)\n is_tombstone = false;\n if (doc._attachments.u1db_conflicts)\n has_conflicts = true;\n }\n emit(doc._id,\n {\n \"couch_rev\": doc._rev,\n \"u1db_rev\": doc.u1db_rev,\n \"is_tombstone\": is_tombstone,\n \"has_conflicts\": has_conflicts,\n }\n );\n }\n}\n" + } + } +}
\ No newline at end of file diff --git a/puppet/modules/site_couchdb/files/designs/shared/syncs.json b/puppet/modules/site_couchdb/files/designs/shared/syncs.json new file mode 100644 index 00000000..bab5622f --- /dev/null +++ b/puppet/modules/site_couchdb/files/designs/shared/syncs.json @@ -0,0 +1,11 @@ +{ + "_id": "_design/syncs", + "updates": { + "put": "function(doc, req){\n if (!doc) {\n doc = {}\n doc['_id'] = 'u1db_sync_log';\n doc['syncs'] = [];\n }\n body = JSON.parse(req.body);\n // remove outdated info\n doc['syncs'] = doc['syncs'].filter(\n function (entry) {\n return entry[0] != body['other_replica_uid'];\n }\n );\n // store u1db rev\n doc['syncs'].push([\n body['other_replica_uid'],\n body['other_generation'],\n body['other_transaction_id']\n ]);\n return [doc, 'ok'];\n}\n\n" + }, + "views": { + "log": { + "map": "function(doc) {\n if (doc._id == 'u1db_sync_log') {\n if (doc.syncs)\n doc.syncs.forEach(function (entry) {\n emit(entry[0],\n {\n 'known_generation': entry[1],\n 'known_transaction_id': entry[2]\n });\n });\n }\n}\n" + } + } +}
\ No newline at end of file diff --git a/puppet/modules/site_couchdb/files/designs/shared/transactions.json b/puppet/modules/site_couchdb/files/designs/shared/transactions.json new file mode 100644 index 00000000..106ad46c --- /dev/null +++ b/puppet/modules/site_couchdb/files/designs/shared/transactions.json @@ -0,0 +1,13 @@ +{ + "_id": "_design/transactions", + "lists": { + "generation": "function(head, req) {\n var row;\n var rows=[];\n // fetch all rows\n while(row = getRow()) {\n rows.push(row);\n }\n if (rows.length > 0)\n send(JSON.stringify({\n \"generation\": rows.length,\n \"doc_id\": rows[rows.length-1]['id'],\n \"transaction_id\": rows[rows.length-1]['value']\n }));\n else\n send(JSON.stringify({\n \"generation\": 0,\n \"doc_id\": \"\",\n \"transaction_id\": \"\",\n }));\n}\n", + "trans_id_for_gen": "function(head, req) {\n var row;\n var rows=[];\n var i = 1;\n var gen = 1;\n if (req.query.gen)\n gen = parseInt(req.query['gen']);\n // fetch all rows\n while(row = getRow())\n rows.push(row);\n if (gen <= rows.length)\n send(JSON.stringify({\n \"generation\": gen,\n \"doc_id\": rows[gen-1]['id'],\n \"transaction_id\": rows[gen-1]['value'],\n }));\n else\n send('{}');\n}\n", + "whats_changed": "function(head, req) {\n var row;\n var gen = 1;\n var old_gen = 0;\n if (req.query.old_gen)\n old_gen = parseInt(req.query['old_gen']);\n send('{\"transactions\":[\\n');\n // fetch all rows\n while(row = getRow()) {\n if (gen > old_gen) {\n if (gen > old_gen+1)\n send(',\\n');\n send(JSON.stringify({\n \"generation\": gen,\n \"doc_id\": row[\"id\"],\n \"transaction_id\": row[\"value\"]\n }));\n }\n gen++;\n }\n send('\\n]}');\n}\n" + }, + "views": { + "log": { + "map": "function(doc) {\n if (doc.u1db_transactions)\n doc.u1db_transactions.forEach(function(t) {\n emit(t[0], // use timestamp as key so the results are ordered\n t[1]); // value is the transaction_id\n });\n}\n" + } + } +}
\ No newline at end of file diff --git a/puppet/modules/site_couchdb/files/designs/tickets/Ticket.json b/puppet/modules/site_couchdb/files/designs/tickets/Ticket.json new file mode 100644 index 00000000..2c9408b8 --- /dev/null +++ b/puppet/modules/site_couchdb/files/designs/tickets/Ticket.json @@ -0,0 +1,50 @@ +{ + "_id": "_design/Ticket", + "language": "javascript", + "views": { + "by_updated_at": { + "map": " function(doc) {\n if ((doc['type'] == 'Ticket') && (doc['updated_at'] != null)) {\n emit(doc['updated_at'], 1);\n }\n }\n", + "reduce": "_sum" + }, + "by_created_at": { + "map": " function(doc) {\n if ((doc['type'] == 'Ticket') && (doc['created_at'] != null)) {\n emit(doc['created_at'], 1);\n }\n }\n", + "reduce": "_sum" + }, + "by_created_by": { + "map": " function(doc) {\n if ((doc['type'] == 'Ticket') && (doc['created_by'] != null)) {\n emit(doc['created_by'], 1);\n }\n }\n", + "reduce": "_sum" + }, + "by_is_open_and_created_at": { + "map": " function(doc) {\n if ((doc['type'] == 'Ticket') && (doc['is_open'] != null) && (doc['created_at'] != null)) {\n emit([doc['is_open'], doc['created_at']], 1);\n }\n }\n", + "reduce": "_sum" + }, + "by_is_open_and_updated_at": { + "map": " function(doc) {\n if ((doc['type'] == 'Ticket') && (doc['is_open'] != null) && (doc['updated_at'] != null)) {\n emit([doc['is_open'], doc['updated_at']], 1);\n }\n }\n", + "reduce": "_sum" + }, + "by_includes_post_by_and_is_open_and_created_at": { + "map": "function(doc) {\n var arr = {}\n if (doc['type'] == 'Ticket' && doc.comments) {\n doc.comments.forEach(function(comment){\n if (comment.posted_by && !arr[comment.posted_by]) {\n //don't add duplicates\n arr[comment.posted_by] = true;\n emit([comment.posted_by, doc.is_open, doc.created_at], 1);\n }\n });\n }\n}\n", + "reduce": "function(key, values, rereduce) { return sum(values); }" + }, + "by_includes_post_by_and_is_open_and_updated_at": { + "map": "function(doc) {\n var arr = {}\n if (doc['type'] == 'Ticket' && doc.comments) {\n doc.comments.forEach(function(comment){\n if (comment.posted_by && !arr[comment.posted_by]) {\n //don't add duplicates\n arr[comment.posted_by] = true;\n emit([comment.posted_by, doc.is_open, doc.updated_at], 1);\n }\n });\n }\n}\n", + "reduce": "function(key, values, rereduce) { return sum(values); }" + }, + "by_includes_post_by_and_updated_at": { + "map": "function(doc) {\n var arr = {}\n if (doc['type'] == 'Ticket' && doc.comments) {\n doc.comments.forEach(function(comment){\n if (comment.posted_by && !arr[comment.posted_by]) {\n //don't add duplicates\n arr[comment.posted_by] = true;\n emit([comment.posted_by, doc.updated_at], 1);\n }\n });\n }\n}\n", + "reduce": "function(key, values, rereduce) { return sum(values); }" + }, + "by_includes_post_by": { + "map": "// TODO: This view is only used in tests--should we keep it?\nfunction(doc) {\n var arr = {}\n if (doc['type'] == 'Ticket' && doc.comments) {\n doc.comments.forEach(function(comment){\n if (comment.posted_by && !arr[comment.posted_by]) {\n //don't add duplicates\n arr[comment.posted_by] = true;\n emit(comment.posted_by, 1);\n }\n });\n }\n}\n", + "reduce": "function(key, values, rereduce) { return sum(values); }" + }, + "by_includes_post_by_and_created_at": { + "map": "function(doc) {\n var arr = {}\n if (doc['type'] == 'Ticket' && doc.comments) {\n doc.comments.forEach(function(comment){\n if (comment.posted_by && !arr[comment.posted_by]) {\n //don't add duplicates\n arr[comment.posted_by] = true;\n emit([comment.posted_by, doc.created_at], 1);\n }\n });\n }\n}\n", + "reduce": "function(key, values, rereduce) { return sum(values); }" + }, + "all": { + "map": " function(doc) {\n if (doc['type'] == 'Ticket') {\n emit(doc._id, null);\n }\n }\n" + } + }, + "couchrest-hash": "9978e2cbeacbe8622c2a7f103bf8130f" +}
\ No newline at end of file diff --git a/puppet/modules/site_couchdb/files/designs/tokens/Token.json b/puppet/modules/site_couchdb/files/designs/tokens/Token.json new file mode 100644 index 00000000..b9025f15 --- /dev/null +++ b/puppet/modules/site_couchdb/files/designs/tokens/Token.json @@ -0,0 +1,14 @@ +{ + "_id": "_design/Token", + "language": "javascript", + "views": { + "by_last_seen_at": { + "map": " function(doc) {\n if ((doc['type'] == 'Token') && (doc['last_seen_at'] != null)) {\n emit(doc['last_seen_at'], 1);\n }\n }\n", + "reduce": "_sum" + }, + "all": { + "map": " function(doc) {\n if (doc['type'] == 'Token') {\n emit(doc._id, null);\n }\n }\n" + } + }, + "couchrest-hash": "541dd924551c42a2317b345effbe65cc" +}
\ No newline at end of file diff --git a/puppet/modules/site_couchdb/files/designs/users/User.json b/puppet/modules/site_couchdb/files/designs/users/User.json new file mode 100644 index 00000000..4089ad97 --- /dev/null +++ b/puppet/modules/site_couchdb/files/designs/users/User.json @@ -0,0 +1,22 @@ +{ + "_id": "_design/User", + "language": "javascript", + "views": { + "by_login": { + "map": " function(doc) {\n if ((doc['type'] == 'User') && (doc['login'] != null)) {\n emit(doc['login'], 1);\n }\n }\n", + "reduce": "_sum" + }, + "all": { + "map": " function(doc) {\n if (doc['type'] == 'User') {\n emit(doc._id, null);\n }\n }\n" + }, + "by_created_at_and_one_month_warning_not_sent": { + "map": "function (doc) {\n if ((doc['type'] == 'User') && (doc['created_at'] != null) && (doc['one_month_warning_sent'] == null)) {\n emit(doc['created_at'], 1);\n } \n}\n", + "reduce": "function(key, values, rereduce) { return sum(values); }" + }, + "by_created_at": { + "map": " function(doc) {\n if ((doc['type'] == 'User') && (doc['created_at'] != null)) {\n emit(doc['created_at'], 1);\n }\n }\n", + "reduce": "_sum" + } + }, + "couchrest-hash": "61840ab3ec0f94ef8bbd6dd208db3b70" +}
\ No newline at end of file diff --git a/puppet/modules/site_couchdb/manifests/add_users.pp b/puppet/modules/site_couchdb/manifests/add_users.pp new file mode 100644 index 00000000..f9ea7349 --- /dev/null +++ b/puppet/modules/site_couchdb/manifests/add_users.pp @@ -0,0 +1,54 @@ +class site_couchdb::add_users { + + # Couchdb users + + ## leap_mx couchdb user + ## read: identities + ## write access to user-<uuid> + couchdb::add_user { $site_couchdb::couchdb_leap_mx_user: + roles => '["identities"]', + pw => $site_couchdb::couchdb_leap_mx_pw, + salt => $site_couchdb::couchdb_leap_mx_salt, + require => Couchdb::Query::Setup['localhost'] + } + + ## nickserver couchdb user + ## r: identities + ## r/w: keycache + couchdb::add_user { $site_couchdb::couchdb_nickserver_user: + roles => '["identities","keycache"]', + pw => $site_couchdb::couchdb_nickserver_pw, + salt => $site_couchdb::couchdb_nickserver_salt, + require => Couchdb::Query::Setup['localhost'] + } + + ## soledad couchdb user + ## r/w: user-<uuid>, shared + ## read: tokens + couchdb::add_user { $site_couchdb::couchdb_soledad_user: + roles => '["tokens"]', + pw => $site_couchdb::couchdb_soledad_pw, + salt => $site_couchdb::couchdb_soledad_salt, + require => Couchdb::Query::Setup['localhost'] + } + + ### tapicero couchdb user + ### admin: needs to be able to create user-<uuid> databases + ### read: users + couchdb::add_user { $site_couchdb::couchdb_tapicero_user: + roles => '["users"]', + pw => $site_couchdb::couchdb_tapicero_pw, + salt => $site_couchdb::couchdb_tapicero_salt, + require => Couchdb::Query::Setup['localhost'] + } + + ## webapp couchdb user + ## read/write: users, tokens, sessions, tickets, identities, customer + couchdb::add_user { $site_couchdb::couchdb_webapp_user: + roles => '["tokens","identities","users"]', + pw => $site_couchdb::couchdb_webapp_pw, + salt => $site_couchdb::couchdb_webapp_salt, + require => Couchdb::Query::Setup['localhost'] + } + +} diff --git a/puppet/modules/site_couchdb/manifests/backup.pp b/puppet/modules/site_couchdb/manifests/backup.pp new file mode 100644 index 00000000..8b5aa6ea --- /dev/null +++ b/puppet/modules/site_couchdb/manifests/backup.pp @@ -0,0 +1,23 @@ +class site_couchdb::backup { + + # general backupninja config + backupninja::config { 'backupninja_config': + usecolors => false, + } + + # dump all DBs locally to /var/backups/couchdb once a day + backupninja::sh { 'couchdb_backup': + command_string => "cd /srv/leap/couchdb/scripts \n./couchdb_dumpall.sh" + } + + # Deploy /etc/leap/couchdb_scripts_defaults.conf so we can exclude + # some databases + + file { '/etc/leap/couchdb_scripts_defaults.conf': + source => 'puppet:///modules/site_couchdb/couchdb_scripts_defaults.conf', + mode => '0644', + owner => 'root', + group => 'root', + } + +} diff --git a/puppet/modules/site_couchdb/manifests/bigcouch/add_nodes.pp b/puppet/modules/site_couchdb/manifests/bigcouch/add_nodes.pp index 241a4914..97e85785 100644 --- a/puppet/modules/site_couchdb/manifests/bigcouch/add_nodes.pp +++ b/puppet/modules/site_couchdb/manifests/bigcouch/add_nodes.pp @@ -1,5 +1,8 @@ class site_couchdb::bigcouch::add_nodes { # loop through neighbors array and add nodes $nodes = $::site_couchdb::bigcouch_config['neighbors'] - couchdb::bigcouch::add_node { $nodes: } + + couchdb::bigcouch::add_node { $nodes: + require => Couchdb::Query::Setup['localhost'] + } } diff --git a/puppet/modules/site_couchdb/manifests/bigcouch/compaction.pp b/puppet/modules/site_couchdb/manifests/bigcouch/compaction.pp new file mode 100644 index 00000000..84aab4ef --- /dev/null +++ b/puppet/modules/site_couchdb/manifests/bigcouch/compaction.pp @@ -0,0 +1,8 @@ +class site_couchdb::bigcouch::compaction { + cron { + 'compact_all_shards': + command => '/srv/leap/couchdb/scripts/bigcouch_compact_all_shards.sh >> /var/log/bigcouch/compaction.log', + hour => 3, + minute => 17; + } +} diff --git a/puppet/modules/site_couchdb/manifests/bigcouch/settle_cluster.pp b/puppet/modules/site_couchdb/manifests/bigcouch/settle_cluster.pp new file mode 100644 index 00000000..aa843e2e --- /dev/null +++ b/puppet/modules/site_couchdb/manifests/bigcouch/settle_cluster.pp @@ -0,0 +1,11 @@ +class site_couchdb::bigcouch::settle_cluster { + + exec { 'wait_for_couch_nodes': + command => '/srv/leap/bin/run_tests --test CouchDB/Are_configured_nodes_online? --retry 6 --wait 10' + } + + exec { 'settle_cluster_membership': + command => '/srv/leap/bin/run_tests --test CouchDB/Is_cluster_membership_ok? --retry 6 --wait 10', + require => Exec['wait_for_couch_nodes'] + } +} diff --git a/puppet/modules/site_couchdb/manifests/create_dbs.pp b/puppet/modules/site_couchdb/manifests/create_dbs.pp new file mode 100644 index 00000000..41500d3a --- /dev/null +++ b/puppet/modules/site_couchdb/manifests/create_dbs.pp @@ -0,0 +1,70 @@ +class site_couchdb::create_dbs { + + # Couchdb databases + + ### customer database + ### r/w: webapp, + couchdb::create_db { 'customers': + members => "{ \"names\": [\"$site_couchdb::couchdb_webapp_user\"], \"roles\": [] }", + require => Couchdb::Query::Setup['localhost'] + } + + ## identities database + ## r: nickserver, leap_mx - needs to be restrict with design document + ## r/w: webapp + couchdb::create_db { 'identities': + members => "{ \"names\": [], \"roles\": [\"identities\"] }", + require => Couchdb::Query::Setup['localhost'] + } + + ## keycache database + ## r/w: nickserver + couchdb::create_db { 'keycache': + members => "{ \"names\": [], \"roles\": [\"keycache\"] }", + require => Couchdb::Query::Setup['localhost'] + } + + ## sessions database + ## r/w: webapp + couchdb::create_db { 'sessions': + members => "{ \"names\": [\"$site_couchdb::couchdb_webapp_user\"], \"roles\": [] }", + require => Couchdb::Query::Setup['localhost'] + } + + ## shared database + ## r/w: soledad + couchdb::create_db { 'shared': + members => "{ \"names\": [\"$site_couchdb::couchdb_soledad_user\"], \"roles\": [] }", + require => Couchdb::Query::Setup['localhost'] + } + + ## tickets database + ## r/w: webapp + couchdb::create_db { 'tickets': + members => "{ \"names\": [\"$site_couchdb::couchdb_webapp_user\"], \"roles\": [] }", + require => Couchdb::Query::Setup['localhost'] + } + + ## tokens database + ## r: soledad - needs to be restricted with a design document + ## r/w: webapp + couchdb::create_db { 'tokens': + members => "{ \"names\": [], \"roles\": [\"tokens\"] }", + require => Couchdb::Query::Setup['localhost'] + } + + ## users database + ## r/w: webapp + couchdb::create_db { 'users': + members => "{ \"names\": [], \"roles\": [\"users\"] }", + require => Couchdb::Query::Setup['localhost'] + } + + ## messages db + ## store messages to the clients such as payment reminders + ## r/w: webapp + couchdb::create_db { 'messages': + members => "{ \"names\": [\"$site_couchdb::couchdb_webapp_user\"], \"roles\": [] }", + require => Couchdb::Query::Setup['localhost'] + } +} diff --git a/puppet/modules/site_couchdb/manifests/designs.pp b/puppet/modules/site_couchdb/manifests/designs.pp new file mode 100644 index 00000000..9e88de64 --- /dev/null +++ b/puppet/modules/site_couchdb/manifests/designs.pp @@ -0,0 +1,20 @@ +class site_couchdb::designs { + + Class['site_couchdb::create_dbs'] + -> Class['site_couchdb::designs'] + + file { '/srv/leap/couchdb/designs': + ensure => directory, + source => 'puppet:///modules/site_couchdb/designs', + recurse => true, + purge => true, + mode => '0755' + } + + exec { '/srv/leap/couchdb/scripts/load_design_documents.sh': + require => Vcsrepo['/srv/leap/couchdb/scripts'], + refreshonly => false + } + +} + diff --git a/puppet/modules/site_couchdb/manifests/init.pp b/puppet/modules/site_couchdb/manifests/init.pp index 802f3224..3614661d 100644 --- a/puppet/modules/site_couchdb/manifests/init.pp +++ b/puppet/modules/site_couchdb/manifests/init.pp @@ -1,83 +1,118 @@ class site_couchdb { tag 'leap_service' - $x509 = hiera('x509') - $key = $x509['key'] - $cert = $x509['cert'] - $ca = $x509['ca_cert'] - - $couchdb_config = hiera('couch') - $couchdb_users = $couchdb_config['users'] - $couchdb_admin = $couchdb_users['admin'] - $couchdb_admin_user = $couchdb_admin['username'] - $couchdb_admin_pw = $couchdb_admin['password'] - $couchdb_admin_salt = $couchdb_admin['salt'] - $couchdb_webapp = $couchdb_users['webapp'] - $couchdb_webapp_user = $couchdb_webapp['username'] - $couchdb_webapp_pw = $couchdb_webapp['password'] - $couchdb_webapp_salt = $couchdb_webapp['salt'] - $couchdb_soledad = $couchdb_users['soledad'] - $couchdb_soledad_user = $couchdb_soledad['username'] - $couchdb_soledad_pw = $couchdb_soledad['password'] - $couchdb_soledad_salt = $couchdb_soledad['salt'] - - $bigcouch_config = $couchdb_config['bigcouch'] - $bigcouch_cookie = $bigcouch_config['cookie'] - - $ednp_port = $bigcouch_config['ednp_port'] + $couchdb_config = hiera('couch') + $couchdb_users = $couchdb_config['users'] + + $couchdb_admin = $couchdb_users['admin'] + $couchdb_admin_user = $couchdb_admin['username'] + $couchdb_admin_pw = $couchdb_admin['password'] + $couchdb_admin_salt = $couchdb_admin['salt'] + + $couchdb_leap_mx = $couchdb_users['leap_mx'] + $couchdb_leap_mx_user = $couchdb_leap_mx['username'] + $couchdb_leap_mx_pw = $couchdb_leap_mx['password'] + $couchdb_leap_mx_salt = $couchdb_leap_mx['salt'] + + $couchdb_nickserver = $couchdb_users['nickserver'] + $couchdb_nickserver_user = $couchdb_nickserver['username'] + $couchdb_nickserver_pw = $couchdb_nickserver['password'] + $couchdb_nickserver_salt = $couchdb_nickserver['salt'] + + $couchdb_soledad = $couchdb_users['soledad'] + $couchdb_soledad_user = $couchdb_soledad['username'] + $couchdb_soledad_pw = $couchdb_soledad['password'] + $couchdb_soledad_salt = $couchdb_soledad['salt'] + + $couchdb_tapicero = $couchdb_users['tapicero'] + $couchdb_tapicero_user = $couchdb_tapicero['username'] + $couchdb_tapicero_pw = $couchdb_tapicero['password'] + $couchdb_tapicero_salt = $couchdb_tapicero['salt'] + + $couchdb_webapp = $couchdb_users['webapp'] + $couchdb_webapp_user = $couchdb_webapp['username'] + $couchdb_webapp_pw = $couchdb_webapp['password'] + $couchdb_webapp_salt = $couchdb_webapp['salt'] + + $couchdb_backup = $couchdb_config['backup'] + + $bigcouch_config = $couchdb_config['bigcouch'] + $bigcouch_cookie = $bigcouch_config['cookie'] + + $ednp_port = $bigcouch_config['ednp_port'] class { 'couchdb': - bigcouch => true, - admin_pw => $couchdb_admin_pw, - admin_salt => $couchdb_admin_salt, - bigcouch_cookie => $bigcouch_cookie, - ednp_port => $ednp_port + bigcouch => true, + admin_pw => $couchdb_admin_pw, + admin_salt => $couchdb_admin_salt, + bigcouch_cookie => $bigcouch_cookie, + ednp_port => $ednp_port, + chttpd_bind_address => '127.0.0.1' + } + + # ensure that we don't have leftovers from previous installations + # where we installed the cloudant bigcouch package + # https://leap.se/code/issues/4971 + class { 'couchdb::bigcouch::package::cloudant': + ensure => absent } - class { 'couchdb::bigcouch::package::cloudant': } + Class['site_config::default'] + -> Class['couchdb::bigcouch::package::cloudant'] + -> Service['shorewall'] + -> Class['site_couchdb::stunnel'] + -> Service['couchdb'] + -> File['/root/.netrc'] + -> Class['site_couchdb::bigcouch::add_nodes'] + -> Class['site_couchdb::bigcouch::settle_cluster'] + -> Class['site_couchdb::create_dbs'] + -> Class['site_couchdb::add_users'] - Class ['couchdb::bigcouch::package::cloudant'] - -> Service ['couchdb'] - -> Class ['site_couchdb::bigcouch::add_nodes'] - -> Couchdb::Create_db['users'] - -> Couchdb::Create_db['tokens'] - -> Couchdb::Add_user[$couchdb_webapp_user] - -> Couchdb::Add_user[$couchdb_soledad_user] + # /etc/couchdb/couchdb.netrc is deployed by couchdb::query::setup + # we symlink this to /root/.netrc for couchdb_scripts (eg. backup) + # and makes life easier for the admin (i.e. using curl/wget without + # passing credentials) + file { + '/root/.netrc': + ensure => link, + target => '/etc/couchdb/couchdb.netrc'; - class { 'site_couchdb::stunnel': - key => $key, - cert => $cert, - ca => $ca + '/srv/leap/couchdb': + ensure => directory } - class { 'site_couchdb::bigcouch::add_nodes': } - couchdb::query::setup { 'localhost': user => $couchdb_admin_user, pw => $couchdb_admin_pw, } - # Populate couchdb - couchdb::add_user { $couchdb_webapp_user: - roles => '["auth"]', - pw => $couchdb_webapp_pw, - salt => $couchdb_webapp_salt + vcsrepo { '/srv/leap/couchdb/scripts': + ensure => present, + provider => git, + source => 'https://leap.se/git/couchdb_scripts', + revision => 'origin/master', + require => File['/srv/leap/couchdb'] } - couchdb::add_user { $couchdb_soledad_user: - roles => '["auth"]', - pw => $couchdb_soledad_pw, - salt => $couchdb_soledad_salt - } - - couchdb::create_db { 'users': - readers => "{ \"names\": [\"$couchdb_webapp_user\"], \"roles\": [] }" - } + include site_couchdb::stunnel + include site_couchdb::bigcouch::add_nodes + include site_couchdb::bigcouch::settle_cluster + include site_couchdb::create_dbs + include site_couchdb::add_users + include site_couchdb::designs + include site_couchdb::logrotate + include site_couchdb::bigcouch::compaction - couchdb::create_db { 'tokens': - readers => "{ \"names\": [], \"roles\": [\"auth\"] }" - } + if $couchdb_backup { include site_couchdb::backup } include site_shorewall::couchdb include site_shorewall::couchdb::bigcouch + + include site_check_mk::agent::couchdb + include site_check_mk::agent::tapicero + + file { '/var/log/bigcouch': + ensure => directory + } + } diff --git a/puppet/modules/site_couchdb/manifests/logrotate.pp b/puppet/modules/site_couchdb/manifests/logrotate.pp new file mode 100644 index 00000000..e1039d49 --- /dev/null +++ b/puppet/modules/site_couchdb/manifests/logrotate.pp @@ -0,0 +1,12 @@ +class site_couchdb::logrotate { + + augeas { + 'logrotate_bigcouch': + context => '/files/etc/logrotate.d/bigcouch/rule', + changes => [ 'set file /opt/bigcouch/var/log/*.log', 'set rotate 7', + 'set schedule daily', 'set compress compress', + 'set missingok missingok', 'set ifempty notifempty', + 'set copytruncate copytruncate' ] + } + +} diff --git a/puppet/modules/site_couchdb/manifests/stunnel.pp b/puppet/modules/site_couchdb/manifests/stunnel.pp index d982013e..91f1e3aa 100644 --- a/puppet/modules/site_couchdb/manifests/stunnel.pp +++ b/puppet/modules/site_couchdb/manifests/stunnel.pp @@ -1,4 +1,4 @@ -class site_couchdb::stunnel ($key, $cert, $ca) { +class site_couchdb::stunnel { $stunnel = hiera('stunnel') @@ -18,22 +18,16 @@ class site_couchdb::stunnel ($key, $cert, $ca) { $ednp_server_connect = $ednp_server['connect'] $ednp_clients = $stunnel['ednp_clients'] + + + include site_config::x509::cert + include site_config::x509::key + include site_config::x509::ca + include x509::variables - $cert_name = 'leap_couchdb' - $ca_name = 'leap_ca' - $ca_path = "${x509::variables::local_CAs}/${ca_name}.crt" - $cert_path = "${x509::variables::certs}/${cert_name}.crt" - $key_path = "${x509::variables::keys}/${cert_name}.key" - - # basic setup: ensure cert, key, ca files are in place, and some generic - # stunnel things are done - class { 'site_stunnel::setup': - cert_name => $cert_name, - key => $key, - cert => $cert, - ca_name => $ca_name, - ca => $ca - } + $ca_path = "${x509::variables::local_CAs}/${site_config::params::ca_name}.crt" + $cert_path = "${x509::variables::certs}/${site_config::params::cert_name}.crt" + $key_path = "${x509::variables::keys}/${site_config::params::cert_name}.key" # setup a stunnel server for the webapp to connect to couchdb stunnel::service { 'couch_server': @@ -46,7 +40,11 @@ class site_couchdb::stunnel ($key, $cert, $ca) { verify => '2', pid => '/var/run/stunnel4/couchserver.pid', rndfile => '/var/lib/stunnel4/.rnd', - debuglevel => '4' + debuglevel => '4', + require => [ + Class['Site_config::X509::Key'], + Class['Site_config::X509::Cert'], + Class['Site_config::X509::Ca'] ]; } @@ -62,7 +60,11 @@ class site_couchdb::stunnel ($key, $cert, $ca) { verify => '2', pid => '/var/run/stunnel4/epmd_server.pid', rndfile => '/var/lib/stunnel4/.rnd', - debuglevel => '4' + debuglevel => '4', + require => [ + Class['Site_config::X509::Key'], + Class['Site_config::X509::Cert'], + Class['Site_config::X509::Ca'] ]; } # setup stunnel clients for Erlang Port Mapper Daemon (epmd) to connect @@ -88,7 +90,11 @@ class site_couchdb::stunnel ($key, $cert, $ca) { verify => '2', pid => '/var/run/stunnel4/ednp_server.pid', rndfile => '/var/lib/stunnel4/.rnd', - debuglevel => '4' + debuglevel => '4', + require => [ + Class['Site_config::X509::Key'], + Class['Site_config::X509::Cert'], + Class['Site_config::X509::Ca'] ]; } # setup stunnel clients for Erlang Distributed Node Protocol (ednp) to connect @@ -101,4 +107,6 @@ class site_couchdb::stunnel ($key, $cert, $ca) { } create_resources(site_stunnel::clients, $ednp_clients, $ednp_client_defaults) + + include site_check_mk::agent::stunnel } diff --git a/puppet/modules/site_haproxy/files/haproxy-stats.cfg b/puppet/modules/site_haproxy/files/haproxy-stats.cfg new file mode 100644 index 00000000..e6335ba2 --- /dev/null +++ b/puppet/modules/site_haproxy/files/haproxy-stats.cfg @@ -0,0 +1,6 @@ +# provide access to stats for the nagios plugin +listen stats 127.0.0.1:8000 + mode http + stats enable + stats uri /haproxy + diff --git a/puppet/modules/site_haproxy/manifests/init.pp b/puppet/modules/site_haproxy/manifests/init.pp index ace88a7b..1a681373 100644 --- a/puppet/modules/site_haproxy/manifests/init.pp +++ b/puppet/modules/site_haproxy/manifests/init.pp @@ -2,7 +2,6 @@ class site_haproxy { class { 'haproxy': enable => true, - version => '1.4.23-0.1~leap60+1', manage_service => true, global_options => { 'log' => '127.0.0.1 local0', @@ -23,4 +22,11 @@ class site_haproxy { } } + # monitor haproxy + concat::fragment { 'stats': + target => '/etc/haproxy/haproxy.cfg', + order => '90', + source => 'puppet:///modules/site_haproxy/haproxy-stats.cfg'; + } + include site_check_mk::agent::haproxy } diff --git a/puppet/modules/site_mx/manifests/couchdb.pp b/puppet/modules/site_mx/manifests/couchdb.pp new file mode 100644 index 00000000..b1f3bd02 --- /dev/null +++ b/puppet/modules/site_mx/manifests/couchdb.pp @@ -0,0 +1,23 @@ +class site_mx::couchdb { + + $stunnel = hiera('stunnel') + $couch_client = $stunnel['couch_client'] + $couch_client_connect = $couch_client['connect'] + + include x509::variables + $ca_path = "${x509::variables::local_CAs}/${site_config::params::ca_name}.crt" + $cert_path = "${x509::variables::certs}/${site_config::params::cert_name}.crt" + $key_path = "${x509::variables::keys}/${site_config::params::cert_name}.key" + + include site_stunnel + + $couchdb_stunnel_client_defaults = { + 'connect_port' => $couch_client_connect, + 'client' => true, + 'cafile' => $ca_path, + 'key' => $key_path, + 'cert' => $cert_path, + } + + create_resources(site_stunnel::clients, $couch_client, $couchdb_stunnel_client_defaults) +} diff --git a/puppet/modules/site_mx/manifests/haproxy.pp b/puppet/modules/site_mx/manifests/haproxy.pp new file mode 100644 index 00000000..988eeaf3 --- /dev/null +++ b/puppet/modules/site_mx/manifests/haproxy.pp @@ -0,0 +1,14 @@ +class site_mx::haproxy { + + include site_haproxy + + $haproxy = hiera('haproxy') + $local_ports = $haproxy['local_ports'] + + # Template uses $global_options, $defaults_options + concat::fragment { 'leap_haproxy_webapp_couchdb': + target => '/etc/haproxy/haproxy.cfg', + order => '20', + content => template('site_webapp/haproxy_couchdb.cfg.erb'), + } +} diff --git a/puppet/modules/site_mx/manifests/init.pp b/puppet/modules/site_mx/manifests/init.pp new file mode 100644 index 00000000..3949c787 --- /dev/null +++ b/puppet/modules/site_mx/manifests/init.pp @@ -0,0 +1,19 @@ +class site_mx { + tag 'leap_service' + Class['site_config::default'] -> Class['site_mx'] + + include site_config::x509::cert + include site_config::x509::key + include site_config::x509::ca + include site_config::x509::client_ca::ca + include site_config::x509::client_ca::key + + + include site_postfix::mx + include site_mx::haproxy + include site_shorewall::mx + include site_shorewall::service::smtp + include site_mx::couchdb + include leap_mx + include site_check_mk::agent::mx +} diff --git a/puppet/modules/site_nagios/files/configs/Debian/nagios.cfg b/puppet/modules/site_nagios/files/configs/Debian/nagios.cfg index 753d1610..e46ebf62 100644 --- a/puppet/modules/site_nagios/files/configs/Debian/nagios.cfg +++ b/puppet/modules/site_nagios/files/configs/Debian/nagios.cfg @@ -1,6 +1,6 @@ ############################################################################## # -# NAGIOS.CFG - Sample Main Config File for Nagios +# NAGIOS.CFG - Sample Main Config File for Nagios # # ############################################################################## @@ -8,7 +8,7 @@ # LOG FILE # This is the main log file where service and host events are logged -# for historical purposes. This should be the first option specified +# for historical purposes. This should be the first option specified # in the config file!!! log_file=/var/log/nagios3/nagios.log @@ -25,6 +25,9 @@ log_file=/var/log/nagios3/nagios.log # Puppet-managed configuration files cfg_dir=/etc/nagios3/conf.d +# check-mk managed configuration files +cfg_dir=/etc/nagios3/local + # Debian also defaults to using the check commands defined by the debian # nagios-plugins package cfg_dir=/etc/nagios-plugins/config @@ -33,7 +36,7 @@ cfg_dir=/etc/nagios-plugins/config # OBJECT CACHE FILE # This option determines where object definitions are cached when -# Nagios starts/restarts. The CGIs read object definitions from +# Nagios starts/restarts. The CGIs read object definitions from # this cache file (rather than looking at the object config files # directly) in order to prevent inconsistencies that can occur # when the config files are modified after Nagios starts. @@ -49,7 +52,7 @@ object_cache_file=/var/cache/nagios3/objects.cache # file. You can then start Nagios with the -u option to have it read # object definitions from this precached file, rather than the standard # object configuration files (see the cfg_file and cfg_dir options above). -# Using a precached object file can speed up the time needed to (re)start +# Using a precached object file can speed up the time needed to (re)start # the Nagios process if you've got a large and/or complex configuration. # Read the documentation section on optimizing Nagios to find our more # about how this feature works. @@ -83,7 +86,7 @@ status_file=/var/cache/nagios3/status.dat # STATUS FILE UPDATE INTERVAL # This option determines the frequency (in seconds) that -# Nagios will periodically dump program, host, and +# Nagios will periodically dump program, host, and # service status data. status_update_interval=10 @@ -91,7 +94,7 @@ status_update_interval=10 # NAGIOS USER -# This determines the effective user that Nagios should run as. +# This determines the effective user that Nagios should run as. # You can either supply a username or a UID. nagios_user=nagios @@ -99,7 +102,7 @@ nagios_user=nagios # NAGIOS GROUP -# This determines the effective group that Nagios should run as. +# This determines the effective group that Nagios should run as. # You can either supply a group name or a GID. nagios_group=nagios @@ -125,7 +128,7 @@ check_external_commands=1 # Nagios to check for external commands every minute. If you specify a # number followed by an "s" (i.e. 15s), this will be interpreted to mean # actual seconds rather than a multiple of the interval_length variable. -# Note: In addition to reading the external command file at regularly +# Note: In addition to reading the external command file at regularly # scheduled intervals, Nagios will also check for external commands after # event handlers are executed. # NOTE: Setting this value to -1 causes Nagios to check the external @@ -140,7 +143,7 @@ command_check_interval=-1 # This is the file that Nagios checks for external command requests. # It is also where the command CGI will write commands that are submitted # by users, so it must be writeable by the user that the web server -# is running as (usually 'nobody'). Permissions should be set at the +# is running as (usually 'nobody'). Permissions should be set at the # directory level instead of on the file, as the file is deleted every # time its contents are processed. # Debian Users: In case you didn't read README.Debian yet, _NOW_ is the @@ -152,9 +155,9 @@ command_file=/var/lib/nagios3/rw/nagios.cmd # EXTERNAL COMMAND BUFFER SLOTS # This settings is used to tweak the number of items or "slots" that -# the Nagios daemon should allocate to the buffer that holds incoming -# external commands before they are processed. As external commands -# are processed by the daemon, they are removed from the buffer. +# the Nagios daemon should allocate to the buffer that holds incoming +# external commands before they are processed. As external commands +# are processed by the daemon, they are removed from the buffer. external_command_buffer_slots=4096 @@ -232,12 +235,12 @@ event_broker_options=-1 # w = Weekly rotation (midnight on Saturday evening) # m = Monthly rotation (midnight last day of month) -log_rotation_method=d +log_rotation_method=n # LOG ARCHIVE PATH -# This is the directory where archived (rotated) log files should be +# This is the directory where archived (rotated) log files should be # placed (assuming you've chosen to do log rotation). log_archive_path=/var/log/nagios3/archives @@ -248,7 +251,7 @@ log_archive_path=/var/log/nagios3/archives # If you want messages logged to the syslog facility, as well as the # Nagios log file set this option to 1. If not, set it to 0. -use_syslog=1 +use_syslog=0 @@ -400,7 +403,7 @@ max_host_check_spread=30 # MAXIMUM CONCURRENT SERVICE CHECKS -# This option allows you to specify the maximum number of +# This option allows you to specify the maximum number of # service checks that can be run in parallel at any given time. # Specifying a value of 1 for this variable essentially prevents # any service checks from being parallelized. A value of 0 @@ -422,7 +425,7 @@ check_result_reaper_frequency=10 # MAX CHECK RESULT REAPER TIME # This is the max amount of time (in seconds) that a single -# check result reaper event will be allowed to run before +# check result reaper event will be allowed to run before # returning control back to Nagios so it can perform other # duties. @@ -436,7 +439,7 @@ max_check_result_reaper_time=30 # service checks that have not yet been processed. # # Note: Make sure that only one instance of Nagios has access -# to this directory! +# to this directory! check_result_path=/var/lib/nagios3/spool/checkresults @@ -445,7 +448,7 @@ check_result_path=/var/lib/nagios3/spool/checkresults # MAX CHECK RESULT FILE AGE # This option determines the maximum age (in seconds) which check -# result files are considered to be valid. Files older than this +# result files are considered to be valid. Files older than this # threshold will be mercilessly deleted without further processing. max_check_result_file_age=3600 @@ -507,14 +510,14 @@ enable_predictive_service_dependency_checks=1 # SOFT STATE DEPENDENCIES -# This option determines whether or not Nagios will use soft state -# information when checking host and service dependencies. Normally -# Nagios will only use the latest hard host or service state when +# This option determines whether or not Nagios will use soft state +# information when checking host and service dependencies. Normally +# Nagios will only use the latest hard host or service state when # checking dependencies. If you want it to use the latest state (regardless -# of whether its a soft or hard state type), enable this option. +# of whether its a soft or hard state type), enable this option. # Values: -# 0 = Don't use soft state dependencies (default) -# 1 = Use soft state dependencies +# 0 = Don't use soft state dependencies (default) +# 1 = Use soft state dependencies soft_state_dependencies=0 @@ -532,7 +535,7 @@ soft_state_dependencies=0 # This option determines whether or not Nagios will attempt to # automatically reschedule active host and service checks to # "smooth" them out over time. This can help balance the load on -# the monitoring server. +# the monitoring server. # WARNING: THIS IS AN EXPERIMENTAL FEATURE - IT CAN DEGRADE # PERFORMANCE, RATHER THAN INCREASE IT, IF USED IMPROPERLY @@ -595,7 +598,7 @@ perfdata_timeout=5 # This setting determines whether or not Nagios will save state # information for services and hosts before it shuts down. Upon # startup Nagios will reload all saved service and host state -# information before starting to monitor. This is useful for +# information before starting to monitor. This is useful for # maintaining long-term data on state statistics, etc, but will # slow Nagios down a bit when it (re)starts. Since its only # a one-time penalty, I think its well worth the additional @@ -607,7 +610,7 @@ retain_state_information=1 # STATE RETENTION FILE # This is the file that Nagios should use to store host and -# service state information before it shuts down. The state +# service state information before it shuts down. The state # information in this file is also read immediately prior to # starting to monitor the network when Nagios is restarted. # This file is used only if the preserve_state_information @@ -630,7 +633,7 @@ retention_update_interval=60 # USE RETAINED PROGRAM STATE -# This setting determines whether or not Nagios will set +# This setting determines whether or not Nagios will set # program status variables based on the values saved in the # retention file. If you want to use retained program status # information, set this value to 1. If not, set this value @@ -657,7 +660,7 @@ use_retained_scheduling_info=1 # program restarts. # # The values of the masks are bitwise ANDs of values specified -# by the "MODATTR_" definitions found in include/common.h. +# by the "MODATTR_" definitions found in include/common.h. # For example, if you do not want the current enabled/disabled state # of flap detection and event handlers for hosts to be retained, you # would use a value of 24 for the host attribute mask... @@ -708,7 +711,7 @@ use_aggressive_host_checking=0 # SERVICE CHECK EXECUTION OPTION # This determines whether or not Nagios will actively execute -# service checks when it initially starts. If this option is +# service checks when it initially starts. If this option is # disabled, checks are not actively made, but Nagios can still # receive and process passive check results that come in. Unless # you're implementing redundant hosts or have a special need for @@ -730,7 +733,7 @@ accept_passive_service_checks=1 # HOST CHECK EXECUTION OPTION # This determines whether or not Nagios will actively execute -# host checks when it initially starts. If this option is +# host checks when it initially starts. If this option is # disabled, checks are not actively made, but Nagios can still # receive and process passive check results that come in. Unless # you're implementing redundant hosts or have a special need for @@ -787,7 +790,7 @@ process_performance_data=0 # These commands are run after every host and service check is # performed. These commands are executed only if the # enable_performance_data option (above) is set to 1. The command -# argument is the short name of a command definition that you +# argument is the short name of a command definition that you # define in your host configuration file. Read the HTML docs for # more information on performance data. @@ -867,7 +870,7 @@ obsess_over_services=0 # OBSESSIVE COMPULSIVE SERVICE PROCESSOR COMMAND # This is the command that is run for every service check that is # processed by Nagios. This command is executed only if the -# obsess_over_services option (above) is set to 1. The command +# obsess_over_services option (above) is set to 1. The command # argument is the short name of a command definition that you # define in your host configuration file. Read the HTML docs for # more information on implementing distributed monitoring. @@ -891,7 +894,7 @@ obsess_over_hosts=0 # OBSESSIVE COMPULSIVE HOST PROCESSOR COMMAND # This is the command that is run for every host check that is # processed by Nagios. This command is executed only if the -# obsess_over_hosts option (above) is set to 1. The command +# obsess_over_hosts option (above) is set to 1. The command # argument is the short name of a command definition that you # define in your host configuration file. Read the HTML docs for # more information on implementing distributed monitoring. @@ -930,9 +933,9 @@ passive_host_checks_are_soft=0 # ORPHANED HOST/SERVICE CHECK OPTIONS -# These options determine whether or not Nagios will periodically +# These options determine whether or not Nagios will periodically # check for orphaned host service checks. Since service checks are -# not rescheduled until the results of their previous execution +# not rescheduled until the results of their previous execution # instance are processed, there exists a possibility that some # checks may never get rescheduled. A similar situation exists for # host checks, although the exact scheduling details differ a bit @@ -1000,9 +1003,9 @@ additional_freshness_latency=15 # FLAP DETECTION OPTION # This option determines whether or not Nagios will try -# and detect hosts and services that are "flapping". +# and detect hosts and services that are "flapping". # Flapping occurs when a host or service changes between -# states too frequently. When Nagios detects that a +# states too frequently. When Nagios detects that a # host or service is flapping, it will temporarily suppress # notifications for that host/service until it stops # flapping. Flap detection is very experimental, so read @@ -1046,7 +1049,7 @@ date_format=iso8601 # the system configured timezone. # # NOTE: In order to display the correct timezone in the CGIs, you -# will also need to alter the Apache directives for the CGI path +# will also need to alter the Apache directives for the CGI path # to include your timezone. Example: # # <Directory "/usr/local/nagios/sbin/"> @@ -1083,7 +1086,7 @@ enable_embedded_perl=1 # This option determines whether or not Nagios will process Perl plugins # and scripts with the embedded Perl interpreter if the plugins/scripts # do not explicitly indicate whether or not it is okay to do so. Read -# the HTML documentation on the embedded Perl interpreter for more +# the HTML documentation on the embedded Perl interpreter for more # information on how this option works. use_embedded_perl_implicitly=1 @@ -1130,7 +1133,7 @@ use_regexp_matching=0 # "TRUE" REGULAR EXPRESSION MATCHING -# This option controls whether or not "true" regular expression +# This option controls whether or not "true" regular expression # matching takes place in the object config files. This option # only has an effect if regular expression matching is enabled # (see above). If this option is DISABLED, regular expression @@ -1183,7 +1186,7 @@ use_large_installation_tweaks=0 # This option determines whether or not Nagios will make all standard # macros available as environment variables when host/service checks # and system commands (event handlers, notifications, etc.) are -# executed. Enabling this option can cause performance issues in +# executed. Enabling this option can cause performance issues in # large installations, as it will consume a bit more memory and (more # importantly) consume more CPU. # Values: 1 - Enable environment variable macros (default) @@ -1224,7 +1227,7 @@ enable_environment_macros=1 # This option determines how much (if any) debugging information will # be written to the debug file. OR values together to log multiple # types of information. -# Values: +# Values: # -1 = Everything # 0 = Nothing # 1 = Functions diff --git a/puppet/modules/site_nagios/manifests/add_host.pp b/puppet/modules/site_nagios/manifests/add_host.pp deleted file mode 100644 index 498552b5..00000000 --- a/puppet/modules/site_nagios/manifests/add_host.pp +++ /dev/null @@ -1,31 +0,0 @@ -define site_nagios::add_host { - $nagios_host = $name - $nagios_hostname = $name['domain_internal'] - $nagios_ip = $name['ip_address'] - $nagios_services = $name['services'] - $nagios_openvpn_gw = $name['openvpn_gateway_address'] - - # Add Nagios host - nagios_host { $nagios_hostname: - address => $nagios_ip, - use => 'generic-host', - } - - # Add Nagios service - - # First, we need to turn the serice array into hash, using a "hash template" - # see https://github.com/ashak/puppet-resource-looping - $nagios_service_hashpart = { - 'hostname' => $nagios_hostname, - 'ip_address' => $nagios_ip, - 'openvpn_gw' => $nagios_openvpn_gw, - } - $dynamic_parameters = { - 'service' => '%s' - } - $nagios_servicename = "${nagios_hostname}_%s" - - $nagios_service_hash = create_resources_hash_from($nagios_servicename, $nagios_services, $nagios_service_hashpart, $dynamic_parameters) - - create_resources ( site_nagios::add_service, $nagios_service_hash ) -} diff --git a/puppet/modules/site_nagios/manifests/add_host_services.pp b/puppet/modules/site_nagios/manifests/add_host_services.pp new file mode 100644 index 00000000..279809d1 --- /dev/null +++ b/puppet/modules/site_nagios/manifests/add_host_services.pp @@ -0,0 +1,28 @@ +define site_nagios::add_host_services ( + $domain_full_suffix, + $domain_internal, + $ip_address, + $services, + $ssh_port, + $openvpn_gateway_address='' ) { + + $nagios_hostname = $domain_internal + + # Add Nagios service + + # First, we need to turn the serice array into hash, using a "hash template" + # see https://github.com/ashak/puppet-resource-looping + $nagios_service_hashpart = { + 'hostname' => $nagios_hostname, + 'ip_address' => $ip_address, + 'openvpn_gw' => $openvpn_gateway_address, + } + $dynamic_parameters = { + 'service' => '%s' + } + $nagios_servicename = "${nagios_hostname}_%s" + + $nagios_service_hash = create_resources_hash_from($nagios_servicename, $services, $nagios_service_hashpart, $dynamic_parameters) + + create_resources ( site_nagios::add_service, $nagios_service_hash ) +} diff --git a/puppet/modules/site_nagios/manifests/add_service.pp b/puppet/modules/site_nagios/manifests/add_service.pp index 6ef3cbf5..8d2a310b 100644 --- a/puppet/modules/site_nagios/manifests/add_service.pp +++ b/puppet/modules/site_nagios/manifests/add_service.pp @@ -3,19 +3,19 @@ define site_nagios::add_service ( case $service { 'webapp': { - $check_command = 'check_https_cert' - $service_description = 'Website Certificate' + nagios_service { + "${name}_cert": + use => 'generic-service', + check_command => 'check_https_cert', + service_description => 'Website Certificate', + host_name => $hostname; + "${name}_website": + use => 'generic-service', + check_command => 'check_https', + service_description => 'Website', + host_name => $hostname + } } - default: { - #notice ("No Nagios service check for service \"$service\"") - } - } - - if ( $check_command != '' ) { - nagios_service { $name: - use => 'generic-service', - check_command => $check_command, - service_description => $service_description, - host_name => $hostname } + default: {} } } diff --git a/puppet/modules/site_nagios/manifests/init.pp b/puppet/modules/site_nagios/manifests/init.pp index cab32905..eb08cdcb 100644 --- a/puppet/modules/site_nagios/manifests/init.pp +++ b/puppet/modules/site_nagios/manifests/init.pp @@ -1,4 +1,6 @@ class site_nagios { tag 'leap_service' + Class['site_config::default'] -> Class['site_nagios'] + include site_nagios::server } diff --git a/puppet/modules/site_nagios/manifests/server.pp b/puppet/modules/site_nagios/manifests/server.pp index c114a39a..85443917 100644 --- a/puppet/modules/site_nagios/manifests/server.pp +++ b/puppet/modules/site_nagios/manifests/server.pp @@ -1,26 +1,34 @@ class site_nagios::server inherits nagios::base { # First, purge old nagios config (see #1467) - class { 'site_nagios::server::purge': - stage => setup - } + class { 'site_nagios::server::purge': } - $nagios_hiera=hiera('nagios') + $nagios_hiera = hiera('nagios') $nagiosadmin_pw = htpasswd_sha1($nagios_hiera['nagiosadmin_pw']) - $hosts = $nagios_hiera['hosts'] + $nagios_hosts = $nagios_hiera['hosts'] include nagios::defaults include nagios::base - #Class ['nagios'] -> Class ['nagios::defaults'] - class {'nagios::apache': + class {'nagios': + # don't manage apache class from nagios, cause we already include + # it in site_apache::common + httpd => 'absent', allow_external_cmd => true, stored_config => false, - #before => Class ['nagios::defaults'] } + file { '/etc/apache2/conf.d/nagios3.conf': + ensure => link, + target => '/usr/share/doc/nagios3-common/examples/apache2.conf', + notify => Service['apache'] + } + + include site_apache::common + include site_apache::module::headers + File ['nagios_htpasswd'] { source => undef, - content => "nagiosadmin:$nagiosadmin_pw", + content => "nagiosadmin:${nagiosadmin_pw}", mode => '0640', } @@ -33,6 +41,18 @@ class site_nagios::server inherits nagios::base { group => 'nagios', } - site_nagios::add_host {$hosts:} + create_resources ( site_nagios::add_host_services, $nagios_hosts ) + + include site_nagios::server::apache + include site_check_mk::server include site_shorewall::monitor + + augeas { + 'logrotate_nagios': + context => '/files/etc/logrotate.d/nagios/rule', + changes => [ 'set file /var/log/nagios3/nagios.log', 'set rotate 7', + 'set schedule daily', 'set compress compress', + 'set missingok missingok', 'set ifempty notifempty', + 'set copytruncate copytruncate' ] + } } diff --git a/puppet/modules/site_nagios/manifests/server/apache.pp b/puppet/modules/site_nagios/manifests/server/apache.pp new file mode 100644 index 00000000..8dbc7e9b --- /dev/null +++ b/puppet/modules/site_nagios/manifests/server/apache.pp @@ -0,0 +1,7 @@ +class site_nagios::server::apache { + include x509::variables + include site_config::x509::commercial::cert + include site_config::x509::commercial::key + include site_config::x509::commercial::ca + +} diff --git a/puppet/modules/site_nagios/manifests/server/purge.pp b/puppet/modules/site_nagios/manifests/server/purge.pp index 39735cd3..6815a703 100644 --- a/puppet/modules/site_nagios/manifests/server/purge.pp +++ b/puppet/modules/site_nagios/manifests/server/purge.pp @@ -1,7 +1,19 @@ -class site_nagios::server::purge { - exec {'purge_conf.d': - command => '/bin/rm -rf /etc/nagios3/conf.d/*', - onlyif => 'test -e /etc/nagios3/conf.d' +class site_nagios::server::purge inherits nagios::base { + # we don't want to get /etc/nagios3 and /etc/nagios3/conf.d + # purged, cause the check-mk-config-nagios3 package + # places its templates in /etc/nagios3/conf.d/check_mk, + # and check_mk -O updated it's nagios config in /etc/nagios3/conf.d/check_mk + File['nagios_cfgdir'] { + purge => false + } + File['nagios_confd'] { + purge => false } + # only purge files in the /etc/nagios3/conf.d/ dir, not in any subdir + exec {'purge_conf.d': + command => '/usr/bin/find /etc/nagios3/conf.d/ -maxdepth 1 -type f -exec rm {} \;', + onlyif => '/usr/bin/find /etc/nagios3/conf.d/ -maxdepth 1 -type f | grep -q "/etc/nagios3/conf.d"', + require => Package['nagios'] + } } diff --git a/puppet/modules/site_nickserver/manifests/init.pp b/puppet/modules/site_nickserver/manifests/init.pp index 7dfa2603..eaf90d55 100644 --- a/puppet/modules/site_nickserver/manifests/init.pp +++ b/puppet/modules/site_nickserver/manifests/init.pp @@ -1,37 +1,47 @@ # -# TODO: currently, this is dependent on some things that are set up in site_webapp +# TODO: currently, this is dependent on some things that are set up in +# site_webapp # # (1) HAProxy -> couchdb # (2) Apache # -# It would be good in the future to make nickserver installable independently of site_webapp. +# It would be good in the future to make nickserver installable independently of +# site_webapp. # class site_nickserver { tag 'leap_service' - include site_config::ruby + Class['site_config::default'] -> Class['site_nickserver'] + + include site_config::ruby::dev # # VARIABLES # $nickserver = hiera('nickserver') - $nickserver_port = $nickserver['port'] # the port that public connects to (should be 6425) - $nickserver_local_port = '64250' # the port that nickserver is actually running on $nickserver_domain = $nickserver['domain'] + $couchdb_user = $nickserver['couchdb_nickserver_user']['username'] + $couchdb_password = $nickserver['couchdb_nickserver_user']['password'] + + # the port that public connects to (should be 6425) + $nickserver_port = $nickserver['port'] + # the port that nickserver is actually running on + $nickserver_local_port = '64250' - $couchdb_user = $nickserver['couchdb_user']['username'] - $couchdb_password = $nickserver['couchdb_user']['password'] - $couchdb_host = 'localhost' # couchdb is available on localhost via haproxy, which is bound to 4096. - $couchdb_port = '4096' # See site_webapp/templates/haproxy_couchdb.cfg.erg + # couchdb is available on localhost via haproxy, which is bound to 4096. + $couchdb_host = 'localhost' + # See site_webapp/templates/haproxy_couchdb.cfg.erg + $couchdb_port = '4096' # temporarily for now: $domain = hiera('domain') $address_domain = $domain['full_suffix'] - $x509 = hiera('x509') - $x509_key = $x509['key'] - $x509_cert = $x509['cert'] - $x509_ca = $x509['ca_cert'] + + + include site_config::x509::cert + include site_config::x509::key + include site_config::x509::ca # # USER AND GROUP @@ -41,6 +51,7 @@ class site_nickserver { ensure => present, allowdupe => false; } + user { 'nickserver': ensure => present, allowdupe => false, @@ -50,31 +61,33 @@ class site_nickserver { } # - # NICKSERVER CODE - # NOTE: in order to support TLS, libssl-dev must be installed before EventMachine gem - # is built/installed. + # NICKSERVER CODE NOTE: in order to support TLS, libssl-dev must be installed + # before EventMachine gem is built/installed. # - package { - 'libssl-dev': ensure => installed; - } + package { 'libssl-dev': ensure => installed } + vcsrepo { '/srv/leap/nickserver': ensure => present, revision => 'origin/master', provider => git, - source => 'git://code.leap.se/nickserver', + source => 'https://leap.se/git/nickserver', owner => 'nickserver', group => 'nickserver', require => [ User['nickserver'], Group['nickserver'] ], notify => Exec['nickserver_bundler_update']; } + exec { 'nickserver_bundler_update': cwd => '/srv/leap/nickserver', command => '/bin/bash -c "/usr/bin/bundle check || /usr/bin/bundle install --path vendor/bundle"', unless => '/usr/bin/bundle check', user => 'nickserver', timeout => 600, - require => [ Class['bundler::install'], Vcsrepo['/srv/leap/nickserver'], Package['libssl-dev'] ], + require => [ + Class['bundler::install'], Vcsrepo['/srv/leap/nickserver'], + Package['libssl-dev'], Class['site_config::ruby::dev'] ], + notify => Service['nickserver']; } @@ -82,7 +95,7 @@ class site_nickserver { # NICKSERVER CONFIG # - file { '/etc/leap/nickserver.yml': + file { '/etc/nickserver.yml': content => template('site_nickserver/nickserver.yml.erb'), owner => nickserver, group => nickserver, @@ -99,8 +112,11 @@ class site_nickserver { ensure => link, target => '/srv/leap/nickserver/bin/nickserver', require => Vcsrepo['/srv/leap/nickserver']; + '/etc/init.d/nickserver': - owner => root, group => 0, mode => '0755', + owner => root, + group => 0, + mode => '0755', source => '/srv/leap/nickserver/dist/debian-init-script', require => Vcsrepo['/srv/leap/nickserver']; } @@ -110,7 +126,11 @@ class site_nickserver { enable => true, hasrestart => true, hasstatus => true, - require => File['/etc/init.d/nickserver']; + require => [ + File['/etc/init.d/nickserver'], + Class['Site_config::X509::Key'], + Class['Site_config::X509::Cert'], + Class['Site_config::X509::Ca'] ]; } # @@ -119,7 +139,7 @@ class site_nickserver { # file { '/etc/shorewall/macro.nickserver': - content => "PARAM - - tcp $nickserver_port", + content => "PARAM - - tcp ${nickserver_port}", notify => Service['shorewall'], require => Package['shorewall']; } @@ -142,21 +162,8 @@ class site_nickserver { } apache::vhost::file { - 'nickserver': content => template('site_nickserver/nickserver-proxy.conf.erb') - } - - x509::key { 'nickserver': - content => $x509_key, - notify => Service[apache]; + 'nickserver': + content => template('site_nickserver/nickserver-proxy.conf.erb') } - x509::cert { 'nickserver': - content => $x509_cert, - notify => Service[apache]; - } - - x509::ca { 'nickserver': - content => $x509_ca, - notify => Service[apache]; - } -}
\ No newline at end of file +} diff --git a/puppet/modules/site_nickserver/templates/nickserver-proxy.conf.erb b/puppet/modules/site_nickserver/templates/nickserver-proxy.conf.erb index 67896cd3..ae06410e 100644 --- a/puppet/modules/site_nickserver/templates/nickserver-proxy.conf.erb +++ b/puppet/modules/site_nickserver/templates/nickserver-proxy.conf.erb @@ -14,9 +14,9 @@ Listen 0.0.0.0:<%= @nickserver_port -%> SSLHonorCipherOrder on SSLCACertificatePath /etc/ssl/certs - SSLCertificateChainFile /etc/ssl/certs/nickserver.pem - SSLCertificateKeyFile /etc/x509/keys/nickserver.key - SSLCertificateFile /etc/x509/certs/nickserver.crt + SSLCertificateChainFile <%= scope.lookupvar('x509::variables::local_CAs') %>/<%= scope.lookupvar('site_config::params::ca_name') %>.crt + SSLCertificateKeyFile <%= scope.lookupvar('x509::variables::keys') %>/<%= scope.lookupvar('site_config::params::cert_name') %>.key + SSLCertificateFile <%= scope.lookupvar('x509::variables::certs') %>/<%= scope.lookupvar('site_config::params::cert_name') %>.crt ProxyPass / http://localhost:<%= @nickserver_local_port %>/ ProxyPreserveHost On # preserve Host header in HTTP request diff --git a/puppet/modules/site_nickserver/templates/nickserver.yml.erb b/puppet/modules/site_nickserver/templates/nickserver.yml.erb index 7aab5605..e717cbaa 100644 --- a/puppet/modules/site_nickserver/templates/nickserver.yml.erb +++ b/puppet/modules/site_nickserver/templates/nickserver.yml.erb @@ -6,7 +6,7 @@ domain: "<%= @address_domain %>" couch_host: "<%= @couchdb_host %>" couch_port: <%= @couchdb_port %> -couch_database: "users" +couch_database: "identities" couch_user: "<%= @couchdb_user %>" couch_password: "<%= @couchdb_password %>" diff --git a/puppet/modules/site_openvpn/manifests/dh_key.pp b/puppet/modules/site_openvpn/manifests/dh_key.pp new file mode 100644 index 00000000..13cc0f5b --- /dev/null +++ b/puppet/modules/site_openvpn/manifests/dh_key.pp @@ -0,0 +1,10 @@ +class site_openvpn::dh_key { + + $x509_config = hiera('x509') + + file { '/etc/openvpn/keys/dh.pem': + content => $x509_config['dh'], + mode => '0644', + } + +} diff --git a/puppet/modules/site_openvpn/manifests/init.pp b/puppet/modules/site_openvpn/manifests/init.pp index 4f900623..7aec0faa 100644 --- a/puppet/modules/site_openvpn/manifests/init.pp +++ b/puppet/modules/site_openvpn/manifests/init.pp @@ -5,8 +5,9 @@ # (2) unlimited only # (3) limited only # -# The difference is that 'unlimited' gateways only allow client certs that match the 'unlimited_prefix', -# and 'limited' gateways only allow certs that match the 'limited_prefix'. +# The difference is that 'unlimited' gateways only allow client certs that match +# the 'unlimited_prefix', and 'limited' gateways only allow certs that match the +# 'limited_prefix'. # # We potentially create four openvpn config files (thus four daemons): # @@ -19,23 +20,30 @@ class site_openvpn { tag 'leap_service' - $openvpn_config = hiera('openvpn') - $x509_config = hiera('x509') - $openvpn_ports = $openvpn_config['ports'] + include site_config::x509::cert + include site_config::x509::key + include site_config::x509::ca_bundle + + + Class['site_config::default'] -> Class['site_openvpn'] + + $openvpn = hiera('openvpn') + $openvpn_ports = $openvpn['ports'] + $openvpn_config = $openvpn['configuration'] if $::ec2_instance_id { $openvpn_gateway_address = $::ipaddress } else { - $openvpn_gateway_address = $openvpn_config['gateway_address'] - if $openvpn_config['second_gateway_address'] { - $openvpn_second_gateway_address = $openvpn_config['second_gateway_address'] + $openvpn_gateway_address = $openvpn['gateway_address'] + if $openvpn['second_gateway_address'] { + $openvpn_second_gateway_address = $openvpn['second_gateway_address'] } else { $openvpn_second_gateway_address = undef } } - $openvpn_allow_unlimited = $openvpn_config['allow_unlimited'] - $openvpn_unlimited_prefix = $openvpn_config['unlimited_prefix'] + $openvpn_allow_unlimited = $openvpn['allow_unlimited'] + $openvpn_unlimited_prefix = $openvpn['unlimited_prefix'] $openvpn_unlimited_tcp_network_prefix = '10.41.0' $openvpn_unlimited_tcp_netmask = '255.255.248.0' $openvpn_unlimited_tcp_cidr = '21' @@ -44,9 +52,9 @@ class site_openvpn { $openvpn_unlimited_udp_cidr = '21' if !$::ec2_instance_id { - $openvpn_allow_limited = $openvpn_config['allow_limited'] - $openvpn_limited_prefix = $openvpn_config['limited_prefix'] - $openvpn_rate_limit = $openvpn_config['rate_limit'] + $openvpn_allow_limited = $openvpn['allow_limited'] + $openvpn_limited_prefix = $openvpn['limited_prefix'] + $openvpn_rate_limit = $openvpn['rate_limit'] $openvpn_limited_tcp_network_prefix = '10.43.0' $openvpn_limited_tcp_netmask = '255.255.248.0' $openvpn_limited_tcp_cidr = '21' @@ -55,8 +63,14 @@ class site_openvpn { $openvpn_limited_udp_cidr = '21' } - # deploy ca + server keys - include site_openvpn::keys + # find out the netmask in cidr format of the primary IF + # thx to https://blog.kumina.nl/tag/puppet-tips-and-tricks/ + # we can do this using an inline_template: + $factname_primary_netmask = "netmask_cidr_${::site_config::params::interface}" + $primary_netmask = inline_template('<%= scope.lookupvar(factname_primary_netmask) %>') + + # deploy dh keys + include site_openvpn::dh_key if $openvpn_allow_unlimited and $openvpn_allow_limited { $unlimited_gateway_address = $openvpn_gateway_address @@ -77,7 +91,8 @@ class site_openvpn { tls_remote => "\"${openvpn_unlimited_prefix}\"", server => "${openvpn_unlimited_tcp_network_prefix}.0 ${openvpn_unlimited_tcp_netmask}", push => "\"dhcp-option DNS ${openvpn_unlimited_tcp_network_prefix}.1\"", - management => '127.0.0.1 1000' + management => '127.0.0.1 1000', + config => $openvpn_config } site_openvpn::server_config { 'udp_config': port => '1194', @@ -86,11 +101,12 @@ class site_openvpn { tls_remote => "\"${openvpn_unlimited_prefix}\"", server => "${openvpn_unlimited_udp_network_prefix}.0 ${openvpn_unlimited_udp_netmask}", push => "\"dhcp-option DNS ${openvpn_unlimited_udp_network_prefix}.1\"", - management => '127.0.0.1 1001' + management => '127.0.0.1 1001', + config => $openvpn_config } } else { - tidy { "/etc/openvpn/tcp_config.conf": } - tidy { "/etc/openvpn/udp_config.conf": } + tidy { '/etc/openvpn/tcp_config.conf': } + tidy { '/etc/openvpn/udp_config.conf': } } if $openvpn_allow_limited { @@ -101,7 +117,8 @@ class site_openvpn { tls_remote => "\"${openvpn_limited_prefix}\"", server => "${openvpn_limited_tcp_network_prefix}.0 ${openvpn_limited_tcp_netmask}", push => "\"dhcp-option DNS ${openvpn_limited_tcp_network_prefix}.1\"", - management => '127.0.0.1 1002' + management => '127.0.0.1 1002', + config => $openvpn_config } site_openvpn::server_config { 'limited_udp_config': port => '1194', @@ -110,11 +127,12 @@ class site_openvpn { tls_remote => "\"${openvpn_limited_prefix}\"", server => "${openvpn_limited_udp_network_prefix}.0 ${openvpn_limited_udp_netmask}", push => "\"dhcp-option DNS ${openvpn_limited_udp_network_prefix}.1\"", - management => '127.0.0.1 1003' + management => '127.0.0.1 1003', + config => $openvpn_config } } else { - tidy { "/etc/openvpn/limited_tcp_config.conf": } - tidy { "/etc/openvpn/limited_udp_config.conf": } + tidy { '/etc/openvpn/limited_tcp_config.conf': } + tidy { '/etc/openvpn/limited_udp_config.conf': } } file { @@ -131,7 +149,12 @@ class site_openvpn { command => '/etc/init.d/openvpn restart', refreshonly => true, subscribe => File['/etc/openvpn'], - require => [ Package['openvpn'], File['/etc/openvpn'] ]; + require => [ + Package['openvpn'], + File['/etc/openvpn'], + Class['Site_config::X509::Key'], + Class['Site_config::X509::Cert'], + Class['Site_config::X509::Ca_bundle'] ]; } cron { 'add_gateway_ips.sh': @@ -155,7 +178,9 @@ class site_openvpn { ensure => running, hasrestart => true, hasstatus => true, - require => Exec['concat_/etc/default/openvpn']; + require => [ + Package['openvpn'], + Exec['concat_/etc/default/openvpn'] ]; } file { @@ -193,4 +218,7 @@ class site_openvpn { target => '/etc/default/openvpn', order => 10; } + + include site_check_mk::agent::openvpn + } diff --git a/puppet/modules/site_openvpn/manifests/keys.pp b/puppet/modules/site_openvpn/manifests/keys.pp deleted file mode 100644 index f3c5b423..00000000 --- a/puppet/modules/site_openvpn/manifests/keys.pp +++ /dev/null @@ -1,51 +0,0 @@ -class site_openvpn::keys { - - x509::key { - 'leap_openvpn': - content => $site_openvpn::x509_config['key'], - notify => Service[openvpn]; - } - - x509::cert { - 'leap_openvpn': - content => $site_openvpn::x509_config['cert'], - notify => Service[openvpn]; - } - - x509::ca { - 'leap_ca': - content => $site_openvpn::x509_config['ca_cert'], - notify => Service[openvpn]; - } - - file { '/etc/openvpn/keys/dh.pem': - content => $site_openvpn::x509_config['dh'], - mode => '0644', - } - - # - # CA bundle -- we want to have the possibility of allowing multiple CAs. - # For now, the reason is to transition to using client CA. In the future, - # we will want to be able to smoothly phase out one CA and phase in another. - # I tried "--capath" for this, but it did not work. - # - - concat { - '/etc/openvpn/ca_bundle.pem': - owner => root, - group => root, - mode => 644, - warn => true, - notify => Service['openvpn']; - } - - concat::fragment { - 'client_ca_cert': - content => $site_openvpn::x509_config['client_ca_cert'], - target => '/etc/openvpn/ca_bundle.pem'; - 'ca_cert': - content => $site_openvpn::x509_config['ca_cert'], - target => '/etc/openvpn/ca_bundle.pem'; - } - -} diff --git a/puppet/modules/site_openvpn/manifests/resolver.pp b/puppet/modules/site_openvpn/manifests/resolver.pp index c1bce858..c74fb509 100644 --- a/puppet/modules/site_openvpn/manifests/resolver.pp +++ b/puppet/modules/site_openvpn/manifests/resolver.pp @@ -60,25 +60,25 @@ class site_openvpn::resolver { path => '/etc/unbound/unbound.conf', line => 'server: include: /etc/unbound/conf.d/vpn_unlimited_tcp_resolver', notify => Service['unbound'], - require => Package['unbound']; + require => [ Package['openvpn'], Package['unbound'] ]; 'add_unlimited_udp_resolver': ensure => $ensure_unlimited, path => '/etc/unbound/unbound.conf', line => 'server: include: /etc/unbound/conf.d/vpn_unlimited_udp_resolver', notify => Service['unbound'], - require => Package['unbound']; + require => [ Package['openvpn'], Package['unbound'] ]; 'add_limited_tcp_resolver': ensure => $ensure_limited, path => '/etc/unbound/unbound.conf', line => 'server: include: /etc/unbound/conf.d/vpn_limited_tcp_resolver', notify => Service['unbound'], - require => Package['unbound']; - 'add_limited_udp_resolver': + require => [ Package['openvpn'], Package['unbound'] ]; + 'add_limited_udp_resolver': ensure => $ensure_limited, path => '/etc/unbound/unbound.conf', line => 'server: include: /etc/unbound/conf.d/vpn_limited_udp_resolver', notify => Service['unbound'], - require => Package['unbound'] + require => [ Package['openvpn'], Package['unbound'] ]; } } diff --git a/puppet/modules/site_openvpn/manifests/server_config.pp b/puppet/modules/site_openvpn/manifests/server_config.pp index 6106cfbb..b1f4997c 100644 --- a/puppet/modules/site_openvpn/manifests/server_config.pp +++ b/puppet/modules/site_openvpn/manifests/server_config.pp @@ -54,7 +54,7 @@ define site_openvpn::server_config( $port, $proto, $local, $server, $push, - $management, $tls_remote = undef) { + $management, $config, $tls_remote = undef) { $openvpn_configname = $name @@ -70,97 +70,97 @@ define site_openvpn::server_config( if $tls_remote != undef { openvpn::option { - "tls-remote $openvpn_configname": - key => 'tls-remote', - value => $tls_remote, - server => $openvpn_configname; + "tls-remote ${openvpn_configname}": + key => 'tls-remote', + value => $tls_remote, + server => $openvpn_configname; } } openvpn::option { - "ca $openvpn_configname": + "ca ${openvpn_configname}": key => 'ca', - value => '/etc/openvpn/ca_bundle.pem', + value => "${x509::variables::local_CAs}/${site_config::params::ca_bundle_name}.crt", server => $openvpn_configname; - "cert $openvpn_configname": + "cert ${openvpn_configname}": key => 'cert', - value => '/etc/x509/certs/leap_openvpn.crt', + value => "${x509::variables::certs}/${site_config::params::cert_name}.crt", server => $openvpn_configname; - "key $openvpn_configname": + "key ${openvpn_configname}": key => 'key', - value => '/etc/x509/keys/leap_openvpn.key', + value => "${x509::variables::keys}/${site_config::params::cert_name}.key", server => $openvpn_configname; - "dh $openvpn_configname": + "dh ${openvpn_configname}": key => 'dh', value => '/etc/openvpn/keys/dh.pem', server => $openvpn_configname; - "tls-cipher $openvpn_configname": + "tls-cipher ${openvpn_configname}": key => 'tls-cipher', - value => 'DHE-RSA-AES128-SHA', + value => $config['tls-cipher'], server => $openvpn_configname; - "auth $openvpn_configname": + "auth ${openvpn_configname}": key => 'auth', - value => 'SHA1', + value => $config['auth'], server => $openvpn_configname; - "cipher $openvpn_configname": + "cipher ${openvpn_configname}": key => 'cipher', - value => 'AES-128-CBC', + value => $config['cipher'], server => $openvpn_configname; - "dev $openvpn_configname": + "dev ${openvpn_configname}": key => 'dev', value => 'tun', server => $openvpn_configname; - "duplicate-cn $openvpn_configname": + "duplicate-cn ${openvpn_configname}": key => 'duplicate-cn', server => $openvpn_configname; - "keepalive $openvpn_configname": + "keepalive ${openvpn_configname}": key => 'keepalive', - value => '5 20', + value => $config['keepalive'], server => $openvpn_configname; - "local $openvpn_configname": + "local ${openvpn_configname}": key => 'local', value => $local, server => $openvpn_configname; - "mute $openvpn_configname": + "mute ${openvpn_configname}": key => 'mute', value => '5', server => $openvpn_configname; - "mute-replay-warnings $openvpn_configname": + "mute-replay-warnings ${openvpn_configname}": key => 'mute-replay-warnings', server => $openvpn_configname; - "management $openvpn_configname": + "management ${openvpn_configname}": key => 'management', value => $management, server => $openvpn_configname; - "proto $openvpn_configname": + "proto ${openvpn_configname}": key => 'proto', value => $proto, server => $openvpn_configname; - "push1 $openvpn_configname": + "push1 ${openvpn_configname}": key => 'push', value => $push, server => $openvpn_configname; - "push2 $openvpn_configname": + "push2 ${openvpn_configname}": key => 'push', value => '"redirect-gateway def1"', server => $openvpn_configname; - "script-security $openvpn_configname": + "script-security ${openvpn_configname}": key => 'script-security', value => '2', server => $openvpn_configname; - "server $openvpn_configname": + "server ${openvpn_configname}": key => 'server', value => $server, server => $openvpn_configname; - "status $openvpn_configname": + "status ${openvpn_configname}": key => 'status', value => '/var/run/openvpn-status 10', server => $openvpn_configname; - "status-version $openvpn_configname": + "status-version ${openvpn_configname}": key => 'status-version', value => '3', server => $openvpn_configname; - "topology $openvpn_configname": + "topology ${openvpn_configname}": key => 'topology', value => 'subnet', server => $openvpn_configname; @@ -169,7 +169,7 @@ define site_openvpn::server_config( # key => 'up', # value => '/etc/openvpn/server-up.sh', # server => $openvpn_configname; - "verb $openvpn_configname": + "verb ${openvpn_configname}": key => 'verb', value => '3', server => $openvpn_configname; diff --git a/puppet/modules/site_openvpn/templates/add_gateway_ips.sh.erb b/puppet/modules/site_openvpn/templates/add_gateway_ips.sh.erb index 05f3d16b..e76b756b 100644 --- a/puppet/modules/site_openvpn/templates/add_gateway_ips.sh.erb +++ b/puppet/modules/site_openvpn/templates/add_gateway_ips.sh.erb @@ -1,11 +1,11 @@ #!/bin/sh -ip addr show dev <%= scope.lookupvar('site_config::params::interface') %> | grep -q <%= @openvpn_gateway_address %>/24 || - ip addr add <%= @openvpn_gateway_address %>/24 dev <%= scope.lookupvar('site_config::params::interface') %> +ip addr show dev <%= scope.lookupvar('site_config::params::interface') %> | grep -q <%= @openvpn_gateway_address %>/<%= @primary_netmask %> || + ip addr add <%= @openvpn_gateway_address %>/<%= @primary_netmask %> dev <%= scope.lookupvar('site_config::params::interface') %> <% if @openvpn_second_gateway_address %> -ip addr show dev <%= scope.lookupvar('site_config::params::interface') %> | grep -q <%= @openvpn_second_gateway_address %>/24 || - ip addr add <%= @openvpn_second_gateway_address %>/24 dev <%= scope.lookupvar('site_config::params::interface') %> +ip addr show dev <%= scope.lookupvar('site_config::params::interface') %> | grep -q <%= @openvpn_second_gateway_address %>/<%= @primary_netmask %> || + ip addr add <%= @openvpn_second_gateway_address %>/<%= @primary_netmask %> dev <%= scope.lookupvar('site_config::params::interface') %> <% end %> /bin/echo 1 > /proc/sys/net/ipv4/ip_forward diff --git a/puppet/modules/site_postfix/files/checks/received_anon b/puppet/modules/site_postfix/files/checks/received_anon new file mode 100644 index 00000000..2822973e --- /dev/null +++ b/puppet/modules/site_postfix/files/checks/received_anon @@ -0,0 +1,2 @@ +/^Received: from (.* \([-._[:alnum:]]+ \[[.[:digit:]]{7,15}\]\))([[:space:]]+).*(\(using [.[:alnum:]]+ with cipher [-A-Z0-9]+ \([0-9]+\/[0-9]+ bits\)\))[[:space:]]+\(Client CN "([[:alnum:]]+)", Issuer "[[:print:]]+" \(verified OK\)\)[[:space:]]+by ([.[:alnum:]]+) \(([^)]+)\) with (E?SMTPS?A?) id ([A-F[:digit:]]+).*/ + REPLACE Received: from [127.0.0.1] (localhost [127.0.0.1])${2}${3}${2}(Authenticated sender: $4)${2}with $7 id $8 diff --git a/puppet/modules/site_postfix/manifests/debug.pp b/puppet/modules/site_postfix/manifests/debug.pp new file mode 100644 index 00000000..f370d166 --- /dev/null +++ b/puppet/modules/site_postfix/manifests/debug.pp @@ -0,0 +1,9 @@ +class site_postfix::debug { + + postfix::config { + 'debug_peer_list': value => '127.0.0.1'; + 'debug_peer_level': value => '1'; + 'smtpd_tls_loglevel': value => '1'; + } + +} diff --git a/puppet/modules/site_postfix/manifests/mx.pp b/puppet/modules/site_postfix/manifests/mx.pp new file mode 100644 index 00000000..bdfee665 --- /dev/null +++ b/puppet/modules/site_postfix/manifests/mx.pp @@ -0,0 +1,74 @@ +class site_postfix::mx { + + $domain_hash = hiera ('domain') + $domain = $domain_hash['full_suffix'] + $host_domain = $domain_hash['full'] + $cert_name = hiera('name') + $mynetworks = join(hiera('mynetworks'), ' ') + + $root_mail_recipient = hiera ('contacts') + $postfix_smtp_listen = 'all' + + include site_config::x509::cert + include site_config::x509::key + include site_config::x509::client_ca::ca + include site_config::x509::client_ca::key + + postfix::config { + 'mynetworks': + value => "127.0.0.0/8 [::1]/128 [fe80::]/64 ${mynetworks}"; + 'mydestination': + value => "\$myorigin, localhost, localhost.\$mydomain, ${domain}"; + 'myhostname': + value => $host_domain; + 'mailbox_size_limit': + value => '0'; + 'home_mailbox': + value => 'Maildir/'; + 'virtual_alias_maps': + value => 'tcp:localhost:4242'; + 'luser_relay': + value => 'vmail'; + 'smtpd_tls_received_header': + value => 'yes'; + # Note: we are setting this here, instead of in site_postfix::mx::smtp_tls + # because the satellites need to have a different value + 'smtp_tls_security_level': + value => 'may'; + } + + include site_postfix::mx::smtpd_checks + include site_postfix::mx::checks + include site_postfix::mx::smtp_tls + include site_postfix::mx::smtpd_tls + include site_postfix::mx::reserved_aliases + + # greater verbosity for debugging, take out for production + #include site_postfix::debug + + user { 'vmail': + ensure => present, + comment => 'Leap Mailspool', + home => '/var/mail/vmail', + shell => '/bin/false', + managehome => true, + } + + class { 'postfix': + preseed => true, + root_mail_recipient => $root_mail_recipient, + smtp_listen => 'all', + mastercf_tail => + "smtps inet n - - - - smtpd + -o smtpd_tls_wrappermode=yes + -o smtpd_tls_security_level=encrypt + -o smtpd_recipient_restrictions=\$smtps_recipient_restrictions + -o smtpd_helo_restrictions=\$smtps_helo_restrictions", + require => [ + Class['Site_config::X509::Key'], + Class['Site_config::X509::Cert'], + Class['Site_config::X509::Client_ca::Key'], + Class['Site_config::X509::Client_ca::Ca'], + User['vmail'] ] + } +} diff --git a/puppet/modules/site_postfix/manifests/mx/checks.pp b/puppet/modules/site_postfix/manifests/mx/checks.pp new file mode 100644 index 00000000..5d75a5e5 --- /dev/null +++ b/puppet/modules/site_postfix/manifests/mx/checks.pp @@ -0,0 +1,41 @@ +class site_postfix::mx::checks { + + file { + '/etc/postfix/checks': + ensure => directory, + mode => '0755', + owner => root, + group => postfix, + require => Package['postfix']; + + '/etc/postfix/checks/helo_checks': + content => template('site_postfix/checks/helo_access.erb'), + mode => '0644', + owner => root, + group => root; + } + + exec { + '/usr/sbin/postmap /etc/postfix/checks/helo_checks': + refreshonly => true, + subscribe => File['/etc/postfix/checks/helo_checks']; + } + + # Anonymize the user's home IP from the email headers (Feature #3866) + package { 'postfix-pcre': ensure => installed, require => Package['postfix'] } + + file { '/etc/postfix/checks/received_anon': + source => 'puppet:///modules/site_postfix/checks/received_anon', + mode => '0644', + owner => root, + group => root, + notify => Service['postfix'] + } + + postfix::config { + 'header_checks': + value => 'pcre:/etc/postfix/checks/received_anon', + require => File['/etc/postfix/checks/received_anon']; + } + +} diff --git a/puppet/modules/site_postfix/manifests/mx/reserved_aliases.pp b/puppet/modules/site_postfix/manifests/mx/reserved_aliases.pp new file mode 100644 index 00000000..83e27376 --- /dev/null +++ b/puppet/modules/site_postfix/manifests/mx/reserved_aliases.pp @@ -0,0 +1,15 @@ +# Defines which mail addresses shouldn't be available and where they should fwd +class site_postfix::mx::reserved_aliases { + + postfix::mailalias { + [ 'abuse', 'admin', 'arin-admin', 'administrator', 'bin', 'cron', + 'certmaster', 'domainadmin', 'games', 'ftp', 'hostmaster', 'lp', + 'maildrop', 'mysql', 'news', 'nobody', 'noc', 'postmaster', 'postgresql', + 'security', 'ssladmin', 'sys', 'usenet', 'uucp', 'webmaster', 'www', + 'www-data', + ]: + ensure => present, + recipient => 'root' + } + +} diff --git a/puppet/modules/site_postfix/manifests/mx/smtp_auth.pp b/puppet/modules/site_postfix/manifests/mx/smtp_auth.pp new file mode 100644 index 00000000..afa70527 --- /dev/null +++ b/puppet/modules/site_postfix/manifests/mx/smtp_auth.pp @@ -0,0 +1,6 @@ +class site_postfix::mx::smtp_auth { + + postfix::config { + 'smtpd_tls_ask_ccert': value => 'yes'; + } +} diff --git a/puppet/modules/site_postfix/manifests/mx/smtp_tls.pp b/puppet/modules/site_postfix/manifests/mx/smtp_tls.pp new file mode 100644 index 00000000..d9b59f40 --- /dev/null +++ b/puppet/modules/site_postfix/manifests/mx/smtp_tls.pp @@ -0,0 +1,27 @@ +class site_postfix::mx::smtp_tls { + + include x509::variables + $ca_path = "${x509::variables::local_CAs}/${site_config::params::ca_name}.crt" + $cert_path = "${x509::variables::certs}/${site_config::params::cert_name}.crt" + $key_path = "${x509::variables::keys}/${site_config::params::cert_name}.key" + + # smtp TLS + postfix::config { + 'smtp_use_tls': value => 'yes'; + 'smtp_tls_CApath': value => '/etc/ssl/certs/'; + 'smtp_tls_CAfile': value => $ca_path; + 'smtp_tls_cert_file': value => $cert_path; + 'smtp_tls_key_file': value => $key_path; + 'smtp_tls_loglevel': value => '1'; + 'smtp_tls_exclude_ciphers': + value => 'aNULL, MD5, DES'; + # upstream default is md5 (since 2.5 and older used it), we force sha1 + 'smtp_tls_fingerprint_digest': + value => 'sha1'; + 'smtp_tls_session_cache_database': + value => 'btree:${data_directory}/smtp_cache'; + # see issue #4011 + 'smtp_tls_protocols': + value => '!SSLv2, !SSLv3'; + } +} diff --git a/puppet/modules/site_postfix/manifests/mx/smtpd_checks.pp b/puppet/modules/site_postfix/manifests/mx/smtpd_checks.pp new file mode 100644 index 00000000..0ec40277 --- /dev/null +++ b/puppet/modules/site_postfix/manifests/mx/smtpd_checks.pp @@ -0,0 +1,31 @@ +class site_postfix::mx::smtpd_checks { + + postfix::config { + 'smtpd_helo_required': + value => 'yes'; + 'checks_dir': + value => '$config_directory/checks'; + 'smtpd_client_restrictions': + value => 'permit_mynetworks,permit'; + 'smtpd_data_restrictions': + value => 'permit_mynetworks, reject_unauth_pipelining, permit'; + 'smtpd_delay_reject': + value => 'yes'; + 'smtpd_helo_restrictions': + value => 'permit_mynetworks, reject_invalid_helo_hostname, reject_non_fqdn_helo_hostname, check_helo_access hash:$checks_dir/helo_checks, permit'; + 'smtpd_recipient_restrictions': + value => 'reject_unknown_recipient_domain, permit_mynetworks, check_recipient_access tcp:localhost:2244, reject_unauth_destination, permit'; + # We should change from permit_tls_all_clientcerts to permit_tls_clientcerts + # with a lookup on $relay_clientcerts! Right now we are listing the only + # valid CA that client certificates can use in the $smtp_tls_CAfile parameter + # but we cannot cut off a certificate that should no longer be used unless + # we use permit_tls_clientcerts with the $relay_clientcerts lookup + 'smtps_recipient_restrictions': + value => 'permit_tls_all_clientcerts, check_recipient_access tcp:localhost:2244, reject_unauth_destination, permit'; + 'smtps_helo_restrictions': + value => 'permit_mynetworks, check_helo_access hash:$checks_dir/helo_checks, permit'; + 'smtpd_sender_restrictions': + value => 'permit_mynetworks, reject_non_fqdn_sender, reject_unknown_sender_domain, permit'; + } + +} diff --git a/puppet/modules/site_postfix/manifests/mx/smtpd_tls.pp b/puppet/modules/site_postfix/manifests/mx/smtpd_tls.pp new file mode 100644 index 00000000..0809c75f --- /dev/null +++ b/puppet/modules/site_postfix/manifests/mx/smtpd_tls.pp @@ -0,0 +1,55 @@ +class site_postfix::mx::smtpd_tls { + + include x509::variables + $ca_path = "${x509::variables::local_CAs}/${site_config::params::client_ca_name}.crt" + $cert_path = "${x509::variables::certs}/${site_config::params::cert_name}.crt" + $key_path = "${x509::variables::keys}/${site_config::params::cert_name}.key" + + + postfix::config { + 'smtpd_use_tls': value => 'yes'; + 'smtpd_tls_CAfile': value => $ca_path; + 'smtpd_tls_cert_file': value => $cert_path; + 'smtpd_tls_key_file': value => $key_path; + 'smtpd_tls_ask_ccert': value => 'yes'; + 'smtpd_tls_security_level': + value => 'may'; + 'smtpd_tls_eecdh_grade': + value => 'ultra'; + 'smtpd_tls_session_cache_database': + value => 'btree:${data_directory}/smtpd_scache'; + } + + # Setup DH parameters + # Instead of using the dh parameters that are created by leap cli, it is more + # secure to generate new parameter files that will only be used for postfix, + # for each machine + + include site_config::packages::gnutls + + # Note, the file name is called dh_1024.pem, but we are generating 2048bit dh + # parameters Neither Postfix nor OpenSSL actually care about the size of the + # prime in "smtpd_tls_dh1024_param_file". You can make it 2048 bits + + exec { 'certtool-postfix-gendh': + command => 'certtool --generate-dh-params --bits 2048 --outfile /etc/postfix/smtpd_tls_dh_param.pem', + user => root, + group => root, + creates => '/etc/postfix/smtpd_tls_dh_param.pem', + require => [ Package['gnutls-bin'], Package['postfix'] ] + } + + # Make sure the dh params file has correct ownership and mode + file { + '/etc/postfix/smtpd_tls_dh_param.pem': + owner => root, + group => root, + mode => '0600', + require => Exec['certtool-postfix-gendh']; + } + + postfix::config { 'smtpd_tls_dh1024_param_file': + value => '/etc/postfix/smtpd_tls_dh_param.pem', + require => File['/etc/postfix/smtpd_tls_dh_param.pem'] + } +} diff --git a/puppet/modules/site_postfix/manifests/satellite.pp b/puppet/modules/site_postfix/manifests/satellite.pp new file mode 100644 index 00000000..5725e6b8 --- /dev/null +++ b/puppet/modules/site_postfix/manifests/satellite.pp @@ -0,0 +1,47 @@ +class site_postfix::satellite { + + $root_mail_recipient = hiera ('contacts') + $mail = hiera ('mail') + $relayhost = $mail['smarthost'] + $cert_name = hiera('name') + + class { '::postfix::satellite': + relayhost => $relayhost, + root_mail_recipient => $root_mail_recipient + } + + # There are special conditions for satellite hosts that will make them not be + # able to contact their relayhost: + # + # 1. they are on openstack/amazon/PC and are on the same cluster as the relay + # host, the MX lookup for the relay host will use the public IP, which cannot + # be contacted + # + # 2. When a domain is used that is not in DNS, because it is internal, + # a testing domain, etc. eg. a .local domain cannot be looked up in DNS + # + # to resolve this, so the satellite can contact the relayhost, we need to set + # the http://www.postfix.org/postconf.5.html#smtp_host_lookup to be 'native' + # which will cause the lookup to use the native naming service + # (nsswitch.conf), which typically defaults to 'files, dns' allowing the + # /etc/hosts to be consulted first, then DNS if the entry doesn't exist. + # + # NOTE: this will make it not possible to enable DANE support through DNSSEC + # with http://www.postfix.org/postconf.5.html#smtp_dns_support_level - but + # this parameter is not available until 2.11. If this ends up being important + # we could also make this an optional parameter for providers without + # dns / local domains + + postfix::config { + 'smtp_host_lookup': + value => 'native'; + + # Note: we are setting this here, instead of in site_postfix::mx::smtp_tls + # because the mx server has to have a different value + 'smtp_tls_security_level': + value => 'encrypt'; + } + + include site_postfix::mx::smtp_tls + +} diff --git a/puppet/modules/site_postfix/templates/checks/helo_access.erb b/puppet/modules/site_postfix/templates/checks/helo_access.erb new file mode 100644 index 00000000..bef3c11d --- /dev/null +++ b/puppet/modules/site_postfix/templates/checks/helo_access.erb @@ -0,0 +1,21 @@ +# THIS FILE IS MANAGED BY PUPPET +# To make changes to this file, please edit your platform directory under +# puppet/modules/site_postfix/templates/checks/helo_access.erb and then deploy + +# The format of this file is the HELO/EHLO domain followed by an action. +# The action could be OK to allow it, REJECT to reject it, or a custom +# status code and message. Any lines that are prefixed by an octothorpe (#) +# will be considered comments. + +# Some examples: +# +# Reject anyone that HELO's with foobar: +# foobar REJECT +# +# Allow the switches to skip this check: +# switch1 OK +# switch2 OK + +# Reject anybody that HELO's as being in our own domain(s) +# anyone who identifies themselves as us is a virus/spammer +<%= domain %> 554 You are not in domain <%= domain %> diff --git a/puppet/modules/site_shorewall/manifests/defaults.pp b/puppet/modules/site_shorewall/manifests/defaults.pp index c62c9307..8f56ac42 100644 --- a/puppet/modules/site_shorewall/manifests/defaults.pp +++ b/puppet/modules/site_shorewall/manifests/defaults.pp @@ -1,9 +1,12 @@ class site_shorewall::defaults { + include shorewall include site_config::params # be safe for development - #if ( $::virtual == 'virtualbox') { $shorewall_startup='0' } + # if ( $::site_config::params::environment == 'local' ) { + # $shorewall_startup='0' + # } # If you want logging: shorewall::params { @@ -18,8 +21,6 @@ class site_shorewall::defaults { options => 'tcpflags,blacklist,nosmurfs'; } - shorewall::routestopped { $site_config::params::interface: } - shorewall::policy { 'fw-to-all': sourcezone => 'fw', @@ -42,5 +43,32 @@ class site_shorewall::defaults { order => 200; } + package { 'shorewall-init': + ensure => installed + } + + augeas { + # stop instead of clear firewall on shutdown + 'shorewall_SAFESTOP': + changes => 'set /files/etc/shorewall/shorewall.conf/SAFESTOP Yes', + lens => 'Shellvars.lns', + incl => '/etc/shorewall/shorewall.conf', + require => Package['shorewall'], + notify => Service[shorewall]; + # require that the interface exist + 'shorewall_REQUIRE_INTERFACE': + changes => 'set /files/etc/shorewall/shorewall.conf/REQUIRE_INTERFACE Yes', + lens => 'Shellvars.lns', + incl => '/etc/shorewall/shorewall.conf', + require => Package['shorewall'], + notify => Service[shorewall]; + # configure shorewall-init + 'shorewall-init': + changes => 'set /files/etc/default/shorewall-init/PRODUCTS shorewall', + lens => 'Shellvars.lns', + incl => '/etc/default/shorewall-init', + require => [ Package['shorewall-init'], Service['shorewall'] ] + } + include site_shorewall::sshd } diff --git a/puppet/modules/site_shorewall/manifests/mx.pp b/puppet/modules/site_shorewall/manifests/mx.pp new file mode 100644 index 00000000..332f164e --- /dev/null +++ b/puppet/modules/site_shorewall/manifests/mx.pp @@ -0,0 +1,24 @@ +class site_shorewall::mx { + + include site_shorewall::defaults + + $smtpd_ports = '25,465,587' + + # define macro for incoming services + file { '/etc/shorewall/macro.leap_mx': + content => "PARAM - - tcp ${smtpd_ports} ", + notify => Service['shorewall'], + require => Package['shorewall'] + } + + + shorewall::rule { + 'net2fw-mx': + source => 'net', + destination => '$FW', + action => 'leap_mx(ACCEPT)', + order => 200; + } + + include site_shorewall::service::smtp +} diff --git a/puppet/modules/site_shorewall/manifests/service/smtp.pp b/puppet/modules/site_shorewall/manifests/service/smtp.pp new file mode 100644 index 00000000..7fbdf14e --- /dev/null +++ b/puppet/modules/site_shorewall/manifests/service/smtp.pp @@ -0,0 +1,13 @@ +class site_shorewall::service::smtp { + + include site_shorewall::defaults + + shorewall::rule { + 'fw2net-http': + source => '$FW', + destination => 'net', + action => 'SMTP(ACCEPT)', + order => 200; + } + +} diff --git a/puppet/modules/site_shorewall/manifests/soledad.pp b/puppet/modules/site_shorewall/manifests/soledad.pp new file mode 100644 index 00000000..518d8689 --- /dev/null +++ b/puppet/modules/site_shorewall/manifests/soledad.pp @@ -0,0 +1,23 @@ +class site_shorewall::soledad { + + $soledad = hiera('soledad') + $soledad_port = $soledad['port'] + + include site_shorewall::defaults + + # define macro for incoming services + file { '/etc/shorewall/macro.leap_soledad': + content => "PARAM - - tcp ${soledad_port}", + notify => Service['shorewall'], + require => Package['shorewall'] + } + + shorewall::rule { + 'net2fw-soledad': + source => 'net', + destination => '$FW', + action => 'leap_soledad(ACCEPT)', + order => 200; + } +} + diff --git a/puppet/modules/site_shorewall/manifests/sshd.pp b/puppet/modules/site_shorewall/manifests/sshd.pp index a8e09e42..88b4102c 100644 --- a/puppet/modules/site_shorewall/manifests/sshd.pp +++ b/puppet/modules/site_shorewall/manifests/sshd.pp @@ -21,4 +21,10 @@ class site_shorewall::sshd { action => 'leap_sshd(ACCEPT)', order => 200; } + + # setup a routestopped rule to allow ssh when shorewall is stopped + shorewall::routestopped { $site_config::params::interface: + options => "- tcp ${ssh_port}" + } + } diff --git a/puppet/modules/site_squid_deb_proxy/manifests/client.pp b/puppet/modules/site_squid_deb_proxy/manifests/client.pp new file mode 100644 index 00000000..27844270 --- /dev/null +++ b/puppet/modules/site_squid_deb_proxy/manifests/client.pp @@ -0,0 +1,5 @@ +class site_squid_deb_proxy::client { + include squid_deb_proxy::client + include site_shorewall::defaults + include shorewall::rules::mdns +} diff --git a/puppet/modules/site_sshd/manifests/authorized_keys.pp b/puppet/modules/site_sshd/manifests/authorized_keys.pp index c18f691c..f36fe20f 100644 --- a/puppet/modules/site_sshd/manifests/authorized_keys.pp +++ b/puppet/modules/site_sshd/manifests/authorized_keys.pp @@ -1,4 +1,7 @@ define site_sshd::authorized_keys ($keys, $ensure = 'present', $home = '') { + # We use a custom define here to deploy the authorized_keys file + # cause puppet doesn't allow purgin before populating this file + # (see https://tickets.puppetlabs.com/browse/PUP-1174) # This line allows default homedir based on $title variable. # If $home is empty, the default is used. $homedir = $home ? {'' => "/home/${title}", default => $home} diff --git a/puppet/modules/site_sshd/manifests/init.pp b/puppet/modules/site_sshd/manifests/init.pp index 90dd2d0e..d9bc1d51 100644 --- a/puppet/modules/site_sshd/manifests/init.pp +++ b/puppet/modules/site_sshd/manifests/init.pp @@ -1,5 +1,6 @@ class site_sshd { $ssh = hiera_hash('ssh') + $hosts = hiera('hosts', '') ## ## SETUP AUTHORIZED KEYS @@ -12,6 +13,23 @@ class site_sshd { } ## + ## SETUP KNOWN HOSTS and SSH_CONFIG + ## + + file { + '/etc/ssh/ssh_known_hosts': + owner => root, + group => root, + mode => '0644', + content => template('site_sshd/ssh_known_hosts.erb'); + '/etc/ssh/ssh_config': + owner => root, + group => root, + mode => '0644', + content => template('site_sshd/ssh_config.erb'); + } + + ## ## OPTIONAL MOSH SUPPORT ## diff --git a/puppet/modules/site_sshd/templates/authorized_keys.erb b/puppet/modules/site_sshd/templates/authorized_keys.erb index 3c65e8ab..69f4d8e6 100644 --- a/puppet/modules/site_sshd/templates/authorized_keys.erb +++ b/puppet/modules/site_sshd/templates/authorized_keys.erb @@ -2,5 +2,9 @@ # all manually added keys will be overridden <% keys.sort.each do |user, hash| -%> +<% if user == 'monitor' -%> +command="/usr/bin/check_mk_agent",no-port-forwarding,no-x11-forwarding,no-agent-forwarding,no-pty,no-user-rc, <%=hash['type']-%> <%=hash['key']%> <%=user%> +<% else -%> <%=hash['type']-%> <%=hash['key']%> <%=user%> +<% end -%> <% end -%> diff --git a/puppet/modules/site_sshd/templates/ssh_config.erb b/puppet/modules/site_sshd/templates/ssh_config.erb new file mode 100644 index 00000000..7e967413 --- /dev/null +++ b/puppet/modules/site_sshd/templates/ssh_config.erb @@ -0,0 +1,23 @@ +# This file is generated by Puppet +# This is the ssh client system-wide configuration file. See +# ssh_config(5) for more information. This file provides defaults for +# users, and the values can be changed in per-user configuration files +# or on the command line. + +Host * + SendEnv LANG LC_* + HashKnownHosts yes + GSSAPIAuthentication yes + GSSAPIDelegateCredentials no +<% if scope.lookupvar('::site_config::params::environment') == 'local' -%> + # + # Vagrant nodes should have strict host key checking + # turned off. The problem is that the host key for a vagrant + # node is specific to the particular instance of the vagrant + # node you have running locally. For this reason, we can't + # track the host keys, or your host key for vpn1 would conflict + # with my host key for vpn1. + # + StrictHostKeyChecking no +<% end -%> + diff --git a/puppet/modules/site_sshd/templates/ssh_known_hosts.erb b/puppet/modules/site_sshd/templates/ssh_known_hosts.erb new file mode 100644 index 00000000..002ab732 --- /dev/null +++ b/puppet/modules/site_sshd/templates/ssh_known_hosts.erb @@ -0,0 +1,7 @@ +# This file is generated by Puppet + +<% @hosts.sort.each do |name, hash| -%> +<% if hash['host_pub_key'] -%> +<%= name%>,<%=hash['domain_full']%>,<%=hash['domain_internal']%>,<%=hash['ip_address']%> <%=hash['host_pub_key']%> +<% end -%> +<% end -%> diff --git a/puppet/modules/site_static/README b/puppet/modules/site_static/README new file mode 100644 index 00000000..bc719782 --- /dev/null +++ b/puppet/modules/site_static/README @@ -0,0 +1,3 @@ +Deploy one or more static websites to a node. + +For now, it only supports `amber` based static sites. Should support plain html and jekyll in the future. diff --git a/puppet/modules/site_static/manifests/domain.pp b/puppet/modules/site_static/manifests/domain.pp new file mode 100644 index 00000000..8af2230f --- /dev/null +++ b/puppet/modules/site_static/manifests/domain.pp @@ -0,0 +1,28 @@ +define site_static::domain ( + $locations, + $ca_cert, + $key, + $cert, + $tls_only) { + + $domain = $name + $base_dir = '/srv/static' + + create_resources(site_static::location, $locations) + + x509::cert { $domain: content => $cert } + x509::key { $domain: content => $key } + x509::ca { "${domain}_ca": content => $ca_cert } + + class { '::apache': no_default_site => true, ssl => true } + include site_apache::module::headers + include site_apache::module::alias + include site_apache::module::expires + include site_apache::module::removeip + include site_apache::module::rewrite + + apache::vhost::file { $domain: + content => template('site_static/apache.conf.erb') + } + +} diff --git a/puppet/modules/site_static/manifests/init.pp b/puppet/modules/site_static/manifests/init.pp new file mode 100644 index 00000000..91a4a7a9 --- /dev/null +++ b/puppet/modules/site_static/manifests/init.pp @@ -0,0 +1,17 @@ +class site_static { + tag 'leap_service' + $static = hiera('static') + $domains = $static['domains'] + $formats = $static['formats'] + + if (member($formats, 'amber')) { + include site_config::ruby::dev + rubygems::gem{'amber': } + } + + create_resources(site_static::domain, $domains) + + include site_shorewall::defaults + include site_shorewall::service::http + include site_shorewall::service::https +}
\ No newline at end of file diff --git a/puppet/modules/site_static/manifests/location.pp b/puppet/modules/site_static/manifests/location.pp new file mode 100644 index 00000000..1ba6807e --- /dev/null +++ b/puppet/modules/site_static/manifests/location.pp @@ -0,0 +1,25 @@ +define site_static::location($path, $format, $source) { + + $file_path = "/srv/static/${name}" + + if ($format == 'amber') { + exec {"amber_build_${name}": + cwd => $file_path, + command => 'amber rebuild', + user => 'www-data', + timeout => 600, + subscribe => Vcsrepo[$file_path] + } + } + + vcsrepo { $file_path: + ensure => present, + force => true, + revision => $source['revision'], + provider => $source['type'], + source => $source['repo'], + owner => 'www-data', + group => 'www-data' + } + +} diff --git a/puppet/modules/site_static/templates/apache.conf.erb b/puppet/modules/site_static/templates/apache.conf.erb new file mode 100644 index 00000000..2abe1a98 --- /dev/null +++ b/puppet/modules/site_static/templates/apache.conf.erb @@ -0,0 +1,77 @@ +<%- + ## + ## An apache config for static websites. + ## + def location_directory(name, location) + if location['format'] == 'amber' + File.join(@base_dir, name, 'public') + else + File.join(@base_dir, name) + end + end + document_root = '/var/www' + @locations.each do |name, location| + if location['path'] == '/' + document_root = location_directory(name, location) + end + end + document_root = document_root.gsub(%r{^/|/$}, '') +-%> + +<VirtualHost *:80> + ServerName <%= @domain %> + ServerAlias www.<%= @domain %> + RewriteEngine On + RewriteRule ^.*$ https://<%= @domain -%>%{REQUEST_URI} [R=permanent,L] +</VirtualHost> + +<VirtualHost *:443> + ServerName <%= @domain %> + ServerAlias www.<%= @domain %> + + #RewriteLog "/var/log/apache2/rewrite.log" + #RewriteLogLevel 3 + + SSLEngine on + SSLProtocol all -SSLv2 + SSLHonorCipherOrder on + SSLCompression off + SSLCipherSuite "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:ECDHE-RSA-RC4-SHA:ECDHE-ECDSA-RC4-SHA:AES128:AES256:RC4-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK" + + Header add Strict-Transport-Security: "max-age=15768000;includeSubdomains" + Header set X-Frame-Options "deny" + + SSLCertificateKeyFile /etc/x509/keys/<%= @domain %>.key + SSLCertificateFile /etc/x509/certs/<%= @domain %>.crt + SSLCertificateChainFile /etc/ssl/certs/<%= @domain %>_ca.pem + + RequestHeader set X_FORWARDED_PROTO 'https' + + DocumentRoot "/<%= document_root %>/" + AccessFileName .htaccess + +<%- @locations.each do |name, location| -%> + <%- path = location['path'].gsub(%r{^/|/$}, '') -%> + <%- directory = location_directory(name, location) -%> + ## + ## <%= name %> + ## + <%- if path == '' -%> + <Directory "/<%= document_root %>/"> + AllowOverride FileInfo Indexes Options=All,MultiViews + Order deny,allow + Allow from all + </Directory> + <%- else -%> + AliasMatch ^/[a-z]{2}/<%=path%>(/.+|/|)$ "/<%=directory%>/$1" + Alias /<%=path%> "/<%=directory%>/" + <Directory "/<%=directory%>/"> + AllowOverride FileInfo Indexes Options=All,MultiViews + Order deny,allow + Allow from all + </Directory> + <%- end -%> + +<%- end -%> + +</VirtualHost> diff --git a/puppet/modules/site_stunnel/manifests/clients.pp b/puppet/modules/site_stunnel/manifests/clients.pp index ed766e1a..837665a3 100644 --- a/puppet/modules/site_stunnel/manifests/clients.pp +++ b/puppet/modules/site_stunnel/manifests/clients.pp @@ -21,6 +21,13 @@ define site_stunnel::clients ( verify => $verify, pid => "/var/run/stunnel4/${pid}.pid", rndfile => $rndfile, - debuglevel => $debuglevel + debuglevel => $debuglevel, + require => [ + Class['Site_config::X509::Key'], + Class['Site_config::X509::Cert'], + Class['Site_config::X509::Ca'] ]; + } + + include site_check_mk::agent::stunnel } diff --git a/puppet/modules/site_stunnel/manifests/setup.pp b/puppet/modules/site_stunnel/manifests/setup.pp deleted file mode 100644 index 92eeb425..00000000 --- a/puppet/modules/site_stunnel/manifests/setup.pp +++ /dev/null @@ -1,24 +0,0 @@ -class site_stunnel::setup ($cert_name, $key, $cert, $ca_name, $ca) { - - include site_stunnel - - x509::key { - $cert_name: - content => $key, - notify => Service['stunnel']; - } - - x509::cert { - $cert_name: - content => $cert, - notify => Service['stunnel']; - } - - x509::ca { - $ca_name: - content => $ca, - notify => Service['stunnel']; - } - -} - diff --git a/puppet/modules/site_tor/manifests/init.pp b/puppet/modules/site_tor/manifests/init.pp index 50ab636b..02368a0e 100644 --- a/puppet/modules/site_tor/manifests/init.pp +++ b/puppet/modules/site_tor/manifests/init.pp @@ -1,11 +1,12 @@ class site_tor { tag 'leap_service' + Class['site_config::default'] -> Class['site_tor'] $tor = hiera('tor') $bandwidth_rate = $tor['bandwidth_rate'] $tor_type = $tor['type'] $nickname = $tor['nickname'] - $contact_email = $tor['contacts'] + $contact_emails = join($tor['contacts'],', ') $address = hiera('ip_address') @@ -13,17 +14,22 @@ class site_tor { tor::daemon::relay { $nickname: port => 9001, address => $address, - contact_info => $contact_email, + contact_info => obfuscate_email($contact_emails), bandwidth_rate => $bandwidth_rate, my_family => '$2A431444756B0E7228A7918C85A8DACFF7E3B050', } - tor::daemon::directory { $::hostname: port => 80 } - - include site_shorewall::tor - - if ( $tor_type != 'exit' ) { + if ( $tor_type == 'exit'){ + tor::daemon::directory { $::hostname: port => 80 } + } + else { + tor::daemon::directory { $::hostname: + port => 80, + port_front_page => ''; + } include site_tor::disable_exit } + include site_shorewall::tor + } diff --git a/puppet/modules/site_webapp/files/migrate_design_documents b/puppet/modules/site_webapp/files/migrate_design_documents deleted file mode 100644 index 6e24aa5b..00000000 --- a/puppet/modules/site_webapp/files/migrate_design_documents +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/sh - -cd /srv/leap/webapp - -# use admin credentials -cp config/couchdb.yml.admin config/couchdb.yml -chown leap-webapp:leap-webapp config/couchdb.yml - -# needs to be run twice -RAILS_ENV=production /usr/bin/bundle exec rake couchrest:migrate -RAILS_ENV=production /usr/bin/bundle exec rake couchrest:migrate - -# use user credentials and remove admin credentials -cp config/couchdb.yml.webapp config/couchdb.yml -chown leap-webapp:leap-webapp config/couchdb.yml - diff --git a/puppet/modules/site_webapp/manifests/apache.pp b/puppet/modules/site_webapp/manifests/apache.pp index 8b340160..21243d34 100644 --- a/puppet/modules/site_webapp/manifests/apache.pp +++ b/puppet/modules/site_webapp/manifests/apache.pp @@ -4,61 +4,20 @@ class site_webapp::apache { $api_domain = $web_api['domain'] $api_port = $web_api['port'] - $x509 = hiera('x509') - $commercial_key = $x509['commercial_key'] - $commercial_cert = $x509['commercial_cert'] - $commercial_root = $x509['commercial_ca_cert'] - $api_key = $x509['key'] - $api_cert = $x509['cert'] - $api_root = $x509['ca_cert'] + $web_domain = hiera('domain') + $domain_name = $web_domain['name'] - class { '::apache': no_default_site => true, ssl => true } - - apache::module { - 'alias': ensure => present; - 'rewrite': ensure => present; - 'headers': ensure => present; - } + include site_apache::common + include site_apache::module::headers + include site_apache::module::alias + include site_apache::module::expires + include site_apache::module::removeip class { 'passenger': use_munin => false } apache::vhost::file { - 'leap_webapp': - content => template('site_apache/vhosts.d/leap_webapp.conf.erb') - } - - apache::vhost::file { 'api': content => template('site_apache/vhosts.d/api.conf.erb') } - x509::key { - 'leap_webapp': - content => $commercial_key, - notify => Service[apache]; - - 'leap_api': - content => $api_key, - notify => Service[apache]; - } - - x509::cert { - 'leap_webapp': - content => $commercial_cert, - notify => Service[apache]; - - 'leap_api': - content => $api_cert, - notify => Service[apache]; - } - - x509::ca { - 'leap_webapp': - content => $commercial_root, - notify => Service[apache]; - - 'leap_api': - content => $api_root, - notify => Service[apache]; - } } diff --git a/puppet/modules/site_webapp/manifests/client_ca.pp b/puppet/modules/site_webapp/manifests/client_ca.pp deleted file mode 100644 index 0d9b15d6..00000000 --- a/puppet/modules/site_webapp/manifests/client_ca.pp +++ /dev/null @@ -1,25 +0,0 @@ -## -## This is for the special CA that is used exclusively for generating -## client certificates by the webapp. -## - -class site_webapp::client_ca { - include x509::variables - - $x509 = hiera('x509') - $cert_path = "${x509::variables::certs}/leap_client_ca.crt" - $key_path = "${x509::variables::keys}/leap_client_ca.key" - - x509::key { - 'leap_client_ca': - source => $x509['client_ca_key'], - group => 'leap-webapp', - notify => Service[apache]; - } - - x509::cert { - 'leap_client_ca': - source => $x509['client_ca_cert'], - notify => Service[apache]; - } -} diff --git a/puppet/modules/site_webapp/manifests/couchdb.pp b/puppet/modules/site_webapp/manifests/couchdb.pp index b4ef0980..ff743fba 100644 --- a/puppet/modules/site_webapp/manifests/couchdb.pp +++ b/puppet/modules/site_webapp/manifests/couchdb.pp @@ -4,8 +4,6 @@ class site_webapp::couchdb { # haproxy listener on port localhost:4096, see site_webapp::haproxy $couchdb_host = 'localhost' $couchdb_port = '4096' - $couchdb_admin_user = $webapp['couchdb_admin_user']['username'] - $couchdb_admin_password = $webapp['couchdb_admin_user']['password'] $couchdb_webapp_user = $webapp['couchdb_webapp_user']['username'] $couchdb_webapp_password = $webapp['couchdb_webapp_user']['password'] @@ -14,65 +12,38 @@ class site_webapp::couchdb { $couch_client_connect = $couch_client['connect'] include x509::variables - $x509 = hiera('x509') - $key = $x509['key'] - $cert = $x509['cert'] - $ca = $x509['ca_cert'] - $cert_name = 'leap_couchdb' - $ca_name = 'leap_ca' - $ca_path = "${x509::variables::local_CAs}/${ca_name}.crt" - $cert_path = "${x509::variables::certs}/${cert_name}.crt" - $key_path = "${x509::variables::keys}/${cert_name}.key" file { - '/srv/leap/webapp/config/couchdb.yml.admin': - content => template('site_webapp/couchdb.yml.admin.erb'), + '/srv/leap/webapp/config/couchdb.yml': + content => template('site_webapp/couchdb.yml.erb'), owner => leap-webapp, group => leap-webapp, mode => '0600', require => Vcsrepo['/srv/leap/webapp']; - '/srv/leap/webapp/config/couchdb.yml.webapp': - content => template('site_webapp/couchdb.yml.erb'), + '/srv/leap/webapp/log': + ensure => directory, owner => leap-webapp, group => leap-webapp, - mode => '0600', + mode => '0755', require => Vcsrepo['/srv/leap/webapp']; - '/srv/leap/webapp/logs/production.log': + '/srv/leap/webapp/log/production.log': + ensure => present, owner => leap-webapp, group => leap-webapp, mode => '0666', require => Vcsrepo['/srv/leap/webapp']; - - '/usr/local/sbin/migrate_design_documents': - source => 'puppet:///modules/site_webapp/migrate_design_documents', - owner => root, - group => root, - mode => '0744'; } - class { 'site_stunnel::setup': - cert_name => $cert_name, - key => $key, - cert => $cert, - ca_name => $ca_name, - ca => $ca - } - - exec { 'migrate_design_documents': - cwd => '/srv/leap/webapp', - command => '/usr/local/sbin/migrate_design_documents', - require => Exec['bundler_update'], - notify => Service['apache']; - } + include site_stunnel $couchdb_stunnel_client_defaults = { 'connect_port' => $couch_client_connect, - 'client' => true, - 'cafile' => $ca_path, - 'key' => $key_path, - 'cert' => $cert_path, + 'client' => true, + 'cafile' => "${x509::variables::local_CAs}/${site_config::params::ca_name}.crt", + 'key' => "${x509::variables::keys}/${site_config::params::cert_name}.key", + 'cert' => "${x509::variables::certs}/${site_config::params::cert_name}.crt", } create_resources(site_stunnel::clients, $couch_client, $couchdb_stunnel_client_defaults) diff --git a/puppet/modules/site_webapp/manifests/cron.pp b/puppet/modules/site_webapp/manifests/cron.pp new file mode 100644 index 00000000..811ad11d --- /dev/null +++ b/puppet/modules/site_webapp/manifests/cron.pp @@ -0,0 +1,17 @@ +class site_webapp::cron { + + # cron tasks that need to be performed to cleanup the database + cron { + 'remove_expired_sessions': + command => 'cd /srv/leap/webapp && bundle exec rake cleanup:sessions', + environment => 'RAILS_ENV=production', + hour => 2, + minute => 30; + + 'remove_expired_tokens': + command => 'cd /srv/leap/webapp && bundle exec rake cleanup:tokens', + environment => 'RAILS_ENV=production', + hour => 3, + minute => 0; + } +} diff --git a/puppet/modules/site_webapp/manifests/haproxy.pp b/puppet/modules/site_webapp/manifests/haproxy.pp index 4a7e3c25..b69c69da 100644 --- a/puppet/modules/site_webapp/manifests/haproxy.pp +++ b/puppet/modules/site_webapp/manifests/haproxy.pp @@ -3,7 +3,6 @@ class site_webapp::haproxy { include site_haproxy $haproxy = hiera('haproxy') - $local_ports = $haproxy['local_ports'] # Template uses $global_options, $defaults_options concat::fragment { 'leap_haproxy_webapp_couchdb': diff --git a/puppet/modules/site_webapp/manifests/init.pp b/puppet/modules/site_webapp/manifests/init.pp index e743dc07..d02a7261 100644 --- a/puppet/modules/site_webapp/manifests/init.pp +++ b/puppet/modules/site_webapp/manifests/init.pp @@ -11,11 +11,18 @@ class site_webapp { $api_version = $webapp['api_version'] $secret_token = $webapp['secret_token'] - include site_config::ruby + Class['site_config::default'] -> Class['site_webapp'] + + include site_config::ruby::dev include site_webapp::apache include site_webapp::couchdb - include site_webapp::client_ca include site_webapp::haproxy + include site_webapp::cron + include site_config::x509::cert + include site_config::x509::key + include site_config::x509::ca + include site_config::x509::client_ca::ca + include site_config::x509::client_ca::key group { 'leap-webapp': ensure => present, @@ -31,19 +38,12 @@ class site_webapp { require => [ Group['leap-webapp'] ]; } - file { '/srv/leap/webapp': - ensure => directory, - owner => 'leap-webapp', - group => 'leap-webapp', - require => User['leap-webapp']; - } - vcsrepo { '/srv/leap/webapp': ensure => present, force => true, - revision => 'origin/master', + revision => $webapp['git']['revision'], provider => git, - source => 'git://code.leap.se/leap_web', + source => $webapp['git']['source'], owner => 'leap-webapp', group => 'leap-webapp', require => [ User['leap-webapp'], Group['leap-webapp'] ], @@ -56,38 +56,58 @@ class site_webapp { unless => '/usr/bin/bundle check', user => 'leap-webapp', timeout => 600, - require => [ Class['bundler::install'], Vcsrepo['/srv/leap/webapp'] ], + require => [ + Class['bundler::install'], + Vcsrepo['/srv/leap/webapp'], + Class['site_config::ruby::dev'], + Service['shorewall'] ], notify => Service['apache']; } + # + # NOTE: in order to support a webapp that is running on a subpath and not the + # root of the domain assets:precompile needs to be run with + # RAILS_RELATIVE_URL_ROOT=/application-root + # + exec { 'compile_assets': - cwd => '/srv/leap/webapp', - command => '/bin/bash -c "/usr/bin/bundle exec rake assets:precompile"', - user => 'leap-webapp', - require => Exec['bundler_update'], - notify => Service['apache']; + cwd => '/srv/leap/webapp', + command => '/bin/bash -c "RAILS_ENV=production /usr/bin/bundle exec rake assets:precompile"', + user => 'leap-webapp', + logoutput => on_failure, + require => Exec['bundler_update'], + notify => Service['apache']; } file { - '/srv/leap/webapp/public/provider.json': + '/srv/leap/webapp/config/provider': + ensure => directory, + require => Vcsrepo['/srv/leap/webapp'], + owner => leap-webapp, group => leap-webapp, mode => '0755'; + + '/srv/leap/webapp/config/provider/provider.json': content => $provider, require => Vcsrepo['/srv/leap/webapp'], owner => leap-webapp, group => leap-webapp, mode => '0644'; + # old provider.json location. this can be removed after everyone upgrades. + '/srv/leap/webapp/public/provider.json': + ensure => absent; + '/srv/leap/webapp/public/ca.crt': ensure => link, require => Vcsrepo['/srv/leap/webapp'], - target => '/usr/local/share/ca-certificates/leap_api.crt'; + target => "${x509::variables::local_CAs}/${site_config::params::ca_name}.crt"; "/srv/leap/webapp/public/${api_version}": - ensure => directory, + ensure => directory, require => Vcsrepo['/srv/leap/webapp'], - owner => leap-webapp, group => leap-webapp, mode => '0755'; + owner => leap-webapp, group => leap-webapp, mode => '0755'; "/srv/leap/webapp/public/${api_version}/config/": - ensure => directory, + ensure => directory, require => Vcsrepo['/srv/leap/webapp'], - owner => leap-webapp, group => leap-webapp, mode => '0755'; + owner => leap-webapp, group => leap-webapp, mode => '0755'; "/srv/leap/webapp/public/${api_version}/config/eip-service.json": content => $eip_service, @@ -106,25 +126,24 @@ class site_webapp { } try::file { - '/srv/leap/webapp/public/favicon.ico': - ensure => 'link', - require => Vcsrepo['/srv/leap/webapp'], - target => $webapp['favicon']; - - '/srv/leap/webapp/app/assets/stylesheets/tail.scss': - ensure => 'link', - require => Vcsrepo['/srv/leap/webapp'], - target => $webapp['tail_scss']; - - '/srv/leap/webapp/app/assets/stylesheets/head.scss': - ensure => 'link', + '/srv/leap/webapp/config/customization': + ensure => directory, + recurse => true, + purge => true, + force => true, + owner => leap-webapp, + group => leap-webapp, + mode => 'u=rwX,go=rX', require => Vcsrepo['/srv/leap/webapp'], - target => $webapp['head_scss']; + notify => Exec['compile_assets'], + source => $webapp['customization_dir']; + } - '/srv/leap/webapp/public/img': - ensure => 'link', + git::changes { + 'public/favicon.ico': + cwd => '/srv/leap/webapp', require => Vcsrepo['/srv/leap/webapp'], - target => $webapp['img_dir']; + user => 'leap-webapp'; } file { @@ -138,5 +157,5 @@ class site_webapp { } include site_shorewall::webapp - + include site_check_mk::agent::webapp } diff --git a/puppet/modules/site_webapp/templates/config.yml.erb b/puppet/modules/site_webapp/templates/config.yml.erb index df562cd9..98f8564e 100644 --- a/puppet/modules/site_webapp/templates/config.yml.erb +++ b/puppet/modules/site_webapp/templates/config.yml.erb @@ -1,9 +1,10 @@ <%- cert_options = @webapp['client_certificates'] -%> production: - admins: [admin] + admins: <%= @webapp['admins'].inspect %> domain: <%= @provider_domain %> - client_ca_key: <%= scope.lookupvar('site_webapp::client_ca::key_path') %> - client_ca_cert: <%= scope.lookupvar('site_webapp::client_ca::cert_path') %> + force_ssl: <%= @webapp['secure'] %> + client_ca_key: <%= scope.lookupvar('x509::variables::keys') %>/<%= scope.lookupvar('site_config::params::client_ca_name') %>.key + client_ca_cert: <%= scope.lookupvar('x509::variables::local_CAs') %>/<%= scope.lookupvar('site_config::params::client_ca_name') %>.crt secret_token: "<%= @secret_token %>" client_cert_lifespan: <%= cert_options['life_span'].to_i %> client_cert_bit_size: <%= cert_options['bit_size'].to_i %> @@ -13,3 +14,4 @@ production: allow_anonymous_certs: <%= @webapp['allow_anonymous_certs'].inspect %> limited_cert_prefix: "<%= cert_options['limited_prefix'] %>" unlimited_cert_prefix: "<%= cert_options['unlimited_prefix'] %>" + minimum_client_version: "<%= @webapp['client_version']['min'] %>" diff --git a/puppet/modules/site_webapp/templates/couchdb.yml.admin.erb b/puppet/modules/site_webapp/templates/couchdb.yml.admin.erb deleted file mode 100644 index a0921add..00000000 --- a/puppet/modules/site_webapp/templates/couchdb.yml.admin.erb +++ /dev/null @@ -1,9 +0,0 @@ -production: - prefix: "" - protocol: 'http' - host: <%= @couchdb_host %> - port: <%= @couchdb_port %> - auto_update_design_doc: false - username: <%= @couchdb_admin_user %> - password: <%= @couchdb_admin_password %> - diff --git a/puppet/modules/site_webapp/templates/haproxy_couchdb.cfg.erb b/puppet/modules/site_webapp/templates/haproxy_couchdb.cfg.erb index f08161ee..1fa01b96 100644 --- a/puppet/modules/site_webapp/templates/haproxy_couchdb.cfg.erb +++ b/puppet/modules/site_webapp/templates/haproxy_couchdb.cfg.erb @@ -1,16 +1,23 @@ listen bigcouch-in - mode http + mode http balance roundrobin - option httplog - option dontlognull - option httpchk GET / - option http-server-close - + option httplog + option dontlognull + option httpchk GET / # health check using simple get to root + option http-server-close # use client keep-alive, but close server connection. + option allbackups # balance among all backups, not just one. + bind localhost:4096 -<% for port in @local_ports -%> - server couchdb_<%=port%> localhost:<%=port%> check inter 3000 fastinter 1000 downinter 1000 rise 2 fall 1 -<% end -%> + default-server inter 3000 fastinter 1000 downinter 1000 rise 2 fall 1 + +<%- if @haproxy['servers'] -%> +<%- @haproxy['servers'].sort.each do |name,server| -%> +<%- backup = server['backup'] ? 'backup' : '' -%> + # <%=name%> + server couchdb_<%=server['port']%> <%=server['host']%>:<%=server['port']%> <%=backup%> weight <%=server['weight']%> check +<%- end -%> +<%- end -%> diff --git a/puppet/modules/soledad/manifests/common.pp b/puppet/modules/soledad/manifests/common.pp new file mode 100644 index 00000000..8a1d664a --- /dev/null +++ b/puppet/modules/soledad/manifests/common.pp @@ -0,0 +1,10 @@ +class soledad::common { + + include soledad + + package { 'soledad-common': + ensure => latest, + require => User['soledad'] + } + +} diff --git a/puppet/modules/soledad/manifests/init.pp b/puppet/modules/soledad/manifests/init.pp new file mode 100644 index 00000000..7cf0b729 --- /dev/null +++ b/puppet/modules/soledad/manifests/init.pp @@ -0,0 +1,29 @@ +class soledad { + + group { 'soledad': + ensure => present, + allowdupe => false; + } + + user { 'soledad': + ensure => present, + allowdupe => false, + gid => 'soledad', + home => '/srv/leap/soledad', + require => Group['soledad']; + } + + file { + '/srv/leap/soledad': + ensure => directory, + owner => 'soledad', + group => 'soledad', + require => User['soledad']; + + '/var/lib/soledad': + ensure => directory, + owner => 'soledad', + group => 'soledad', + require => User['soledad']; + } +} diff --git a/puppet/modules/soledad/manifests/server.pp b/puppet/modules/soledad/manifests/server.pp new file mode 100644 index 00000000..394e6032 --- /dev/null +++ b/puppet/modules/soledad/manifests/server.pp @@ -0,0 +1,63 @@ +class soledad::server { + tag 'leap_service' + include soledad + include site_apt::preferences::twisted + + $soledad = hiera('soledad') + $couchdb_user = $soledad['couchdb_soledad_user']['username'] + $couchdb_password = $soledad['couchdb_soledad_user']['password'] + + $couchdb_host = 'localhost' + $couchdb_port = '5984' + + $soledad_port = $soledad['port'] + + include site_config::x509::cert + include site_config::x509::key + include site_config::x509::ca + + # + # SOLEDAD CONFIG + # + + file { '/etc/leap/soledad-server.conf': + content => template('soledad/soledad-server.conf.erb'), + owner => 'soledad', + group => 'soledad', + mode => '0600', + notify => Service['soledad-server'], + require => Class['soledad']; + } + + package { 'soledad-server': + ensure => latest, + require => [ + Class['site_apt::preferences::twisted'], + Class['site_apt::leap_repo'] ]; + } + + file { '/etc/default/soledad': + content => template('soledad/default-soledad.erb'), + owner => 'soledad', + group => 'soledad', + mode => '0600', + notify => Service['soledad-server'], + require => Class['soledad']; + } + + service { 'soledad-server': + ensure => running, + enable => true, + hasstatus => true, + hasrestart => true, + require => Class['soledad'], + subscribe => [ + Package['soledad-server'], + Class['Site_config::X509::Key'], + Class['Site_config::X509::Cert'], + Class['Site_config::X509::Ca'] ]; + } + + include site_shorewall::soledad + include site_check_mk::agent::soledad +} diff --git a/puppet/modules/soledad/templates/default-soledad.erb b/puppet/modules/soledad/templates/default-soledad.erb new file mode 100644 index 00000000..32504e38 --- /dev/null +++ b/puppet/modules/soledad/templates/default-soledad.erb @@ -0,0 +1,5 @@ +# this file is managed by puppet +START=yes +CERT_PATH=<%= scope.lookupvar('x509::variables::certs') %>/<%= scope.lookupvar('site_config::params::cert_name') %>.crt +PRIVKEY_PATH=<%= scope.lookupvar('x509::variables::keys') %>/<%= scope.lookupvar('site_config::params::cert_name') %>.key +HTTPS_PORT=<%=@soledad_port%> diff --git a/puppet/modules/soledad/templates/soledad-server.conf.erb b/puppet/modules/soledad/templates/soledad-server.conf.erb new file mode 100644 index 00000000..47d1f6e4 --- /dev/null +++ b/puppet/modules/soledad/templates/soledad-server.conf.erb @@ -0,0 +1,3 @@ +[soledad-server] +couch_url = http://<%= @couchdb_user %>:<%= @couchdb_password %>@<%= @couchdb_host %>:<%= @couchdb_port %> + diff --git a/puppet/modules/squid_deb_proxy b/puppet/modules/squid_deb_proxy new file mode 160000 +Subproject e796aac43aa9781069e167459253d040504c209 diff --git a/puppet/modules/sshd b/puppet/modules/sshd -Subproject bd2e283ab59430a7b3194804f1c8da7a9b58f8f +Subproject 1eabfe1b590f6663c2558f949408a08fc5f58fa diff --git a/puppet/modules/stdlib b/puppet/modules/stdlib -Subproject 66e0fa8f1bc5062e9d753598ad17602c378a299 +Subproject 71cb0f4c2c3bf95f62c9f189f5cef155b09a968 diff --git a/puppet/modules/stunnel b/puppet/modules/stunnel -Subproject fc1589a5f09d80f58d730d4e1f6a8058483f61f +Subproject ec49fd93c2469bc5c13f7e6a7d25468613e1b84 diff --git a/puppet/modules/sysctl b/puppet/modules/sysctl new file mode 160000 +Subproject 975852b7acc1125b4cd9d4d490b9abd8d31217e diff --git a/puppet/modules/tapicero/files/tapicero.init b/puppet/modules/tapicero/files/tapicero.init new file mode 100755 index 00000000..7a9af45f --- /dev/null +++ b/puppet/modules/tapicero/files/tapicero.init @@ -0,0 +1,60 @@ +#!/bin/sh + +### BEGIN INIT INFO +# Provides: tapicero +# Required-Start: $remote_fs $syslog +# Required-Stop: $remote_fs $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: tapicero initscript +# Description: Controls tapicero daemon +### END INIT INFO + +PATH=/sbin:/usr/sbin:/bin:/usr/bin +BUNDLER=/usr/bin/bundle +NAME=tapicero +HOME="/srv/leap" +DAEMON="${HOME}/${NAME}/bin/${NAME}" +BUNDLE_GEMFILE="${HOME}/${NAME}/Gemfile" + +export BUNDLE_GEMFILE + +# exit if the daemon doesn't exist +[ -x "$DAEMON" ] || exit 0 + +. /lib/init/vars.sh +. /lib/lsb/init-functions + +if [ "$VERBOSE" != no ]; then + OPTIONS="--verbose" +else + OPTIONS="" +fi + +case "$1" in + start) + $BUNDLER exec $DAEMON start $OPTIONS + exit $? + ;; + stop) + $BUNDLER exec $DAEMON stop $OPTIONS + exit $? + ;; + restart) + $BUNDLER exec $DAEMON restart $OPTIONS + exit $? + ;; + reload) + $BUNDLER exec $DAEMON reload $OPTIONS + exit $? + ;; + status) + $BUNDLER exec $DAEMON status $OPTIONS + exit $? + ;; + *) + echo "Usage: /etc/init.d/$NAME {start|stop|reload|restart|status}" + exit 1 +esac + +exit 0 diff --git a/puppet/modules/tapicero/manifests/init.pp b/puppet/modules/tapicero/manifests/init.pp new file mode 100644 index 00000000..743e8a84 --- /dev/null +++ b/puppet/modules/tapicero/manifests/init.pp @@ -0,0 +1,123 @@ +class tapicero { + tag 'leap_service' + + $couchdb = hiera('couch') + $couchdb_port = $couchdb['port'] + + $couchdb_users = $couchdb['users'] + + $couchdb_admin_user = $couchdb_users['admin']['username'] + $couchdb_admin_password = $couchdb_users['admin']['password'] + + $couchdb_soledad_user = $couchdb_users['soledad']['username'] + $couchdb_leap_mx_user = $couchdb_users['leap_mx']['username'] + + + Class['site_config::default'] -> Class['tapicero'] + + include site_config::ruby::dev + + # + # USER AND GROUP + # + + group { 'tapicero': + ensure => present, + allowdupe => false; + } + + user { 'tapicero': + ensure => present, + allowdupe => false, + gid => 'tapicero', + home => '/srv/leap/tapicero', + require => Group['tapicero']; + } + + # + # TAPICERO FILES + # + + file { + + ## + ## TAPICERO DIRECTORIES + ## + + '/srv/leap/tapicero': + ensure => directory, + owner => 'tapicero', + group => 'tapicero', + require => User['tapicero']; + + '/var/lib/leap/tapicero': + ensure => directory, + owner => 'tapicero', + group => 'tapicero', + require => User['tapicero']; + + ## + ## TAPICERO CONFIG + ## + + '/etc/leap/tapicero.yaml': + content => template('tapicero/tapicero.yaml.erb'), + owner => 'tapicero', + group => 'tapicero', + mode => '0600', + notify => Service['tapicero']; + + ## + ## TAPICERO INIT + ## + + '/etc/init.d/tapicero': + source => 'puppet:///modules/tapicero/tapicero.init', + owner => root, + group => 0, + mode => '0755', + require => Vcsrepo['/srv/leap/tapicero']; + } + + # + # TAPICERO CODE + # + + vcsrepo { '/srv/leap/tapicero': + ensure => present, + force => true, + revision => 'origin/master', + provider => git, + source => 'https://leap.se/git/tapicero', + owner => 'tapicero', + group => 'tapicero', + require => [ User['tapicero'], Group['tapicero'] ], + notify => Exec['tapicero_bundler_update'] + } + + exec { 'tapicero_bundler_update': + cwd => '/srv/leap/tapicero', + command => '/bin/bash -c "/usr/bin/bundle check || /usr/bin/bundle install --path vendor/bundle --without test development"', + unless => '/usr/bin/bundle check', + user => 'tapicero', + timeout => 600, + require => [ + Class['bundler::install'], + Vcsrepo['/srv/leap/tapicero'], + Class['site_config::ruby::dev'] ], + notify => Service['tapicero']; + } + + # + # TAPICERO DAEMON + # + + service { 'tapicero': + ensure => running, + enable => true, + hasstatus => true, + hasrestart => true, + require => File['/etc/init.d/tapicero']; + } + +} diff --git a/puppet/modules/tapicero/templates/tapicero.yaml.erb b/puppet/modules/tapicero/templates/tapicero.yaml.erb new file mode 100644 index 00000000..8e19b22f --- /dev/null +++ b/puppet/modules/tapicero/templates/tapicero.yaml.erb @@ -0,0 +1,42 @@ +# +# Default configuration options for Tapicero +# + +# couch connection configuration +connection: + protocol: "http" + host: "localhost" + port: <%= @couchdb_port %> + username: <%= @couchdb_admin_user %> + password: <%= @couchdb_admin_password %> + prefix : "" + suffix : "" + +# file to store the last processed user record in so we can resume after +# a restart: +seq_file: "/var/lib/leap/tapicero/tapicero.seq" + +# Configure log_file like this if you want to log to a file instead of syslog: +# log_file: "/var/leap/log/tapicero.log" +log_level: info + +# tapicero specific options +options: + # prefix for per user databases: + db_prefix: "user-" + + # security settings to be used for the per user databases + security: + admins: + names: + # We explicitly allow the admin user to access per user databases, even + # though admin access ignores per database security we just do this to be + # explicit about this + - <%= @couchdb_admin_user %> + roles: [] + readers: + names: + - <%= @couchdb_soledad_user %> + - <%= @couchdb_leap_mx_user %> + roles: [] + diff --git a/puppet/modules/tor b/puppet/modules/tor -Subproject a780e84001177f10a86a7bf824589c0553f513a +Subproject dcb6e748864e7dfd3c14f4f2aba4c9120f12b78 diff --git a/puppet/modules/try/manifests/file.pp b/puppet/modules/try/manifests/file.pp index 47a8c269..cd1bb035 100644 --- a/puppet/modules/try/manifests/file.pp +++ b/puppet/modules/try/manifests/file.pp @@ -1,60 +1,112 @@ # -# like built-in type "file", but gets gracefully ignored if the target does not exist or is undefined. +# Works like the built-in type "file", but gets gracefully ignored if the target/source does not exist or is undefined. # -# /bin/true and /usr/bin/test are hardcoded to their paths in debian. +# Also, if the source or target doesn't exist, and the destination is a git repo, then the file is restored from git. +# +# All executable paths are hardcoded to their paths in debian. +# +# known limitations: +# * this is far too noisy +# * $restore does not work for directories +# * only file:// $source is supported +# * $content is not supported, only $target or $source. +# * does not auto-require all the parent directories like 'file' does # - define try::file ( $ensure = undef, $target = undef, + $source = undef, + $owner = undef, + $group = undef, + $recurse = undef, + $purge = undef, + $force = undef, + $mode = undef, $restore = true) { - if $target != undef { - exec { "check_${name}": - command => "/bin/true", - onlyif => "/usr/bin/test -e '${target}'", - loglevel => info; + # dummy exec to propagate requires: + # metaparameter 'require' will get triggered by this dummy exec + # so then we just need to depend on this to capture all requires. + # exec { $name: command => "/bin/true" } + + exec { + "chmod_${name}": + command => "/bin/chmod -R ${mode} '${name}'", + onlyif => "/usr/bin/test $mode", + refreshonly => true, + loglevel => debug; + "chown_${name}": + command => "/bin/chown -R ${owner} '${name}'", + onlyif => "/usr/bin/test $owner", + refreshonly => true, + loglevel => debug; + "chgrp_${name}": + command => "/bin/chgrp -R ${group} '${name}'", + onlyif => "/usr/bin/test $group", + refreshonly => true, + loglevel => debug; + } + + if $target { + exec { "symlink_${name}": + command => "/bin/ln -s ${target} ${name}", + onlyif => "/usr/bin/test -d '${target}'", } - file { "$name": - ensure => $ensure, - target => $target, - require => $require ? { - undef => Exec["check_${name}"], - default => [ $require, Exec["check_${name}"] ] - }, - loglevel => info; + } elsif $source { + if $ensure == 'directory' { + if $purge { + exec { "rsync_${name}": + command => "/usr/bin/rsync -r --delete '${source}/' '${name}'", + onlyif => "/usr/bin/test -d '${source}'", + unless => "/usr/bin/diff -rq '${source}' '${name}'", + notify => [Exec["chmod_${name}"], Exec["chown_${name}"], Exec["chgrp_${name}"]] + } + } else { + exec { "cp_r_${name}": + command => "/bin/cp -r '${source}' '${name}'", + onlyif => "/usr/bin/test -d '${source}'", + unless => "/usr/bin/diff -rq '${source}' '${name}'", + notify => [Exec["chmod_${name}"], Exec["chown_${name}"], Exec["chgrp_${name}"]] + } + } + } else { + exec { "cp_${name}": + command => "/bin/cp --remove-destination '${source}' '${name}'", + onlyif => "/usr/bin/test -e '${source}'", + unless => "/usr/bin/test ! -h '${name}' && /usr/bin/diff -q '${source}' '${name}'", + notify => [Exec["chmod_${name}"], Exec["chown_${name}"], Exec["chgrp_${name}"]] + } } } # - # if the target does not exist (or is undef), and the file happens to be in a git repo, + # if the target/source does not exist (or is undef), and the file happens to be in a git repo, # then restore the file to its original state. # - if $target == undef or $restore { + + if $target { + $target_or_source = $target + } else { + $target_or_source = $source + } + + if ($target_or_source == undef) or $restore { $file_basename = basename($name) $file_dirname = dirname($name) $command = "git rev-parse && unlink '${name}'; git checkout -- '${file_basename}' && chown --reference='${file_dirname}' '${name}'; true" debug($command) - if $target == undef { + if $target_or_source == undef { exec { "restore_${name}": command => $command, cwd => $file_dirname, - require => $require ? { - undef => undef, - default => [ $require ] - }, loglevel => info; } } else { exec { "restore_${name}": - unless => "/usr/bin/test -e '${target}'", + unless => "/usr/bin/test -e '${target_or_source}'", command => $command, cwd => $file_dirname, - require => $require ? { - undef => undef, - default => [ $require ] - }, loglevel => info; } } diff --git a/puppet/modules/vcsrepo b/puppet/modules/vcsrepo -Subproject 4db1120c78763f5244dc6c9d2e0d064a6ef363e +Subproject f92d09226cfddb0c7e5e342dd199d8ea05b497c |