1
1
const _ = require ( 'lodash' ) ;
2
2
const fs = require ( 'fs' ) ;
3
+ const https = require ( 'https' ) ;
3
4
const tempWrite = require ( 'temp-write' ) ;
4
5
const moment = require ( 'moment' ) ;
5
6
const logger = require ( '../logger' ) . ssl ;
@@ -15,6 +16,7 @@ const letsencryptConfig = '/etc/letsencrypt.ini';
15
16
const certbotCommand = 'certbot' ;
16
17
const archiver = require ( 'archiver' ) ;
17
18
const path = require ( 'path' ) ;
19
+ const { isArray } = require ( 'lodash' ) ;
18
20
19
21
function omissions ( ) {
20
22
return [ 'is_deleted' ] ;
@@ -1124,6 +1126,94 @@ const internalCertificate = {
1124
1126
} else {
1125
1127
return Promise . resolve ( ) ;
1126
1128
}
1129
+ } ,
1130
+
1131
+ testHttpsChallenge : async ( access , domains ) => {
1132
+ await access . can ( 'certificates:list' ) ;
1133
+
1134
+ if ( ! isArray ( domains ) ) {
1135
+ throw new error . InternalValidationError ( 'Domains must be an array of strings' ) ;
1136
+ }
1137
+ if ( domains . length === 0 ) {
1138
+ throw new error . InternalValidationError ( 'No domains provided' ) ;
1139
+ }
1140
+
1141
+ // Create a test challenge file
1142
+ const testChallengeDir = '/data/letsencrypt-acme-challenge/.well-known/acme-challenge' ;
1143
+ const testChallengeFile = testChallengeDir + '/test-challenge' ;
1144
+ fs . mkdirSync ( testChallengeDir , { recursive : true } ) ;
1145
+ fs . writeFileSync ( testChallengeFile , 'Success' , { encoding : 'utf8' } ) ;
1146
+
1147
+ async function performTestForDomain ( domain ) {
1148
+ logger . info ( 'Testing http challenge for ' + domain ) ;
1149
+ const url = `http://${ domain } /.well-known/acme-challenge/test-challenge` ;
1150
+ const formBody = `method=G&url=${ encodeURI ( url ) } &bodytype=T&requestbody=&headername=User-Agent&headervalue=None&locationid=1&ch=false&cc=false` ;
1151
+ const options = {
1152
+ method : 'POST' ,
1153
+ headers : {
1154
+ 'Content-Type' : 'application/x-www-form-urlencoded' ,
1155
+ 'Content-Length' : Buffer . byteLength ( formBody )
1156
+ }
1157
+ } ;
1158
+
1159
+ const result = await new Promise ( ( resolve ) => {
1160
+
1161
+ const req = https . request ( 'https://www.site24x7.com/tools/restapi-tester' , options , function ( res ) {
1162
+ let responseBody = '' ;
1163
+
1164
+ res . on ( 'data' , ( chunk ) => responseBody = responseBody + chunk ) ;
1165
+ res . on ( 'end' , function ( ) {
1166
+ const parsedBody = JSON . parse ( responseBody + '' ) ;
1167
+ if ( res . statusCode !== 200 ) {
1168
+ logger . warn ( `Failed to test HTTP challenge for domain ${ domain } ` , res ) ;
1169
+ resolve ( undefined ) ;
1170
+ }
1171
+ resolve ( parsedBody ) ;
1172
+ } ) ;
1173
+ } ) ;
1174
+
1175
+ // Make sure to write the request body.
1176
+ req . write ( formBody ) ;
1177
+ req . end ( ) ;
1178
+ req . on ( 'error' , function ( e ) { logger . warn ( `Failed to test HTTP challenge for domain ${ domain } ` , e ) ;
1179
+ resolve ( undefined ) ; } ) ;
1180
+ } ) ;
1181
+
1182
+ if ( ! result ) {
1183
+ // Some error occurred while trying to get the data
1184
+ return 'failed' ;
1185
+ } else if ( `${ result . responsecode } ` === '200' && result . htmlresponse === 'Success' ) {
1186
+ // Server exists and has responded with the correct data
1187
+ return 'ok' ;
1188
+ } else if ( `${ result . responsecode } ` === '200' ) {
1189
+ // Server exists but has responded with wrong data
1190
+ logger . info ( `HTTP challenge test failed for domain ${ domain } because of invalid returned data:` , result . htmlresponse ) ;
1191
+ return 'wrong-data' ;
1192
+ } else if ( `${ result . responsecode } ` === '404' ) {
1193
+ // Server exists but responded with a 404
1194
+ logger . info ( `HTTP challenge test failed for domain ${ domain } because code 404 was returned` ) ;
1195
+ return '404' ;
1196
+ } else if ( `${ result . responsecode } ` === '0' || ( typeof result . reason === 'string' && result . reason . toLowerCase ( ) === 'host unavailable' ) ) {
1197
+ // Server does not exist at domain
1198
+ logger . info ( `HTTP challenge test failed for domain ${ domain } the host was not found` ) ;
1199
+ return 'no-host' ;
1200
+ } else {
1201
+ // Other errors
1202
+ logger . info ( `HTTP challenge test failed for domain ${ domain } because code ${ result . responsecode } was returned` ) ;
1203
+ return `other:${ result . responsecode } ` ;
1204
+ }
1205
+ }
1206
+
1207
+ const results = { } ;
1208
+
1209
+ for ( const domain of domains ) {
1210
+ results [ domain ] = await performTestForDomain ( domain ) ;
1211
+ }
1212
+
1213
+ // Remove the test challenge file
1214
+ fs . unlinkSync ( testChallengeFile ) ;
1215
+
1216
+ return results ;
1127
1217
}
1128
1218
} ;
1129
1219
0 commit comments