Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
start:
echo This Makefile has no default action. Be specific.
dev-server:
node development/server

dynamodb:
docker-compose up -d dynamodb

dynamodb-tables: dynamodb
./development/create-tables.sh

list-dev-api-keys:
./development/list-api-keys.sh

do-full-recovery:
docker-compose run --rm do-full-recovery
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ For details about the various API endpoints, see
must be provided as an `x-api-key` header in the HTTP request.
- We create a new API Key and email it to that email address.
* NOTE: At the moment, we do not actually send that email, since our use case
is so limited that we can simply look up the API Key in the database.
is so limited that we can simply look up the API Key in the database. For
local development, run `make list-dev-api-keys` to see it.
- The consumer does a `POST` to `/api-key/activate`, providing the email address
and the API Key.
- We respond with an API Secret (which is actually an AES key, which we will use
Expand Down
27 changes: 27 additions & 0 deletions development/create-tables.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/usr/bin/env bash

set -e

aws dynamodb create-table \
--table-name development_server_api-key \
--attribute-definitions AttributeName=value,AttributeType=S \
--key-schema AttributeName=value,KeyType=HASH \
--billing-mode PAY_PER_REQUEST \
--endpoint-url http://localhost:8000 \
--region localhost

aws dynamodb create-table \
--table-name development_server_totp \
--attribute-definitions AttributeName=uuid,AttributeType=S \
--key-schema AttributeName=uuid,KeyType=HASH \
--billing-mode PAY_PER_REQUEST \
--endpoint-url http://localhost:8000 \
--region localhost

aws dynamodb create-table \
--table-name development_server_u2f \
--attribute-definitions AttributeName=uuid,AttributeType=S \
--key-schema AttributeName=uuid,KeyType=HASH \
--billing-mode PAY_PER_REQUEST \
--endpoint-url http://localhost:8000 \
--region localhost
11 changes: 11 additions & 0 deletions development/development.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Table names for our code to use
API_KEY_TABLE_NAME=development_server_api-key
TOTP_TABLE_NAME=development_server_totp
U2F_TABLE_NAME=development_server_u2f

# Dynamo DB endpoint for our code to use (not directly used by AWS). If not
# provided, a default value will be calculated by AWS's code using the region.
DYNAMO_DB_ENDPOINT=http://localhost:8000

# AWS environment variables
AWS_REGION=localhost
8 changes: 8 additions & 0 deletions development/list-api-keys.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/usr/bin/env bash

set -e

aws dynamodb scan \
--table-name development_server_api-key \
--endpoint-url http://localhost:8000 \
--region localhost
55 changes: 55 additions & 0 deletions development/server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
require('dotenv').config({ path: 'development/development.env' });

const express = require('express');
const bodyParser = require('body-parser');

const apiKeyHandlers = require('../handlers/api-key.js');
const totpHandlers = require('../handlers/totp.js');
const u2fHandlers = require('../handlers/u2f.js');

const app = express();
const mapTo = requestHandler => (request, response) => {
const {event, callback} = mimicApiGateway(request, response);
requestHandler(event, {}, callback);
};
const mimicApiGateway = (request, response) => {
return {
event: createEventFrom(request),
callback: createCallbackUsing(response),
};
};
const createEventFrom = request => {
return {
headers: request.headers,
body: request.body,
pathParameters: request.params,
}
};
const createCallbackUsing = response => (error, data) => {
if (error) {
response.status(500).send(error);
} else {
response.status(data.statusCode).send(data.body);
}
};

// Parse the request body and always return as a text string.
app.use(bodyParser.text({type: () => true}));

// @todo - Figure out how best to handle these "private" API endpoints.
app.post('/api-key', mapTo(apiKeyHandlers.create));
app.post('/api-key/activate', mapTo(apiKeyHandlers.activate));

app.post('/totp', mapTo(totpHandlers.create));
app.delete('/totp/:uuid', mapTo(totpHandlers.delete));
app.post('/totp/:uuid/validate', mapTo(totpHandlers.validate));

app.post('/u2f', mapTo(u2fHandlers.createRegistration));
app.delete('/u2f/:uuid', mapTo(u2fHandlers.delete));
app.put('/u2f/:uuid', mapTo(u2fHandlers.validateRegistration));
app.post('/u2f/:uuid/auth', mapTo(u2fHandlers.createAuthentication));
app.put('/u2f/:uuid/auth', mapTo(u2fHandlers.validateAuthentication));

app.listen(8080, () => {
console.log('Local development server listening on port 8080')
});
5 changes: 5 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,8 @@ services:
- ./:/data
working_dir: /data
command: ./recovery/do-full-recovery.sh

dynamodb:
image: amazon/dynamodb-local
ports:
- "8000:8000"
4 changes: 3 additions & 1 deletion models/api-key.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

const AWS = require('aws-sdk');
const crypto = require('crypto');
const dynamoDb = new AWS.DynamoDB.DocumentClient();
const dynamoDb = new AWS.DynamoDB.DocumentClient({
endpoint: process.env.DYNAMO_DB_ENDPOINT
});
const password = require('../helpers/password.js');
const response = require ('../helpers/response.js');

Expand Down
4 changes: 3 additions & 1 deletion models/totp.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

const apiKey = require('../models/api-key.js');
const AWS = require('aws-sdk');
const dynamoDb = new AWS.DynamoDB.DocumentClient();
const dynamoDb = new AWS.DynamoDB.DocumentClient({
endpoint: process.env.DYNAMO_DB_ENDPOINT
});
const encryption = require('../helpers/encryption.js');
const password = require('../helpers/password.js');
const qrCode = require('qrcode');
Expand Down
4 changes: 3 additions & 1 deletion models/u2f.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

const apiKey = require('../models/api-key.js');
const AWS = require('aws-sdk');
const dynamoDb = new AWS.DynamoDB.DocumentClient();
const dynamoDb = new AWS.DynamoDB.DocumentClient({
endpoint: process.env.DYNAMO_DB_ENDPOINT
});
const encryption = require('../helpers/encryption.js');
const response = require('../helpers/response.js');
const u2f = require('u2f');
Expand Down
Loading