walnut.js/README.md

283 lines
7.0 KiB
Markdown
Raw Normal View History

2015-11-28 07:40:33 +00:00
walnut
======
An opinionated, constrained, secure application framework with a hard shell - like iOS, but for a home server.
Security Features
2017-07-28 23:16:56 +00:00
-----------------
* JSON-only APIs
* JWT (not cookie*) authentication
* no server-rendered html
* disallows urlencoded forms, except for secured webhooks
* disallows cookies, except for protected static assets
* api.* subdomain for apis
* assets.* subdomain for protected assets
* *must* sit behind a trusted https proxy (such as [Goldilocks](https://git.daplie.com/Daplie/goldilocks.js)
* HTTPS-only (checks for X-Forwarded-For)
* AES, RSA, and ECDSA encryption and signing
* Safe against CSRF, XSS, and SQL injection
* Safe against Compression attacks
\*Cookies are used only for GETs and only where using a token would be less secure -
such as images which would otherwise require the token to be passed into the img src.
They are also scoped such that CSRF attacks are not possible.
Application Features
2017-07-28 23:16:56 +00:00
--------------------
* JSON-only expressjs APIs
* Capability-based permissions system for (oauth3-discoverable) packages such as
* large file access (files@daplie.com)
* database access (data@daplie.com)
* scheduling (for background tasks, alerts, alarms, calendars, reminders, etc) (events@daplie.com)
* payments (credit card) (payments@daplie.com)
* email (email@daplie.com)
* SMS (texting) (tel@daplie.com)
* voice (calls and answering machine) (tel@daplie.com)
* lamba-style functions (functions@daplie.com)
* Per-app, per-site, and per-user configurations
* Multi-Tentated Application Management
* Built-in OAuth2 & OAuth3 support
2015-11-28 07:40:33 +00:00
2017-07-28 23:16:56 +00:00
Install
-------
2017-05-05 20:03:02 +00:00
```bash
2017-05-31 00:55:32 +00:00
curl https://daplie.me/install-scripts | bash
2017-05-05 20:03:02 +00:00
daplie-install-walnut
2017-05-31 00:55:32 +00:00
```
You could also, of course, try installing from the repository directly
(especially if you have goldilocks or some similar already installed)
```bash
mkdir -p /srv/walnut/
git clone git@git.daplie.com:Daplie/walnut.js.git /srv/walnut/core
2017-05-31 00:56:02 +00:00
pushd /srv/walnut/core
git checkout v1
popd
bash /srv/walnut/core/install-helper.sh
2017-05-31 00:55:32 +00:00
```
Initial Configuration
-------------
2015-11-28 07:40:33 +00:00
Once installed and started you can visit <https://localhost.daplie.me:3000>.
2015-11-28 07:40:33 +00:00
```
curl http://localhost.daplie.me:3000 -H 'X-Forwarded-Proto: https'
```
2015-11-28 07:40:33 +00:00
2017-06-13 16:56:44 +00:00
API
---
API docs are here https://git.daplie.com/Daplie/com.example.hello
2015-11-28 07:40:33 +00:00
Structure
=====
Currently being tested with Ubuntu, Raspbian, and Debian on Digital Ocean, Raspberry Pi, and Heroku.
```
/srv/walnut/
├── setup.sh (in-progress)
├── core
2017-05-19 05:20:09 +00:00
│ ├── bin
│ ├── boot
│ ├── holepunch
│ └── lib
2017-06-13 16:52:26 +00:00
├── etc
│ └── client-api-grants
2015-11-28 07:40:33 +00:00
├── node_modules
├── packages
2017-05-19 05:20:09 +00:00
│ ├── apis
│ ├── pages
│ └── services
2015-11-28 07:40:33 +00:00
└── var
2017-06-13 16:52:26 +00:00
└── sites
2015-11-28 07:40:33 +00:00
```
* `core` contains all walnut code
* `node_modules` is a flat installation of all dependencies
* `certs` is a directory for Let's Encrypt (or custom) certificates
* `var` is a directory for database files and such
* `packages` contains 3 types of packages
2017-05-19 05:20:09 +00:00
Will install to
---------------
```
/srv/walnut/core/
/etc/walnut
/opt/walnut
/var/log/walnut
/etc/systemd/system/walnut.service
/etc/tmpfiles.d/walnut.conf
```
Implementation details
----------------
Initialization
--------------
2015-11-28 07:40:33 +00:00
2017-05-19 05:20:09 +00:00
needs to know its primary domain
```
2017-07-28 23:26:02 +00:00
POST https://api.<domain.tld>/api/walnut@daplie.com/init
2017-05-19 05:20:09 +00:00
{ "domain": "<domain.tld>" }
```
2017-05-22 17:17:55 +00:00
The following domains are required to point to WALNUT server
```
<domain.tld>
www.<domain.tld>
api.<domain.tld>
assets.<domain.tld>
cloud.<domain.tld>
api.cloud.<domain.tld>
```
Example `/etc/goldilocks/goldilocks.yml`:
```yml
tls:
email: domains@example.com
servernames:
- example.com
- www.example.com
- api.example.com
- assets.example.com
- cloud.example.com
- api.cloud.example.com
http:
trust_proxy: true
modules:
- name: proxy
domains:
- '*'
address: '127.0.0.1:3000'
```
2017-05-19 05:20:09 +00:00
Resetting the Initialization
----------------------------
Once you run the app the initialization files will appear in these locations
```
/srv/walnut/var/com.daplie.walnut.config.sqlite3
2017-05-26 20:23:17 +00:00
/srv/walnut/config/<domain.tld>/config.json
2017-05-19 05:20:09 +00:00
```
2015-11-28 07:40:33 +00:00
2017-05-19 05:20:09 +00:00
Deleting those files will rese
2017-05-19 07:45:41 +00:00
Accessing static apps
---------------------
Static apps are stored in `packages/pages`
```
# App ID as files with a list of packages they should load
2017-05-22 17:17:55 +00:00
# note that '#' is used in place of '/' because files and folders may not contain '/' in their names
/srv/walnut/packages/sites/<domain.tld#path> # https://domain.tld/path
/srv/walnut/packages/sites/<domain.tld> # https://domain.tld and https://domain.tld/foo match
# packages are directories with reverse dns name # For the sake of debugging these packages can be accessed directly, without a site by
/srv/walnut/packages/pages/<tld.domain.package> # matches apps.<domain.tld>/<package-name> and <domain.tld>/apps/<package-name>
```
Accessing REST APIs
-------------------
2017-05-19 07:45:41 +00:00
2017-05-22 17:17:55 +00:00
```
# Apps are granted access to use a package by listing it in the grants file by the name of the app url (domain.tld)
/srv/walnut/packages/client-api-grants/<domain.tld> # matches api.<domain.tld>/api/ and contains a list of allowed REST APIs
# the REST apis themselves are submatched as api.<domain.tld>/api/<tld.domain.package>
# packages are directories with reverse dns name, a package.json, and an index.js
/srv/walnut/packages/rest/<tld.domain.package>
```
Example tree with contents:
Here `com.example.hello` is a package with a REST API and a static page
and `foobar.me` is a WALNUT-configured domain (smithfam.net, etc).
2017-05-22 17:22:32 +00:00
The packages:
2017-05-22 17:17:55 +00:00
```
/srv/walnut/packages/
├── api
├── pages
│ └── com.example.hello
│ └── index.html
│ '''
<html>
<head><title>com.example.hello</title></head>
<body>
<h1>com.example.hello</h1>
</body>
</html>
│ '''
├── rest
│ └── com.example.hello
│ ├── package.json
│ └── index.js
│ '''
│ 'use strict';
│ module.exports.create = function (conf, deps, app) {
│ app.use('/', function (req, res) {
│ console.log('[com.example.hello] req.url', req.url);
│ res.send({ message: 'hello' });
│ });
│ return deps.Promise.resolve();
│ };
│ '''
2017-05-22 17:22:32 +00:00
└── services
```
The permissions:
```
/srv/walnut/packages/
├── client-api-grants
│ └── cloud.foobar.me
│ '''
│ com.example.hello # refers to /srv/walnut/packages/rest/com.example.hello
│ '''
2017-05-22 17:17:55 +00:00
└── sites
└── daplie.me
'''
com.example.hello # refers to /srv/walnut/packages/pages/com.example.hello
'''
2017-05-19 07:45:41 +00:00
```
2017-06-14 02:03:22 +00:00
API
---
```
req.apiUrlPrefix => https://api.example.com/api/tld.domain.pkg
```
TODO
----
* HTTPS Key Pinning
* Heroku (pending completion of PostgreSQL support)
* [GunDB](https://gundb.io) Support
* OpenID support