at 22.05-pre 10 kB view raw
1/* 2 Pleroma E2E VM test. 3 4 Abstract: 5 ========= 6 Using pleroma, postgresql, a local CA cert, a nginx reverse proxy 7 and a toot-based client, we're going to: 8 9 1. Provision a pleroma service from scratch (pleroma config + postgres db). 10 2. Create a "jamy" admin user. 11 3. Send a toot from this user. 12 4. Send a upload from this user. 13 5. Check the toot is part of the server public timeline 14 15 Notes: 16 - We need a fully functional TLS setup without having any access to 17 the internet. We do that by issuing a self-signed cert, add this 18 self-cert to the hosts pki trust store and finally spoof the 19 hostnames using /etc/hosts. 20 - For this NixOS test, we *had* to store some DB-related and 21 pleroma-related secrets to the store. Keep in mind the store is 22 world-readable, it's the worst place possible to store *any* 23 secret. **DO NOT DO THIS IN A REAL WORLD DEPLOYMENT**. 24*/ 25 26import ./make-test-python.nix ({ pkgs, ... }: 27 let 28 send-toot = pkgs.writeScriptBin "send-toot" '' 29 set -eux 30 # toot is using the requests library internally. This library 31 # sadly embed its own certificate store instead of relying on the 32 # system one. Overriding this pretty bad default behaviour. 33 export REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt 34 35 export TOOT_LOGIN_CLI_PASSWORD="jamy-password" 36 toot login_cli -i "pleroma.nixos.test" -e "jamy@nixos.test" 37 echo "Login OK" 38 39 # Send a toot then verify it's part of the public timeline 40 echo "y" | toot post "hello world Jamy here" 41 echo "Send toot OK" 42 echo "y" | toot timeline | grep -c "hello world Jamy here" 43 echo "Get toot from timeline OK" 44 45 # Test file upload 46 echo "y" | toot upload ${db-seed} | grep -c "https://pleroma.nixos.test/media" 47 echo "File upload OK" 48 49 echo "=====================================================" 50 echo "= SUCCESS =" 51 echo "= =" 52 echo "= We were able to sent a toot + a upload and =" 53 echo "= retrieve both of them in the public timeline. =" 54 echo "=====================================================" 55 ''; 56 57 provision-db = pkgs.writeScriptBin "provision-db" '' 58 set -eux 59 sudo -u postgres psql -f ${db-seed} 60 ''; 61 62 test-db-passwd = "SccZOvTGM//BMrpoQj68JJkjDkMGb4pHv2cECWiI+XhVe3uGJTLI0vFV/gDlZ5jJ"; 63 64 /* For this NixOS test, we *had* to store this secret to the store. 65 Keep in mind the store is world-readable, it's the worst place 66 possible to store *any* secret. **DO NOT DO THIS IN A REAL WORLD 67 DEPLOYMENT**.*/ 68 db-seed = pkgs.writeText "provision.psql" '' 69 CREATE USER pleroma WITH ENCRYPTED PASSWORD '${test-db-passwd}'; 70 CREATE DATABASE pleroma OWNER pleroma; 71 \c pleroma; 72 --Extensions made by ecto.migrate that need superuser access 73 CREATE EXTENSION IF NOT EXISTS citext; 74 CREATE EXTENSION IF NOT EXISTS pg_trgm; 75 CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; 76 ''; 77 78 pleroma-conf = '' 79 import Config 80 81 config :pleroma, Pleroma.Web.Endpoint, 82 url: [host: "pleroma.nixos.test", scheme: "https", port: 443], 83 http: [ip: {127, 0, 0, 1}, port: 4000] 84 85 config :pleroma, :instance, 86 name: "NixOS test pleroma server", 87 email: "pleroma@nixos.test", 88 notify_email: "pleroma@nixos.test", 89 limit: 5000, 90 registrations_open: true 91 92 config :pleroma, :media_proxy, 93 enabled: false, 94 redirect_on_failure: true 95 #base_url: "https://cache.pleroma.social" 96 97 config :pleroma, Pleroma.Repo, 98 adapter: Ecto.Adapters.Postgres, 99 username: "pleroma", 100 password: "${test-db-passwd}", 101 database: "pleroma", 102 hostname: "localhost", 103 pool_size: 10, 104 prepare: :named, 105 parameters: [ 106 plan_cache_mode: "force_custom_plan" 107 ] 108 109 config :pleroma, :database, rum_enabled: false 110 config :pleroma, :instance, static_dir: "/var/lib/pleroma/static" 111 config :pleroma, Pleroma.Uploaders.Local, uploads: "/var/lib/pleroma/uploads" 112 config :pleroma, configurable_from_database: false 113 ''; 114 115 /* For this NixOS test, we *had* to store this secret to the store. 116 Keep in mind the store is world-readable, it's the worst place 117 possible to store *any* secret. **DO NOT DO THIS IN A REAL WORLD 118 DEPLOYMENT**. 119 In a real-word deployment, you'd handle this either by: 120 - manually upload your pleroma secrets to /var/lib/pleroma/secrets.exs 121 - use a deployment tool such as morph or NixOps to deploy your secrets. 122 */ 123 pleroma-conf-secret = pkgs.writeText "secrets.exs" '' 124 import Config 125 126 config :joken, default_signer: "PS69/wMW7X6FIQPABt9lwvlZvgrJIncfiAMrK9J5mjVus/7/NJJi1DsDA1OghBE5" 127 128 config :pleroma, Pleroma.Web.Endpoint, 129 secret_key_base: "NvfmU7lYaQrmmxt4NACm0AaAfN9t6WxsrX0NCB4awkGHvr1S7jyshlEmrjaPFhhq", 130 signing_salt: "3L41+BuJ" 131 132 config :web_push_encryption, :vapid_details, 133 subject: "mailto:pleroma@nixos.test", 134 public_key: "BKjfNX9-UqAcncaNqERQtF7n9pKrB0-MO-juv6U5E5XQr_Tg5D-f8AlRjduAguDpyAngeDzG8MdrTejMSL4VF30", 135 private_key: "k7o9onKMQrgMjMb6l4fsxSaXO0BTNAer5MVSje3q60k" 136 ''; 137 138 /* For this NixOS test, we *had* to store this secret to the store. 139 Keep in mind the store is world-readable, it's the worst place 140 possible to store *any* secret. **DO NOT DO THIS IN A REAL WORLD 141 DEPLOYMENT**. 142 In a real-word deployment, you'd handle this either by: 143 - manually upload your pleroma secrets to /var/lib/pleroma/secrets.exs 144 - use a deployment tool such as morph or NixOps to deploy your secrets. 145 */ 146 provision-secrets = pkgs.writeScriptBin "provision-secrets" '' 147 set -eux 148 cp "${pleroma-conf-secret}" "/var/lib/pleroma/secrets.exs" 149 chown pleroma:pleroma /var/lib/pleroma/secrets.exs 150 ''; 151 152 /* For this NixOS test, we *had* to store this secret to the store. 153 Keep in mind the store is world-readable, it's the worst place 154 possible to store *any* secret. **DO NOT DO THIS IN A REAL WORLD 155 DEPLOYMENT**. 156 */ 157 provision-user = pkgs.writeScriptBin "provision-user" '' 158 set -eux 159 160 # Waiting for pleroma to be up. 161 timeout 5m bash -c 'while [[ "$(curl -s -o /dev/null -w '%{http_code}' https://pleroma.nixos.test/api/v1/instance)" != "200" ]]; do sleep 2; done' 162 pleroma_ctl user new jamy jamy@nixos.test --password 'jamy-password' --moderator --admin -y 163 ''; 164 165 tls-cert = pkgs.runCommand "selfSignedCerts" { buildInputs = [ pkgs.openssl ]; } '' 166 openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -nodes -subj '/CN=pleroma.nixos.test' -days 36500 167 mkdir -p $out 168 cp key.pem cert.pem $out 169 ''; 170 171 /* Toot is preventing users from feeding login_cli a password non 172 interactively. While it makes sense most of the times, it's 173 preventing us to login in this non-interactive test. This patch 174 introduce a TOOT_LOGIN_CLI_PASSWORD env variable allowing us to 175 provide a password to toot login_cli 176 177 If https://github.com/ihabunek/toot/pull/180 gets merged at some 178 point, feel free to remove this patch. */ 179 custom-toot = pkgs.toot.overrideAttrs(old:{ 180 patches = [ (pkgs.fetchpatch { 181 url = "https://github.com/NinjaTrappeur/toot/commit/b4a4c30f41c0cb7e336714c2c4af9bc9bfa0c9f2.patch"; 182 sha256 = "sha256-0xxNwjR/fStLjjUUhwzCCfrghRVts+fc+fvVJqVcaFg="; 183 }) ]; 184 }); 185 186 hosts = nodes: '' 187 ${nodes.pleroma.config.networking.primaryIPAddress} pleroma.nixos.test 188 ${nodes.client.config.networking.primaryIPAddress} client.nixos.test 189 ''; 190 in { 191 name = "pleroma"; 192 nodes = { 193 client = { nodes, pkgs, config, ... }: { 194 security.pki.certificateFiles = [ "${tls-cert}/cert.pem" ]; 195 networking.extraHosts = hosts nodes; 196 environment.systemPackages = with pkgs; [ 197 custom-toot 198 send-toot 199 ]; 200 }; 201 pleroma = { nodes, pkgs, config, ... }: { 202 security.pki.certificateFiles = [ "${tls-cert}/cert.pem" ]; 203 networking.extraHosts = hosts nodes; 204 networking.firewall.enable = false; 205 environment.systemPackages = with pkgs; [ 206 provision-db 207 provision-secrets 208 provision-user 209 ]; 210 services = { 211 pleroma = { 212 enable = true; 213 configs = [ 214 pleroma-conf 215 ]; 216 }; 217 postgresql = { 218 enable = true; 219 package = pkgs.postgresql_12; 220 }; 221 nginx = { 222 enable = true; 223 virtualHosts."pleroma.nixos.test" = { 224 addSSL = true; 225 sslCertificate = "${tls-cert}/cert.pem"; 226 sslCertificateKey = "${tls-cert}/key.pem"; 227 locations."/" = { 228 proxyPass = "http://127.0.0.1:4000"; 229 extraConfig = '' 230 add_header 'Access-Control-Allow-Origin' '*' always; 231 add_header 'Access-Control-Allow-Methods' 'POST, PUT, DELETE, GET, PATCH, OPTIONS' always; 232 add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, Idempotency-Key' always; 233 add_header 'Access-Control-Expose-Headers' 'Link, X-RateLimit-Reset, X-RateLimit-Limit, X-RateLimit-Remaining, X-Request-Id' always; 234 if ($request_method = OPTIONS) { 235 return 204; 236 } 237 add_header X-XSS-Protection "1; mode=block"; 238 add_header X-Permitted-Cross-Domain-Policies none; 239 add_header X-Frame-Options DENY; 240 add_header X-Content-Type-Options nosniff; 241 add_header Referrer-Policy same-origin; 242 add_header X-Download-Options noopen; 243 proxy_http_version 1.1; 244 proxy_set_header Upgrade $http_upgrade; 245 proxy_set_header Connection "upgrade"; 246 proxy_set_header Host $host; 247 client_max_body_size 16m; 248 ''; 249 }; 250 }; 251 }; 252 }; 253 }; 254 }; 255 256 testScript = { nodes, ... }: '' 257 pleroma.wait_for_unit("postgresql.service") 258 pleroma.succeed("provision-db") 259 pleroma.succeed("provision-secrets") 260 pleroma.systemctl("restart pleroma.service") 261 pleroma.wait_for_unit("pleroma.service") 262 pleroma.succeed("provision-user") 263 client.succeed("send-toot") 264 ''; 265})