@@ -77,7 +77,7 @@ const internalCertificate = {
7777 . where ( 'id' , certificate . id )
7878 . andWhere ( 'provider' , 'letsencrypt' )
7979 . patch ( {
80- expires_on : certificateModel . raw ( 'FROM_UNIXTIME(' + cert_info . dates . to + ') ')
80+ expires_on : moment ( cert_info . dates . to , 'X' ) . format ( 'YYYY-MM-DD HH:mm:ss ')
8181 } ) ;
8282 } )
8383 . catch ( ( err ) => {
@@ -141,36 +141,60 @@ const internalCertificate = {
141141 } ) ;
142142 } )
143143 . then ( ( in_use_result ) => {
144- // 3. Generate the LE config
145- return internalNginx . generateLetsEncryptRequestConfig ( certificate )
146- . then ( internalNginx . reload )
147- . then ( ( ) => {
144+ // Is CloudFlare, no config needed, so skip 3 and 5.
145+ if ( data . meta . cloudflare_use ) {
146+ return internalNginx . reload ( ) . then ( ( ) => {
148147 // 4. Request cert
149- return internalCertificate . requestLetsEncryptSsl ( certificate ) ;
150- } )
151- . then ( ( ) => {
152- // 5. Remove LE config
153- return internalNginx . deleteLetsEncryptRequestConfig ( certificate ) ;
154- } )
155- . then ( internalNginx . reload )
156- . then ( ( ) => {
157- // 6. Re-instate previously disabled hosts
158- return internalCertificate . enableInUseHosts ( in_use_result ) ;
159- } )
160- . then ( ( ) => {
161- return certificate ;
148+ return internalCertificate . requestLetsEncryptCloudFlareDnsSsl ( certificate , data . meta . cloudflare_token ) ;
162149 } )
163- . catch ( ( err ) => {
164- // In the event of failure, revert things and throw err back
165- return internalNginx . deleteLetsEncryptRequestConfig ( certificate )
166- . then ( ( ) => {
167- return internalCertificate . enableInUseHosts ( in_use_result ) ;
168- } )
169- . then ( internalNginx . reload )
170- . then ( ( ) => {
171- throw err ;
172- } ) ;
173- } ) ;
150+ . then ( internalNginx . reload )
151+ . then ( ( ) => {
152+ // 6. Re-instate previously disabled hosts
153+ return internalCertificate . enableInUseHosts ( in_use_result ) ;
154+ } )
155+ . then ( ( ) => {
156+ return certificate ;
157+ } )
158+ . catch ( ( err ) => {
159+ // In the event of failure, revert things and throw err back
160+ return internalCertificate . enableInUseHosts ( in_use_result )
161+ . then ( internalNginx . reload )
162+ . then ( ( ) => {
163+ throw err ;
164+ } ) ;
165+ } ) ;
166+ } else {
167+ // 3. Generate the LE config
168+ return internalNginx . generateLetsEncryptRequestConfig ( certificate )
169+ . then ( internalNginx . reload )
170+ . then ( ( ) => {
171+ // 4. Request cert
172+ return internalCertificate . requestLetsEncryptSsl ( certificate ) ;
173+ } )
174+ . then ( ( ) => {
175+ // 5. Remove LE config
176+ return internalNginx . deleteLetsEncryptRequestConfig ( certificate ) ;
177+ } )
178+ . then ( internalNginx . reload )
179+ . then ( ( ) => {
180+ // 6. Re-instate previously disabled hosts
181+ return internalCertificate . enableInUseHosts ( in_use_result ) ;
182+ } )
183+ . then ( ( ) => {
184+ return certificate ;
185+ } )
186+ . catch ( ( err ) => {
187+ // In the event of failure, revert things and throw err back
188+ return internalNginx . deleteLetsEncryptRequestConfig ( certificate )
189+ . then ( ( ) => {
190+ return internalCertificate . enableInUseHosts ( in_use_result ) ;
191+ } )
192+ . then ( internalNginx . reload )
193+ . then ( ( ) => {
194+ throw err ;
195+ } ) ;
196+ } ) ;
197+ }
174198 } )
175199 . then ( ( ) => {
176200 // At this point, the letsencrypt cert should exist on disk.
@@ -180,7 +204,7 @@ const internalCertificate = {
180204 return certificateModel
181205 . query ( )
182206 . patchAndFetchById ( certificate . id , {
183- expires_on : certificateModel . raw ( 'FROM_UNIXTIME(' + cert_info . dates . to + ') ')
207+ expires_on : moment ( cert_info . dates . to , 'X' ) . format ( 'YYYY-MM-DD HH:mm:ss ')
184208 } )
185209 . then ( ( saved_row ) => {
186210 // Add cert data for audit log
@@ -558,7 +582,7 @@ const internalCertificate = {
558582 // TODO: This uses a mysql only raw function that won't translate to postgres
559583 return internalCertificate . update ( access , {
560584 id : data . id ,
561- expires_on : certificateModel . raw ( 'FROM_UNIXTIME(' + validations . certificate . dates . to + ') ') ,
585+ expires_on : moment ( validations . certificate . dates . to , 'X' ) . format ( 'YYYY-MM-DD HH:mm:ss ') ,
562586 domain_names : [ validations . certificate . cn ] ,
563587 meta : _ . clone ( row . meta ) // Prevent the update method from changing this value that we'll use later
564588 } )
@@ -733,7 +757,6 @@ const internalCertificate = {
733757 '--agree-tos ' +
734758 '--email "' + certificate . meta . letsencrypt_email + '" ' +
735759 '--preferred-challenges "dns,http" ' +
736- '--webroot ' +
737760 '--domains "' + certificate . domain_names . join ( ',' ) + '" ' +
738761 ( le_staging ? '--staging' : '' ) ;
739762
@@ -748,6 +771,39 @@ const internalCertificate = {
748771 } ) ;
749772 } ,
750773
774+ /**
775+ * @param {Object } certificate the certificate row
776+ * @param {String } apiToken the cloudflare api token
777+ * @returns {Promise }
778+ */
779+ requestLetsEncryptCloudFlareDnsSsl : ( certificate , apiToken ) => {
780+ logger . info ( 'Requesting Let\'sEncrypt certificates via Cloudflare DNS for Cert #' + certificate . id + ': ' + certificate . domain_names . join ( ', ' ) ) ;
781+
782+ let tokenLoc = '~/cloudflare-token' ;
783+ let storeKey = 'echo "dns_cloudflare_api_token = ' + apiToken + '" > ' + tokenLoc ;
784+
785+ let cmd =
786+ storeKey + ' && ' +
787+ certbot_command + ' certonly --non-interactive ' +
788+ '--cert-name "npm-' + certificate . id + '" ' +
789+ '--agree-tos ' +
790+ '--email "' + certificate . meta . letsencrypt_email + '" ' +
791+ '--domains "' + certificate . domain_names . join ( ',' ) + '" ' +
792+ '--dns-cloudflare --dns-cloudflare-credentials ' + tokenLoc +
793+ ( le_staging ? ' --staging' : '' )
794+ + ' && rm ' + tokenLoc ;
795+
796+ if ( debug_mode ) {
797+ logger . info ( 'Command:' , cmd ) ;
798+ }
799+
800+ return utils . exec ( cmd ) . then ( ( result ) => {
801+ logger . info ( result ) ;
802+ return result ;
803+ } ) ;
804+ } ,
805+
806+
751807 /**
752808 * @param {Access } access
753809 * @param {Object } data
@@ -761,15 +817,17 @@ const internalCertificate = {
761817 } )
762818 . then ( ( certificate ) => {
763819 if ( certificate . provider === 'letsencrypt' ) {
764- return internalCertificate . renewLetsEncryptSsl ( certificate )
820+ let renewMethod = certificate . meta . cloudflare_use ? internalCertificate . renewLetsEncryptCloudFlareSsl : internalCertificate . renewLetsEncryptSsl ;
821+
822+ return renewMethod ( certificate )
765823 . then ( ( ) => {
766824 return internalCertificate . getCertificateInfoFromFile ( '/etc/letsencrypt/live/npm-' + certificate . id + '/fullchain.pem' ) ;
767825 } )
768826 . then ( ( cert_info ) => {
769827 return certificateModel
770828 . query ( )
771829 . patchAndFetchById ( certificate . id , {
772- expires_on : certificateModel . raw ( 'FROM_UNIXTIME(' + cert_info . dates . to + ') ')
830+ expires_on : moment ( cert_info . dates . to , 'X' ) . format ( 'YYYY-MM-DD HH:mm:ss ')
773831 } ) ;
774832 } )
775833 . then ( ( updated_certificate ) => {
@@ -815,6 +873,29 @@ const internalCertificate = {
815873 } ) ;
816874 } ,
817875
876+ /**
877+ * @param {Object } certificate the certificate row
878+ * @returns {Promise }
879+ */
880+ renewLetsEncryptCloudFlareSsl : ( certificate ) => {
881+ logger . info ( 'Renewing Let\'sEncrypt certificates for Cert #' + certificate . id + ': ' + certificate . domain_names . join ( ', ' ) ) ;
882+
883+ let cmd = certbot_command + ' renew --non-interactive ' +
884+ '--cert-name "npm-' + certificate . id + '" ' +
885+ '--disable-hook-validation ' +
886+ ( le_staging ? '--staging' : '' ) ;
887+
888+ if ( debug_mode ) {
889+ logger . info ( 'Command:' , cmd ) ;
890+ }
891+
892+ return utils . exec ( cmd )
893+ . then ( ( result ) => {
894+ logger . info ( result ) ;
895+ return result ;
896+ } ) ;
897+ } ,
898+
818899 /**
819900 * @param {Object } certificate the certificate row
820901 * @param {Boolean } [throw_errors]
@@ -824,7 +905,6 @@ const internalCertificate = {
824905 logger . info ( 'Revoking Let\'sEncrypt certificates for Cert #' + certificate . id + ': ' + certificate . domain_names . join ( ', ' ) ) ;
825906
826907 let cmd = certbot_command + ' revoke --non-interactive ' +
827- '--config "' + le_config + '" ' +
828908 '--cert-path "/etc/letsencrypt/live/npm-' + certificate . id + '/fullchain.pem" ' +
829909 '--delete-after-revoke ' +
830910 ( le_staging ? '--staging' : '' ) ;
0 commit comments