diff --git a/README.md b/README.md index f0ffb17f..26c219ac 100644 --- a/README.md +++ b/README.md @@ -127,7 +127,7 @@ jobs: ## Use registered public SSH key(s) -By default anybody can connect to the tmate session. You can opt-in to install the public SSH keys [that you have registered with your GitHub profile](https://docs.github.com/en/github/authenticating-to-github/adding-a-new-ssh-key-to-your-github-account). +If [you have registered one or more public SSH keys with your GitHub profile](https://docs.github.com/en/github/authenticating-to-github/adding-a-new-ssh-key-to-your-github-account), tmate will be started such that only those keys are authorized to connect, otherwise anybody can connect to the tmate session. If you want to require a public SSH key to be installed with the tmate session, no matter whether the user who started the workflow has registered any in their GitHub profile, you will need to configure the setting `limit-access-to-actor` to `true`, like so: ```yaml name: CI diff --git a/action.yml b/action.yml index dc30e6d8..1e8e6822 100644 --- a/action.yml +++ b/action.yml @@ -16,9 +16,9 @@ inputs: required: false default: 'true' limit-access-to-actor: - description: 'If only the public SSH keys of the user triggering the workflow should be authorized' + description: 'Whether to authorize only the public SSH keys of the user triggering the workflow (defaults to true if the GitHub profile of the user has a public SSH key)' required: false - default: 'false' + default: 'auto' tmate-server-host: description: 'The hostname for your tmate server (e.g. ssh.example.org)' required: false diff --git a/lib/index.js b/lib/index.js index ab808329..1b0716bb 100644 --- a/lib/index.js +++ b/lib/index.js @@ -12630,7 +12630,10 @@ async function run() { } let newSessionExtra = "" - if (core.getInput("limit-access-to-actor") === "true") { + let tmateSSHDashI = "" + let publicSSHKeysWarning = "" + const limitAccessToActor = core.getInput("limit-access-to-actor") + if (limitAccessToActor === "true" || limitAccessToActor === "auto") { const { actor, apiUrl } = github.context const auth = core.getInput('github-token') const octokit = new dist_node/* Octokit */.v({ auth, baseUrl: apiUrl }) @@ -12639,13 +12642,16 @@ async function run() { username: actor }) if (keys.data.length === 0) { - throw new Error(`No public SSH keys registered with ${actor}'s GitHub profile`) + if (limitAccessToActor === "auto") publicSSHKeysWarning = `No public SSH keys found for ${actor}; continuing without them even if it is less secure (please consider adding an SSH key, see https://docs.github.com/en/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account)` + else throw new Error(`No public SSH keys registered with ${actor}'s GitHub profile`) + } else { + const sshPath = external_path_default().join(external_os_default().homedir(), ".ssh") + await external_fs_default().promises.mkdir(sshPath, { recursive: true }) + const authorizedKeysPath = external_path_default().join(sshPath, "authorized_keys") + await external_fs_default().promises.writeFile(authorizedKeysPath, keys.data.map(e => e.key).join('\n')) + newSessionExtra = `-a "${authorizedKeysPath}"` + tmateSSHDashI = "ssh -i " } - const sshPath = external_path_default().join(external_os_default().homedir(), ".ssh") - await external_fs_default().promises.mkdir(sshPath, { recursive: true }) - const authorizedKeysPath = external_path_default().join(sshPath, "authorized_keys") - await external_fs_default().promises.writeFile(authorizedKeysPath, keys.data.map(e => e.key).join('\n')) - newSessionExtra = `-a "${authorizedKeysPath}"` } const tmate = `${tmateExecutable} -S /tmp/tmate.sock`; @@ -12684,10 +12690,16 @@ async function run() { core.debug("Entering main loop") while (true) { + if (publicSSHKeysWarning) { + core.warning(publicSSHKeysWarning) + } if (tmateWeb) { core.info(`Web shell: ${tmateWeb}`); } core.info(`SSH: ${tmateSSH}`); + if (tmateSSHDashI) { + core.info(`or: ${tmateSSH.replace(/^ssh/, tmateSSHDashI)}`) + } if (continueFileExists()) { core.info("Exiting debugging session because the continue file was created") diff --git a/src/index.js b/src/index.js index d1e158d3..ee07bcf1 100644 --- a/src/index.js +++ b/src/index.js @@ -79,7 +79,10 @@ export async function run() { } let newSessionExtra = "" - if (core.getInput("limit-access-to-actor") === "true") { + let tmateSSHDashI = "" + let publicSSHKeysWarning = "" + const limitAccessToActor = core.getInput("limit-access-to-actor") + if (limitAccessToActor === "true" || limitAccessToActor === "auto") { const { actor, apiUrl } = github.context const auth = core.getInput('github-token') const octokit = new Octokit({ auth, baseUrl: apiUrl }) @@ -88,13 +91,16 @@ export async function run() { username: actor }) if (keys.data.length === 0) { - throw new Error(`No public SSH keys registered with ${actor}'s GitHub profile`) + if (limitAccessToActor === "auto") publicSSHKeysWarning = `No public SSH keys found for ${actor}; continuing without them even if it is less secure (please consider adding an SSH key, see https://docs.github.com/en/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account)` + else throw new Error(`No public SSH keys registered with ${actor}'s GitHub profile`) + } else { + const sshPath = path.join(os.homedir(), ".ssh") + await fs.promises.mkdir(sshPath, { recursive: true }) + const authorizedKeysPath = path.join(sshPath, "authorized_keys") + await fs.promises.writeFile(authorizedKeysPath, keys.data.map(e => e.key).join('\n')) + newSessionExtra = `-a "${authorizedKeysPath}"` + tmateSSHDashI = "ssh -i " } - const sshPath = path.join(os.homedir(), ".ssh") - await fs.promises.mkdir(sshPath, { recursive: true }) - const authorizedKeysPath = path.join(sshPath, "authorized_keys") - await fs.promises.writeFile(authorizedKeysPath, keys.data.map(e => e.key).join('\n')) - newSessionExtra = `-a "${authorizedKeysPath}"` } const tmate = `${tmateExecutable} -S /tmp/tmate.sock`; @@ -133,10 +139,16 @@ export async function run() { core.debug("Entering main loop") while (true) { + if (publicSSHKeysWarning) { + core.warning(publicSSHKeysWarning) + } if (tmateWeb) { core.info(`Web shell: ${tmateWeb}`); } core.info(`SSH: ${tmateSSH}`); + if (tmateSSHDashI) { + core.info(`or: ${tmateSSH.replace(/^ssh/, tmateSSHDashI)}`) + } if (continueFileExists()) { core.info("Exiting debugging session because the continue file was created")