Refactored Holo Init
===
## Longer term discussion
### Security implications of controlling a machine through web application
We are recommending that we continue to pursue "access on local network" options for security reasons.
The hAppy team has written their code to date with a context assumption of "local access".
So, we are still working under that paradigm
Under a local network access paradigm for hp-admin:
Key issues:
1. We do NOT want to produce an outcome that introduces imperative management of state of the machine. This is an absolute critical requirement. We have the option not to do that in the execution of any request, and so the solution provided will utilize the underlying nix system to make changes to state of the system at all times.
2. Direct access to underlying system should not be granted to any application, and the actions should instead be abstracted by services that live on the machine that can perform validation/authorize changes based on the best possible validation of the request.
The specified actions at https://hackmd.io/UI8da3lxRbCJjf8nfQyudA#In-version-2-closed-alpha-wave-1 range from just getting information off of the machine, all the way to changing the state of the machine. But a simple "API" for any application can be
1. Create signed request in queue
2. Wait for response
3. Display response
... and then on the back end we would handle these as we see fit: running a command, generating a nix expression, etc
## Notes on the specification for this sprint
Per user story https://www.pivotaltracker.com/story/show/168404617
### Claim machine API/Application
We are proposing
Data collected
```mermaid
sequenceDiagram
participant B as Browser
participant A as Auth Server
participant F as FreshDesk
participant E as Email
participant Z as ZeroTier
B->>A: I want to verify *this* email
A-->>+F: Checks that *this* email is allowed in Closed Alpha
F-->>-A: Yes
A->>E: Send a verification code to *this* email
E->>B: User clicks link
B->>+A: Link contains signature and ZeroTier ID
A-->>Z: Authorize given ID
Z-->>A: Success
A->>-B: Success
```
http://authorizer.holohost.net - **will ignore requests without a valid path**
- Data currently stored
- freshdesk_key (freshdesk api auth key)
- freshdesk_pass (is ignored)
- network_id (zerotier network id)
- super_secret_hmac_key (our symmetric key)
- zerotier_auth_token (zerotier api auth key)
#### `POST /v1/auth`
POST http://authorizer.holo.host/v1/auth - **requires POST and params**
```
{
"email": "sam.rose@holo.host",
"zerotier_address": "ab01cf1594"
}
```
- Checks email against Freshdesk API. Exits with 401 on error
- Creates `hmac` from worker's symmetric key and data
```
{
"zerotier_address": <ZeroTier address>
}
```
- Sends an authorization email with https://authorizor.holo.host/v1/challenge link.
Responses:
- 200 OK
- 400 Bad Request: missing parameter
- 401 Unauthorized: email address not found
#### `GET /v1/challenge`
GET http://authorizer.holohost.net/v1/challenge?hmac=validhmac&addr=someaddr&exp=exp
**requires GET & hmac & network address & expiration**
Example: `/v1/challenge?hmac=uG1XC4EsfqTNL9xu4k77ort/1pW7wOrFrwgzhlS75ONeWnkMVmsFmQ&addr=ab01cf1594&exp=1570739123388`
`hmac` is Base64-encoded [keyed BLAKE2b](https://tools.ietf.org/html/rfc7693#section-1) HMAC of:
```
{
"zerotier_address": <ZeroTier address>
}
```
To determine validity, Cloudflare worker should reconstruct message and try to validate `hmac`
If valid, adds given ZeroTier address to Holo networks using https://my.zerotier.com/central-api.html#member-member-post endpoint.
Responses:
- 200 OK
- 400 Bad Request: missing parameter or malformed data
## New Holo Init Workflow
Initial configuration of blank HoloPort comes from key material and user configured email + password (salted+hashed) saved as a JSON file on USB stick.
### Entropy for Holochain + ZT Key Generation
This can be generated offline on an air-gapped machine (eg. from DPKI), if desired, or online directly at https://quickstart.holo.host for less security-conscious people.
```mermaid
sequenceDiagram
participant quickstart.holo.host
participant Browser
participant User
participant USB
participant HoloPort
participant CloudFlare Worker
quickstart.holo.host->>Browser: UI Application
Note over Browser,User: Save Page for offline use
User->>Browser: Select 'Configure New HoloPort' page
Browser->>User: Present UI to collect Entropy, etc.
User->>Browser: Select Create Key / Supply DPKI Entropy
User->>Browser: Enter email + password
Browser->>User: Compute JSON HoloPort config package, present Link
User->>USB: Save JSON file via link
USB->>HoloPort: Insert USB w/ JSON, reboot HoloPort
Note over USB,HoloPort: - conf. BIOS to boot from USB
Note over USB,HoloPort: - Loader checks kernel+initrd sig. on hard drive
Note over USB,HoloPort: - boot kernel+initrd from hard drive
USB->>HoloPort: Kernel starts Holochain conductor w/ key from USB
HoloPort--xUSB: Service ejects USB, blacklists device kernel module
User->>Browser: Select 'Monitor HoloPort Status' page
Browser-->CloudFlare Worker: Establish Websocket to receive Status Updates
```
#### Preventing Post-Boot USB Access
Booting from USB into a signature-checking bootloader that confirms the signature of the kernel + initrd before loading is the first step.
To protect this phase, we must also prevent access to the USB after boot, and also prevent changing the BIOS:
1) Prevent kernel modules from being loaded:
- https://www.google.ru/amp/s/linux-audit.com/increase-kernel-integrity-with-disabled-linux-kernel-modules-loading/amp/
> The Linux kernel can be configured to disallow loading new kernel modules. The sysctl key kernel.modules_disabled is very straightforward for this purpose. In this article, we will have a look at the configuration of this option.
1) Prevent BIOS from being updated:
- https://wiki.archlinux.org/index.php/Flashing_BIOS_from_Linux
> Note: With Linux kernel versions greater than 4.4, CONFIG_IO_STRICT_DEVMEM a new kernel security measure can make flashrom stop working, in that case you can try adding iomem=relaxed to your kernel parameters.
By ensuring that immediately after the Holochain conductor loads the key material from the USB, that the USB is ejected, modules removed, and the kernel permanently prevented from loading new modules, no further access to the USB is possible. Any new kernel modules must be included in a signed kernel+initrd update from Holo.
By preventing access to device memory, and preventing upgrading the BIOS, we prevent post-boot programs from adjusting the boot procedure.
Of course, physical access to the HoloPort allows circumvention of all of these protectsion.
### Booting HoloPort & Authenticating to Holo ZT Network
1 cloudflare worker microservice (zato is deprecated)
HC key is generated, data sent to service, Email sent, email validation link clicked, node authorized on zerotier
Holoport detects it is authorized on zerotier
We now map into Holo router.
```mermaid
sequenceDiagram
participant quickstart.holo.host
participant Holoport
participant Cloudflare Worker
participant Freshdesk API
participant Email Validate
participant Zerotier API
participant Holo Router
quickstart.holo.host->>Holoport: Submit email, key entropy via USB stick
loop Holoport
Holoport->>Holoport: Generate keys
end
Holoport->>Cloudflare Worker: POST email, zt_address
Cloudflare Worker->>Freshdesk API: check email
# Cloudflare Worker->>quickstart.holo.host: email found/not found in freshdesk.
Freshdesk API->>Cloudflare Worker: email valid
Cloudflare Worker->>Email Validate: Validation Email sent.
#Cloudflare Worker->>quickstart.holo.host: Validation Email event.
Email Validate->>Cloudflare Worker: link clicked
#Cloudflare Worker->>quickstart.holo.host: email validation link clicked.
Cloudflare Worker->>Zerotier API: Node authorized on zerotier network
#Cloudflare Worker->>quickstart.holo.host: node authorized on zerotier.
Zerotier API->>Holoport: Holoport Recognizes Node Auth on zerotier
Holoport->>Holo Router: Holoport writes key and signature to router
quickstart.holo.host->>Holo Router: test for hp-admin DNS
Holo Router->>quickstart.holo.host: Success! Start hp-admin
```
## HP Admin API
## Authentication
http basic auth
### OS Update
```
user:pass (signed requests with key derived from password)
POST /os-update
Responses
HTTP 200 OK
HTTP 401 Unauthorized
```
## OS info
```
user:pass
GET /os-info
Reponses
HTTP 200 OK
{
"public_key":"<key>",
"email":"</email>",
"registered":true,
"zero_tier":"status from zt listnetworks info",
"os_version":"<version>",
"os_release_version":"<release_version>"
}
HTTP 401 Unauthorized
```
## Reset holoport
A rescue image on USB stick will be required to address this
### Reset states:
#### Factory reset zero out to virgin OS uninitialized
(Throw away all data on restored machine)
#### Restore or transfer to another machine initialized state
Reset and save all data
#### Backup all mutable data
We just back up all mutable data
### Sketch of Holoport services