GitFOSS
.js
JavaScript
(text/javascript)
#!/usr/bin/node
const fs = require("fs");
const { HttpClient } = require("./http_client");

async function main(args, sshOriginalCommand) {
  const [_, __, username] = args;

  if (username == null || username.trim() === "") {
    console.log(JSON.stringify({ success: false }));
    process.exit(128);
  }

  if (sshOriginalCommand == null) {
    console.log(JSON.stringify({ success: false }));
    process.exit(128);
  }

  try {
    const authorizedKeysBuffer = fs.readFileSync(
      "/home/git/.ssh/authorized_keys",
      { encoding: "utf8" },
    );

    const authKeys = authorizedKeysBuffer
      .split("\n")
      .map((line) =>
        line.startsWith("#")
          ? { type: "comment", text: line }
          : line.trim() !== ""
            ? { type: "key", text: line.trim() }
            : null,
      )
      .filter((x) => x != null && x.type === "key");

    const userPk = authKeys.find(
      (key) =>
        key.text.includes(`command="ssh_command ${username}"`) ||
        key.text.includes(`command="/usr/bin/ssh_command ${username}"`),
    );

    if (userPk == null) {
      console.log(JSON.stringify({ success: false }));
      return process.exit(128);
    }

    const pk = userPk.text;

    const sshRsaIndex = pk.indexOf("ssh-rsa");
    const publicKey = pk.substring(sshRsaIndex);

    const [command, repoSlug] = sshOriginalCommand
      .split(" ")
      .map((part) => part.replace(/\'/g, "").trim());

    const client = new HttpClient();

    const data = JSON.stringify({
      command,
      repoSlug,
      username,
      publicKey,
    });

    // authenticate against live prod api by default.
    const DEPLOYMENT_DOMAIN = process.env.DEPLOYMENT_DOMAIN || "127.0.0.1"; //|| "gitfoss.dev";
    const DEPLOYMENT_SCHEME = process.env.DEPLOYMENT_SCHEME || "http"; //|| "https";
    const PORT = process.env.PORT || 1337; //|| 443;
    const PORT_STR = DEPLOYMENT_SCHEME === "https" ? "" : `:${PORT}`;
    const SSH_AUTH_HELPER_URL = `${DEPLOYMENT_SCHEME}://${DEPLOYMENT_DOMAIN}${PORT_STR}/_ssh/auth`;

    const res = await client.post(SSH_AUTH_HELPER_URL, {
      headers: {
        "Content-Type": "application/json",
        "Content-Length": Buffer.byteLength(data),
      },
      body: data,
    });

    if (res.ok === false) {
      console.log(JSON.stringify({ success: false }));
      return process.exit(128);
    }

    if ((await res.isJson()) === false) {
      console.log(JSON.stringify({ success: false }));
      return process.exit(128);
    }

    const json = await res.json();

    if (json.success === false) {
      console.log(JSON.stringify({ success: false }));
      return process.exit(128);
    }
  } catch (e) {
    console.log(
      JSON.stringify({
        success: false,
        error: e,
      }),
    );
    process.exit(128);
  }

  // success!
  // print only the json so ssh_command can parse and continue

  const GIT_REPOSITORIES_ROOT =
    process.env.GIT_REPOSITORIES_ROOT || "/var/lib/gitfoss/repos";

  json.gitRepositoryDir = `${GIT_REPOSITORIES_ROOT}${repoSlug.replace(/\.git$/, "")}.git`;

  console.log(JSON.stringify({ success: true, ...json }));
  process.exit(0);
}

main(process.argv, process.env.SSH_ORIGINAL_COMMAND);