// Short-lived SSH access through certificates: one made by ssh-keygen read and judged as sshd would,
// one signed here that ssh-keygen accepts in turn, and each reason a login would be refused.
//
//   SSH_CERT_SAMPLES=http://127.0.0.1:9000 quillo run ssh_certs.qwe
//   then open http://localhost:8080/read, /check, /sign, /refused and /make-failures
//
// SSH_CERT_SAMPLES is a helper that runs `ssh-keygen`: in a real program the CA key lives in a secret
// store, and the certificates reach you as `-cert.pub` text.

use "ssh_certs.qwer"

let SAMPLES = env("SSH_CERT_SAMPLES", "http://127.0.0.1:9000")
fn s() = http.get(`${SAMPLES}/sample`).json
fn inspect(cert) = http.post(`${SAMPLES}/inspect`, { cert }).json

route GET /read {
    let x = s()
    let c = ssh_cert_read(x.user)?
    let h = ssh_cert_read(x.host)?
    {
        type: c.type,
        id: c.key_id,
        serial: c.serial,
        principals: c.principals,
        algorithm: c.algorithm,
        ca: c.ca_fingerprint == x.ca_fingerprint,
        ext: keys(c.extensions),
        critical: ssh_cert_read(x.limited)?.critical_options,
        host: [h.type, h.principals],
        until: ssh_cert_read(x.forever)?.until,
        rsa_ca: ssh_cert_read(x.rsa_ca)?.ca_algorithm,
    }
}

route GET /check {
    let x = s()
    let trusted = { ca: [x.ca_public] }
    let c = ssh_cert_check(x.user, { ...trusted, principal: "deploy" })?
    let limited = ssh_cert_check(x.limited, { ...trusted, principal: "backup", source_address: "10.1.2.3" })?
    {
        ok: c.ok,
        by_fingerprint: ssh_cert_check(x.user, { ca: [x.ca_fingerprint], principal: "ada" })?.ok,
        host: ssh_cert_check(x.host, { ...trusted, type: "host", principal: "web1.example.com" })?.ok,
        command: limited.force_command,
        rsa_ca: ssh_cert_check(x.rsa_ca, { ca: [x.rsa_public], principal: "ada" })?.ok,
    }
}

route GET /sign {
    let x = s()
    let ca = ssh_ca_keygen("ed25519", "test ca")?
    let cert = ssh_cert_sign(x.user_key, ca.private_key, { key_id: "ada@laptop", principals: ["ada", "deploy"], serial: 77, valid_for: 3600, critical_options: { "force-command": "/usr/bin/uptime", "source-address": "10.0.0.0/8,192.168.1.1" }, comment: "issued" })?
    let host = ssh_cert_sign(x.user_key, ca.private_key, { type: "host", key_id: "web1", principals: ["web1.example.com"], forever: true })?
    let by_ec = ssh_cert_sign(x.user_key, ssh_ca_keygen("ecdsa-p256", "ec ca")?.private_key, { key_id: "e", principals: ["a"], valid_for: 60 })?
    let by_rsa = ssh_cert_sign(x.user_key, ssh_ca_keygen("rsa", "rsa ca")?.private_key, { key_id: "r", principals: ["a"], valid_for: 60 })?
    let by_pass = ssh_cert_sign(x.user_key, x.locked_ca, { key_id: "p", principals: ["a"], valid_for: 60, passphrase: "open sesame" })?
    let keygen = inspect(cert)
    {
        ssh_keygen: keygen.ok,
        says: keygen.lines,
        host_type: inspect(host).ok,
        ec: inspect(by_ec).ok,
        rsa: inspect(by_rsa).ok,
        passphrase: inspect(by_pass).ok,
        mine: ssh_cert_check(cert, { ca: [ca.public_key], principal: "ada", source_address: "192.168.1.1" })?.serial,
        default_ext: len(ssh_cert_read(cert)?.extensions),
    }
}

route GET /refused {
    let x = s()
    let trusted = { ca: [x.ca_public] }
    {
        other_ca: ssh_cert_check(x.rsa_ca, trusted).error != null,
        expired: ssh_cert_check(x.expired, trusted).error != null,
        later: ssh_cert_check(x.future, trusted).error != null,
        wrong_type: ssh_cert_check(x.host, { ...trusted, principal: "x" }).error,
        no_principal: ssh_cert_check(x.user, { ...trusted, principal: "root" }).error,
        anyone: ssh_cert_check(x.anyone, { ...trusted, principal: "root" }).error,
        outside: ssh_cert_check(x.limited, { ...trusted, source_address: "8.8.8.8" }).error,
        no_address: ssh_cert_check(x.limited, trusted).error,
        unknown_option: ssh_cert_check(x.strange, trusted).error,
        tampered: ssh_cert_check(x.tampered, trusted).error,
        no_ca: ssh_cert_check(x.user, {}).error,
        plain_key: ssh_cert_read(x.user_key).error,
    }
}

route GET /make-failures {
    let x = s()
    let ca = ssh_ca_keygen("ed25519", "ca")?
    let sign = (spec) => ssh_cert_sign(x.user_key, ca.private_key, spec).error
    {
        no_id: sign({ principals: ["a"], valid_for: 60 }),
        no_time: sign({ key_id: "a", principals: ["a"] }),
        no_principals: sign({ key_id: "a", valid_for: 60 }),
        backwards: sign({ key_id: "a", principals: ["a"], valid_after: 2000, valid_before: 1000 }),
        bad_type: sign({ key_id: "a", principals: ["a"], valid_for: 60, type: "robot" }),
        host_option: sign({ key_id: "a", principals: ["a"], valid_for: 60, type: "host", critical_options: { "force-command": "x" } }),
        bad_kind: ssh_ca_keygen("dsa", "x").error,
        locked: ssh_cert_sign(x.user_key, x.locked_ca, { key_id: "a", principals: ["a"], valid_for: 60 }).error,
        wrong_pass: ssh_cert_sign(x.user_key, x.locked_ca, { key_id: "a", principals: ["a"], valid_for: 60, passphrase: "no" }).error,
    }
}
