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