1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
|
class profile::apache {
class { 'apache':
root_directory_secured => true,
root_directory_options => ["All"],
default_mods => false,
default_vhost => false,
user => "http",
group => "http",
log_formats => {
combined => '%v %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %p',
common => '%h %l %u %t \"%r\" %>s %b',
}
}
::apache::custom_config { 'log_config.conf':
content => 'CustomLog "/var/log/httpd/access_log" combined',
filename => 'log_config.conf'
}
::apache::custom_config { 'protocols.conf':
content => 'Protocols h2 http/1.1',
filename => 'protocols.conf'
}
::apache::custom_config { 'document_root.conf':
source => "puppet:///modules/profile/apache/document_root.conf",
filename => "document_root.conf"
}
::apache::custom_config { 'immae.conf':
source => "puppet:///modules/profile/apache/immae.conf",
filename => 'immae.conf'
}
::apache::custom_config { 'letsencrypt.conf':
source => "puppet:///modules/profile/apache/letsencrypt.conf",
filename => 'letsencrypt.conf'
}
$apache_vhost_default = {
no_proxy_uris => [
"/maintenance_immae.html",
"/googleb6d69446ff4ca3e5.html",
"/.well-known/acme-challenge"
],
no_proxy_uris_match => [
'^/licen[cs]es?_et_tip(ping)?$',
'^/licen[cs]es?_and_tip(ping)?$',
'^/licen[cs]es?$',
'^/tip(ping)?$',
]
}
exec { 'Start-apache':
command => "/usr/bin/systemctl start httpd",
before => Class["::letsencrypt"],
unless => "/usr/bin/systemctl is-active httpd",
}
$letsencrypt_certonly_default = {
plugin => "webroot",
webroot_paths => ["/srv/http/"],
notify => Class['Apache::Service'],
require => [Exec['Start-apache'],Apache::Vhost["redirect_no_ssl"],Apache::Custom_config["letsencrypt.conf"]],
manage_cron => true,
}
class { '::letsencrypt':
install_method => "package",
package_name => "certbot",
package_command => "certbot",
email => lookup('letsencrypt::email'),
}
$real_hostname = lookup("base_installation::real_hostname", { "default_value" => undef })
unless empty($real_hostname) {
if (lookup("letsencrypt::try_for_real_hostname", { "default_value" => true })) {
letsencrypt::certonly { $real_hostname:
before => Apache::Vhost["default_ssl"];
default: * => $::profile::apache::letsencrypt_certonly_default;
}
$ssl_cert = "/etc/letsencrypt/live/$real_hostname/cert.pem"
$ssl_key = "/etc/letsencrypt/live/$real_hostname/privkey.pem"
$ssl_chain = "/etc/letsencrypt/live/$real_hostname/chain.pem"
} else {
ssl::self_signed_certificate { $real_hostname:
common_name => $real_hostname,
country => "FR",
days => "3650",
organization => "Immae",
directory => "/etc/httpd/conf/ssl",
before => Apache::Vhost["default_ssl"],
}
$ssl_key = "/etc/httpd/conf/ssl/$real_hostname.key"
$ssl_cert = "/etc/httpd/conf/ssl/$real_hostname.crt"
$ssl_chain = undef
}
apache::vhost { "default_ssl":
port => '443',
docroot => '/srv/http',
servername => $real_hostname,
directoryindex => 'index.htm index.html',
ssl => true,
ssl_key => $ssl_key,
ssl_cert => $ssl_cert,
ssl_chain => $ssl_chain,
priority => 0;
default: * => $::profile::apache::apache_vhost_default;
}
}
lookup("letsencrypt::hosts", { "default_value" => [] }).each |$host| {
if ($host != $real_hostname) { # Done above already
letsencrypt::certonly { $host: ;
default: * => $letsencrypt_certonly_default;
}
}
}
apache::vhost { "redirect_no_ssl":
port => '80',
error_log => false,
log_level => undef,
access_log => false,
docroot => false,
servername => "",
serveraliases => "*",
priority => 99,
rewrites => [
{
rewrite_cond => '"%{REQUEST_URI}" "!^/\.well-known"',
rewrite_rule => '^(.+) https://%{HTTP_HOST}$1 [R=301]'
}
]
}
class { 'apache::mod::ssl':
ssl_protocol => [ 'all', '-SSLv3' ],
# Given by
# https://mozilla.github.io/server-side-tls/ssl-config-generator/
ssl_cipher => "ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS",
# FIXME: need SSLSessionTickets off
ssl_stapling => true,
ssl_stapling_return_errors => false,
# FIXME: SSLStaplingResponderTimeout 5
ssl_ca => '/etc/ssl/certs/ca-certificates.crt',
}
class { 'apache::mod::alias': }
class { 'apache::mod::autoindex': }
# Included by ssl
# class { 'apache::mod::mime': }
class { 'apache::mod::deflate': }
class { 'apache::mod::rewrite': }
class { 'apache::mod::dir':
indexes => ["index.html"]
}
file { [
"/srv/http",
"/srv/http/.well-known"]:
ensure => "directory",
mode => "0755",
owner => "root",
group => "root",
}
file { "/srv/http/index.html":
mode => "0644",
owner => "root",
group => "root",
source => "puppet:///modules/profile/apache/index.html",
}
file { "/srv/http/maintenance_immae.html":
mode => "0644",
owner => "root",
group => "root",
source => "puppet:///modules/profile/apache/maintenance_immae.html",
}
file { "/srv/http/googleb6d69446ff4ca3e5.html":
mode => "0644",
owner => "root",
group => "root",
source => "puppet:///modules/profile/apache/googleb6d69446ff4ca3e5.html",
}
}
|