v3.0.0: Webroot Authentication for Let's Encrypt
This commit is contained in:
		
							parent
							
								
									d89e3959fd
								
							
						
					
					
						commit
						d07dffd46e
					
				
							
								
								
									
										33
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										33
									
								
								README.md
									
									
									
									
									
								
							| @ -1,6 +1,6 @@ | |||||||
| # [acme-http-01-{{servicename}}.js](https://git.rootprojects.org/root/acme-http-01-{{servicename}}.js) | a [Root](https://rootprojects.org/) project | # [acme-http-01-webroot.js](https://git.rootprojects.org/root/acme-http-01-webroot.js) | a [Root](https://rootprojects.org/) project | ||||||
| 
 | 
 | ||||||
| {{ Service Title }} Storage + Let's Encrypt for Node.js - ACME http-01 challenges w/ ACME.js and Greenlock.js | Webroot Authentication + Let's Encrypt for Node.js - ACME http-01 challenges w/ ACME.js and Greenlock.js | ||||||
| 
 | 
 | ||||||
| Handles ACME http-01 challenges. Compatible with ACME.js and Greenlock.js. Passes acme-http-01-test. | Handles ACME http-01 challenges. Compatible with ACME.js and Greenlock.js. Passes acme-http-01-test. | ||||||
| 
 | 
 | ||||||
| @ -8,7 +8,10 @@ Handles ACME http-01 challenges. Compatible with ACME.js and Greenlock.js. Passe | |||||||
| 
 | 
 | ||||||
| -   Compatible | -   Compatible | ||||||
|     -   Let’s Encrypt v2.1 / ACME draft 18 (2019) |     -   Let’s Encrypt v2.1 / ACME draft 18 (2019) | ||||||
|     -   {{ Service Title }} API |     -   Works with your web root | ||||||
|  |         -   Apache | ||||||
|  |         -   Nginx | ||||||
|  |         -   Lighttpd | ||||||
|     -   ACME.js, Greenlock.js, and others |     -   ACME.js, Greenlock.js, and others | ||||||
| -   Quality | -   Quality | ||||||
|     -   node v6 compatible VanillaJS |     -   node v6 compatible VanillaJS | ||||||
| @ -18,22 +21,24 @@ Handles ACME http-01 challenges. Compatible with ACME.js and Greenlock.js. Passe | |||||||
| # Install | # Install | ||||||
| 
 | 
 | ||||||
| ```js | ```js | ||||||
| npm install --save acme-http-01-{{servicename}} | npm install --save acme-http-01-webroot | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| {{ Service Title }} Token: |  | ||||||
| 
 |  | ||||||
| -   Login to your account at: {{ Service URL }} |  | ||||||
| -   {{ Instructions to generate token }} |  | ||||||
| 
 |  | ||||||
| # Usage | # Usage | ||||||
| 
 | 
 | ||||||
| First you create an instance with your credentials: | First you create an instance with your credentials: | ||||||
| 
 | 
 | ||||||
| ```js | ```js | ||||||
| var http01 = require('acme-http-01-{{servicename}}').create({ | var http01 = require('acme-http-01-webroot').create({ | ||||||
| 	baseUrl: '{{ api url }}', // default | 	webroot: '~/.local/tmp/acme-challenge' // default | ||||||
| 	token: 'xxxx' | }); | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | Template example: | ||||||
|  | 
 | ||||||
|  | ```js | ||||||
|  | var http01 = require('acme-http-01-webroot').create({ | ||||||
|  | 	webroot: '/srv/www/{domain}/.well-known/acme-challenge' | ||||||
| }); | }); | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| @ -73,7 +78,7 @@ There are only 4 methods: | |||||||
| ```js | ```js | ||||||
| http01 | http01 | ||||||
| 	.set({ | 	.set({ | ||||||
| 		altname: 'foo.example.co.uk', | 		identifier: { value: 'foo.example.co.uk' }, | ||||||
| 		token: 'xxxx' | 		token: 'xxxx' | ||||||
| 		keyAuthorization: 'xxxx.yyyy' | 		keyAuthorization: 'xxxx.yyyy' | ||||||
| 	}) | 	}) | ||||||
| @ -103,7 +108,7 @@ See AUTHORS for contact info. | |||||||
| 
 | 
 | ||||||
| # Legal | # Legal | ||||||
| 
 | 
 | ||||||
| [acme-http-01-{{servicename}}.js](https://git.coolaj86.com/coolaj86/acme-http-01-{{servicename}}.js) | MPL-2.0 | [Terms of Use](https://therootcompany.com/legal/#terms) | [Privacy Policy](https://therootcompany.com/legal/#privacy) | [acme-http-01-webroot.js](https://git.coolaj86.com/coolaj86/acme-http-01-webroot.js) | MPL-2.0 | [Terms of Use](https://therootcompany.com/legal/#terms) | [Privacy Policy](https://therootcompany.com/legal/#privacy) | ||||||
| 
 | 
 | ||||||
| Copyright 2019 AJ ONeal | Copyright 2019 AJ ONeal | ||||||
| Copyright 2019 The Root Group LLC | Copyright 2019 The Root Group LLC | ||||||
|  | |||||||
| @ -1,2 +1,2 @@ | |||||||
| ZONE=example.co.uk | RECORD=example.co.uk | ||||||
| TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx | WEBROOT=/tmp/acme-challenge | ||||||
|  | |||||||
							
								
								
									
										75
									
								
								lib/index.js
									
									
									
									
									
								
							
							
						
						
									
										75
									
								
								lib/index.js
									
									
									
									
									
								
							| @ -1,31 +1,82 @@ | |||||||
| 'use strict'; | 'use strict'; | ||||||
| 
 | 
 | ||||||
| var request; | //var request;
 | ||||||
| var defaults = {}; | var promisify = require('util').promisify; | ||||||
|  | var os = require('os'); | ||||||
|  | var fs = require('fs'); | ||||||
|  | var writeFile = promisify(fs.writeFile); | ||||||
|  | var readFile = promisify(fs.readFile); | ||||||
|  | var unlink = promisify(fs.unlink); | ||||||
|  | var mkdirp = promisify(require('@root/mkdirp')); | ||||||
|  | var path = require('path'); | ||||||
|  | 
 | ||||||
|  | var defaults = { | ||||||
|  | 	webroot: path.join(require('os').tmpdir(), 'acme-challenge') | ||||||
|  | }; | ||||||
| 
 | 
 | ||||||
| module.exports.create = function(config) { | module.exports.create = function(config) { | ||||||
|  | 	var webroot = config.webroot || config.webrootPath || defaults.webroot; | ||||||
|  | 
 | ||||||
|  | 	function tpl(str, ch) { | ||||||
|  | 		return str | ||||||
|  | 			.replace(/\s*{+\s*domain\s*}+\s*/gi, ch.identifier.value) | ||||||
|  | 			.replace(/^~/, os.homedir()); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	return { | 	return { | ||||||
|  | 		// exposed to make testable
 | ||||||
|  | 		_tpl: tpl, | ||||||
|  | 
 | ||||||
| 		init: function(opts) { | 		init: function(opts) { | ||||||
| 			request = opts.request; | 			//request = opts.request;
 | ||||||
| 			return null; | 			return null; | ||||||
| 		}, | 		}, | ||||||
| 
 | 
 | ||||||
| 		set: function(data) { | 		set: function(data) { | ||||||
| 			var ch = data.challenge; | 			// console.log('Add Key Auth URL', data);
 | ||||||
| 			// console.info('Add Key Auth URL', data);
 |  | ||||||
| 			throw Error('setting key authorization not implemented'); |  | ||||||
| 		}, |  | ||||||
| 
 | 
 | ||||||
| 		remove: function(data) { |  | ||||||
| 			var ch = data.challenge; | 			var ch = data.challenge; | ||||||
| 			// console.info('Remove Key Auth URL', data);
 | 			var pathname = tpl(webroot, ch); | ||||||
| 			throw Error('removing key authorization not implemented'); | 
 | ||||||
|  | 			return mkdirp(pathname) | ||||||
|  | 				.then(function() { | ||||||
|  | 					return writeFile( | ||||||
|  | 						path.join(pathname, ch.token), | ||||||
|  | 						ch.keyAuthorization | ||||||
|  | 					); | ||||||
|  | 				}) | ||||||
|  | 				.then(function() { | ||||||
|  | 					return null; | ||||||
|  | 				}); | ||||||
| 		}, | 		}, | ||||||
| 
 | 
 | ||||||
| 		get: function(data) { | 		get: function(data) { | ||||||
|  | 			// console.log('List Key Auth URL', data);
 | ||||||
|  | 
 | ||||||
| 			var ch = data.challenge; | 			var ch = data.challenge; | ||||||
| 			// console.info('List Key Auth URL', data);
 | 			var pathname = tpl(webroot, ch); | ||||||
| 			throw Error('retrieving key authorization not implemented'); | 
 | ||||||
|  | 			return readFile(path.join(pathname, ch.token), 'utf8') | ||||||
|  | 				.then(function(keyAuth) { | ||||||
|  | 					return { keyAuthorization: keyAuth }; | ||||||
|  | 				}) | ||||||
|  | 				.catch(function(err) { | ||||||
|  | 					if ('ENOENT' !== err.code) { | ||||||
|  | 						throw err; | ||||||
|  | 					} | ||||||
|  | 					return null; | ||||||
|  | 				}); | ||||||
|  | 		}, | ||||||
|  | 
 | ||||||
|  | 		remove: function(data) { | ||||||
|  | 			// console.log('Remove Key Auth URL', data);
 | ||||||
|  | 
 | ||||||
|  | 			var ch = data.challenge; | ||||||
|  | 			var pathname = tpl(webroot, ch); | ||||||
|  | 
 | ||||||
|  | 			return unlink(path.join(pathname, ch.token)).then(function() { | ||||||
|  | 				return null; | ||||||
|  | 			}); | ||||||
| 		} | 		} | ||||||
| 	}; | 	}; | ||||||
| }; | }; | ||||||
|  | |||||||
							
								
								
									
										34
									
								
								package-lock.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								package-lock.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							| @ -0,0 +1,34 @@ | |||||||
|  | { | ||||||
|  | 	"name": "acme-http-01-webroot", | ||||||
|  | 	"version": "3.0.0", | ||||||
|  | 	"lockfileVersion": 1, | ||||||
|  | 	"requires": true, | ||||||
|  | 	"dependencies": { | ||||||
|  | 		"@root/mkdirp": { | ||||||
|  | 			"version": "1.0.0", | ||||||
|  | 			"resolved": "https://registry.npmjs.org/@root/mkdirp/-/mkdirp-1.0.0.tgz", | ||||||
|  | 			"integrity": "sha512-hxGAYUx5029VggfG+U9naAhQkoMSXtOeXtbql97m3Hi6/sQSRL/4khKZPyOF6w11glyCOU38WCNLu9nUcSjOfA==" | ||||||
|  | 		}, | ||||||
|  | 		"@root/request": { | ||||||
|  | 			"version": "1.3.11", | ||||||
|  | 			"resolved": "https://registry.npmjs.org/@root/request/-/request-1.3.11.tgz", | ||||||
|  | 			"integrity": "sha512-3a4Eeghcjsfe6zh7EJ+ni1l8OK9Fz2wL1OjP4UCa0YdvtH39kdXB9RGWuzyNv7dZi0+Ffkc83KfH0WbPMiuJFw==", | ||||||
|  | 			"dev": true | ||||||
|  | 		}, | ||||||
|  | 		"acme-challenge-test": { | ||||||
|  | 			"version": "3.3.2", | ||||||
|  | 			"resolved": "https://registry.npmjs.org/acme-challenge-test/-/acme-challenge-test-3.3.2.tgz", | ||||||
|  | 			"integrity": "sha512-0AbMcaON20wpI5vzFDAqwcv2VerY4xIlNCqX0w1xEJUIu/EQtQNmkje+rKNuy2TUl2KBMdIaR6YBbJUdaEiC4w==", | ||||||
|  | 			"dev": true, | ||||||
|  | 			"requires": { | ||||||
|  | 				"@root/request": "^1.3.11" | ||||||
|  | 			} | ||||||
|  | 		}, | ||||||
|  | 		"dotenv": { | ||||||
|  | 			"version": "8.0.0", | ||||||
|  | 			"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.0.0.tgz", | ||||||
|  | 			"integrity": "sha512-30xVGqjLjiUOArT4+M5q9sYdvuR4riM6yK9wMcas9Vbp6zZa+ocC9dp6QoftuhTPhFAiLK/0C5Ni2nou/Bk8lg==", | ||||||
|  | 			"dev": true | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										14
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								package.json
									
									
									
									
									
								
							| @ -1,7 +1,7 @@ | |||||||
| { | { | ||||||
| 	"name": "acme-http-01-{{servicename}}", | 	"name": "acme-http-01-webroot", | ||||||
| 	"version": "0.0.1", | 	"version": "3.0.0", | ||||||
| 	"description": "{{ Service Title }} + Let's Encrypt for Node.js - ACME http-01 challenges w/ ACME.js and Greenlock.js", | 	"description": "Webroot Authentication + Let's Encrypt for Node.js - ACME http-01 challenges w/ ACME.js and Greenlock.js", | ||||||
| 	"main": "index.js", | 	"main": "index.js", | ||||||
| 	"files": [ | 	"files": [ | ||||||
| 		"lib", | 		"lib", | ||||||
| @ -12,10 +12,10 @@ | |||||||
| 	}, | 	}, | ||||||
| 	"repository": { | 	"repository": { | ||||||
| 		"type": "git", | 		"type": "git", | ||||||
| 		"url": "https://git.coolaj86.com/coolaj86/acme-http-01-{{servicename}}.js.git" | 		"url": "https://git.coolaj86.com/coolaj86/acme-http-01-webroot.js.git" | ||||||
| 	}, | 	}, | ||||||
| 	"keywords": [ | 	"keywords": [ | ||||||
| 		"{{servicename}}", | 		"webroot", | ||||||
| 		"storage", | 		"storage", | ||||||
| 		"http-01", | 		"http-01", | ||||||
| 		"letsencrypt", | 		"letsencrypt", | ||||||
| @ -31,5 +31,7 @@ | |||||||
| 		"acme-challenge-test": "^3.3.2", | 		"acme-challenge-test": "^3.3.2", | ||||||
| 		"dotenv": "^8.0.0" | 		"dotenv": "^8.0.0" | ||||||
| 	}, | 	}, | ||||||
| 	"dependencies": {} | 	"dependencies": { | ||||||
|  | 		"@root/mkdirp": "^1.0.0" | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										14
									
								
								test.js
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								test.js
									
									
									
									
									
								
							| @ -24,3 +24,17 @@ tester | |||||||
| 		console.error(e.message); | 		console.error(e.message); | ||||||
| 		console.error(e.stack); | 		console.error(e.stack); | ||||||
| 	}); | 	}); | ||||||
|  | 
 | ||||||
|  | var ch = { identifier: { value: 'foo.example.co.uk' } }; | ||||||
|  | //var ch = { domain: 'foo.example.co.uk' };
 | ||||||
|  | var homeish = challenger._tpl('~/.local/tmp/acme-challenge', ch); | ||||||
|  | console.log(homeish); | ||||||
|  | if ('/' !== homeish[0] || /~/.test(homeish)) { | ||||||
|  | 	throw new Error('Not the expected value for home tmp: ' + homeish); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | var srvish = challenger._tpl('/srv/{domain}/.well-known/acme-challenge', ch); | ||||||
|  | console.log(srvish); | ||||||
|  | if ('/' !== srvish[0] || /~/.test(srvish)) { | ||||||
|  | 	throw new Error('Not the expected value for srv template: ' + srvish); | ||||||
|  | } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user