Skip to content

Commit f21e513

Browse files
committed
Initial commit
0 parents  commit f21e513

36 files changed

Lines changed: 682 additions & 0 deletions

.babelrc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"presets": [
3+
"es2015",
4+
"react",
5+
"stage-0"
6+
]
7+
}

.eslintrc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"extends": "standard"
3+
}

.gitignore

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Logs
2+
logs
3+
*.log
4+
npm-debug.log*
5+
6+
# Runtime data
7+
pids
8+
*.pid
9+
*.seed
10+
11+
# Directory for instrumented libs generated by jscoverage/JSCover
12+
lib-cov
13+
14+
# Coverage directory used by tools like istanbul
15+
coverage
16+
17+
# nyc test coverage
18+
.nyc_output
19+
20+
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
21+
.grunt
22+
23+
# node-waf configuration
24+
.lock-wscript
25+
26+
# Compiled binary addons (http://nodejs.org/api/addons.html)
27+
build/Release
28+
29+
# Dependency directories
30+
node_modules
31+
jspm_packages
32+
33+
# Optional npm cache directory
34+
.npm
35+
36+
# Optional REPL history
37+
.node_repl_history

README.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Node Lambda Lets-Encrypt
2+
3+
Use [AWS Lambda](https://aws.amazon.com/lambda/) to manage SSL certificates for
4+
Lets-Encrypt.
5+
6+
## Project status
7+
This project has just begun, I will be adding features as fast as I can to get it to completion in a relatively short time period (9-26-2016)
8+
9+
# Why do I want this?
10+
Rather than having to dedicate a machine to running the Lets-Encrypt client to
11+
maintain your certificate for your site, you can let it all
12+
live on Amazon's infrastructure for cheap. You'll receive notification if
13+
anything goes wrong, and there's no hardware or virtual machines for you to
14+
manage.
15+
16+
# How does it work?
17+
18+
This works by running a Lambda function once per day which will check
19+
your certificate's expiration, and renew it if it is nearing expiration.
20+
21+
Since Lambda is billed in 100ms increments and this only needs to run once a day
22+
for less than 10seconds each time the cost to run this is less than a
23+
penny per month(i.e. effectively free)
24+
25+
## Special Thanks
26+
A few shout-outs to inspiring projects...
27+
* @ubergeek42 for https://github.com/ubergeek42/lambda-letsencrypt
28+
* @Daplie for https://github.com/Daplie/le-acme-core and https://github.com/Daplie/rsa-compat.js

app.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
require('babel-register')
2+
3+
const express = require('express')
4+
5+
const app = express()
6+
app.use('/certificate', require('./routes/certificate'))
7+
8+
app.listen(process.env.PORT || 3000)
9+
10+
// production error handler
11+
// no stacktraces leaked to user
12+
app.use((err, req, res, next) => {
13+
res.status(err.status || 500)
14+
res.send(JSON.stringify(err))
15+
})
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"AWS_ACCESS_KEY_ID": "AWS_ACCESS_KEY_ID",
3+
"AWS_SECRET_ACCESS_KEY": "AWS_SECRET_ACCESS_KEY"
4+
}

config/default.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"AWS_ACCESS_KEY_ID": "",
3+
"AWS_SECRET_ACCESS_KEY": "",
4+
"region": "us-east-1",
5+
"s3-config-bucket": "",
6+
"s3-cert-bucket": "",
7+
"sns-arn": "",
8+
"acme-challenge-expires-in": 3,
9+
"acme-dns-retry": 30,
10+
"acme-dns-retry-delay-ms": 2000,
11+
"acme-site-key": "",
12+
"acme-site-info-file": "",
13+
"acme-user-info-file": "",
14+
"acme-user-email": "",
15+
"acme-user-key-bits": 2048,
16+
"acme-directory-url": "https://acme-staging.api.letsencrypt.org"
17+
}

package.json

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
{
2+
"name": "node-letsencrypt-lambda",
3+
"version": "1.0.0",
4+
"description": "Free Lets-Encrypt certificate management for CloudFront/AWS written in nodejs",
5+
"main": "app.js",
6+
"scripts": {
7+
"dev": "cross-env NODE_ENV=development node app"
8+
},
9+
"keywords": [
10+
"letsencrypt",
11+
"nodejs",
12+
"aws"
13+
],
14+
"author": "Larry Anderson",
15+
"license": "ISC",
16+
"dependencies": {
17+
"aws-sdk": "~2.4.14",
18+
"babel-loader": "^6.2.5",
19+
"babel-plugin-transform-class-properties": "^6.16.0",
20+
"babel-plugin-transform-runtime": "^6.12.0",
21+
"babel-polyfill": "^6.16.0",
22+
"babel-preset-es2015": "^6.16.0",
23+
"babel-preset-react": "^6.16.0",
24+
"babel-preset-stage-0": "^6.16.0",
25+
"babel-register": "^6.16.3",
26+
"config": "^1.20.3",
27+
"es6-promisify": "^4.1.0",
28+
"eslint": "^3.7.0",
29+
"eslint-config-standard": "^6.2.0",
30+
"eslint-plugin-standard": "^2.0.1",
31+
"express": "^4.14.0",
32+
"node-forge": "^0.6.42",
33+
"promise": "^7.1.1",
34+
"rsa-compat": "^1.2.7",
35+
"superagent": "~1.8.4",
36+
"superagent-promise": "^1.1.0",
37+
"underscore": "^1.8.3",
38+
"urlsafe-base64": "^1.0.0",
39+
"webpack": "^1.13.2",
40+
"winston": "~2.2.0"
41+
},
42+
"devDependencies": {
43+
"concurrently": "^2.2.0",
44+
"cross-env": "~1.0.8",
45+
"eslint": "^3.6.0",
46+
"eslint-config-standard": "^6.0.1",
47+
"eslint-plugin-promise": "^2.0.1",
48+
"eslint-plugin-standard": "^2.0.0"
49+
}
50+
}

routes/certificate.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import generateCertificate from '../src/acme/generateCertificate'
2+
import isExpired from '../src/util/isExpired'
3+
import config from 'config'
4+
5+
const runHandler = (expired) => (expired ? generateCertificate() : Promise.resolve({msg: 'Certificate is still valid, going back to bed.'}))
6+
7+
module.exports = (req, res, next) => {
8+
isExpired(config.get('acme-site-key'))
9+
.then(runHandler)
10+
.then((data) => {
11+
res.send(data)
12+
})
13+
.catch(next)
14+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import config from 'config'
2+
import sendSignedRequest from '../sendSignedRequest'
3+
4+
const getChallenges = (keypair, authzUrl) =>
5+
sendSignedRequest({
6+
resource: 'new-authz',
7+
identifier: {
8+
type: 'dns',
9+
value: config.get('acme-site-key')
10+
}
11+
}, keypair, authzUrl)
12+
.then((data) => Promise.resolve(data.body))
13+
14+
module.exports = getChallenges

0 commit comments

Comments
 (0)