@@ -11,13 +11,15 @@ const internalDeadHost = require('./internal/dead-host');
1111const internalNginx = require ( './internal/nginx' ) ;
1212const internalAccessList = require ( './internal/access-list' ) ;
1313const internalStream = require ( './internal/stream' ) ;
14+ const internalCertificate = require ( './internal/certificate' ) ;
1415
1516const accessListModel = require ( './models/access_list' ) ;
1617const accessListAuthModel = require ( './models/access_list_auth' ) ;
1718const proxyHostModel = require ( './models/proxy_host' ) ;
1819const redirectionHostModel = require ( './models/redirection_host' ) ;
1920const deadHostModel = require ( './models/dead_host' ) ;
2021const streamModel = require ( './models/stream' ) ;
22+ const certificateModel = require ( './models/certificate' ) ;
2123
2224module . 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 ( / f u l l c h a i n ( [ 0 - 9 ] ) + ?\. p e m / 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