show challenges
Esse commit está contido em:
		
							pai
							
								
									ec9a2606f6
								
							
						
					
					
						commit
						d646edf045
					
				
							
								
								
									
										11
									
								
								index.html
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								index.html
									
									
									
									
									
								
							| @ -25,10 +25,12 @@ | ||||
| 
 | ||||
|     <!-- Step 3 Set Challanges --> | ||||
|     <form class="js-acme-form js-acme-form-challenges"> | ||||
|       <div class="js-acme-challenges"> | ||||
| 
 | ||||
|       <label>How will you validate your domain?</label> | ||||
|       <label><input class="js-acme-challenge-type" type="radio" value="http-01" checked required> | ||||
|       <label><input class="js-acme-challenge-type" name="acme-challenge-type" type="radio" value="http-01" checked required> | ||||
|         File Upload to HTTP Web Server</label> | ||||
|       <label><input class="js-acme-challenge-type" type="radio" value="dns-01" required> | ||||
|       <label><input class="js-acme-challenge-type" name="acme-challenge-type" type="radio" value="dns-01" required> | ||||
|         TXT Records on DNS Name Server</label> | ||||
| 
 | ||||
|       Verify Domains & Sub-Domains: | ||||
| @ -66,11 +68,12 @@ | ||||
|           </tr> | ||||
|         </tbody> | ||||
|       </table> | ||||
|       </div> | ||||
| 
 | ||||
|       <div class="js-acme-wildcards"> | ||||
|       <div class="js-acme-wildcard"> | ||||
|         Verify Wildcard Domains: | ||||
| 
 | ||||
|         <table class="js-acme-table-wildcards"> | ||||
|         <table class="js-acme-table-wildcard"> | ||||
|           <thead> | ||||
|             <tr> | ||||
|               <th>Hostname</th> | ||||
|  | ||||
							
								
								
									
										181
									
								
								js/app.js
									
									
									
									
									
								
							
							
						
						
									
										181
									
								
								js/app.js
									
									
									
									
									
								
							| @ -18,13 +18,32 @@ | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|   function submitForm(ev) { | ||||
|     steps[i].submit(ev); | ||||
|     i += 1; | ||||
|   } | ||||
|   $qsa('.js-acme-form').forEach(function ($el) { | ||||
|     $el.addEventListener('submit', function (ev) { | ||||
|       ev.preventDefault(); | ||||
|       steps[i].submit(ev); | ||||
|       i += 1; | ||||
|       submitForm(ev); | ||||
|     }); | ||||
|   }); | ||||
|   function updateChallengeType() { | ||||
|     var input = this || $qs('.js-acme-challenge-type'); | ||||
|     console.log('ch type radio:', input.value); | ||||
|     $qs('.js-acme-table-wildcard').hidden = true; | ||||
|     $qs('.js-acme-table-http-01').hidden = true; | ||||
|     $qs('.js-acme-table-dns-01').hidden = true; | ||||
|     if (info.challenges.wildcard) { | ||||
|       $qs('.js-acme-table-wildcard').hidden = false; | ||||
|     } | ||||
|     if (info.challenges[input.value]) { | ||||
|       $qs('.js-acme-table-' + input.value).hidden = false; | ||||
|     } | ||||
|   } | ||||
|   $qsa('.js-acme-challenge-type').forEach(function ($el) { | ||||
|     $el.addEventListener('change', updateChallengeType); | ||||
|   }); | ||||
| 
 | ||||
|   steps[1] = function () { | ||||
|     hideForms(); | ||||
| @ -85,6 +104,7 @@ | ||||
|       console.log('account jwk:'); | ||||
|       console.log(jwk); | ||||
|       delete jwk.key_ops; | ||||
|       info.jwk = jwk; | ||||
|       return BACME.accounts.sign({ | ||||
|         jwk: jwk | ||||
|       , contacts: [ 'mailto:' + email ] | ||||
| @ -117,6 +137,7 @@ | ||||
| 
 | ||||
|       return p2.then(function (_kid) { | ||||
|         kid = _kid; | ||||
|         info.kid = kid; | ||||
|         return BACME.orders.sign({ | ||||
|           jwk: jwk | ||||
|         , identifiers: info.identifiers | ||||
| @ -124,12 +145,95 @@ | ||||
|         }).then(function (signedOrder) { | ||||
|           return BACME.orders.create({ | ||||
|             signedOrder: signedOrder | ||||
|           }).then(function (/*challengeIndexes*/) { | ||||
|             return BACME.challenges.all().then(function (challenges) { | ||||
|               console.log('challenges:'); | ||||
|               console.log(challenges); | ||||
|               // TODO populate challenges in table
 | ||||
|               steps[i](); | ||||
|           }).then(function (order) { | ||||
|             info.finalizeUrl = order.finalize; | ||||
|             return BACME.thumbprint({ jwk: jwk }).then(function (thumbprint) { | ||||
|               return BACME.challenges.all().then(function (claims) { | ||||
|                 console.log('claims:'); | ||||
|                 console.log(claims); | ||||
|                 var obj = { 'dns-01': [], 'http-01': [], 'wildcard': [] }; | ||||
|                 var map = { | ||||
|                   'http-01': '.js-acme-table-http-01' | ||||
|                 , 'dns-01': '.js-acme-table-dns-01' | ||||
|                 , 'wildcard': '.js-acme-table-wildcard' | ||||
|                 } | ||||
|                 var tpls = {}; | ||||
|                 info.challenges = obj; | ||||
|                 Object.keys(map).forEach(function (k) { | ||||
|                   var sel = map[k] + ' tbody'; | ||||
|                   console.log(sel); | ||||
|                   tpls[k] = $qs(sel).innerHTML; | ||||
|                   $qs(map[k] + ' tbody').innerHTML = ''; | ||||
|                 }); | ||||
| 
 | ||||
|                 // TODO make Promise-friendly
 | ||||
|                 return Promise.all(claims.map(function (claim) { | ||||
|                   var hostname = claim.identifier.value; | ||||
|                   return Promise.all(claim.challenges.map(function (c) { | ||||
|                     var keyAuth = BACME.challenges['http-01']({ | ||||
|                       token: c.token | ||||
|                     , thumbprint: thumbprint | ||||
|                     , challengeDomain: hostname | ||||
|                     }); | ||||
|                     return BACME.challenges['dns-01']({ | ||||
|                       keyAuth: keyAuth | ||||
|                     , challengeDomain: hostname | ||||
|                     }).then(function (dnsAuth) { | ||||
|                       var data = { | ||||
|                         type: c.type | ||||
|                       , hostname: hostname | ||||
|                       , url: c.url | ||||
|                       , token: c.token | ||||
|                       , keyAuthorization: keyAuth | ||||
|                       , httpPath: keyAuth.path | ||||
|                       , httpAuth: keyAuth.value | ||||
|                       , dnsType: dnsAuth.type | ||||
|                       , dnsHost: dnsAuth.host | ||||
|                       , dnsAnswer: dnsAuth.answer | ||||
|                       }; | ||||
| 
 | ||||
|                       obj[c.type].push(data); | ||||
|                       console.log(''); | ||||
|                       console.log('CHALLENGE'); | ||||
|                       console.log(claim); | ||||
|                       console.log(c); | ||||
|                       console.log(data); | ||||
|                       console.log(''); | ||||
| 
 | ||||
|                       if (claim.wildcard) { | ||||
|                         obj.wildcard.push(data); | ||||
|                         $qs(map.wildcard).innerHTML += '<tr><td>' + data.hostname + '</td><td>' + data.dnsHost + '</td><td>' + data.dnsAnswer + '</td></tr>'; | ||||
|                       } else { | ||||
|                         obj[data.type].push(data); | ||||
|                         if ('dns-01' === data.type) { | ||||
|                           $qs(map[data.type]).innerHTML += '<tr><td>' + data.hostname + '</td><td>' + data.dnsHost + '</td><td>' + data.dnsAnswer + '</td></tr>'; | ||||
|                         } else if ('http-01' === data.type) { | ||||
|                           $qs(map[data.type]).innerHTML += '<tr><td>' + data.hostname + '</td><td>' + data.httpPath + '</td><td>' + data.httpAuth + '</td></tr>'; | ||||
|                         } else { | ||||
|                           throw new Error('Unexpected type: ' + data.type); | ||||
|                         } | ||||
|                       } | ||||
| 
 | ||||
|                     }); | ||||
| 
 | ||||
|                   })); | ||||
|                 })).then(function () { | ||||
| 
 | ||||
|                   // hide wildcard if no wildcard
 | ||||
|                   // hide http-01 and dns-01 if only wildcard
 | ||||
|                   if (!obj.wildcard.length) { | ||||
|                     $qs('.js-acme-wildcard').hidden = true; | ||||
|                   } | ||||
|                   if (!obj['http-01'].length) { | ||||
|                     $qs('.js-acme-challenges').hidden = true; | ||||
|                   } | ||||
| 
 | ||||
|                   updateChallengeType(); | ||||
| 
 | ||||
|                   steps[i](); | ||||
|                 }); | ||||
| 
 | ||||
|               }); | ||||
|             }); | ||||
|           }); | ||||
|         }); | ||||
| @ -144,11 +248,72 @@ | ||||
|     hideForms(); | ||||
|     $qs('.js-acme-form-challenges').hidden = false; | ||||
|   }; | ||||
|   steps[3].submit = function () { | ||||
|     var chType = $qs('.js-acme-challenge-type').value; | ||||
|     var ps = []; | ||||
| 
 | ||||
|     // do each wildcard, if any
 | ||||
|     // do each challenge, by selected type only
 | ||||
|     [ 'wildcard', chType].forEach(function (typ) { | ||||
|       info.challenges[typ].forEach(function (ch) { | ||||
|         // { jwk, challengeUrl, accountId (kid) }
 | ||||
|         ps.push(BACME.challenges.accept({ | ||||
|           jwk: info.jwk | ||||
|         , challengeUrl: ch.url | ||||
|         , accountId: info.kid | ||||
|         })); | ||||
|       }); | ||||
|     }); | ||||
| 
 | ||||
|     return Promise.all(ps).then(function (results) { | ||||
|       console.log('challenge status:', results); | ||||
|       var polls = results.slice(0); | ||||
|       var allsWell = true; | ||||
| 
 | ||||
|       function checkPolls() { | ||||
|         return new Promise(function (resolve) { | ||||
|           setTimeout(resolve, 1000); | ||||
|         }).then(function () { | ||||
|           return Promise.all(polls.map(function (poll) { | ||||
|             return BACME.challenges.check({ challengePollUrl: poll.url }); | ||||
|           })).then(function () { | ||||
|             polls = polls.filter(function (poll) { | ||||
|               //return 'valid' !== poll.status && 'invalid' !== poll.status;
 | ||||
|               if ('pending' === poll.status) { | ||||
|                 return true; | ||||
|               } | ||||
|               if ('valid' !== poll.status) { | ||||
|                 allsWell = false; | ||||
|                 console.warn('BAD POLL STATUS', poll); | ||||
|               } | ||||
|               // TODO show status in HTML
 | ||||
|             }); | ||||
| 
 | ||||
|             if (polls.length) { | ||||
|               return checkPolls(); | ||||
|             } | ||||
|             return true; | ||||
|           }); | ||||
|         }); | ||||
|       } | ||||
| 
 | ||||
|       return checkPolls().then(function () { | ||||
|         if (allsWell) { | ||||
|           return submitForm(); | ||||
|         } | ||||
|       }); | ||||
|     }); | ||||
|   }; | ||||
| 
 | ||||
|   // spinner
 | ||||
|   steps[4] = function () { | ||||
|     hideForms(); | ||||
|     $qs('.js-acme-form-poll').hidden = false; | ||||
|   } | ||||
|   steps[4].submit = function () { | ||||
|     console.log('Congrats! Auto advancing...'); | ||||
|     return BACME.order | ||||
|   }; | ||||
| 
 | ||||
|   steps[5] = function () { | ||||
|     hideForms(); | ||||
|  | ||||
							
								
								
									
										113
									
								
								js/bacme.js
									
									
									
									
									
								
							
							
						
						
									
										113
									
								
								js/bacme.js
									
									
									
									
									
								
							| @ -289,11 +289,10 @@ BACME.orders = {}; | ||||
| BACME.orders.sign = function (opts) { | ||||
| 	var payload64 = BACME._jsto64({ identifiers: opts.identifiers }); | ||||
| 
 | ||||
| 	var protected64 = BACME._jsto64( | ||||
| 		{ nonce: nonce, alg: 'ES256', url: orderUrl, kid: opts.kid } | ||||
| 	); | ||||
| 
 | ||||
| 	return BACME._importKey(opts.jwk).then(function (abstractKey) { | ||||
|     var protected64 = BACME._jsto64( | ||||
|       { nonce: nonce, alg: abstractKey.meta.alg/*'ES256'*/, url: orderUrl, kid: opts.kid } | ||||
|     ); | ||||
|     console.log('abstractKey:'); | ||||
|     console.log(abstractKey); | ||||
|     return BACME._sign({ | ||||
| @ -378,7 +377,16 @@ BACME.challenges.view = function () { | ||||
| 
 | ||||
|       BACME._logBody(result); | ||||
| 
 | ||||
|       return { token: challenge.token, url: challenge.url, domain: result.identifier.value, challenges: result.challenges }; | ||||
|       return { | ||||
|         challenges: result.challenges | ||||
|       , expires: result.expires | ||||
|       , identifier: result.identifier | ||||
|       , status: result.status | ||||
|       , wildcard: result.wildcard | ||||
|       //, token: challenge.token
 | ||||
|       //, url: challenge.url
 | ||||
|       //, domain: result.identifier.value,
 | ||||
|       }; | ||||
| 		}); | ||||
| 	}); | ||||
| }; | ||||
| @ -420,12 +428,13 @@ BACME.thumbprint = function (opts) { | ||||
| 	}); | ||||
| }; | ||||
| 
 | ||||
| BACME.challenges['http-01'] = function () { | ||||
| // { token, thumbprint, challengeDomain }
 | ||||
| BACME.challenges['http-01'] = function (opts) { | ||||
| 	// The contents of the key authorization file
 | ||||
| 	keyAuth = token + '.' + thumbprint; | ||||
| 	keyAuth = opts.token + '.' + opts.thumbprint; | ||||
| 
 | ||||
| 	// Where the key authorization file goes
 | ||||
| 	httpPath = 'http://' + challengeDomain + '/.well-known/acme-challenge/' + token; | ||||
| 	httpPath = 'http://' + opts.challengeDomain + '/.well-known/acme-challenge/' + opts.token; | ||||
| 
 | ||||
|   console.log("echo '" + keyAuth + "' > '" + httpPath + "'"); | ||||
| 
 | ||||
| @ -435,16 +444,17 @@ BACME.challenges['http-01'] = function () { | ||||
|   }; | ||||
| }; | ||||
| 
 | ||||
| BACME.challenges['dns-01'] = function () { | ||||
| // { keyAuth }
 | ||||
| BACME.challenges['dns-01'] = function (opts) { | ||||
| 	return window.crypto.subtle.digest( | ||||
| 		{ name: "SHA-256", } | ||||
| 	, textEncoder.encode(keyAuth) | ||||
| 	, textEncoder.encode(opts.keyAuth) | ||||
| 	).then(function(hash){ | ||||
| 		dnsAuth = btoa(Array.prototype.map.call(new Uint8Array(hash), function (ch) { | ||||
| 			return String.fromCharCode(ch); | ||||
| 		}).join('')).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/g, ''); | ||||
| 
 | ||||
| 		dnsRecord = '_acme-challenge.' + challengeDomain; | ||||
| 		dnsRecord = '_acme-challenge.' + opts.challengeDomain; | ||||
| 
 | ||||
| 		console.log('DNS TXT Auth:'); | ||||
| 		// The name of the record
 | ||||
| @ -462,55 +472,48 @@ BACME.challenges['dns-01'] = function () { | ||||
| 
 | ||||
| var challengePollUrl; | ||||
| 
 | ||||
| BACME.challenges.accept = function () { | ||||
| // { jwk, challengeUrl, accountId (kid) }
 | ||||
| BACME.challenges.accept = function (opts) { | ||||
|   var payload64 = BACME._jsto64( | ||||
| 		{} | ||||
| 	); | ||||
| 
 | ||||
| 	var protected64 = BACME._jsto64( | ||||
| 		{ nonce: nonce, alg: 'ES256', url: challengeUrl, kid: accountId } | ||||
| 	); | ||||
| 
 | ||||
| 	nonce = null; | ||||
| 	return window.crypto.subtle.sign( | ||||
| 		{ name: "ECDSA", hash: { name: "SHA-256" } } | ||||
| 	, accountKeypair.privateKey | ||||
| 	, textEncoder.encode(protected64 + '.' + payload64) | ||||
| 	).then(function (signature) { | ||||
| 
 | ||||
| 		var sig64 = btoa(Array.prototype.map.call(new Uint8Array(signature), function (ch) { | ||||
| 			return String.fromCharCode(ch); | ||||
| 		}).join('')).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/g, ''); | ||||
| 
 | ||||
| 		var body = { | ||||
| 			protected: protected64 | ||||
| 		, payload: payload64 | ||||
| 		, signature: sig64 | ||||
| 		}; | ||||
|   return BACME._import(opts.jwk).then(function (abstractKey) { | ||||
|     var protected64 = BACME._jsto64( | ||||
|       { nonce: nonce, alg: abstractKey.meta.alg/*'ES256'*/, url: opts.challengeUrl, kid: opts.accountId } | ||||
|     ); | ||||
| 		return BACME._sign({ | ||||
|       abstractKey: abstractKey | ||||
|     , payload64: payload64 | ||||
|     , protected64: protected64 | ||||
|     }); | ||||
|   }).then(function (signedAccept) { | ||||
| 
 | ||||
| 		return window.fetch( | ||||
| 			challengeUrl | ||||
| 			opts.challengeUrl | ||||
| 		, { mode: 'cors' | ||||
| 			, method: 'POST' | ||||
| 			, headers: { 'Content-Type': 'application/jose+json' } | ||||
| 			, body: JSON.stringify(body) | ||||
| 			, body: JSON.stringify(signedAccept) | ||||
| 			} | ||||
| 		).then(function (resp) { | ||||
|       BACME._logHeaders(resp); | ||||
| 			nonce = resp.headers.get('replay-nonce'); | ||||
| 
 | ||||
| 			return resp.json().then(function (reply) { | ||||
| 				challengePollUrl = reply.url; | ||||
|         challengePollUrl = reply.url; | ||||
| 
 | ||||
| 				console.log('Challenge ACK:'); | ||||
| 				console.log(JSON.stringify(reply)); | ||||
|         return reply; | ||||
| 			}); | ||||
| 		}); | ||||
| 	}); | ||||
| }; | ||||
| 
 | ||||
| BACME.challenges.check = function () { | ||||
| 	return window.fetch(challengePollUrl, { mode: 'cors' }).then(function (resp) { | ||||
| BACME.challenges.check = function (opts) { | ||||
| 	return window.fetch(opts.challengePollUrl, { mode: 'cors' }).then(function (resp) { | ||||
|     BACME._logHeaders(resp); | ||||
| 		nonce = resp.headers.get('replay-nonce'); | ||||
| 
 | ||||
| @ -558,38 +561,30 @@ BACME.orders.generateCsr = function (keypair, domains) { | ||||
| 
 | ||||
| var certificateUrl; | ||||
| 
 | ||||
| BACME.orders.finalize = function () { | ||||
| // { csr, jwk, finalizeUrl, accountId }
 | ||||
| BACME.orders.finalize = function (opts) { | ||||
| 	var payload64 = BACME._jsto64( | ||||
| 		{ csr: csr } | ||||
| 	); | ||||
| 
 | ||||
| 	var protected64 = BACME._jsto64( | ||||
| 		{ nonce: nonce, alg: 'ES256', url: finalizeUrl, kid: accountId } | ||||
| 		{ csr: opts.csr } | ||||
| 	); | ||||
| 
 | ||||
| 	nonce = null; | ||||
| 	return window.crypto.subtle.sign( | ||||
| 		{ name: "ECDSA", hash: { name: "SHA-256" } } | ||||
| 	, accountKeypair.privateKey | ||||
| 	, textEncoder.encode(protected64 + '.' + payload64) | ||||
| 	).then(function (signature) { | ||||
| 
 | ||||
| 		var sig64 = btoa(Array.prototype.map.call(new Uint8Array(signature), function (ch) { | ||||
| 			return String.fromCharCode(ch); | ||||
| 		}).join('')).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/g, ''); | ||||
| 
 | ||||
| 		var body = { | ||||
| 			protected: protected64 | ||||
| 		, payload: payload64 | ||||
| 		, signature: sig64 | ||||
| 		}; | ||||
|   return BACME._import(opts.jwk).then(function (abstractKey) { | ||||
|     var protected64 = BACME._jsto64( | ||||
|       { nonce: nonce, alg: abstractKey.meta.alg/*'ES256'*/, url: opts.finalizeUrl, kid: opts.accountId } | ||||
|     ); | ||||
| 		return BACME._sign({ | ||||
|       abstractKey: abstractKey | ||||
|     , payload64: payload64 | ||||
|     , protected64: protected64 | ||||
|     }); | ||||
|   }).then(function (signedFinal) { | ||||
| 
 | ||||
| 		return window.fetch( | ||||
| 			finalizeUrl | ||||
| 		, { mode: 'cors' | ||||
| 			, method: 'POST' | ||||
| 			, headers: { 'Content-Type': 'application/jose+json' } | ||||
| 			, body: JSON.stringify(body) | ||||
| 			, body: JSON.stringify(signedFinal) | ||||
| 			} | ||||
| 		).then(function (resp) { | ||||
|       BACME._logHeaders(resp); | ||||
| @ -598,6 +593,8 @@ BACME.orders.finalize = function () { | ||||
| 			return resp.json().then(function (reply) { | ||||
| 				certificateUrl = reply.certificate; | ||||
|         BACME._logBody(reply); | ||||
| 
 | ||||
|         return reply; | ||||
| 			}); | ||||
| 		}); | ||||
| 	}); | ||||
|  | ||||
		Carregando…
	
	
			
			x
			
			
		
	
		Referência em uma nova issue
	
	Block a user