diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 205bedaf0b86d05a8f87ffcf368d6024d2fd57cb..b91f7d5f175a32a49a5ed0788a87146d9b86c3f3 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -23,6 +23,7 @@ unit-tests: vulnerability-scan: stage: "test" script: + - "sed -i 's/undefined/\"unundefined\"/' morph/grid/local/secrets/users.nix" - "ci-tools/vulnerability-scan security-report.json" - "ci-tools/count-vulnerabilities <security-report.json" artifacts: diff --git a/ci-tools/vulnerability-scan b/ci-tools/vulnerability-scan index 48bf51e071a398f37565717a22b2066d3f905fbe..3162e49511697ed0ea13e0121a67336405ce5225 100755 --- a/ci-tools/vulnerability-scan +++ b/ci-tools/vulnerability-scan @@ -21,7 +21,7 @@ OUTPUT=$1 [ -e scan-target ] && rm -v scan-target nix-shell --run ' set -x -if morph_result=$(morph build morph/grid/testing/grid.nix 2>&1); then +if morph_result=$(morph build morph/grid/local/grid.nix 2>&1); then object=$(echo "$morph_result" | tail -n 1) ln -s "$object" scan-target else diff --git a/morph/README.rst b/morph/README.rst index d4a89a373a1bef767ad26859d495f1528a4fb7ca..12472518ad8e061764d6812694c306e87553c843 100644 --- a/morph/README.rst +++ b/morph/README.rst @@ -42,6 +42,23 @@ grid Specific grid definitions live in subdirectories beneath this directory. +secrets +~~~~~~~ + +This must be created and populated before the grid can be built or deployed. + +This directory contains all of the secrets necessary to deploy the grid. +Secrets beneath this directory are referenced by ``config.json`` and ``grid.nix`` +(and possibly elsewhere). +Some of the paths are configurable and some are just convention. +This path is **ignored** by git. +The intended workflow is that the secrets will be maintained on secure storage and a symlink to the correct location created here. +This keeps the secrets themselves out of the git working tree as an extra protection against unintentionally committing them. + +An exception is the ``secrets`` directory in the ``local`` morph grid: +That directory is fully populated, provided as an example, and mostly: not very secret. +Do not deploy these keys to machines reachable via the internet. + config.json ~~~~~~~~~~~ diff --git a/morph/grid/local/.gitignore b/morph/grid/local/.gitignore index 86a37fb6544e909b2b2cd8579d5756d6d2d319da..8000dd9db47c0b9dd34046ec17880dcbb27e5eb9 100644 --- a/morph/grid/local/.gitignore +++ b/morph/grid/local/.gitignore @@ -1,2 +1 @@ .vagrant - diff --git a/morph/grid/local/README.rst b/morph/grid/local/README.rst index 38981f75bfb82dbac31269f8abdcd086ca7e4c8d..73bfbbdd2a11922fe696161fe8346d7e10157313 100644 --- a/morph/grid/local/README.rst +++ b/morph/grid/local/README.rst @@ -1,71 +1,51 @@ Set up and use a network of local development VMs ------------------------------------------------- -... using `Vagrant <https://www.vagrantup.com/>`_ to manage VirtualBox VMs [#]_. -To get started, first install Vagrant and make sure it works. -One possible way to do it in NixOS: +... using `Vagrant <https://www.vagrantup.com/>`_ to manage VirtualBox VMs. +(The author of this documentation wasted a lot of time trying to get Vagrant to work with KVM/libvirt. +Issues with networking that looked like guest misconfigurations vanished after changing to the better-tested combination of Vagrant and VirtualBox.) -1. Install Vagrant, by adding the packages: - - - ``vagrant`` (orchestrating virtual machines on the command line) - - Only use when version >= 2.2.16 has become available. Else see below. - - Optional: ``packer`` (for creating your own VM images) - -2. Add configuration to install and enable VirtualBox: - - - ``virtualisation.virtualbox.host.enable = true;`` - -3. Add your user to the ``vboxusers`` group, for example: - - - ``users.extraGroups.vboxusers.members = [ "flo" "jp" ];`` - - -.. [#] The author of this documentation wasted a lot of time trying to get Vagrant to work with KVM/libvirt. Issues with networking that looked like guest misconfigurations vanished after changing to the better-tested combination of Vagrant and VirtualBox. +Use the local development environment +````````````````````````````````````` -Pre-Vagrant 2.2.16: Get Vagrant with the required fixes for NixOS guests -```````````````````````````````````````````````````````````````````````` +1. Enter the morph local grid directory:: -The Vagrant nixos-guest template `received a critical update on 2021-03-08 <https://github.com/hashicorp/vagrant/commit/990d94ed9d0b3092e855bc1bb9deeeb7aa7792cf>`_ which came out with Vagrant version 2.2.16. + cd morph/grid/local -If you run an older Nixpkgs, retrieve and use the latest Vagrant development version like so:: +2. Enter the project's nix-shell:: - NIX_PATH=nixpkgs=https://github.com/NixOS/nixpkgs/archive/refs/heads/master.tar.gz nix-shell -p vagrant + nix-shell ../../../shell.nix - -Use the local development environment -````````````````````````````````````` - -1. Build and start the VMs:: +3. Build and start the VMs:: VAGRANT_DEFAULT_PROVIDER=virtualbox vagrant up -2. Then, once:: +4. Then, add the Vagrant SSH configuration to your user's ``~/.ssh/config`` file:: - vagrant ssh-config > ./vagrant-ssh-config + install -d ~/.ssh ; vagrant ssh-config >> ~/.ssh/config -3. Edit the output: Add the IPs from ``grid.nix`` to the ``vagrant-ssh-config`` **Host match blocks** so the config reads like:: +5. Edit the generated configuration: Add the ``publicIP`` addresses from ``grid.nix`` to ssh config **Host** match blocks (**not** HostName) so the ``Host`` lines all read like:: Host payments1 192.168.67.21 - HostName 192.168.67.21 + HostName 127.0.0.1 User vagrant - Port 22 [...] -4. Then, make morph use this ssh config either - with newer morph [#]_ - by pointing it to it:: - - export SSH_CONFIG_FILE=./vagrant-ssh-config + Latest Morph honors the ``SSH_CONFIG_FILE`` environment variable (`since 3f90aa88 (March 2020, v 1.5.0) <https://github.com/DBCDK/morph/commit/3f90aa885fac1c29fce9242452fa7c0c505744ef#diff-d155ad793bd62e6ea4c44ba985049ecb13a4f4f32f799791b2bce695a16c0101>`_), so in the future this should get a bit more convenient. - Or, with older morph, adding the config to your user's ``~/.ssh/config`` file. +6. Add your SSH key to ``users.nix`` so you'll be able to log in after deploying the new configuration:: - .. [#] Morph honors the ``SSH_CONFIG_FILE`` environment variable `since 3f90aa88 (March 2020, v 1.5.0) <https://github.com/DBCDK/morph/commit/3f90aa885fac1c29fce9242452fa7c0c505744ef#diff-d155ad793bd62e6ea4c44ba985049ecb13a4f4f32f799791b2bce695a16c0101>`_. + $EDITOR secrets/users.nix -5. Then, build and deploy our software to the Vagrant VMs:: +7. Then, build and deploy our software to the Vagrant VMs:: morph build grid.nix morph push grid.nix + morph deploy grid.nix boot + vagrant halt + vagrant up morph upload-secrets grid.nix - morph deploy grid.nix switch - You will now be able to log in with the users and keys you set in your ``localdev-users.nix`` file. + You should now be able to log in with the users and keys you set in your ``users.nix`` file. diff --git a/morph/grid/local/Vagrantfile b/morph/grid/local/Vagrantfile index 761812c83be88e6bc9196acc06ea405b51573d8c..82bbef1063b108829261670fdceb2e27af8d6764 100644 --- a/morph/grid/local/Vagrantfile +++ b/morph/grid/local/Vagrantfile @@ -14,6 +14,10 @@ Vagrant.configure("2") do |config| config.vm.box_version = "20.09" config.vm.box_check_update = false config.vm.network "private_network", ip: "192.168.67.21" + # Add self signed SSL key for zkap-issuer: + config.vm.provision "file", source: "secrets/payments-localdev-ssl", destination: "/tmp/payments-localdev-ssl" + config.vm.provision "shell", inline: "sudo mkdir -p /var/lib/letsencrypt/live/payments.localdev/" + config.vm.provision "shell", inline: "sudo mv /tmp/payments-localdev-ssl/* /var/lib/letsencrypt/live/payments.localdev/" end config.vm.define "storage1" do |config| diff --git a/morph/grid/local/config.json b/morph/grid/local/config.json index c08955eb24d0c7046dbb4862cf7b81d1ca3e0a0a..38f00367bf2fa36ad7663c89f7849146783b8515 100644 --- a/morph/grid/local/config.json +++ b/morph/grid/local/config.json @@ -1,10 +1,10 @@ { "publicStoragePort": 8898 -, "ristrettoSigningKeyPath": "../../PrivateStorageSecrets/ristretto.signing-key" -, "stripeSecretKeyPath": "../../PrivateStorageSecrets/privatestorageio-testing-stripe.secret" -, "monitoringvpnKeyDir": "../../PrivateStorageSecrets/monitoringvpn" +, "ristrettoSigningKeyPath": "./secrets/ristretto.signing-key" +, "stripeSecretKeyPath": "./secrets/stripe.secret" +, "monitoringvpnKeyDir": "./secrets/monitoringvpn" , "monitoringvpnEndpoint": "192.168.67.24:51820" , "passValue": 1000000 -, "issuerDomain": "payments.localdev" +, "issuerDomains": ["payments.localdev"] , "letsEncryptAdminEmail": "florian@privatestorage.io" , "allowedChargeOrigins": [ "http://localhost:5000" diff --git a/morph/grid/local/grid.nix b/morph/grid/local/grid.nix index b71c6e614de9eeedc2cd7ed6f3d0b8fb289e9268..0c114ccf11b9ddb963d5e2e6297b6a7c83792aba 100644 --- a/morph/grid/local/grid.nix +++ b/morph/grid/local/grid.nix @@ -6,7 +6,10 @@ import ../../lib/make-grid.nix { config = ./config.json; nodes = cfg: let - sshUsers = import ../../../../PrivateStorageSecrets/localdev-users.nix; + sshUsers = import ./secrets/users.nix; + + # Get absolute vpn key directory path, as a string: + monitoringvpnKeyDir = toString ./. + "/${cfg.monitoringvpnKeyDir}"; # TBD: derive these automatically: hostsMap = { @@ -19,31 +22,34 @@ import ../../lib/make-grid.nix { nodeExporterTargets = [ "monitoring1" "payments1" "storage1" "storage2" ]; in { - "payments1" = import ../../lib/make-issuer.nix (rec { + "payments1" = import ../../lib/make-issuer.nix (cfg // rec { publicIPv4 = "192.168.67.21"; monitoringvpnIPv4 = "172.23.23.11"; hardware = import ./virtual-hardware.nix ({ inherit publicIPv4; }); stateVersion = "19.03"; + inherit monitoringvpnKeyDir; inherit sshUsers; - } // cfg); + }); - "storage1" = import ../../lib/make-testing.nix (rec { + "storage1" = import ../../lib/make-testing.nix (cfg // rec { publicIPv4 = "192.168.67.22"; monitoringvpnIPv4 = "172.23.23.12"; hardware = import ./virtual-hardware.nix ({ inherit publicIPv4; }); stateVersion = "19.09"; + inherit monitoringvpnKeyDir; inherit sshUsers; - } // cfg); + }); - "storage2" = import ../../lib/make-testing.nix (rec { + "storage2" = import ../../lib/make-testing.nix (cfg // rec { publicIPv4 = "192.168.67.23"; monitoringvpnIPv4 = "172.23.23.13"; hardware = import ./virtual-hardware.nix ({ inherit publicIPv4; }); stateVersion = "19.09"; + inherit monitoringvpnKeyDir; inherit sshUsers; - } // cfg); + }); - "monitoring1" = import ../../lib/make-monitoring.nix (rec { + "monitoring1" = import ../../lib/make-monitoring.nix (cfg // rec { publicIPv4 = "192.168.67.24"; monitoringvpnIPv4 = "172.23.23.1"; inherit vpnClientIPs; @@ -51,7 +57,8 @@ import ../../lib/make-grid.nix { inherit nodeExporterTargets; hardware = import ./virtual-hardware.nix ({ inherit publicIPv4; }); stateVersion = "19.09"; + inherit monitoringvpnKeyDir; inherit sshUsers; - } // cfg); + }); }; } diff --git a/morph/grid/local/secrets/monitoringvpn/172.23.23.11.key b/morph/grid/local/secrets/monitoringvpn/172.23.23.11.key new file mode 100644 index 0000000000000000000000000000000000000000..22f11b7bc230a1a1b08d68850caa375171cc386d --- /dev/null +++ b/morph/grid/local/secrets/monitoringvpn/172.23.23.11.key @@ -0,0 +1 @@ +cLP62YAYoA7FY+OhSLR64DIHekOjGGQlfJAWp5cYP00= diff --git a/morph/grid/local/secrets/monitoringvpn/172.23.23.11.pub b/morph/grid/local/secrets/monitoringvpn/172.23.23.11.pub new file mode 100644 index 0000000000000000000000000000000000000000..44c0d84b7ad9c50c75c379fd7589dd33370b3e58 --- /dev/null +++ b/morph/grid/local/secrets/monitoringvpn/172.23.23.11.pub @@ -0,0 +1 @@ +GYNjLkoyQ1d3OMymYbgq40WAHIUzrSEGBWXvxqceF00= diff --git a/morph/grid/local/secrets/monitoringvpn/172.23.23.12.key b/morph/grid/local/secrets/monitoringvpn/172.23.23.12.key new file mode 100644 index 0000000000000000000000000000000000000000..e717bf7ec42129926ceae6c7a44372738162378e --- /dev/null +++ b/morph/grid/local/secrets/monitoringvpn/172.23.23.12.key @@ -0,0 +1 @@ +qFjBtvJKBchzl2HwFvEDoe3zFzyc10osiRlP8HOk2n0= diff --git a/morph/grid/local/secrets/monitoringvpn/172.23.23.12.pub b/morph/grid/local/secrets/monitoringvpn/172.23.23.12.pub new file mode 100644 index 0000000000000000000000000000000000000000..18110f20c3bb734fd229f1bd7f87f37050130b6a --- /dev/null +++ b/morph/grid/local/secrets/monitoringvpn/172.23.23.12.pub @@ -0,0 +1 @@ +veio/0E0sJYOjwp3E8EccCyME1pqjkZr4R6whFMdrhs= diff --git a/morph/grid/local/secrets/monitoringvpn/172.23.23.13.key b/morph/grid/local/secrets/monitoringvpn/172.23.23.13.key new file mode 100644 index 0000000000000000000000000000000000000000..6dd5087e19e8e9e97f3b459a30563555d10de155 --- /dev/null +++ b/morph/grid/local/secrets/monitoringvpn/172.23.23.13.key @@ -0,0 +1 @@ +8HlKTvxZBAZeww6JaNk9kBPjSfT0pVMbDJbzV67yUGE= diff --git a/morph/grid/local/secrets/monitoringvpn/172.23.23.13.pub b/morph/grid/local/secrets/monitoringvpn/172.23.23.13.pub new file mode 100644 index 0000000000000000000000000000000000000000..d80b7abbfa20982e69772e6cd66f20dea946582d --- /dev/null +++ b/morph/grid/local/secrets/monitoringvpn/172.23.23.13.pub @@ -0,0 +1 @@ +4VlUMl9FubrLWaN0pRvfdNjjRBQzfCVLMA2lU7OwPzA= diff --git a/morph/grid/local/secrets/monitoringvpn/preshared.key b/morph/grid/local/secrets/monitoringvpn/preshared.key new file mode 100644 index 0000000000000000000000000000000000000000..4389e80504f524ecb9b8ee2e8248882da55a7097 --- /dev/null +++ b/morph/grid/local/secrets/monitoringvpn/preshared.key @@ -0,0 +1 @@ +E7KTLVnWMmP/mIEkU8WX2DBZJaeMS2+sYArRZuGT1o4= diff --git a/morph/grid/local/secrets/monitoringvpn/server.key b/morph/grid/local/secrets/monitoringvpn/server.key new file mode 100644 index 0000000000000000000000000000000000000000..01058684fdb2438b4bff23f0370939628c3ef18c --- /dev/null +++ b/morph/grid/local/secrets/monitoringvpn/server.key @@ -0,0 +1 @@ +iOp2pk2HWyNgRnke7nJgFwodkTWMyHRIKwe8pk+bN3M= diff --git a/morph/grid/local/secrets/monitoringvpn/server.pub b/morph/grid/local/secrets/monitoringvpn/server.pub new file mode 100644 index 0000000000000000000000000000000000000000..188c4b4cdea11ca02add26cba104ce61af0ee4c1 --- /dev/null +++ b/morph/grid/local/secrets/monitoringvpn/server.pub @@ -0,0 +1 @@ +ojo+p9ZE03GN66ewoIlrHmyV7ICt+2LV32Prs66JsA4= diff --git a/morph/grid/local/secrets/payments-localdev-ssl/cert.pem b/morph/grid/local/secrets/payments-localdev-ssl/cert.pem new file mode 100644 index 0000000000000000000000000000000000000000..5300ed591899cb802f2ceff49ac5aa195bb87d12 --- /dev/null +++ b/morph/grid/local/secrets/payments-localdev-ssl/cert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDGTCCAgGgAwIBAgIUM9YnOMe2yYQuCLpYiI2TpZg21AMwDQYJKoZIhvcNAQEL +BQAwHDEaMBgGA1UEAwwRcGF5bWVudHMubG9jYWxkZXYwHhcNMjEwNjA5MTQzNzU4 +WhcNMzEwNjA3MTQzNzU4WjAcMRowGAYDVQQDDBFwYXltZW50cy5sb2NhbGRldjCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOBCvkMprdRjD8ECeweMVTFT +pILu5VA8HC8XK15Y4iE8G48cSYE3m/e6w5g4JvfXgED9eY+1/ZazQXVI6sojnfHL +Vj9XqsUww3IVtq2Zn+0B8YTrbNxcDH77mUx0mUziAm1bglmoNbd4+q0Fe8FhK/EN +Jj7UppRjD2ziV9Mw7UT1JjMbfSo7/7ZOV2cWk+hezOywsE+3BM6mju1aHbbYryAd +EzRwfQKcI/9PC84Bck9e+tEiWQImBf8DguQ+ChuSOmGtP1rI+hq5HfCimH0NCCNS +iUfNVcubz920FRBeAx9oM0G/u4feeS8T5a1PThZrdhjIycEmU5wsM7F34RzkuEkC +AwEAAaNTMFEwHQYDVR0OBBYEFAbBfAFOlx4c53CNgsRlobFwUIBbMB8GA1UdIwQY +MBaAFAbBfAFOlx4c53CNgsRlobFwUIBbMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI +hvcNAQELBQADggEBACD+47l30gGaZBPvuCMc/CENLmuqZqj7WGGmWcmUAzsdEgHt +Q1zhj4un4u4qQ78jeT+cjqNK9qartQIjxzYTpn6lKDBpM9sS2G7RdLxOWWRVAXQj +Cv6l0tEQArIqqMnzmECe0VDCc97kTg6tnMLFeyQL29XSSNIpS0DiQ+NC69fyrF2E +vt2bAi+QTlN1U1ZGDJqWlwqkpI3xTRDJnmRPuVNrt07gkMWeSJHEI98Qcve7Ujf3 +hFcAnbshJ8iXxbNjTFIQcCJzHq1UF+eZo8BF1ixYmrk/jmaLNBOSy93tOk1XeJfS +XtV6X9jmAE20V0XV8uCli6cDxQQYthll/1q5JYQ= +-----END CERTIFICATE----- diff --git a/morph/grid/local/secrets/payments-localdev-ssl/chain.pem b/morph/grid/local/secrets/payments-localdev-ssl/chain.pem new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/morph/grid/local/secrets/payments-localdev-ssl/privkey.pem b/morph/grid/local/secrets/payments-localdev-ssl/privkey.pem new file mode 100644 index 0000000000000000000000000000000000000000..36b699fab9e7dac880daf89ae3f9a7ea9ce732ef --- /dev/null +++ b/morph/grid/local/secrets/payments-localdev-ssl/privkey.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDgQr5DKa3UYw/B +AnsHjFUxU6SC7uVQPBwvFyteWOIhPBuPHEmBN5v3usOYOCb314BA/XmPtf2Ws0F1 +SOrKI53xy1Y/V6rFMMNyFbatmZ/tAfGE62zcXAx++5lMdJlM4gJtW4JZqDW3ePqt +BXvBYSvxDSY+1KaUYw9s4lfTMO1E9SYzG30qO/+2TldnFpPoXszssLBPtwTOpo7t +Wh222K8gHRM0cH0CnCP/TwvOAXJPXvrRIlkCJgX/A4LkPgobkjphrT9ayPoauR3w +oph9DQgjUolHzVXLm8/dtBUQXgMfaDNBv7uH3nkvE+WtT04Wa3YYyMnBJlOcLDOx +d+Ec5LhJAgMBAAECggEARI3in6FkFCLcNAJQHbSWbmfFSIlC7E4Tx4lrpoHBTquT +OSJKjgez0/zxwdyYfPcRq8xQls/pX2IYxoOt0nEk3T9tdBuWhoUrmfptR5BIxSjs +7dcSBiLVZxP+ftK98jS8zTVGGaZEFXwUFUQx2qGbzypX4Kkc6wuFMaHXeyXfwk4j +v3lOTpT7kX/3iVXzQU9Y5m45W1bbt3lSV4yCndOt/4Xg5d4ue6UcUsyg/r8m5wsU +nCc14L0HsY/VCCRISmDwa4UoqHGfQv6+XXxLT8gJM7H8PkZK8TRV/ZG2Yug63wDS +xkhMZBodGoYuQpB19Y+NxjwG8Se7RxcCAyS7zcYcCQKBgQD/VWesc2/TplikifQf +LJl+utiQ9G/o3wAquAKInxQOcUxOm1fsvjgsLfrjpAVj0D3qD0Sf3lSp7z3tpUMf +MSi9MgNunSU7pKST7jex6BJNU0TTRcFnoqcIlUYiDoLLbkkVlf8Nome88gkwJRKZ +RjI+6ES9hGaM85QEgjdtRNGXIwKBgQDg2JPfVXYyrOIITus/DHHv8em1RuGCIe6X +T3M0+GgJ27hOEeneAyzk4aWvVzE3/3lxx55ePGRAz43jPrUxn0kfy/Jx4UMKsEW+ +XzR7CfxTxamUx/mq2bbqk+bbnXZZQedAip4eQ23GbWdrE4/v83JXzWj355yUQCQk +uuIcda7fowKBgEY20CmmHOxQ5DNrFEy2UQd+jitebJ/XIw6cR2YWiMdn9JnxMf6S +WJQdmM6cvjayfzQsOqzT0OhiN99wAMNFG3TbmgIDCMgcAH4Flh9AODg3W8fVeNfs +7I35rq2S2/jhPQvIkbjIHkrhLBGnQDQSD6Mo8C5FiIXePaf3vxI3SIONAoGAZdOv +pEUf8nM5KmoTP8pzDyePn/kpx7V2SDBDDIozE8PeA/043MKzYjSOxInIUIPyjATL +RAI1pORabb/Ib2CjzTKf6dMKeZy6+SxEqDQtggLSef7WovlWTYYN1wfIwUOHZ0Nf +uHTxEhwZ6fRCC3lFH153W04ZK0qhE8FPBXSGbeECgYBcY0QmOd3ao3v0xscKmPlM +E9MICgwgEJ6pAsaOI30OHqUAtlqrlw5ph3skxlLUpHWW6OUczUUV6nwguk4piuee +1J9uuA02FlIvvUy5Bsrgqlu0Lj5vJ8Im2Go9dJ8k/m9J5BUgDdPuNwnmjiyNQurd +Fl50FWx/3WeJB2qK981vmw== +-----END PRIVATE KEY----- diff --git a/morph/grid/local/secrets/ristretto.signing-key b/morph/grid/local/secrets/ristretto.signing-key new file mode 100644 index 0000000000000000000000000000000000000000..8726b7060694499f61cc15ba826f3933b88795a5 --- /dev/null +++ b/morph/grid/local/secrets/ristretto.signing-key @@ -0,0 +1 @@ +NAQBkEEUKPDtq8af5anlHvWMjeSVoH56RnpCTy70QwA= \ No newline at end of file diff --git a/morph/grid/local/secrets/stripe.secret b/morph/grid/local/secrets/stripe.secret new file mode 100644 index 0000000000000000000000000000000000000000..ebf3fdabcd222af9ca7ed46bf0b45a2fd18a603e --- /dev/null +++ b/morph/grid/local/secrets/stripe.secret @@ -0,0 +1 @@ +sk_test_Dr+XLVjkC0oO3Zw8Ws0yWtDLqR1sM+/fmw diff --git a/morph/grid/local/secrets/users.nix b/morph/grid/local/secrets/users.nix new file mode 100644 index 0000000000000000000000000000000000000000..93a8b660c78fa12b1e20c6d560f78efb1b5684c7 --- /dev/null +++ b/morph/grid/local/secrets/users.nix @@ -0,0 +1,4 @@ +# Add your public key. Example: +# let key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHx7wJQNqKn8jOC4AxySRL2UxidNp7uIK9ad3pMb1ifF flo@fs-la"; +let key = undefined; +in { "root" = key; "vagrant" = key; } diff --git a/morph/grid/production/.gitignore b/morph/grid/production/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..db2fc0de62d01d6d7eec83f8f3e8c3b13b20392a --- /dev/null +++ b/morph/grid/production/.gitignore @@ -0,0 +1 @@ +secrets diff --git a/morph/grid/production/config.json b/morph/grid/production/config.json index ec60acc70dcdc90409b84e0b19ce9c2cb3d27cfa..e71cb8b4b5f999e3059f0669c2bc3f92f29242a6 100644 --- a/morph/grid/production/config.json +++ b/morph/grid/production/config.json @@ -1,11 +1,16 @@ { "publicStoragePort": 8898 -, "ristrettoSigningKeyPath": "../../PrivateStorageSecrets/ristretto.signing-key" -, "stripeSecretKeyPath": "../../PrivateStorageSecrets/stripe.secret" +, "ristrettoSigningKeyPath": "./secrets/ristretto.signing-key" +, "stripeSecretKeyPath": "./secrets/stripe.secret" , "passValue": 1000000 -, "issuerDomain": "payments.privatestorage.io" +, "issuerDomains": [ + "payments.privatestorage.io" + , "payments.private.storage" + ] , "letsEncryptAdminEmail": "jean-paul@privatestorage.io" , "allowedChargeOrigins": [ "https://privatestorage.io" , "https://www.privatestorage.io" + , "https://private.storage" + , "https://www.private.storage" ] } diff --git a/morph/grid/production/grid.nix b/morph/grid/production/grid.nix index 7c9abe142fa98a6ceeebb3c8dc6d53dec2622e8c..f5735d259dbff27f1d9cabbbca512af81d4550bb 100644 --- a/morph/grid/production/grid.nix +++ b/morph/grid/production/grid.nix @@ -6,7 +6,7 @@ import ../../lib/make-grid.nix { config = ./config.json; nodes = cfg: let - sshUsers = import ../../../../PrivateStorageSecrets/production-users.nix; + sshUsers = import ./secrets/users.nix; in { # Here are the hosts that are in this morph network. This is sort of like # a server manifest. We try to keep as many of the specific details as diff --git a/morph/grid/testing/.gitignore b/morph/grid/testing/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..db2fc0de62d01d6d7eec83f8f3e8c3b13b20392a --- /dev/null +++ b/morph/grid/testing/.gitignore @@ -0,0 +1 @@ +secrets diff --git a/morph/grid/testing/config.json b/morph/grid/testing/config.json index d0b1b814601ec076aa3fb77b55e589f8e7c5782d..f5aed85fe73e24b8403b4bce9cb34aefc8091d34 100644 --- a/morph/grid/testing/config.json +++ b/morph/grid/testing/config.json @@ -1,10 +1,14 @@ { "publicStoragePort": 8898 -, "ristrettoSigningKeyPath": "../../PrivateStorageSecrets/ristretto.signing-key" -, "stripeSecretKeyPath": "../../PrivateStorageSecrets/privatestorageio-testing-stripe.secret" -, "monitoringvpnKeyDir": "../../PrivateStorageSecrets/monitoringvpn" +, "ristrettoSigningKeyPath": "./secrets/ristretto.signing-key" +, "stripeSecretKeyPath": "./secrets/privatestorageio-testing-stripe.secret" +, "monitoringvpnKeyDir": "./secrets/monitoringvpn" , "monitoringvpnEndpoint": "monitoring.privatestorage-staging.com:51820" +, "stripeSecretKeyPath": "./secrets/stripe.secret" , "passValue": 1000000 -, "issuerDomain": "payments.privatestorage-staging.com" +, "issuerDomains": [ + "payments.privatestorage-staging.com" + , "payments.extra.privatestorage-staging.com" + ] , "letsEncryptAdminEmail": "jean-paul@privatestorage.io" , "allowedChargeOrigins": [ "http://localhost:5000" diff --git a/morph/grid/testing/grid.nix b/morph/grid/testing/grid.nix index ed002cbe0a23a60874201c1dbf6bea15a36a1d87..e31a28f2eb7817f393f4e8b6b71972b7fd2f79f1 100644 --- a/morph/grid/testing/grid.nix +++ b/morph/grid/testing/grid.nix @@ -6,49 +6,49 @@ import ../../lib/make-grid.nix { config = ./config.json; nodes = cfg: let - importDef = default: path: ( - if builtins.pathExists path - then import path - else default - ); - sshUsers = importDef {} ../../../../PrivateStorageSecrets/staging-users.nix; + sshUsers = import ./secrets/users.nix; + + # Get absolute vpn key directory path, as a string: + monitoringvpnKeyDir = toString ./. + "/${cfg.monitoringvpnKeyDir}"; # TBD: derive these automatically: hostsMap = { "172.23.23.1" = [ "monitoring" "monitoring.monitoringvpn" ]; - "172.23.23.11" = [ "payments" "payments.monitoringvpn" ]; + "172.23.23.11" = [ "payments" "payments.monitoringvpn" ]; "172.23.23.12" = [ "storage001" "storage001.monitoringvpn" ]; }; vpnClientIPs = [ "172.23.23.11" "172.23.23.12" ]; nodeExporterTargets = [ "monitoring" "payments" "storage001" ]; in { - "payments" = import ../../lib/make-issuer.nix ({ - publicIPv4 = "18.197.42.120"; + "payments" = import ../../lib/make-issuer.nix (cfg // { + publicIPv4 = "18.194.183.13"; monitoringvpnIPv4 = "172.23.23.11"; + inherit monitoringvpnKeyDir; inherit sshUsers; hardware = ../../lib/issuer-aws.nix; stateVersion = "19.03"; - } // cfg); + }); "storage001" = import ../../lib/make-testing.nix (cfg // { publicIPv4 = "3.120.26.190"; monitoringvpnIPv4 = "172.23.23.12"; + inherit monitoringvpnKeyDir; inherit sshUsers; hardware = ./testing001-hardware.nix; stateVersion = "19.03"; }); - "monitoring" = import ../../lib/make-monitoring.nix ({ + "monitoring" = import ../../lib/make-monitoring.nix (cfg // { publicIPv4 = "18.156.171.217"; monitoringvpnIPv4 = "172.23.23.1"; + inherit monitoringvpnKeyDir; inherit vpnClientIPs; inherit hostsMap; inherit nodeExporterTargets; - nginxExporterTargets = [ ]; hardware = ../../lib/issuer-aws.nix; stateVersion = "19.09"; inherit sshUsers; - } // cfg); + }); }; } diff --git a/morph/lib/make-issuer.nix b/morph/lib/make-issuer.nix index 7ca7992c94776af560c667f2c0949cb1bfdaed65..bbdf0cebbf770738e9ccb997daec75e58df021b5 100644 --- a/morph/lib/make-issuer.nix +++ b/morph/lib/make-issuer.nix @@ -1,7 +1,7 @@ { hardware , ristrettoSigningKeyPath , stripeSecretKeyPath -, issuerDomain +, issuerDomains , letsEncryptAdminEmail , allowedChargeOrigins , sshUsers @@ -76,7 +76,7 @@ in rec { database = "SQLite3"; databasePath = "/var/db/vouchers.sqlite3"; inherit letsEncryptAdminEmail; - domain = issuerDomain; + domains = issuerDomains; inherit allowedChargeOrigins; }; @@ -86,5 +86,6 @@ in rec { enable = true; ip = monitoringvpnIPv4; endpoint = monitoringvpnEndpoint; + endpointPublicKeyFile = monitoringvpnKeyDir + "/server.pub"; }; } diff --git a/morph/lib/make-monitoring.nix b/morph/lib/make-monitoring.nix index acd8c1e924f48b5a838b209e4bb09d21f34f368f..8eb53c6db9552e65a84e5d3e5564449db437e902 100644 --- a/morph/lib/make-monitoring.nix +++ b/morph/lib/make-monitoring.nix @@ -40,8 +40,7 @@ in rec { deployment = { targetHost = publicIPv4; - - secrets = { } // vpnSecrets; + secrets = vpnSecrets; }; imports = [ @@ -58,6 +57,7 @@ in rec { enable = true; ip = monitoringvpnIPv4; inherit vpnClientIPs; + pubKeysPath = monitoringvpnKeyDir; }; services.private-storage.monitoring.grafana = { diff --git a/morph/lib/make-testing.nix b/morph/lib/make-testing.nix index 974cfcbb69d8160bef682ccaf2bbdeda197b1f41..3f6e767db5ee734a8ca2314b216d4fa602c01907 100644 --- a/morph/lib/make-testing.nix +++ b/morph/lib/make-testing.nix @@ -75,5 +75,6 @@ in rec { enable = true; ip = monitoringvpnIPv4; endpoint = monitoringvpnEndpoint; + endpointPublicKeyFile = monitoringvpnKeyDir + "/server.pub"; }; } diff --git a/nixos/modules/issuer.nix b/nixos/modules/issuer.nix index 6ad4f1b8fa01d570e8b6e1d5c4acfbeb42757822..fb93ce35cce8c9cadbad5a04e888b0cca991f9c7 100644 --- a/nixos/modules/issuer.nix +++ b/nixos/modules/issuer.nix @@ -18,12 +18,11 @@ in { The package to use for the ZKAP issuer. ''; }; - services.private-storage-issuer.domain = lib.mkOption { - default = "payments.privatestorage.io"; - type = lib.types.str; - example = lib.literalExample "payments.example.com"; + services.private-storage-issuer.domains = lib.mkOption { + type = lib.types.listOf lib.types.str; + example = lib.literalExample [ "payments.example.com" ]; description = '' - The domain name at which the issuer is reachable. + The domain names at which the issuer is reachable. ''; }; services.private-storage-issuer.tls = lib.mkOption { @@ -115,6 +114,10 @@ in { config = let certroot = "/var/lib/letsencrypt/live"; + # We'll refer to this collection of domains by the first domain in the + # list. + domain = builtins.head cfg.domains; + certServiceName = "cert-${domain}"; in lib.mkIf cfg.enable { # Add a systemd service to run PaymentServer. systemd.services.zkapissuer = { @@ -124,7 +127,7 @@ in { # Make sure we have a certificate the first time, if we are running over # TLS and require a certificate. - requires = lib.optional cfg.tls "cert-${cfg.domain}.service"; + requires = lib.optional cfg.tls "${certServiceName}.service"; after = [ # Make sure there is a network so we can bind to all of the @@ -133,7 +136,7 @@ in { ] ++ # Make sure we run after the certificate is issued, if we are running # over TLS and require a certificate. - lib.optional cfg.tls "cert-${cfg.domain}.service"; + lib.optional cfg.tls "${certServiceName}.service"; # It really shouldn't ever exit on its own! If it does, it's a bug # we'll have to fix. Restart it and hope it doesn't happen too much @@ -157,9 +160,9 @@ in { if cfg.tls then "--https-port 443 " + - "--https-certificate-path ${certroot}/${cfg.domain}/cert.pem " + - "--https-certificate-chain-path ${certroot}/${cfg.domain}/chain.pem " + - "--https-key-path ${certroot}/${cfg.domain}/privkey.pem" + "--https-certificate-path ${certroot}/${domain}/cert.pem " + + "--https-certificate-chain-path ${certroot}/${domain}/chain.pem " + + "--https-key-path ${certroot}/${domain}/privkey.pem" else # Only for automated testing. "--http-port 80"; @@ -179,20 +182,20 @@ in { # Certificate renewal. We must declare that we *require* it in our # service above. - systemd.services."cert-${cfg.domain}" = { + systemd.services."${certServiceName}" = { enable = true; - description = "Issue/Renew certificate for ${cfg.domain}"; + description = "Certificate ${domain}"; serviceConfig = { ExecStart = let configArgs = "--config-dir /var/lib/letsencrypt --work-dir /var/run/letsencrypt --logs-dir /var/run/log/letsencrypt"; in - pkgs.writeScript "cert-${cfg.domain}-start.sh" '' + pkgs.writeScript "cert-${domain}-start.sh" '' #!${pkgs.runtimeShell} -e # Register if necessary. ${pkgs.certbot}/bin/certbot register ${configArgs} --non-interactive --agree-tos -m ${cfg.letsEncryptAdminEmail} || true # Obtain the certificate. - ${pkgs.certbot}/bin/certbot certonly ${configArgs} --non-interactive --standalone --domains ${cfg.domain} + ${pkgs.certbot}/bin/certbot certonly ${configArgs} --non-interactive --standalone --expand --domains ${builtins.concatStringsSep "," cfg.domains} ''; }; }; diff --git a/nixos/modules/monitoring/vpn/client.nix b/nixos/modules/monitoring/vpn/client.nix index 4c651f612ef7d906a44efd99e68a054b7708c912..dbd50b82ef5b09495e332e6fbb7ac5676f5ac322 100644 --- a/nixos/modules/monitoring/vpn/client.nix +++ b/nixos/modules/monitoring/vpn/client.nix @@ -49,7 +49,6 @@ in { endpointPublicKeyFile = lib.mkOption { type = lib.types.path; example = lib.literalExample ../PrivateStorageSecrets/monitoringvpn/server.pub; - default = ../../../../../PrivateStorageSecrets/monitoringvpn/server.pub; description = '' File with base64 public key generated by <command>cat private.key | wg pubkey > pubkey.pub</command>. ''; diff --git a/nixos/modules/monitoring/vpn/server.nix b/nixos/modules/monitoring/vpn/server.nix index b7f8c00cf74b961ac2e2c4228f824ae8f933b0e5..2374ddc8657fb299fb83155cbabe328cd54c1aaf 100644 --- a/nixos/modules/monitoring/vpn/server.nix +++ b/nixos/modules/monitoring/vpn/server.nix @@ -52,7 +52,6 @@ in { pubKeysPath = lib.mkOption { type = lib.types.path; example = lib.literalExample ../PrivateStorageSecrets/monitoringvpn; - default = ../../../../../PrivateStorageSecrets/monitoringvpn; description = '' The path to the directory that holds the public keys. ''; diff --git a/nixos/modules/ssh.nix b/nixos/modules/ssh.nix index 59ee2fec949be247143041379626f35b7d8bf657..667bdd26215b4e0978781244741dd4c5313cefbd 100644 --- a/nixos/modules/ssh.nix +++ b/nixos/modules/ssh.nix @@ -37,6 +37,10 @@ # password-based authentication at all. PermitEmptyPasswords no + # Agent forwarding is fraught. It can be used by an attacker to + # leverage one compromised system into more. Discourage its use. + AllowAgentForwarding no + # Only allow authentication as one of the configured users, not random # other (often system-managed) users. Possibly this is also # superfluous! NixOS system users have nologin as their shell ... so they diff --git a/nixos/modules/tests/get-passes.py b/nixos/modules/tests/get-passes.py index 691a3d26f37125379df85c85481cfdac67741d07..63b59e5700e0fa0c659f04df8fa889a0501f125f 100755 --- a/nixos/modules/tests/get-passes.py +++ b/nixos/modules/tests/get-passes.py @@ -95,7 +95,7 @@ def charge_json(voucher): return { "token": "tok_abcdef", "voucher": voucher, - "amount": "100", + "amount": "650", "currency": "USD", } diff --git a/nixos/modules/tests/private-storage.nix b/nixos/modules/tests/private-storage.nix index e085f8bc7142da4067745bdee233c82e7b1e8d1c..cbf4c5937ca6780ce9e931d6ceec91c29643fbc3 100644 --- a/nixos/modules/tests/private-storage.nix +++ b/nixos/modules/tests/private-storage.nix @@ -134,7 +134,7 @@ in { services.private-storage-issuer = { enable = true; - domain = "issuer"; + domains = ["issuer"]; tls = false; issuer = "Ristretto"; inherit ristrettoSigningKeyPath; diff --git a/nixpkgs-2105.json b/nixpkgs-2105.json new file mode 100644 index 0000000000000000000000000000000000000000..d441d00995a78a20cc8677a85ced2a675a9502ae --- /dev/null +++ b/nixpkgs-2105.json @@ -0,0 +1,4 @@ +{ "name": "stable2105" +, "url": "https://releases.nixos.org/nixos/21.05/nixos-21.05.804.5de44c15758/nixexprs.tar.xz" +, "sha256": "002zvc16hyrbs0icx1qj255c9dqjpdxx4bhhfjndlj3kwn40by0m" +} diff --git a/nixpkgs.json b/nixpkgs.json index a13edba683061306533106d1f2d1e5c6eacaadba..33b343ef3498ae226218f59be257e808e9a88c7e 100644 --- a/nixpkgs.json +++ b/nixpkgs.json @@ -1,4 +1,4 @@ { "name": "nixpkgs" -, "url": "https://github.com/PrivateStorageio/nixpkgs/archive/d7c46f46c3e6acfcde44bb05877fd5c9f07dfe1b.tar.gz" -, "sha256": "1vddxhp3ljaq9qqzbpjp2kx34ps7nzbsn4zy31x0748a52rlsh0q" +, "url": "https://github.com/PrivateStorageio/nixpkgs/archive/8c7a61c658e32eaccf666e5fe818a996c36a988f.tar.gz" +, "sha256": "1ln0a8c20qykm57wl901lixny1fcfmzgbavd7pbjk6jbnfij59bl" } diff --git a/shell.nix b/shell.nix index b15b7c66b110a785480142c3b1d34b3d365004f6..6e46c9ca0feaa3ab6fbd22c1228ec786a49e79b6 100644 --- a/shell.nix +++ b/shell.nix @@ -1,12 +1,12 @@ let - nixpkgs-pin = builtins.fromJSON (builtins.readFile ./nixpkgs.json); - nixpkgs-src = builtins.fetchTarball nixpkgs-pin; - nixpkgs = import nixpkgs-src { }; + nixpkgs = import (builtins.fetchTarball (builtins.fromJSON (builtins.readFile ./nixpkgs.json))) { }; + stable2105 = import (builtins.fetchTarball (builtins.fromJSON (builtins.readFile ./nixpkgs-2105.json))) { }; in { pkgs ? nixpkgs }: pkgs.mkShell { NIX_PATH = "nixpkgs=${nixpkgs.path}"; buildInputs = [ pkgs.morph + stable2105.vagrant ]; }