"$data/account/$env/account.db", "account's signing key" => "$data/account/$env/assert-key.pem", "account's code" => "$apps/account/$env/public/index.php", "account's secret for account" => dirname(env("RC_SECRETS"), 2) . "/account/$env/account", "account's facts" => dirname(env("RC_FACTS")) . "/account/deploy.json", "the platform's secrets" => "/etc/ratcloud/secrets", // a fixed platform path: the door, not a setting "account's repository" => "/opt/account.git/config", ]; $connects = [ "the server's own web server (127.0.0.1:80)" => ["127.0.0.1", 80], "the cloud metadata service (169.254.169.254:80)" => ["169.254.169.254", 80], "the private network (10.0.0.1:80)" => ["10.0.0.1", 80], ]; $out = []; foreach ($reads as $what => $path) { $php = @file_get_contents($path, false, null, 0, 1) !== false; $p = proc_open(["/usr/bin/head", "-c", "1", "--", $path], [1 => ["pipe", "w"], 2 => ["pipe", "w"]], $pipes); stream_get_contents($pipes[1]); $err = trim(stream_get_contents($pipes[2])); $rc = proc_close($p); $why = preg_replace('#^.*: #', "", $err) ?: "read"; $state = $php || $rc === 0 ? "opened" : (str_contains($err, "Permission denied") ? "refused" : "missing"); if (str_contains($err, "Is a directory")) { // a directory: try to list it instead $p = proc_open(["/usr/bin/ls", "--", $path], [1 => ["pipe", "w"], 2 => ["pipe", "w"]], $pipes); stream_get_contents($pipes[1]); $err = trim(stream_get_contents($pipes[2])); $rc = proc_close($p); $why = preg_replace('#^.*: #', "", $err) ?: "listed"; $state = $rc === 0 ? "opened" : (str_contains($err, "Permission denied") ? "refused" : "missing"); } $out[] = ["door" => "read $what", "target" => $path, "result" => $state, "why" => "as uid " . posix_getpwuid(posix_geteuid())["name"] . ": $why"]; } foreach ($connects as $what => [$ip, $port]) { $s = @fsockopen($ip, $port, $no, $err, 2); if ($s) fclose($s); $out[] = ["door" => "connect to $what", "target" => "$ip:$port", "result" => $s ? "opened" : "refused", "why" => $s ? "connected" : ($err ?: "error $no")]; } return $out; } // The control: the same tries on doors that should open. If these fail, so would everything. function controls(): array { $u = parse_url(env("RC_PUBLISH")); $s = @fsockopen($u["host"], $u["port"], $no, $err, 2); if ($s) fclose($s); $p = proc_open(["/usr/bin/head", "-c", "1", "--", env("RC_DATA") . "/zoo.db"], [1 => ["pipe", "w"], 2 => ["pipe", "w"]], $pipes); stream_get_contents($pipes[1]); stream_get_contents($pipes[2]); return ["own data" => proc_close($p) === 0, "own publish port" => (bool)$s]; } return [ "n" => 9, "wing" => "Isolation", "title" => "Try the doors", "promise" => "An app cannot open another app's files, and it cannot reach the server's own internal network.", "block" => "Every app runs as its own unix user in a sandbox, behind a firewall. RC_DATA is the one place it can write; everything else on the box is someone else's.", "show" => function (?array $me): string { $root = ""; foreach ((fact("platform.json")["check"]["checks"] ?? []) as $c) { if (str_starts_with($c["line"], "(exhibit 9)") || str_starts_with($c["line"], "An app cannot read")) $root .= "
Root tries them too, as every app, every hour: