1
0
mirror of https://github.com/mail-in-a-box/mailinabox.git synced 2026-03-31 21:17:23 +02:00

Merge branch 'master' into management-memory-usage

This commit is contained in:
yodax
2015-12-26 20:28:22 +01:00
15 changed files with 149 additions and 102 deletions

View File

@@ -0,0 +1,253 @@
# This list is derived from https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2.
# The columns are ISO_3166-1_alpha-2 code, display name, Wikipedia page name.
# The top 21 countries by number of Internet users are grouped first, see
# https://en.wikipedia.org/wiki/List_of_countries_by_number_of_Internet_users.
CN China
IN India
US United States
JP Japan
BR Brazil
RU Russian Federation Russia
DE Germany
NG Nigeria
GB United Kingdom
FR France
MX Mexico
EG Egypt
KR South Korea
VN Vietnam
ID Indonesia
PH Philippines
TR Turkey
IT Italy
PK Pakistan
ES Spain
CA Canada
AD Andorra
AE United Arab Emirates
AF Afghanistan
AG Antigua and Barbuda
AI Anguilla
AL Albania
AM Armenia
AO Angola
AQ Antarctica
AR Argentina
AS American Samoa
AT Austria
AU Australia
AW Aruba
AX Åland Islands
AZ Azerbaijan
BA Bosnia and Herzegovina
BB Barbados
BD Bangladesh
BE Belgium
BF Burkina Faso
BG Bulgaria
BH Bahrain
BI Burundi
BJ Benin
BL Saint Barthélemy
BM Bermuda
BN Brunei
BO Bolivia
BQ Bonaire, Sint Eustatius and Saba Caribbean Netherlands
BS Bahamas The Bahamas
BT Bhutan
BV Bouvet Island
BW Botswana
BY Belarus
BZ Belize
CC Cocos (Keeling) Islands
CD Congo, the Democratic Republic of the Democratic Republic of the Congo
CF Central African Republic
CG Congo Republic of the Congo
CH Switzerland
CI Côte d'Ivoire
CK Cook Islands
CL Chile
CM Cameroon
CO Colombia
CR Costa Rica
CU Cuba
CV Cabo Verde
CW Curaçao
CX Christmas Island
CY Cyprus
CZ Czech Republic
DJ Djibouti
DK Denmark
DM Dominica
DO Dominican Republic
DZ Algeria
EC Ecuador
EE Estonia
EH Western Sahara
ER Eritrea
ET Ethiopia
FI Finland
FJ Fiji
FK Falkland Islands (Malvinas) Falkland Islands
FM Federated States of Micronesia
FO Faroe Islands
GA Gabon
GD Grenada
GE Georgia Georgia (country)
GF French Guiana
GG Guernsey
GH Ghana
GI Gibraltar
GL Greenland
GM Gambia The Gambia
GN Guinea
GP Guadeloupe
GQ Equatorial Guinea
GR Greece
GS South Georgia and the South Sandwich Islands
GT Guatemala
GU Guam
GW Guinea-Bissau
GY Guyana
HK Hong Kong
HM Heard Island and McDonald Islands
HN Honduras
HR Croatia
HT Haiti
HU Hungary
IE Ireland Republic of Ireland
IL Israel
IM Isle of Man
IO British Indian Ocean Territory
IQ Iraq
IR Iran
IS Iceland
JE Jersey
JM Jamaica
JO Jordan
KE Kenya
KG Kyrgyzstan
KH Cambodia
KI Kiribati
KM Comoros
KN Saint Kitts and Nevis
KP North Korea
KW Kuwait
KY Cayman Islands
KZ Kazakhstan
LA Laos
LB Lebanon
LC Saint Lucia
LI Liechtenstein
LK Sri Lanka
LR Liberia
LS Lesotho
LT Lithuania
LU Luxembourg
LV Latvia
LY Libya
MA Morocco
MC Monaco
MD Moldova
ME Montenegro
MF Saint Martin (French part) Collectivity of Saint Martin
MG Madagascar
MH Marshall Islands
MK Macedonia Republic of Macedonia
ML Mali
MM Myanmar
MN Mongolia
MO Macao Macau
MP Northern Mariana Islands
MQ Martinique
MR Mauritania
MS Montserrat
MT Malta
MU Mauritius
MV Maldives
MW Malawi
MY Malaysia
MZ Mozambique
NA Namibia
NC New Caledonia
NE Niger
NF Norfolk Island
NI Nicaragua
NL Netherlands
NO Norway
NP Nepal
NR Nauru
NU Niue
NZ New Zealand
OM Oman
PA Panama
PE Peru
PF French Polynesia
PG Papua New Guinea
PL Poland
PM Saint Pierre and Miquelon
PN Pitcairn Pitcairn Islands
PR Puerto Rico
PS Palestine State of Palestine
PT Portugal
PW Palau
PY Paraguay
QA Qatar
RE Réunion
RO Romania
RS Serbia
RW Rwanda
SA Saudi Arabia
SB Solomon Islands
SC Seychelles
SD Sudan
SE Sweden
SG Singapore
SH Saint Helena, Ascension and Tristan da Cunha
SI Slovenia
SJ Svalbard and Jan Mayen
SK Slovakia
SL Sierra Leone
SM San Marino
SN Senegal
SO Somalia
SR Suriname
SS South Sudan
ST Sao Tome and Principe
SV El Salvador
SX Sint Maarten (Dutch part) Sint Maarten
SY Syria
SZ Swaziland
TC Turks and Caicos Islands
TD Chad
TF French Southern Territories French Southern and Antarctic Lands
TG Togo
TH Thailand
TJ Tajikistan
TK Tokelau
TL Timor-Leste East Timor
TM Turkmenistan
TN Tunisia
TO Tonga
TT Trinidad and Tobago
TV Tuvalu
TW Taiwan
TZ Tanzania
UA Ukraine
UG Uganda
UM United States Minor Outlying Islands
UY Uruguay
UZ Uzbekistan
VA Vatican City
VC Saint Vincent and the Grenadines
VE Venezuela
VG Virgin Islands, British British Virgin Islands
VI Virgin Islands, U.S. United States Virgin Islands
VU Vanuatu
WF Wallis and Futuna
WS Samoa
YE Yemen
YT Mayotte
ZA South Africa
ZM Zambia
ZW Zimbabwe
1 # This list is derived from https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2.
2 # The columns are ISO_3166-1_alpha-2 code, display name, Wikipedia page name.
3 # The top 21 countries by number of Internet users are grouped first, see
4 # https://en.wikipedia.org/wiki/List_of_countries_by_number_of_Internet_users.
5 CN China
6 IN India
7 US United States
8 JP Japan
9 BR Brazil
10 RU Russian Federation Russia
11 DE Germany
12 NG Nigeria
13 GB United Kingdom
14 FR France
15 MX Mexico
16 EG Egypt
17 KR South Korea
18 VN Vietnam
19 ID Indonesia
20 PH Philippines
21 TR Turkey
22 IT Italy
23 PK Pakistan
24 ES Spain
25 CA Canada
26 AD Andorra
27 AE United Arab Emirates
28 AF Afghanistan
29 AG Antigua and Barbuda
30 AI Anguilla
31 AL Albania
32 AM Armenia
33 AO Angola
34 AQ Antarctica
35 AR Argentina
36 AS American Samoa
37 AT Austria
38 AU Australia
39 AW Aruba
40 AX Åland Islands
41 AZ Azerbaijan
42 BA Bosnia and Herzegovina
43 BB Barbados
44 BD Bangladesh
45 BE Belgium
46 BF Burkina Faso
47 BG Bulgaria
48 BH Bahrain
49 BI Burundi
50 BJ Benin
51 BL Saint Barthélemy
52 BM Bermuda
53 BN Brunei
54 BO Bolivia
55 BQ Bonaire, Sint Eustatius and Saba Caribbean Netherlands
56 BS Bahamas The Bahamas
57 BT Bhutan
58 BV Bouvet Island
59 BW Botswana
60 BY Belarus
61 BZ Belize
62 CC Cocos (Keeling) Islands
63 CD Congo, the Democratic Republic of the Democratic Republic of the Congo
64 CF Central African Republic
65 CG Congo Republic of the Congo
66 CH Switzerland
67 CI Côte d'Ivoire
68 CK Cook Islands
69 CL Chile
70 CM Cameroon
71 CO Colombia
72 CR Costa Rica
73 CU Cuba
74 CV Cabo Verde
75 CW Curaçao
76 CX Christmas Island
77 CY Cyprus
78 CZ Czech Republic
79 DJ Djibouti
80 DK Denmark
81 DM Dominica
82 DO Dominican Republic
83 DZ Algeria
84 EC Ecuador
85 EE Estonia
86 EH Western Sahara
87 ER Eritrea
88 ET Ethiopia
89 FI Finland
90 FJ Fiji
91 FK Falkland Islands (Malvinas) Falkland Islands
92 FM Federated States of Micronesia
93 FO Faroe Islands
94 GA Gabon
95 GD Grenada
96 GE Georgia Georgia (country)
97 GF French Guiana
98 GG Guernsey
99 GH Ghana
100 GI Gibraltar
101 GL Greenland
102 GM Gambia The Gambia
103 GN Guinea
104 GP Guadeloupe
105 GQ Equatorial Guinea
106 GR Greece
107 GS South Georgia and the South Sandwich Islands
108 GT Guatemala
109 GU Guam
110 GW Guinea-Bissau
111 GY Guyana
112 HK Hong Kong
113 HM Heard Island and McDonald Islands
114 HN Honduras
115 HR Croatia
116 HT Haiti
117 HU Hungary
118 IE Ireland Republic of Ireland
119 IL Israel
120 IM Isle of Man
121 IO British Indian Ocean Territory
122 IQ Iraq
123 IR Iran
124 IS Iceland
125 JE Jersey
126 JM Jamaica
127 JO Jordan
128 KE Kenya
129 KG Kyrgyzstan
130 KH Cambodia
131 KI Kiribati
132 KM Comoros
133 KN Saint Kitts and Nevis
134 KP North Korea
135 KW Kuwait
136 KY Cayman Islands
137 KZ Kazakhstan
138 LA Laos
139 LB Lebanon
140 LC Saint Lucia
141 LI Liechtenstein
142 LK Sri Lanka
143 LR Liberia
144 LS Lesotho
145 LT Lithuania
146 LU Luxembourg
147 LV Latvia
148 LY Libya
149 MA Morocco
150 MC Monaco
151 MD Moldova
152 ME Montenegro
153 MF Saint Martin (French part) Collectivity of Saint Martin
154 MG Madagascar
155 MH Marshall Islands
156 MK Macedonia Republic of Macedonia
157 ML Mali
158 MM Myanmar
159 MN Mongolia
160 MO Macao Macau
161 MP Northern Mariana Islands
162 MQ Martinique
163 MR Mauritania
164 MS Montserrat
165 MT Malta
166 MU Mauritius
167 MV Maldives
168 MW Malawi
169 MY Malaysia
170 MZ Mozambique
171 NA Namibia
172 NC New Caledonia
173 NE Niger
174 NF Norfolk Island
175 NI Nicaragua
176 NL Netherlands
177 NO Norway
178 NP Nepal
179 NR Nauru
180 NU Niue
181 NZ New Zealand
182 OM Oman
183 PA Panama
184 PE Peru
185 PF French Polynesia
186 PG Papua New Guinea
187 PL Poland
188 PM Saint Pierre and Miquelon
189 PN Pitcairn Pitcairn Islands
190 PR Puerto Rico
191 PS Palestine State of Palestine
192 PT Portugal
193 PW Palau
194 PY Paraguay
195 QA Qatar
196 RE Réunion
197 RO Romania
198 RS Serbia
199 RW Rwanda
200 SA Saudi Arabia
201 SB Solomon Islands
202 SC Seychelles
203 SD Sudan
204 SE Sweden
205 SG Singapore
206 SH Saint Helena, Ascension and Tristan da Cunha
207 SI Slovenia
208 SJ Svalbard and Jan Mayen
209 SK Slovakia
210 SL Sierra Leone
211 SM San Marino
212 SN Senegal
213 SO Somalia
214 SR Suriname
215 SS South Sudan
216 ST Sao Tome and Principe
217 SV El Salvador
218 SX Sint Maarten (Dutch part) Sint Maarten
219 SY Syria
220 SZ Swaziland
221 TC Turks and Caicos Islands
222 TD Chad
223 TF French Southern Territories French Southern and Antarctic Lands
224 TG Togo
225 TH Thailand
226 TJ Tajikistan
227 TK Tokelau
228 TL Timor-Leste East Timor
229 TM Turkmenistan
230 TN Tunisia
231 TO Tonga
232 TT Trinidad and Tobago
233 TV Tuvalu
234 TW Taiwan
235 TZ Tanzania
236 UA Ukraine
237 UG Uganda
238 UM United States Minor Outlying Islands
239 UY Uruguay
240 UZ Uzbekistan
241 VA Vatican City
242 VC Saint Vincent and the Grenadines
243 VE Venezuela
244 VG Virgin Islands, British British Virgin Islands
245 VI Virgin Islands, U.S. United States Virgin Islands
246 VU Vanuatu
247 WF Wallis and Futuna
248 WS Samoa
249 YE Yemen
250 YT Mayotte
251 ZA South Africa
252 ZM Zambia
253 ZW Zimbabwe

View File

@@ -28,6 +28,14 @@ try:
except OSError:
pass
# for generating CSRs we need a list of country codes
csr_country_codes = []
with open(os.path.join(os.path.dirname(me), "csr_country_codes.tsv")) as f:
for line in f:
if line.strip() == "" or line.startswith("#"): continue
code, name = line.strip().split("\t")[0:2]
csr_country_codes.append((code, name))
app = Flask(__name__, template_folder=os.path.abspath(os.path.join(os.path.dirname(me), "templates")))
# Decorator to protect views that require a user with 'admin' privileges.
@@ -101,9 +109,12 @@ def index():
return render_template('index.html',
hostname=env['PRIMARY_HOSTNAME'],
storage_root=env['STORAGE_ROOT'],
no_users_exist=no_users_exist,
no_admins_exist=no_admins_exist,
backup_s3_hosts=backup_s3_hosts,
csr_country_codes=csr_country_codes,
)
@app.route('/me')
@@ -321,7 +332,7 @@ def dns_get_dump():
def ssl_get_csr(domain):
from ssl_certificates import create_csr
ssl_private_key = os.path.join(os.path.join(env["STORAGE_ROOT"], 'ssl', 'ssl_private_key.pem'))
return create_csr(domain, ssl_private_key, env)
return create_csr(domain, ssl_private_key, request.form.get('countrycode', ''), env)
@app.route('/ssl/install', methods=['POST'])
@authorized_personnel_only

8
management/daily_tasks.sh Executable file
View File

@@ -0,0 +1,8 @@
#!/bin/bash
# This script is run daily (at 3am each night).
# Take a backup.
management/backup.py
# Run status checks and email the administrator if anything changed.
management/status_checks.py --show-changes --smtp

View File

@@ -283,26 +283,40 @@ def build_zone(domain, all_domains, additional_records, www_redirect_domains, en
def build_tlsa_record(env):
# A DANE TLSA record in DNS specifies that connections on a port
# must use TLS and the certificate must match a particular certificate.
# must use TLS and the certificate must match a particular criteria.
#
# Thanks to http://blog.huque.com/2012/10/dnssec-and-certificates.html
# for explaining all of this!
# and https://community.letsencrypt.org/t/please-avoid-3-0-1-and-3-0-2-dane-tlsa-records-with-le-certificates/7022
# for explaining all of this! Also see https://tools.ietf.org/html/rfc6698#section-2.1
# and https://github.com/mail-in-a-box/mailinabox/issues/268#issuecomment-167160243.
#
# There are several criteria. We used to use "3 0 1" criteria, which
# meant to pin a leaf (3) certificate (0) with SHA256 hash (1). But
# certificates change, and especially as we move to short-lived certs
# they change often. The TLSA record handily supports the criteria of
# a leaf certificate (3)'s subject public key (1) with SHA256 hash (1).
# The subject public key is the public key portion of the private key
# that generated the CSR that generated the certificate. Since we
# generate a private key once the first time Mail-in-a-Box is set up
# and reuse it for all subsequent certificates, the TLSA record will
# remain valid indefinitely.
# Get the hex SHA256 of the DER-encoded server certificate:
certder = shell("check_output", [
"/usr/bin/openssl",
"x509",
"-in", os.path.join(env["STORAGE_ROOT"], "ssl", "ssl_certificate.pem"),
"-outform", "DER"
],
return_bytes=True)
certhash = hashlib.sha256(certder).hexdigest()
from ssl_certificates import load_cert_chain, load_pem
from cryptography.hazmat.primitives.serialization import Encoding, PublicFormat
fn = os.path.join(env["STORAGE_ROOT"], "ssl", "ssl_certificate.pem")
cert = load_pem(load_cert_chain(fn)[0])
subject_public_key = cert.public_key().public_bytes(Encoding.DER, PublicFormat.SubjectPublicKeyInfo)
# We could have also loaded ssl_private_key.pem and called priv_key.public_key().public_bytes(...)
pk_hash = hashlib.sha256(subject_public_key).hexdigest()
# Specify the TLSA parameters:
# 3: This is the certificate that the client should trust. No CA is needed.
# 0: The whole certificate is matched.
# 1: The certificate is SHA256'd here.
return "3 0 1 " + certhash
# 3: Match the (leaf) certificate. (No CA, no trust path needed.)
# 1: Match its subject public key.
# 1: Use SHA256.
return "3 1 1 " + pk_hash
def build_sshfp_records():
# The SSHFP record is a way for us to embed this server's SSH public

View File

@@ -137,12 +137,12 @@ def get_domain_ssl_files(domain, ssl_certificates, env, allow_missing_cert=False
return cert_info['private-key'], cert_info['certificate'], via
def create_csr(domain, ssl_key, env):
def create_csr(domain, ssl_key, country_code, env):
return shell("check_output", [
"openssl", "req", "-new",
"-key", ssl_key,
"-sha256",
"-subj", "/C=%s/ST=/L=/O=/CN=%s" % (env["CSR_COUNTRY"], domain)])
"-subj", "/C=%s/ST=/L=/O=/CN=%s" % (country_code, domain)])
def install_cert(domain, ssl_cert, ssl_chain, env):
# Write the combined cert+chain to a temporary path and validate that it is OK.
@@ -184,21 +184,22 @@ def install_cert(domain, ssl_cert, ssl_chain, env):
# When updating the cert for PRIMARY_HOSTNAME, symlink it from the system
# certificate path, which is hard-coded for various purposes, and then
# update DNS (because of the DANE TLSA record), postfix, and dovecot,
# which all use the file.
# restart postfix and dovecot.
if domain == env['PRIMARY_HOSTNAME']:
# Update symlink.
system_ssl_certificate = os.path.join(os.path.join(env["STORAGE_ROOT"], 'ssl', 'ssl_certificate.pem'))
os.unlink(system_ssl_certificate)
os.symlink(ssl_certificate, system_ssl_certificate)
# Update DNS & restart postfix and dovecot so they pick up the new file.
from dns_update import do_dns_update
ret.append( do_dns_update(env) )
# Restart postfix and dovecot so they pick up the new file.
shell('check_call', ["/usr/sbin/service", "postfix", "restart"])
shell('check_call', ["/usr/sbin/service", "dovecot", "restart"])
ret.append("mail services restarted")
# The DANE TLSA record will remain valid so long as the private key
# hasn't changed. We don't ever change the private key automatically.
# If the user does it, they must manually update DNS.
# Update the web configuration so nginx picks up the new certificate file.
from web_update import do_web_update
ret.append( do_web_update(env) )

View File

@@ -28,6 +28,15 @@
<p><select id="ssldomain" onchange="show_csr()" class="form-control" style="width: auto"></select></p>
<p>What country are you in? This is required by some SSL certificate providers. You may leave this blank if you know your SSL certificate provider doesn't require it.</p>
<p><select id="sslcc" onchange="show_csr()" class="form-control" style="width: auto">
<option value="">(Select)</option>
{% for code, name in csr_country_codes %}
<option value="{{code}}">{{name}}</option>
{% endfor %}
</select></p>
<div id="csr_info" style="display: none">
<p>You will need to provide the SSL certificate provider this Certificate Signing Request (CSR):</p>
@@ -94,6 +103,7 @@ function show_csr() {
"/ssl/csr/" + $('#ssldomain').val(),
"POST",
{
countrycode: $('#sslcc').val()
},
function(data) {
$('#ssl_csr').text(data);

View File

@@ -32,12 +32,6 @@
<p>You MUST manually copy the encryption password from <tt class="backup-encpassword-file"></tt> to a safe and secure location. You will need this file to decrypt backup files. It is NOT stored in your Amazon S3 bucket.</p>
</div>
</div>
<div class="form-group backup-target-local backup-target-s3">
<label for="min-age" class="col-sm-2 control-label">How many days should backups be kept?</label>
<div class="col-sm-8">
<input type="number" class="form-control" rows="1" id="min-age">
</div>
</div>
<div class="form-group backup-target-s3">
<label for="backup-target-s3-host" class="col-sm-2 control-label">S3 Region</label>
<div class="col-sm-8">
@@ -66,6 +60,13 @@
<input type="text" class="form-control" rows="1" id="backup-target-pass">
</div>
</div>
<div class="form-group backup-target-local backup-target-s3">
<label for="min-age" class="col-sm-2 control-label">Days:</label>
<div class="col-sm-8">
<input type="number" class="form-control" rows="1" id="min-age">
<div class="small" style="margin-top: 2px">This is the <i>minimum</i> number of days backup data is kept for. The box makes an incremental backup, so backup data is often kept much longer. An incremental backup file that is less than this number of days old requires that all previous increments back to the most recent full backup, plus that full backup, remain available.</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button id="set-s3-backup-button" type="submit" class="btn btn-primary">Save</button>