Browse Source

Refactor and standardize SSL/TLS and vhost config

Make SSL/TLS certificate file handling and snakeoil fallback logic
more flexible, no longer expecting you to unconditionally set file
paths so you can just provide contents and allow the module to store
them in a location it considers sane.

Also adjust the vhost template to match the pattern we've been
standardizing on across existing modules (such as our recently
improved mediawiki module), with clearer variable scope lookups and
stronger crypto configuration.

While in the vicinity, also remove a hard-coded default ServerAdmin
E-mail address default to make the module less OpenStack-community
specific.

Change-Id: I238682ac05bdd20ec293b7a16370563763e35249
master
Jeremy Stanley 2 years ago
parent
commit
a72ab07bef
5 changed files with 168 additions and 86 deletions
  1. 103
    18
      manifests/certificates.pp
  2. 6
    9
      manifests/httpd.pp
  3. 1
    1
      manifests/init.pp
  4. 1
    1
      manifests/vars.pp
  5. 57
    57
      templates/vhost.erb

+ 103
- 18
manifests/certificates.pp View File

@@ -26,30 +26,115 @@ class phabricator::certificates (
26 26
   $ssl_key_file_contents   = $phabricator::vars::ssl_key_file_contents,
27 27
 ) {
28 28
 
29
-  if $ssl_cert_file_contents != undef {
30
-    file { $ssl_cert_file:
31
-      owner   => 'root',
32
-      group   => 'root',
33
-      mode    => '0640',
34
-      content => $ssl_cert_file_contents,
29
+  # To use the standard ssl-certs package snakeoil certificate, leave both
30
+  # $ssl_cert_file and $ssl_cert_file_contents empty. To use an existing
31
+  # certificate, specify its path for $ssl_cert_file and leave
32
+  # $ssl_cert_file_contents empty. To manage the certificate with puppet,
33
+  # provide $ssl_cert_file_contents and optionally specify the path to use for
34
+  # it in $ssl_cert_file.
35
+  if ($ssl_cert_file == undef) and ($ssl_cert_file_contents == undef) {
36
+    $cert_file = '/etc/ssl/certs/ssl-cert-snakeoil.pem'
37
+    if ! defined(Package['ssl-cert']) {
38
+      package { 'ssl-cert':
39
+        ensure => present,
40
+      }
41
+    }
42
+  } else {
43
+    if $ssl_cert_file == undef {
44
+      $cert_file = "/etc/ssl/certs/${::fqdn}.pem"
45
+      if ! defined(File['/etc/ssl/certs']) {
46
+        file { '/etc/ssl/certs':
47
+          ensure => directory,
48
+          owner  => 'root',
49
+          group  => 'root',
50
+          mode   => '0755',
51
+          before => File[$cert_file],
52
+        }
53
+      }
54
+    } else {
55
+      $cert_file = $ssl_cert_file
56
+    }
57
+    if $ssl_cert_file_contents != undef {
58
+      file { $cert_file:
59
+        ensure  => present,
60
+        owner   => 'root',
61
+        group   => 'root',
62
+        mode    => '0644',
63
+        content => $ssl_cert_file_contents,
64
+      }
35 65
     }
36 66
   }
37 67
 
38
-  if $ssl_key_file_contents != undef {
39
-    file { $ssl_key_file:
40
-      owner   => 'root',
41
-      group   => 'ssl-cert',
42
-      mode    => '0640',
43
-      content => $ssl_key_file_contents,
68
+  # To avoid using an intermediate certificate chain, leave both
69
+  # $ssl_chain_file and $ssl_chain_file_contents empty. To use an existing
70
+  # chain, specify its path for $ssl_chain_file and leave
71
+  # $ssl_chain_file_contents empty. To manage the chain with puppet, provide
72
+  # $ssl_chain_file_contents and optionally specify the path to use for it in
73
+  # $ssl_chain_file.
74
+  if ($ssl_chain_file == undef) and ($ssl_chain_file_contents == undef) {
75
+    $chain_file = undef
76
+  } else {
77
+    if $ssl_chain_file == undef {
78
+      $chain_file = "/etc/ssl/certs/${::fqdn}_intermediate.pem"
79
+      if ! defined(File['/etc/ssl/certs']) {
80
+        file { '/etc/ssl/certs':
81
+          ensure => directory,
82
+          owner  => 'root',
83
+          group  => 'root',
84
+          mode   => '0755',
85
+          before => File[$chain_file],
86
+        }
87
+      }
88
+    } else {
89
+      $chain_file = $ssl_chain_file
90
+    }
91
+    if $ssl_chain_file_contents != undef {
92
+      file { $chain_file:
93
+        ensure  => present,
94
+        owner   => 'root',
95
+        group   => 'root',
96
+        mode    => '0644',
97
+        content => $ssl_chain_file_contents,
98
+      }
44 99
     }
45 100
   }
46 101
 
47
-  if $ssl_chain_file_contents != undef {
48
-    file { $ssl_chain_file:
49
-      owner   => 'root',
50
-      group   => 'root',
51
-      mode    => '0640',
52
-      content => $ssl_chain_file_contents,
102
+  # To use the standard ssl-certs package snakeoil key, leave both
103
+  # $ssl_key_file and $ssl_key_file_contents empty. To use an existing key,
104
+  # specify its path for $ssl_key_file and leave $ssl_key_file_contents empty.
105
+  # To manage the key with puppet, provide $ssl_key_file_contents and
106
+  # optionally specify the path to use for it in $ssl_key_file.
107
+  if ($ssl_key_file == undef) and ($ssl_key_file_contents == undef) {
108
+    $key_file = '/etc/ssl/private/ssl-cert-snakeoil.key'
109
+    if ! defined(Package['ssl-cert']) {
110
+      package { 'ssl-cert':
111
+        ensure => present,
112
+      }
113
+    }
114
+  } else {
115
+    if $ssl_key_file == undef {
116
+      $key_file = "/etc/ssl/private/${::fqdn}.key"
117
+      if ! defined(File['/etc/ssl/private']) {
118
+        file { '/etc/ssl/private':
119
+          ensure => directory,
120
+          owner  => 'root',
121
+          group  => 'root',
122
+          mode   => '0700',
123
+          before => File[$key_file],
124
+        }
125
+      }
126
+    } else {
127
+      $key_file = $ssl_key_file
128
+    }
129
+    if $ssl_key_file_contents != undef {
130
+      file { $key_file:
131
+        ensure  => present,
132
+        owner   => 'root',
133
+        group   => 'root',
134
+        mode    => '0600',
135
+        content => $ssl_key_file_contents,
136
+      }
53 137
     }
54 138
   }
139
+
55 140
 }

+ 6
- 9
manifests/httpd.pp View File

@@ -17,11 +17,7 @@
17 17
 # Set up the virtual host for phabricator.
18 18
 #
19 19
 class phabricator::httpd (
20
-  $ssl_cert_file      = $phabricator::vars::ssl_cert_file,
21
-  $ssl_chain_file     = $phabricator::vars::ssl_chain_file,
22
-  $ssl_key_file       = $phabricator::vars::ssl_key_file,
23 20
   $httpd_vhost        = $phabricator::vars::httpd_vhost,
24
-  $httpd_admin_email  = $phabricator::vars::httpd_admin_email,
25 21
   $httpd_docroot      = $phabricator::vars::httpd_docroot,
26 22
 ) {
27 23
   include ::httpd
@@ -39,11 +35,12 @@ class phabricator::httpd (
39 35
   # Set up Phabricator as TLS.
40 36
   if defined(Class['phabricator::certificates']) {
41 37
     ::httpd::vhost { $httpd_vhost:
42
-      port     => 443,
43
-      docroot  => $httpd_docroot,
44
-      priority => '50',
45
-      template => 'phabricator/vhost.erb',
46
-      ssl      => true,
38
+      port       => 443, # Is required despite not being used.
39
+      docroot    => $httpd_docroot,
40
+      priority   => '50',
41
+      template   => 'phabricator/vhost.erb',
42
+      ssl        => true,
43
+      vhost_name => $httpd_vhost,
47 44
     }
48 45
   }
49 46
 }

+ 1
- 1
manifests/init.pp View File

@@ -42,7 +42,7 @@ class phabricator (
42 42
 
43 43
   # Httpd config.
44 44
   $httpd_vhost             = $::fqdn,
45
-  $httpd_admin_email       = 'noc@openstack.org',
45
+  $httpd_admin_email       = "webmaster@${::fqdn}",
46 46
 ) {
47 47
 
48 48
   # Set up the shared configuration.

+ 1
- 1
manifests/vars.pp View File

@@ -39,7 +39,7 @@ class phabricator::vars (
39 39
 
40 40
   # Virtual host config.
41 41
   $httpd_vhost             = $::fqdn,
42
-  $httpd_admin_email       = 'noc@openstack.org',
42
+  $httpd_admin_email       = "webmaster@${::fqdn}",
43 43
 ) {
44 44
 
45 45
   # Non-configurable-options (derived)

+ 57
- 57
templates/vhost.erb View File

@@ -1,70 +1,70 @@
1
+# ************************************
2
+# Managed by Puppet
3
+# ************************************
4
+
5
+# Unconditionally redirect all HTTP traffic for this vhost to HTTPS
1 6
 <VirtualHost *:80>
2
-    ServerAdmin <%= @httpd_admin_email %>
3
-    ServerName <%= @httpd_vhost %>
7
+  ServerName <%= @vhost_name %>
8
+  ServerAdmin <%= scope['phabricator::vars::httpd_admin_email'] %>
9
+  RewriteEngine On
10
+  RewriteRule ^/(.*) https://<%= @vhost_name %>/$1 [last,redirect=permanent]
11
+  LogLevel warn
12
+  ErrorLog /var/log/apache2/<%= @vhost_name %>_error.log
13
+  CustomLog /var/log/apache2/<%= @vhost_name %>_access.log combined
14
+  ServerSignature Off
15
+</VirtualHost>
4 16
 
5
-    DocumentRoot /var/www
6
-    <Directory />
7
-        Options FollowSymLinks
8
-        AllowOverride None
9
-    </Directory>
10
-    <Directory /var/www/>
11
-        Options Indexes FollowSymLinks MultiViews
12
-        AllowOverride None
13
-        Order allow,deny
14
-        Allow from all
15
-    </Directory>
17
+<VirtualHost *:443>
16 18
 
17
-    RewriteEngine on
18
-    RewriteCond %{SERVER_PORT} !^443$
19
-    RewriteRule ^/(.*)$ https://<%= @httpd_vhost %>/$1 [L,R]
19
+  ServerName <%= @vhost_name %>
20
+  ServerAdmin <%= scope['phabricator::vars::httpd_admin_email'] %>
20 21
 
21
-    ErrorLog /var/log/apache2/phabricator-error.log
22
+  SSLEngine on
23
+  SSLProtocol All -SSLv2 -SSLv3
24
+  # Once the machine is using something to terminate TLS that supports ECDHE
25
+  # then this should be edited to remove the RSA+AESGCM:RSA+AES so that PFS
26
+  # only is guaranteed.
27
+  SSLCipherSuite ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!AES256:!aNULL:!eNULL:!MD5:!DSS:!PSK:!SRP
28
+  SSLHonorCipherOrder on
29
+  SSLCertificateFile <%= scope['phabricator::certs::cert_file'] %>
30
+  SSLCertificateKeyFile <%= scope['phabricator::certs::key_file'] %>
31
+<% unless [nil, :undef].include?(scope['phabricator::certs::chain_file']) %>
32
+  SSLCertificateChainFile <%= scope['phabricator::certs::chain_file'] %>
33
+<% end %>
22 34
 
23
-    # Possible values include: debug, info, notice, warn, error, crit,
24
-    # alert, emerg.
25
-    LogLevel warn
35
+  DocumentRoot <%= @docroot %>
36
+  <Directory />
37
+    Options FollowSymLinks
38
+    AllowOverride None
39
+  </Directory>
40
+  <Directory <%= @docroot %>>
41
+    Options Indexes FollowSymLinks MultiViews
42
+    AllowOverride None
43
+    Order allow,deny
44
+    Allow from all
45
+    Require all granted
46
+  </Directory>
26 47
 
27
-    CustomLog /var/log/apache2/phabricator-access.log combined
28
-    ServerSignature Off
48
+  <Location <%= scope['phabricator::auth_location'] %> >
49
+    AuthType OpenID
50
+    require valid-user
51
+    AuthOpenIDSingleIdP <%= scope['phabricator::authopenidsingleidp'] %>
52
+  </Location>
29 53
 
30
-</VirtualHost>
31
-<VirtualHost *:443>
32
-    ServerAdmin noc@openstack.org
33
-    ServerName <%= @httpd_vhost %>
54
+  RewriteEngine On
55
+  RewriteRule ^/rsrc/(.*) - [last,qsappend]
56
+  RewriteRule ^/favicon.ico - [last,qsappend]
57
+  RewriteRule ^(.*) /index.php?__path__=$1 [B,last,qsappend]
34 58
 
35
-    SSLEngine on
36
-    SSLProtocol All -SSLv2 -SSLv3
37
-    SSLCertificateFile      <%= @ssl_cert_file %>
38
-    SSLCertificateKeyFile   <%= @ssl_key_file %>
39
-    <%# scope.lookupvar returns nil for an undefined variable in puppet 4 -%>
40
-    <%# scope.lookupvar returns :undef for an undefined variable in puppet 3 -%>
41
-    <% unless ['', nil, :undef].include?(scope.lookupvar("ssl_chain_file")) %>
42
-    SSLCertificateChainFile <%= @ssl_chain_file %>
43
-    <% end %>
59
+  SetEnv PHABRICATOR_ENV production
44 60
 
45
-    DocumentRoot <%= @httpd_docroot %>
46
-    <Directory />
47
-        Options FollowSymLinks
48
-        AllowOverride None
49
-    </Directory>
50
-    <Directory <%= @httpd_docroot %>>
51
-        Options Indexes FollowSymLinks MultiViews
52
-        AllowOverride None
53
-        Order allow,deny
54
-        Allow from all
55
-        Require all granted
56
-    </Directory>
61
+  # Possible values include: debug, info, notice, warn, error, crit,
62
+  # alert, emerg.
63
+  LogLevel warn
57 64
 
58
-    <Location <%= @auth_location %> >
59
-        AuthType OpenID
60
-        require valid-user
61
-        AuthOpenIDSingleIdP <%= @authopenidsingleidp %>
62
-    </Location>
65
+  ErrorLog /var/log/apache2/<%= @vhost_name %>_error.log
66
+  CustomLog /var/log/apache2/<%= @vhost_name %>_access.log combined
63 67
 
64
-    RewriteEngine on
65
-    RewriteRule ^/rsrc/(.*)     -                       [L,QSA]
66
-    RewriteRule ^/favicon.ico   -                       [L,QSA]
67
-    RewriteRule ^(.*)$          /index.php?__path__=$1  [B,L,QSA]
68
+  ServerSignature Off
68 69
 
69
-    SetEnv PHABRICATOR_ENV production
70 70
 </VirtualHost>

Loading…
Cancel
Save