3
3
4
4
const fs = require ( 'fs' ) ;
5
5
const http = require ( 'http' ) ;
6
+ const { promisify} = require ( 'util' ) ;
7
+ const chmod = promisify ( fs . chmod ) ;
8
+ const readFile = promisify ( fs . readFile ) ;
9
+ const writeFile = promisify ( fs . writeFile ) ;
6
10
7
11
const certificates = require ( './certificates' ) ;
8
12
const db = require ( './db' ) ;
@@ -11,26 +15,8 @@ const oauth2 = require('./oauth2');
11
15
12
16
const hostname = db . get ( 'hostname' , 'localhost' ) ;
13
17
14
- // Run given tasks in parrallel, and only call `next()` when all have succeeded.
15
- exports . executeInParallel = function ( tasks , next ) {
16
- let complete = 0 ;
17
-
18
- for ( const task of tasks ) {
19
- try {
20
- task ( ( ) => {
21
- complete ++ ;
22
- if ( complete === tasks . length ) {
23
- next ( ) ;
24
- }
25
- } ) ;
26
- } catch ( error ) {
27
- log ( '[fail] boot task' , error ) ;
28
- }
29
- }
30
- } ;
31
-
32
18
// Permanently redirect all HTTP requests to HTTPS.
33
- exports . forwardHttp = function ( next ) {
19
+ exports . forwardHttp = function ( ) {
34
20
const ports = db . get ( 'ports' ) ;
35
21
if ( ! ports . http || ! ports . https ) {
36
22
// Use `make ports` to set up this unprivileged HTTP port.
@@ -55,17 +41,14 @@ exports.forwardHttp = function (next) {
55
41
response . end ( ) ;
56
42
} ) ;
57
43
58
- forwarder . listen ( ports . http , ( ) => {
59
- log ( '[ok] forwarding http:// → https://' ) ;
60
- next ( ) ;
61
- } ) ;
44
+ const listen = promisify ( forwarder . listen ) ;
45
+ return listen ( ports . http ) ;
62
46
} ;
63
47
64
48
// Verify HTTPS certificates and generate new ones if necessary.
65
- exports . ensureHttpsCertificates = function ( next ) {
49
+ exports . ensureHttpsCertificates = async function ( ) {
66
50
if ( db . get ( 'security' ) . forceHttp ) {
67
51
log ( '[warning] skipped https credentials verification' ) ;
68
- next ( ) ;
69
52
return ;
70
53
}
71
54
@@ -79,7 +62,6 @@ exports.ensureHttpsCertificates = function (next) {
79
62
80
63
if ( valid ) {
81
64
log ( '[ok] verified https credentials' ) ;
82
- next ( ) ;
83
65
return ;
84
66
}
85
67
@@ -100,38 +82,34 @@ exports.ensureHttpsCertificates = function (next) {
100
82
}
101
83
102
84
log ( 'requesting new https credentials…' ) ;
103
- certificates . createHTTPSCertificate ( parameters )
104
- . then ( ( { certificate, accountKey } ) => {
105
- https . ca = [ certificate . ca ] ;
85
+ return certificates . createHTTPSCertificate ( parameters )
86
+ . then ( ( { certificate, accountKey} ) => {
87
+ https . ca = [ certificate . ca ] ;
106
88
https . crt = certificate . cert ;
107
89
https . key = certificate . privkey ;
108
90
letsencrypt . key = accountKey ;
109
91
db . save ( ) ;
110
92
log ( '[ok] new https credentials installed' ) ;
111
- next ( ) ;
112
- } )
113
- . catch ( error => {
114
- log ( '[fail] letsencrypt' , error ) ;
115
93
} ) ;
116
94
} ;
117
95
118
96
// Verify Docker TLS certificates, generate new ones if necessary.
119
- exports . ensureDockerTlsCertificates = function ( next ) {
97
+ exports . ensureDockerTlsCertificates = async function ( ) {
120
98
// Read all TLS certificates.
121
99
const tls = db . get ( 'tls' ) ;
122
100
const ca = tls . ca || { } ;
123
101
const client = tls . client || { } ;
124
102
const server = { } ;
125
103
126
104
try {
127
- server . ca = fs . readFileSync ( './docker.ca' , 'utf8' ) ;
128
- server . crt = fs . readFileSync ( './docker.crt' , 'utf8' ) ;
129
- server . key = fs . readFileSync ( './docker.key' , 'utf8' ) ;
105
+ server . ca = await readFile ( './docker.ca' , 'utf8' ) ;
106
+ server . crt = await readFile ( './docker.crt' , 'utf8' ) ;
107
+ server . key = await readFile ( './docker.key' , 'utf8' ) ;
130
108
} catch ( error ) {
131
109
if ( error . code !== 'ENOENT' ) {
132
110
log ( '[fail] could not read docker-tls certificates' , error ) ;
133
- return ;
134
111
}
112
+ throw error ;
135
113
}
136
114
137
115
let caValid = certificates . isValid ( {
@@ -142,42 +120,41 @@ exports.ensureDockerTlsCertificates = function (next) {
142
120
let serverValid = false ;
143
121
144
122
if ( ! caValid ) {
145
- resetAllCertificates ( ) ;
123
+ await resetAllCertificates ( ) ;
146
124
return ;
147
125
}
148
126
149
127
clientValid = certificates . isValid ( {
150
- ca : [ ca . crt ] ,
128
+ ca : [ ca . crt ] ,
151
129
crt : client . crt ,
152
130
key : client . key
153
131
} ) ;
154
132
155
133
serverValid = certificates . isValid ( {
156
- ca : [ ca . crt ] ,
134
+ ca : [ ca . crt ] ,
157
135
crt : server . crt ,
158
136
key : server . key ,
159
137
hostname : hostname
160
138
} ) && ( server . ca . trim ( ) === ca . crt . trim ( ) ) ;
161
139
162
140
if ( caValid && clientValid && serverValid ) {
163
141
log ( '[ok] verified docker-tls credentials' ) ;
164
- next ( ) ;
165
142
return ;
166
143
}
167
144
168
145
if ( ! clientValid ) {
169
- resetClientCertificate ( ) ;
146
+ await resetClientCertificate ( ) ;
170
147
}
171
148
172
149
if ( ! serverValid ) {
173
- resetServerCertificate ( ) ;
150
+ await resetServerCertificate ( ) ;
174
151
}
175
152
176
153
// Task: Reset the TLS certificate authority, then all depending certificates.
177
- function resetAllCertificates ( ) {
154
+ async function resetAllCertificates ( ) {
178
155
const parameters = {
179
156
commonName : 'ca' ,
180
- basicConstraints : { cA : true } ,
157
+ basicConstraints : { cA : true } ,
181
158
keyUsage : {
182
159
keyCertSign : true ,
183
160
digitalSignature : true ,
@@ -186,16 +163,13 @@ exports.ensureDockerTlsCertificates = function (next) {
186
163
} ;
187
164
188
165
log ( 'generating new docker-tls certificate authority…' ) ;
189
- certificates . createTLSCertificate ( parameters ) . then ( ( { crt, key } ) => {
190
- ca . crt = crt ;
191
- ca . key = key ;
192
- tls . ca = ca ;
193
- caValid = true ;
194
- resetClientCertificate ( ) ;
195
- resetServerCertificate ( ) ;
196
- } ) . catch ( error => {
197
- log ( '[fail] tls' , error ) ;
198
- } ) ;
166
+ const { crt, key} = await certificates . createTLSCertificate ( parameters ) ;
167
+ ca . crt = crt ;
168
+ ca . key = key ;
169
+ tls . ca = ca ;
170
+ caValid = true ;
171
+ await resetClientCertificate ( ) ;
172
+ await resetServerCertificate ( ) ;
199
173
}
200
174
201
175
// Task: Reset the TLS client certificate.
@@ -210,103 +184,80 @@ exports.ensureDockerTlsCertificates = function (next) {
210
184
} ;
211
185
212
186
log ( 'generating new docker-tls client certificate…' ) ;
213
- certificates . createTLSCertificate ( parameters ) . then ( ( { crt, key } ) => {
187
+ return certificates . createTLSCertificate ( parameters ) . then ( ( { crt, key} ) => {
214
188
client . crt = crt ;
215
189
client . key = key ;
216
190
tls . client = client ;
217
191
clientValid = true ;
218
- done ( ) ;
219
- } ) . catch ( error => {
220
- log ( '[fail] tls' , error ) ;
221
192
} ) ;
222
193
}
223
194
224
195
// Task: Reset the TLS server certificate.
225
- function resetServerCertificate ( ) {
196
+ async function resetServerCertificate ( ) {
226
197
const parameters = {
227
198
commonName : hostname ,
228
- altNames : [ 'localhost' ] ,
199
+ altNames : [ 'localhost' ] ,
229
200
caCrt : ca . crt ,
230
201
caKey : ca . key
231
202
} ;
232
203
233
204
log ( 'generating new docker-tls server certificate…' ) ;
234
- certificates . createTLSCertificate ( parameters ) . then ( ( { crt, key } ) => {
235
- server . crt = crt ;
236
- server . key = key ;
237
- const filesToWrite = {
238
- './docker.ca' : ca . crt ,
239
- './docker.crt' : server . crt ,
240
- './docker.key' : server . key
241
- } ;
242
-
243
- for ( const file in filesToWrite ) {
244
- const path = file ;
245
- const value = filesToWrite [ path ] ;
246
- fs . writeFile ( path , value , ( error ) => {
247
- if ( error ) {
248
- log ( '[fail] unable to write ' + path , error ) ;
249
- return ;
250
- }
251
-
252
- fs . chmod ( path , 0o600 /* read + write by owner */ , ( error ) => {
253
- if ( error ) {
254
- log ( '[fail] unable to protect ' + path , error ) ;
255
- return ;
256
- }
257
-
258
- delete filesToWrite [ path ] ;
259
- if ( Object . keys ( filesToWrite ) . length === 0 ) {
260
- // FIXME: Can we force the docker daemon to restart here, or to
261
- // switch certificates? Maybe we can do something like this:
262
- // `exec('sudo service docker restart')` ?
263
- log ( '[fail] please manually restart the docker daemon' ) ;
264
- // But continue anyway.
265
- serverValid = true ;
266
- done ( ) ;
267
- }
268
- } ) ;
269
- } ) ;
205
+ const { crt, key} = await certificates . createTLSCertificate ( parameters ) ;
206
+ server . crt = crt ;
207
+ server . key = key ;
208
+ const filesToWrite = {
209
+ './docker.ca' : ca . crt ,
210
+ './docker.crt' : server . crt ,
211
+ './docker.key' : server . key
212
+ } ;
213
+
214
+ for ( const file in filesToWrite ) {
215
+ const path = file ;
216
+ const value = filesToWrite [ path ] ;
217
+ try {
218
+ await writeFile ( path , value ) ;
219
+ } catch ( error ) {
220
+ log ( '[fail] unable to write ' + path , error ) ;
221
+ throw error ;
222
+ }
223
+ try {
224
+ await chmod ( path , 0o600 /* read + write by owner */ ) ;
225
+ } catch ( error ) {
226
+ log ( '[fail] unable to protect ' + path , error ) ;
227
+ throw error ;
270
228
}
271
- } ) . catch ( error => {
272
- log ( '[fail] tls' , error ) ;
273
- } ) ;
274
- }
275
229
276
- // Wait for all required tasks to finish before proceeding.
277
- function done ( ) {
278
- if ( ! caValid || ! clientValid || ! serverValid ) {
279
- // Some tasks are not finished yet. Let's wait.
280
- return ;
230
+ delete filesToWrite [ path ] ;
231
+ if ( Object . keys ( filesToWrite ) . length === 0 ) {
232
+ // FIXME: Can we force the docker daemon to restart here, or to
233
+ // switch certificates? Maybe we can do something like this:
234
+ // `exec('sudo service docker restart')` ?
235
+ log ( '[warning] please manually restart the docker daemon' ) ;
236
+ // But continue anyway.
237
+ serverValid = true ;
238
+ }
281
239
}
282
-
283
- // eslint-disable-next-line no-func-assign
284
- done = null ;
285
- db . save ( ) ;
286
- log ( '[ok] new docker-tls credentials installed' ) ;
287
- next ( ) ;
288
240
}
241
+
242
+ db . save ( ) ;
243
+ log ( '[ok] new docker-tls credentials installed' ) ;
289
244
} ;
290
245
291
246
// Verify OAuth2 client access to a Janitor instance (for cluster hosts).
292
- exports . verifyJanitorOAuth2Access = function ( next ) {
247
+ exports . verifyJanitorOAuth2Access = async function ( ) {
293
248
const parameters = {
294
249
provider : 'janitor' ,
295
250
path : '/api/hosts/' + hostname ,
296
251
serviceRequest : true
297
252
} ;
298
253
299
- oauth2 . request ( parameters ) . then ( ( { body, response } ) => {
300
- log ( '[ok] verified janitor-oauth2 access' ) ;
301
- next ( ) ;
302
- } ) . catch ( error => {
303
- log ( '[fail] janitor-oauth2 access problem' , error ) ;
304
- } ) ;
254
+ await oauth2 . request ( parameters ) ;
255
+ log ( '[ok] verified janitor-oauth2 access' ) ;
305
256
} ;
306
257
307
258
// Provide our Docker TLS client certificates to the Janitor instance.
308
- exports . registerDockerClient = function ( next ) {
309
- const { ca, client } = db . get ( 'tls' ) ;
259
+ exports . registerDockerClient = async function ( ) {
260
+ const { ca, client} = db . get ( 'tls' ) ;
310
261
const parameters = {
311
262
provider : 'janitor' ,
312
263
path : '/api/hosts/' + hostname ,
@@ -320,10 +271,6 @@ exports.registerDockerClient = function (next) {
320
271
serviceRequest : true
321
272
} ;
322
273
323
- oauth2 . request ( parameters ) . then ( ( { body, response } ) => {
324
- log ( '[ok] registered docker-tls credentials' ) ;
325
- next ( ) ;
326
- } ) . catch ( error => {
327
- log ( '[fail] unable to register docker-tls credentials:' , error ) ;
328
- } ) ;
274
+ await oauth2 . request ( parameters ) ;
275
+ log ( '[ok] registered docker-tls credentials' ) ;
329
276
} ;
0 commit comments