add template, implement auth and zones
This commit is contained in:
		
							parent
							
								
									3e67322d69
								
							
						
					
					
						commit
						22c1e761e0
					
				
							
								
								
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@ -1,3 +1,7 @@
 | 
				
			|||||||
 | 
					*.json
 | 
				
			||||||
 | 
					service_account.json
 | 
				
			||||||
 | 
					credentials.json
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# ---> Node
 | 
					# ---> Node
 | 
				
			||||||
# Logs
 | 
					# Logs
 | 
				
			||||||
logs
 | 
					logs
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										28
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								README.md
									
									
									
									
									
								
							@ -1,3 +1,29 @@
 | 
				
			|||||||
# acme-dns-01-googlecloud.js
 | 
					# acme-dns-01-googlecloud.js
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Google Cloud DNS for Let's Encrypt / ACME dns-01 challenges with ACME.js and Greenlock.js
 | 
					Google Domains + Let's Encrypt for Node.js - ACME dns-01 challenges w/ ACME.js and Greenlock.js
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In Progress. Would love help. Please contact @coolaj86 on Keybase.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-   [x] zones
 | 
				
			||||||
 | 
					-   [ ] set
 | 
				
			||||||
 | 
					-   [ ] get
 | 
				
			||||||
 | 
					-   [ ] remove
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Implementation Details
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-   https://cloud.google.com/dns/docs/reference/v1/
 | 
				
			||||||
 | 
					-   https://cloud.google.com/service-usage/docs/getting-started#api
 | 
				
			||||||
 | 
					-   https://github.com/google/oauth2l
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Usage
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					First you create an instance with your credentials:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```js
 | 
				
			||||||
 | 
					var dns01 = require('acme-dns-01-googlecloud').create({
 | 
				
			||||||
 | 
						baseUrl: 'https://www.googleapis.com/dns/v1/', // default
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // contains private_key, private_key_id, project_id, and client_email
 | 
				
			||||||
 | 
						serviceAccountPath: __dirname + '/service_account.json'
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										3
									
								
								example.env
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								example.env
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					# NOT credentials.json
 | 
				
			||||||
 | 
					GOOGLE_APPLICATION_CREDENTIALS=/Users/me/service_account.json
 | 
				
			||||||
 | 
					ZONE=example.co.uk
 | 
				
			||||||
							
								
								
									
										3
									
								
								index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								index.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = require('./lib/index.js');
 | 
				
			||||||
							
								
								
									
										36
									
								
								lib/auth.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								lib/auth.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,36 @@
 | 
				
			|||||||
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var Keypairs = require('keypairs');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports.getToken = function(serviceAccount) {
 | 
				
			||||||
 | 
						var jwt = '';
 | 
				
			||||||
 | 
						var exp = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (exp - Date.now() > 0) {
 | 
				
			||||||
 | 
							return Promise.resolve(jwt);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return module.exports.generateToken(serviceAccount).then(function(_jwt) {
 | 
				
			||||||
 | 
							jwt = _jwt;
 | 
				
			||||||
 | 
							exp = Math.round(Date.now()) - 15 * 60 * 60 * 1000;
 | 
				
			||||||
 | 
							return jwt;
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports.generateToken = function(serviceAccount) {
 | 
				
			||||||
 | 
						var sa = serviceAccount;
 | 
				
			||||||
 | 
						return Keypairs.import({ pem: sa.private_key }).then(function(key) {
 | 
				
			||||||
 | 
							return Keypairs.signJwt({
 | 
				
			||||||
 | 
								jwk: key,
 | 
				
			||||||
 | 
								iss: sa.client_email,
 | 
				
			||||||
 | 
								exp: '1h',
 | 
				
			||||||
 | 
								header: {
 | 
				
			||||||
 | 
									kid: sa.private_key_id
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								claims: {
 | 
				
			||||||
 | 
									aud: 'ndev.clouddns.readwrite',
 | 
				
			||||||
 | 
									sub: sa.client_email
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										74
									
								
								lib/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								lib/index.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,74 @@
 | 
				
			|||||||
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var auth = require('./auth.js');
 | 
				
			||||||
 | 
					var defaults = {
 | 
				
			||||||
 | 
						baseUrl: 'https://www.googleapis.com/dns/v1/'
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports.create = function(config) {
 | 
				
			||||||
 | 
						var request;
 | 
				
			||||||
 | 
						var baseUrl = (config.baseUrl || defaults.baseUrl).replace(/\/$/, '');
 | 
				
			||||||
 | 
						var sa = getServiceAccount(config);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return {
 | 
				
			||||||
 | 
							init: function(opts) {
 | 
				
			||||||
 | 
								request = opts.request;
 | 
				
			||||||
 | 
								return null;
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							zones: function(data) {
 | 
				
			||||||
 | 
								//console.info('List Zones', data);
 | 
				
			||||||
 | 
								return api({
 | 
				
			||||||
 | 
									url: baseUrl + '/projects/' + sa.project_id + '/managedZones',
 | 
				
			||||||
 | 
									json: true
 | 
				
			||||||
 | 
								}).then(function(resp) {
 | 
				
			||||||
 | 
									return resp.body.managedZones.map(function(zone) {
 | 
				
			||||||
 | 
										// slice out the leading and trailing single quotes, and the trailing dot
 | 
				
			||||||
 | 
										// (assuming that all 'dnsName's probably look the same)
 | 
				
			||||||
 | 
										return zone.dnsName.slice(1, zone.dnsName.length - 2);
 | 
				
			||||||
 | 
									});
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							set: function(data) {
 | 
				
			||||||
 | 
								// console.info('Add TXT', data);
 | 
				
			||||||
 | 
								throw Error('setting TXT not implemented');
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							remove: function(data) {
 | 
				
			||||||
 | 
								// console.info('Remove TXT', data);
 | 
				
			||||||
 | 
								throw Error('removing TXT not implemented');
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							get: function(data) {
 | 
				
			||||||
 | 
								// console.info('List TXT', data);
 | 
				
			||||||
 | 
								throw Error('listing TXTs not implemented');
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						function api(opts) {
 | 
				
			||||||
 | 
							return auth.getToken(sa).then(function(token) {
 | 
				
			||||||
 | 
								opts.headers = opts.headers || {};
 | 
				
			||||||
 | 
								opts.headers.Authorization = 'Bearer ' + token;
 | 
				
			||||||
 | 
								return request(opts);
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						function getServiceAccount(config) {
 | 
				
			||||||
 | 
							var saPath =
 | 
				
			||||||
 | 
								config.serviceAccountPath ||
 | 
				
			||||||
 | 
								process.env.GOOGLE_APPLICATION_CREDENTIALS;
 | 
				
			||||||
 | 
							var sa = config.serviceAccount || require(saPath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (
 | 
				
			||||||
 | 
								!sa ||
 | 
				
			||||||
 | 
								!(
 | 
				
			||||||
 | 
									sa.private_key &&
 | 
				
			||||||
 | 
									sa.private_key_id &&
 | 
				
			||||||
 | 
									sa.client_email &&
 | 
				
			||||||
 | 
									sa.project_id
 | 
				
			||||||
 | 
								)
 | 
				
			||||||
 | 
							) {
 | 
				
			||||||
 | 
								throw new Error(
 | 
				
			||||||
 | 
									'missing or incomplete service_account.json: set serviceAccount serviceAccountPath'
 | 
				
			||||||
 | 
								);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return sa;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										37
									
								
								test.js
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										37
									
								
								test.js
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,37 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env node
 | 
				
			||||||
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// See https://git.coolaj86.com/coolaj86/acme-challenge-test.js
 | 
				
			||||||
 | 
					var tester = require('acme-challenge-test');
 | 
				
			||||||
 | 
					require('dotenv').config();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Usage: node ./test.js example.com xxxxxxxxx
 | 
				
			||||||
 | 
					var zone = process.argv[2] || process.env.ZONE;
 | 
				
			||||||
 | 
					var config = {
 | 
				
			||||||
 | 
						serviceAccountPath:
 | 
				
			||||||
 | 
							process.argv[3] || process.env.GOOGLE_APPLICATION_CREDENTIALS
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					var challenger = require('./index.js').create(config);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Google has its own special authentication
 | 
				
			||||||
 | 
					var sa = require(config.serviceAccountPath);
 | 
				
			||||||
 | 
					require('./lib/auth.js')
 | 
				
			||||||
 | 
						.getToken(sa)
 | 
				
			||||||
 | 
						.then(function(jwt) {
 | 
				
			||||||
 | 
							console.info('\nAuthorization: Bearer ' + jwt + '\n');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// The dry-run tests can pass on, literally, 'example.com'
 | 
				
			||||||
 | 
							// but the integration tests require that you have control over the domain
 | 
				
			||||||
 | 
							return tester
 | 
				
			||||||
 | 
								.testZone('dns-01', zone, challenger)
 | 
				
			||||||
 | 
								.then(function() {
 | 
				
			||||||
 | 
									console.info('PASS', zone);
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
								.catch(function(e) {
 | 
				
			||||||
 | 
									console.error(e.message);
 | 
				
			||||||
 | 
									console.error(e.stack);
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						.catch(function(err) {
 | 
				
			||||||
 | 
							console.error(err.stack);
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user