Skip to content

Commit d092d4b

Browse files
author
Jamie Curnow
committed
Certificate importer
1 parent c7260bc commit d092d4b

File tree

1 file changed

+157
-4
lines changed

1 file changed

+157
-4
lines changed

src/backend/importer.js

Lines changed: 157 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,15 @@ const internalDeadHost = require('./internal/dead-host');
1111
const internalNginx = require('./internal/nginx');
1212
const internalAccessList = require('./internal/access-list');
1313
const internalStream = require('./internal/stream');
14+
const internalCertificate = require('./internal/certificate');
1415

1516
const accessListModel = require('./models/access_list');
1617
const accessListAuthModel = require('./models/access_list_auth');
1718
const proxyHostModel = require('./models/proxy_host');
1819
const redirectionHostModel = require('./models/redirection_host');
1920
const deadHostModel = require('./models/dead_host');
2021
const streamModel = require('./models/stream');
22+
const certificateModel = require('./models/certificate');
2123

2224
module.exports = function () {
2325

@@ -126,9 +128,156 @@ module.exports = function () {
126128
// - /etc/letsencrypt/renewal Modify filenames and file content
127129

128130
return new Promise((resolve, reject) => {
129-
// TODO
130-
resolve();
131-
});
131+
// 1. List all folders in `archive`
132+
// 2. Create certificates from those folders, rename them, add to map
133+
// 3.
134+
135+
try {
136+
resolve(fs.readdirSync('/etc/letsencrypt/archive'));
137+
} catch (err) {
138+
reject(err);
139+
}
140+
})
141+
.then(archive_dirs => {
142+
return new Promise((resolve, reject) => {
143+
batchflow(archive_dirs).sequential()
144+
.each((i, archive_dir_name, next) => {
145+
importCertificate(access, archive_dir_name)
146+
.then(() => {
147+
next();
148+
})
149+
.catch(err => {
150+
next(err);
151+
});
152+
})
153+
.end(results => {
154+
resolve(results);
155+
});
156+
});
157+
158+
});
159+
};
160+
161+
/**
162+
* @param {Access} access
163+
* @param {String} archive_dir_name
164+
* @returns {Promise}
165+
*/
166+
const importCertificate = function (access, archive_dir_name) {
167+
logger.info('Importing Certificate: ' + archive_dir_name);
168+
169+
let full_archive_path = '/etc/letsencrypt/archive/' + archive_dir_name;
170+
let full_live_path = '/etc/letsencrypt/live/' + archive_dir_name;
171+
172+
let new_archive_path = '/etc/letsencrypt/archive/';
173+
let new_live_path = '/etc/letsencrypt/live/';
174+
175+
// 1. Create certificate row to get the ID
176+
return certificateModel
177+
.query()
178+
.insertAndFetch({
179+
owner_user_id: 1,
180+
provider: 'letsencrypt',
181+
nice_name: archive_dir_name,
182+
domain_names: [archive_dir_name]
183+
})
184+
.then(certificate => {
185+
certificate_map[archive_dir_name] = certificate.id;
186+
187+
// 2. rename archive folder name
188+
new_archive_path = new_archive_path + 'npm-' + certificate.id;
189+
//logger.debug('Renaming archive folder:', full_archive_path, '->', new_archive_path);
190+
191+
fs.renameSync(full_archive_path, new_archive_path);
192+
193+
return certificate;
194+
})
195+
.then(certificate => {
196+
// 3. rename live folder name
197+
new_live_path = new_live_path + 'npm-' + certificate.id;
198+
199+
//logger.debug('Renaming live folder:', full_live_path, '->', new_live_path);
200+
201+
fs.renameSync(full_live_path, new_live_path);
202+
203+
// and also update the symlinks in this folder:
204+
process.chdir(new_live_path);
205+
let version = getCertificateVersion(new_archive_path);
206+
let names = [
207+
['cert.pem', 'cert' + version + '.pem'],
208+
['chain.pem', 'chain' + version + '.pem'],
209+
['fullchain.pem', 'fullchain' + version + '.pem'],
210+
['privkey.pem', 'privkey' + version + '.pem']
211+
];
212+
213+
names.map(function (name) {
214+
//logger.debug('Live Link:', name);
215+
216+
// remove symlink
217+
try {
218+
fs.unlinkSync(new_live_path + '/' + name[0]);
219+
} catch (err) {
220+
// do nothing
221+
logger.error(err);
222+
}
223+
224+
//logger.debug('Creating Link:', '../../archive/npm-' + certificate.id + '/' + name[1]);
225+
// create new symlink
226+
fs.symlinkSync('../../archive/npm-' + certificate.id + '/' + name[1], name[0]);
227+
});
228+
229+
return certificate;
230+
})
231+
.then(certificate => {
232+
// 4. rename and update renewal config file
233+
let config_file = '/etc/letsencrypt/renewal/' + archive_dir_name + '.conf';
234+
235+
return utils.exec('sed -i \'s/\\/config/\\/data/g\' ' + config_file)
236+
.then(() => {
237+
let escaped = archive_dir_name.split('.').join('\\.');
238+
return utils.exec('sed -i \'s/\\/' + escaped + '/\\/npm-' + certificate.id + '/g\' ' + config_file);
239+
})
240+
.then(() => {
241+
//rename config file
242+
fs.renameSync(config_file, '/etc/letsencrypt/renewal/npm-' + certificate.id + '.conf');
243+
return certificate;
244+
});
245+
})
246+
.then(certificate => {
247+
// 5. read the cert info back in to the db
248+
return internalCertificate.getCertificateInfoFromFile(new_live_path + '/fullchain.pem')
249+
.then(cert_info => {
250+
return certificateModel
251+
.query()
252+
.patchAndFetchById(certificate.id, {
253+
expires_on: certificateModel.raw('FROM_UNIXTIME(' + cert_info.dates.to + ')')
254+
});
255+
});
256+
});
257+
};
258+
259+
/**
260+
* @param {String} archive_path
261+
* @returns {Integer}
262+
*/
263+
const getCertificateVersion = function (archive_path) {
264+
let version = 1;
265+
266+
try {
267+
let files = fs.readdirSync(archive_path);
268+
269+
files.map(function (file) {
270+
let res = file.match(/fullchain([0-9])+?\.pem/im);
271+
if (res && parseInt(res[1], 10) > version) {
272+
version = parseInt(res[1], 10);
273+
}
274+
});
275+
276+
} catch (err) {
277+
// do nothing
278+
}
279+
280+
return version;
132281
};
133282

134283
/**
@@ -388,7 +537,11 @@ module.exports = function () {
388537
})
389538
.then(() => {
390539
// Write the /config/v2-imported file so we don't import again
391-
// TODO
540+
fs.writeFile('/config/v2-imported', 'true', function(err) {
541+
if (err) {
542+
logger.err(err);
543+
}
544+
});
392545
});
393546
})
394547
);

0 commit comments

Comments
 (0)