at master 4.5 kB view raw
1{ lib, pkgs, ... }: 2let 3 certs = pkgs.runCommand "cryptpadSelfSignedCerts" { buildInputs = [ pkgs.openssl ]; } '' 4 mkdir -p $out 5 cd $out 6 openssl req -x509 -newkey rsa:4096 \ 7 -keyout key.pem -out cert.pem -nodes -days 3650 \ 8 -subj '/CN=cryptpad.localhost' \ 9 -addext 'subjectAltName = DNS.1:cryptpad.localhost, DNS.2:cryptpad-sandbox.localhost' 10 ''; 11 # data sniffed from cryptpad's /checkup network trace, seems to be re-usable 12 test_write_data = pkgs.writeText "cryptpadTestData" '' 13 {"command":"WRITE_BLOCK","content":{"publicKey":"O2onvM62pC1io6jQKm8Nc2UyFXcd4kOmOsBIoYtZ2ik=","signature":"aXcM9SMO59lwA7q7HbYB+AnzymmxSyy/KhkG/cXIBVzl8v+kkPWXmFuWhcuKfRF8yt3Zc3ktIsHoFyuyDSAwAA==","ciphertext":"AFwCIfBHKdFzDKjMg4cu66qlJLpP+6Yxogbl3o9neiQou5P8h8yJB8qgnQ=="},"publicKey":"O2onvM62pC1io6jQKm8Nc2UyFXcd4kOmOsBIoYtZ2ik=","nonce":"bitSbJMNSzOsg98nEzN80a231PCkBQeH"} 14 ''; 15 seleniumScript = 16 pkgs.writers.writePython3Bin "selenium-script" 17 { 18 libraries = with pkgs.python3Packages; [ selenium ]; 19 } 20 '' 21 from sys import stderr 22 from time import time 23 from selenium import webdriver 24 from selenium.webdriver.common.by import By 25 from selenium.webdriver.firefox.options import Options 26 from selenium.webdriver.support.ui import WebDriverWait 27 from selenium.webdriver.support import expected_conditions as EC 28 29 options = Options() 30 options.add_argument("--headless") 31 service = webdriver.FirefoxService(executable_path="${lib.getExe pkgs.geckodriver}") # noqa: E501 32 33 driver = webdriver.Firefox(options=options, service=service) 34 driver.implicitly_wait(10) 35 driver.get("https://cryptpad.localhost") 36 37 WebDriverWait(driver, 10).until( 38 EC.text_to_be_present_in_element( 39 (By.TAG_NAME, "body"), "CryptPad") 40 ) 41 42 driver.find_element(By.PARTIAL_LINK_TEXT, "Sheet").click() 43 44 # Title changes once the sheet is rendered, which can take 45 # a lot of time on first run (browser generates keypair etc) 46 start = time() 47 WebDriverWait(driver, 60).until( 48 EC.title_contains('Sheet') 49 ) 50 print(f"Sheets done loading in {time() - start}", file=stderr) 51 52 # check screen looks sane... 53 # driver.print_page() and dump pdf somewhere through pdftotext? OCR? 54 55 driver.close() 56 ''; 57in 58{ 59 name = "cryptpad"; 60 meta = with pkgs.lib.maintainers; { 61 maintainers = [ martinetd ]; 62 }; 63 64 nodes.machine = { 65 environment.systemPackages = [ 66 pkgs.firefox-unwrapped 67 ]; 68 services.cryptpad = { 69 enable = true; 70 configureNginx = true; 71 settings = { 72 httpUnsafeOrigin = "https://cryptpad.localhost"; 73 httpSafeOrigin = "https://cryptpad-sandbox.localhost"; 74 }; 75 }; 76 services.nginx = { 77 virtualHosts."cryptpad.localhost" = { 78 enableACME = false; 79 sslCertificate = "${certs}/cert.pem"; 80 sslCertificateKey = "${certs}/key.pem"; 81 }; 82 }; 83 security = { 84 pki.certificateFiles = [ "${certs}/cert.pem" ]; 85 }; 86 }; 87 88 testScript = '' 89 machine.wait_for_unit("cryptpad.service") 90 machine.wait_for_unit("nginx.service") 91 machine.wait_for_open_port(3000) 92 93 # test home page 94 machine.succeed("curl --fail https://cryptpad.localhost -o /tmp/cryptpad_home.html") 95 machine.succeed("grep -F 'CryptPad: Collaboration suite' /tmp/cryptpad_home.html") 96 97 # test scripts/build.js actually generated customize content from config 98 machine.succeed("grep -F 'meta property=\"og:url\" content=\"https://cryptpad.localhost/index.html' /tmp/cryptpad_home.html") 99 100 # make sure child pages are accessible (e.g. check nginx try_files paths) 101 machine.succeed( 102 "grep -oE '/(customize|components)[^\"]*' /tmp/cryptpad_home.html" 103 " | while read -r page; do" 104 " curl -O --fail https://cryptpad.localhost$page || exit;" 105 " done") 106 107 # test some API (e.g. check cryptpad main process) 108 machine.succeed("curl --fail -d @${test_write_data} -H 'Content-Type: application/json' https://cryptpad.localhost/api/auth") 109 110 # page loads 111 machine.succeed("${lib.getExe seleniumScript}") 112 113 # test telemetry has been disabled 114 machine.fail("journalctl -u cryptpad | grep TELEMETRY"); 115 116 # for future improvements 117 machine.log(machine.execute("systemd-analyze security cryptpad.service")[1]) 118 ''; 119}