Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release/2.0 acacia #33

Merged
merged 113 commits into from
Jan 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
113 commits
Select commit Hold shift + click to select a range
8ee357e
Fix/13 improve auth security (#14)
tahpot Oct 10, 2022
7914cdf
Support the new decentralized did-client implementation (#32)
tahpot Oct 10, 2022
5eaed07
adding acacia testnet
nick-verida Oct 18, 2022
6ab2b57
Update sample.env
Oct 18, 2022
9e1d05b
Fix server tests. Add support for deleting all databases for a user. …
tahpot Oct 24, 2022
6210736
Update dependencies to acacia rc2
Oct 24, 2022
be3203d
Update account node dependency for tests
Oct 25, 2022
c0112cf
Fix issue with documenting how to configure HMAC key in couchdb
Nov 3, 2022
0f5af85
Add better comments
Nov 3, 2022
bf53c57
Update config to use testnet storage node
Nov 3, 2022
4aa8072
Add docker and docker-compose (#27)
dmty Nov 4, 2022
8d17f2a
Remove lambda support
Nov 4, 2022
243c5a5
Details on how to do the Docker build and push it.
nick-verida Nov 4, 2022
7fc5e8f
Update REARME.md: enable_cors = true
nick-verida Nov 7, 2022
9bd0c87
update Docker build command
nick-verida Nov 8, 2022
b39f8e9
Changes to make deployment work. Yarn build must happen in Docker con…
nick-verida Nov 8, 2022
2a7d9c0
Support signing all responses using the storage node VDA private key.…
tahpot Nov 16, 2022
5f88f8f
Add support for /user/usage details (#43)
tahpot Nov 16, 2022
cb6d319
add logging to make debugging Docker image somewhat possible
nick-verida Nov 17, 2022
32017fd
fix logging message
nick-verida Nov 17, 2022
ac87b3f
update README to correct authentication info. Add logging to dbInit e…
nick-verida Nov 18, 2022
46c4e8e
logging for failure of /auth/public; clean up pakage.json
nick-verida Nov 21, 2022
8c4aa71
update docs on HASH_KEY not being needed
nick-verida Nov 23, 2022
6ff6d4a
Feature/37 implement vip 3 (#44)
tahpot Nov 24, 2022
c31aa8e
Update README.md
nick-verida Nov 24, 2022
d865284
Force lowercase username when generating usernames
Nov 25, 2022
b586725
Merge branch 'release/2.0-acacia' of https://github.com/verida/storag…
Nov 25, 2022
e8baaf2
Add comments about running tests
Nov 28, 2022
72e3d78
Include permissions in database info
Nov 28, 2022
bdfe7df
Merge branch 'release/2.0-acacia' of https://github.com/verida/storag…
Nov 28, 2022
bf84f9e
Update dependencies to next release candidate
Nov 28, 2022
fab16de
delay start of docker image until $DB_HOST reolves
nick-verida Nov 29, 2022
67f48f2
Add support for a NODE_URI
Nov 29, 2022
5c3d755
Merge branch 'release/2.0-acacia' of github.com:verida/storage-node i…
nick-verida Nov 29, 2022
ac1cd76
typo
nick-verida Nov 29, 2022
019c7c8
remove checking for network now SN supports different endpoint
nick-verida Nov 29, 2022
28a1bd7
Move signature tests to the end to avoid issues with testing servers …
Nov 30, 2022
6569f71
Merge branch 'release/2.0-acacia' of https://github.com/verida/storag…
Nov 30, 2022
e21412d
Support internal and external DB hostnames
Dec 2, 2022
2ad2162
Fix hostname generation.
Dec 5, 2022
7965b01
Fix build external host
Dec 5, 2022
9e29a1a
Add console errors and warnings to help with debugging
Dec 5, 2022
c9d1574
Support looking up a DID document and caching it
Dec 6, 2022
dbfb625
Include public key in system status
Dec 6, 2022
9b813fa
Feature/49 server replication (#50)
tahpot Dec 15, 2022
5420410
Feature/49 server replication (#51)
tahpot Dec 20, 2022
fa5adf9
Feature/52 user db list replicated (#54)
tahpot Dec 21, 2022
f76b0fa
Fix trailing slash issue
Dec 21, 2022
a1fbc58
Fix trailing slash issues
Dec 21, 2022
64edc87
Adding cache checks for DID documents
Dec 22, 2022
84f8292
Fix database list database incorrect config
Dec 26, 2022
bb085de
Handle missing DID document
Dec 26, 2022
eea2bc2
Throw error if unknown check databse error
Dec 26, 2022
fa7b409
Improve service endpoint checks on checkReplication()
Dec 27, 2022
39df867
Ensure user database list database has replicator local role
Dec 27, 2022
37a88b2
Fix issue with user database list database not being recreated. Minor…
Dec 27, 2022
ccd13d0
Handle garbage collection where token already deleted
Dec 27, 2022
fc0e6e9
Handle user database list database document conflict
Dec 27, 2022
678d33c
Fix caching of couch instance not respecting external v internal
Dec 29, 2022
30d8975
Add debug output to nodes about cache status
Dec 31, 2022
a86c6b7
Add error message when unable to resolve DID
Jan 3, 2023
840275f
Add debug logging
Jan 4, 2023
82f347b
Unify storage node checks and hashes to use the hostname only
Jan 4, 2023
14f536d
Make endpointUri more resiliant
Jan 4, 2023
f868760
Upgrade encryption utils to latest
Jan 4, 2023
35b48d1
Support recoverying from replication credential errors
Jan 4, 2023
13e8a87
Add debug logging
Jan 5, 2023
f4a829d
Add storage node HTTP timeouts. Add more debugging.
Jan 5, 2023
bc15135
Fix replicater creds to have replicaterUsername has id
Jan 5, 2023
a757f86
Fix replicater username to only use hostname
Jan 5, 2023
d2e2b0f
Fix incorrect username being loaded
Jan 5, 2023
6597864
Fix replication to start working upon creation of new databases, only…
Jan 5, 2023
dcfbacc
Check replication credentials after all databases have been checked.
Jan 5, 2023
101d63c
Refactor how endpoint security checks occur. Cleanup console output.
Jan 5, 2023
764d76a
Improve debug output
Jan 6, 2023
4f72948
More debug output for testing
Jan 6, 2023
f5f2d74
Remove redundant record variable
Jan 6, 2023
72825d6
Add delete failed replication meethod
Jan 6, 2023
2a6d64f
Fix incorrect delete replication code
Jan 6, 2023
240402a
More debugging
Jan 6, 2023
d42ed55
More debug output
Jan 6, 2023
2d9fcdf
Update order of code
Jan 6, 2023
772502f
Change order so that failed replication entries are removed first, so…
Jan 6, 2023
a250431
Add more debug output for testing=
Jan 7, 2023
a3fdfd9
Force update of remote credentials if they are definitely invalid
Jan 9, 2023
750396b
Add debug output
Jan 9, 2023
d526263
Add more debug output
Jan 10, 2023
7dd7963
Fix issue with fetchReplicaterCredential setting the wrong key for th…
Jan 10, 2023
265f65a
Fix incorrect username
Jan 10, 2023
47def93
Restructure how replication fails are fixed
Jan 10, 2023
184ffc2
Add more debug output, fix replication status id parameter
Jan 10, 2023
0af42d8
More debug output
Jan 10, 2023
56e8647
More debugging
Jan 10, 2023
e61579e
Fix sample.env comment
Jan 11, 2023
622e2d6
Reduce debug output
Jan 11, 2023
d377e2c
d
Jan 11, 2023
11b8678
Refactor replication and improve debug output
Jan 11, 2023
fbd6e42
Handle unable to fetch DID error
Jan 11, 2023
3bb23f8
Add checkreplication debug header
Jan 11, 2023
bae3c14
Lots of bug fixes and refactor
Jan 11, 2023
12b1f8f
Bug fix incorrect instance reference
Jan 11, 2023
0766b29
Force cache refresh if service endpoint not found
Jan 11, 2023
cc80ef7
Handle missing did document
Jan 11, 2023
dbaceb3
set winning_revs_only: true
Jan 11, 2023
ffaac07
Remove winning_revs_only
Jan 11, 2023
4738a46
Remove permissions check
Jan 11, 2023
eb17f5d
Add debug logging
Jan 11, 2023
cf4a1ac
More debug output
Jan 11, 2023
6854121
Debug to find error
Jan 11, 2023
40913aa
Merge branch 'fix/acacia-replication-issues' into release/2.0-acacia
Jan 11, 2023
7e9bcaf
Support ignore cache option when fetching DID document
Jan 13, 2023
4f474f2
Correctly handle empty DIDs
Jan 13, 2023
6c05ab4
Update CHANGELOG in preparation for v2.0.0 release
Jan 13, 2023
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
11 changes: 11 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
node_modules

.git
.github

dist
.env*
docker-compose.yml
Dockerfile
*.md
claudia.*
94 changes: 94 additions & 0 deletions .github/workflows/build-docker.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
name: build-docker-image

on:
push:
branches:
- 'main'
tags:
- 'v*'
pull_request:
workflow_dispatch:

jobs:
build:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v3

# qemu and buildx are for multi-platform images and caching
- name: Set up QEMU
uses: docker/setup-qemu-action@v2

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2

# set up local caching
- name: Cache Docker layers
uses: actions/cache@v3
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-

- name: Docker meta
id: meta
uses: docker/metadata-action@v4
with:
images: |
verida/storage-node
ghcr.io/verida/storage-node
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha

# get the correct AW role to push image to ECR
- name: Configure AWS credentials from Testnet account
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
role-duration-seconds: 1500
role-to-assume: arn:aws:iam::737954963756:role/github-testnet-deploy-role
aws-region: us-east-1

# login to push to DockerHub
- name: Login to DockerHub
if: github.event_name != 'pull_request'
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

# login to push to GHCR
- name: Login to GHCR
if: github.event_name != 'pull_request'
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and push
uses: docker/build-push-action@v3
with:
platforms: linux/amd64 # ,linux/arm64,linux/arm/v7
context: .
push: ${{ github.event_name != 'pull_request' }}
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max
tags: ${{ steps.meta.output.tags }}
labels: ${{ steps.meta.output.labels }}

# Temp fix
# https://github.com/docker/build-push-action/issues/252
# https://github.com/moby/buildkit/issues/1896
- name: Move cache
run: |
rm -rf /tmp/.buildx-cache
mv /tmp/.buildx-cache-new /tmp/.buildx-cache
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ dist
.DS_Store
.vscode
curl_tests
dbdata

.env
.env*
.env*
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
14.17.1
14.20.0
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
2023-01-13 (2.0.0)
--------------------

- Support blockchain DID registry
- Support refresh and access tokens
- Support server side replication, including cehcks and recovery
- Support device disconnections
- Support maintaining database of context specific databases to enable monitoring of usage
- Support database deletion
- Support create, update, retreive and delete DID documents
- Support `/lookup/did` endpoint to provide a DID document caching service
- Remove lambda support
- Support docker containers


2021-09-17 (1.2.0)
--------------------
Expand Down
33 changes: 33 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
FROM node:14.20.0-slim as node

ENV NODE_ENV=production
EXPOSE 5000

RUN mkdir /storage-node && chown -R node:node /storage-node
WORKDIR /storage-node

# this ensures we fix simlinks for npx and yarn
RUN corepack disable && corepack enable

RUN apt-get update \
&& apt-get -qq install -y --no-install-recommends \
git ca-certificates dnsutils \
&& rm -rf /var/lib/apt/lists/*

# new stage
FROM node AS source

USER node
# Copy the current directory
COPY --chown=node:node . .

# we need devDependencies to build. Setting --production=false ignores NODE_ENV (deliberatly)
RUN yarn install --production=false --frozen-lockfile
# we have to build inside the container in case we are on a Mac building a linux image
RUN yarn build


### prod stage
# Note: use --init option when running the container to have better signal forwarding
FROM source as prod
CMD ["node", "--trace-warnings", "./dist/server.js"]
93 changes: 84 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,23 @@ Key features:
- Adding a second layer of security by managing per-database ACL validation rules
- Providing applications with user's database connection strings

## How Authorization Works

This is the login flow:

1. The Verida Account makes a request to the storage node API to obtain an auth JWT to be signed (`/auth/generateAuthJwt`). This prevents replay attacks.
2. The Verida Account signs a consent message using their private key. This consent message proves the user wants to unlock a specific application context
3. The Verida Account submits the signed authorization request (`/auth/authenticate`). Assuming the signed AuthJWT is valid, the storage node returns a refresh token and an access token
4. The Verida Account can then use the access token to either; 1) make storage node requests (ie: create database) or 2) directly access CouchDB as an authenticated user (using `Bearer` token auth)
5. When the access token expires, the Verida Account can use the refresh token to request a new access token (`/auth/connect`)
6. If a refresh token is close to expiry, the Verida Account can use the active refresh token to obtain a new refresh token (`/auth/regenerateRefreshToken`)

When a Verida Account authenticates, it can designate an `authenticate` requst to be linked to a particular device by specifying the `deviceId` in the request.

This allows a specific device to be linked to a refresh token. A call to `/auth/invalidateDeviceId` can be used to invalidate any refresh tokens linked to the specified `deviceId`. This allows the Verida Vault to remotely log out an application that previously logged in.

Note: This only invalidates the refresh token. The access token will remain valid until it expires. It's for this reason that access tokens are configured to have a short expiry (5 minutes by default). CouchDB does not support manually invalidating access tokens, so we have to take this timeout approach to invalidation.

## Usage

```bash
Expand All @@ -30,7 +47,6 @@ This server is running on the Verida Testnet and is accessible by any applicatio

A `sample.env` is included. Copy this to `.env` and update the configuration:

- `HASH_KEY`: A unique hash key that is used as entropy when generating an alpha numeric username from a DID. Set this to a unique value when first running the server. DO NOT change this key once the server is up and running as you will end up with a mismatch of usernames. If you run multiple servers in front of a cluster of CouchDB instances, all servers must use the same `HASH_KEY`.
- `DID_SERVER_URL`: URL of a Verida DID Server endpoint.
- `DB_PROTOCOL`: Protocol to use when connecting to CouchDB (`http` or `https`).
- `DB_USER`: Username of CouchDB Admin (has access to create users and databases).
Expand All @@ -40,12 +56,15 @@ A `sample.env` is included. Copy this to `.env` and update the configuration:
- `DB_REJECT_UNAUTHORIZED_SSL`: Boolean indicating if unauthorized SSL certificates should be rejected (`true` or `false`). Defaults to `false` for development testing. Must be `true` for production environments otherwise SSL certificates won't be verified.
- `DB_PUBLIC_USER`: Alphanumeric string for a public database user. These credentials can be requested by anyone and provide access to all databases where the permissions have been set to `public`.
- `DB_PUBLIC_PASS`: Alphanumeric string for a public database password.
- `ACCESS_TOKEN_EXPIRY`: Number of seconds before an access token expires. The protocol will use the refresh token to obtain a new access token. CouchDB does not support a way to force the expiry of an issued token, so the access token expiry should always be set to 5 minutes (300)
- `REFRESH_TOKEN_EXPIRY`: Number of seconds before a refresh token expires. Users will be forced to re-login once this time limit is reached. This should be set to 7 days (604800).
- `ACCESS_JWT_SIGN_PK`: The access token private key. The base64 version of this must be specified in the CouchDB configuration under `jwt_keys/hmac:_default`
- `REFRESH_JWT_SIGN_PK`: The refresh token private key

### Setting up environment variables on Windows

* On a powershell execute the following ( replica of `.env` )
```bash
$env:HASH_KEY="this_is_not_prod_hash_key"
$env:DID_SERVER_URL="https://dids.testnet.verida.io:5001"
$env:DID_CACHE_DURATION=3600
$env:DB_PROTOCOL="http"
Expand All @@ -63,27 +82,83 @@ $env:DB_PUBLIC_PASS="784c2n780c9cn0789"
- CORS must be enabled so that database requests can come from any domain name
- A valid user must be enforced for security reasons

[Ensure `{chttpd_auth, jwt_authentication_handler}` is added to the list of the active `chttpd/authentication_handlers`](https://docs.couchdb.org/en/stable/api/server/authn.html?highlight=jwt#jwt-authentication)



```
[httpd]
WWW-Authenticate = Basic realm="administrator"
[couchdb]
single_node=true

[chttpd]
authentication_handlers = {chttpd_auth, jwt_authentication_handler}, {chttpd_auth, cookie_authentication_handler}, {chttpd_auth, default_authentication_handler}
enable_cors = true

[chttpd_auth]
require_valid_user = true

[jwt_auth]
required_claims = exp

[jwt_keys]
hmac:_default = <base64 secret key>

[cors]
origins = *
credentials = true
methods = GET, PUT, POST, HEAD, DELETE
headers = accept, authorization, content-type, origin, referer, x-csrf-token
```

## Lambda deployment
The `hmac:_default` key is a base64 encoded representation of the access token JWT private key

## Generating JWT key

Note: A secret key (string) suitable for `jwt_keys` can be base64 encoded with the following:

```
const secretKey = 'secretKey'
const encodedKey = Buffer.from(secretKey).toString('base64')
```

This can be tested via curl:

```
curl -H "Host: localhost:5984" \
-H "accept: application/json, text/plain, */*" \
-H "authorization: Bearer <bearer_token>" \
"http://localhost:5984/_session"
```

Where:

- `bearer_token` - A bearer token generated via the `test/jwt` unit test
- `localhost` - Replace this with the hostname of the server being tested

## Docker

You can spin up storage node API on your machine with Docker:
```shell
docker run --init --env-file=.env verida/storage-node:latest
```

### Deploying a new Docker Image to Docker Hub

Note that this uses the experimental `buildx` command to build both AMD64 (Intel/AMD servers) and ARM64 (Mac) images.

* Login (details in BitWarden)
```
docker buildx build --platform linux/amd64,linux/arm64 --push -t verida/storage-node:latest .
```


## Tests

We use [Claudia.js](https://claudiajs.com/) to turn our Express app into an Express-on-Lambda app.
Run tests with `yarn run tests`

Before doing any Lambda deployments you **MUST** translate your `.env` file (or one for production) to JSON as `.env.prod.json`.
See the [Claudia Docs for information](https://claudiajs.com/news/2016/11/24/claudia-2.2.0-environment-vars.html).
Note: The tests in `server.js` require the server to be running locally. The other tests operate fine without the server running.

Verida staff can see the [internal Verida repo]( https://github.com/verida/infrastructure/blob/develop/storage_node.md) for docs on this.
Common issues when running tests:

1. `Bad key`: The key in CouchDB configuration for `jwt_keys/hmac:_default` is not a valid Base64 encoded key
2. `HMAC error`: The key in CouchDB configuration for `jwt_keys/hmac:_default` does not match `ACCESS_JWT_SIGN_PK` in `.env`
11 changes: 0 additions & 11 deletions claudia.au1.testnet.json

This file was deleted.

10 changes: 0 additions & 10 deletions claudia.dev.json

This file was deleted.

11 changes: 0 additions & 11 deletions claudia.sg1.testnet.json

This file was deleted.

11 changes: 0 additions & 11 deletions claudia.use1.testnet.json

This file was deleted.

14 changes: 0 additions & 14 deletions lambda.js

This file was deleted.

Loading