1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-19 12:00:55 +01:00
phorge-phorge/scripts/ssh/ssh-exec.php

298 lines
8.4 KiB
PHP
Raw Normal View History

Implement SSHD glue and Conduit SSH endpoint Summary: - Build "sshd-auth" (for authentication) and "sshd-exec" (for command execution) binaries. These are callable by "sshd-vcs", located [[https://github.com/epriestley/sshd-vcs | in my account on GitHub]]. They are based on precursors [[https://github.com/epriestley/sshd-vcs-glue | here on GitHub]] which I deployed for TenXer about a year ago, so I have some confidence they at least basically work. - The problem this solves is that normally every user would need an account on a machine to connect to it, and/or their public keys would all need to be listed in `~/.authorized_keys`. This is a big pain in most installs. Software like Gitosis/Gitolite solve this problem by giving you an easy way to add public keys to `~/.authorized_keys`, but this is pretty gross. - Roughly, instead of looking in `~/.authorized_keys` when a user connects, the patched sshd instead runs `echo <public key> | sshd-auth`. The `sshd-auth` script looks up the public key and authorizes the matching user, if they exist. It also forces sshd to run `sshd-exec` instead of a normal shell. - `sshd-exec` receives the authenticated user and any command which was passed to ssh (like `git receive-pack`) and can route them appropriately. - Overall, this permits a single account to be set up on a server which all Phabricator users can connect to without any extra work, and which can safely execute commands and apply appropriate permissions, and disable users when they are disabled in Phabricator and all that stuff. - Build out "sshd-exec" to do more thorough checks and setup, and delegate command execution to Workflows (they now exist, and did not when I originally built this stuff). - Convert @btrahan's conduit API script into a workflow and slightly simplify it (ConduitCall did not exist at the time it was written). The next steps here on the Repository side are to implement Workflows for Git, SVN and HG wire protocols. These will mostly just proxy the protocols, but also need to enforce permissions. So the approach will basically be: - Implement workflows for stuff like `git receive-pack`. - These workflows will implement enough of the underlying protocol to determine what resource the user is trying to access, and whether they want to read or write it. - They'll then do a permissons check, and kick the user out if they don't have permission to do whatever they are trying to do. - If the user does have permission, we just proxy the rest of the transaction. Next steps on the Conduit side are more simple: - Make ConduitClient understand "ssh://" URLs. Test Plan: Ran `sshd-exec --phabricator-ssh-user epriestley conduit differential.query`, etc. This will get a more comprehensive test once I set up sshd-vcs. Reviewers: btrahan, vrana Reviewed By: btrahan CC: aran Maniphest Tasks: T603, T550 Differential Revision: https://secure.phabricator.com/D4229
2012-12-19 20:08:07 +01:00
#!/usr/bin/env php
<?php
$ssh_start_time = microtime(true);
Implement SSHD glue and Conduit SSH endpoint Summary: - Build "sshd-auth" (for authentication) and "sshd-exec" (for command execution) binaries. These are callable by "sshd-vcs", located [[https://github.com/epriestley/sshd-vcs | in my account on GitHub]]. They are based on precursors [[https://github.com/epriestley/sshd-vcs-glue | here on GitHub]] which I deployed for TenXer about a year ago, so I have some confidence they at least basically work. - The problem this solves is that normally every user would need an account on a machine to connect to it, and/or their public keys would all need to be listed in `~/.authorized_keys`. This is a big pain in most installs. Software like Gitosis/Gitolite solve this problem by giving you an easy way to add public keys to `~/.authorized_keys`, but this is pretty gross. - Roughly, instead of looking in `~/.authorized_keys` when a user connects, the patched sshd instead runs `echo <public key> | sshd-auth`. The `sshd-auth` script looks up the public key and authorizes the matching user, if they exist. It also forces sshd to run `sshd-exec` instead of a normal shell. - `sshd-exec` receives the authenticated user and any command which was passed to ssh (like `git receive-pack`) and can route them appropriately. - Overall, this permits a single account to be set up on a server which all Phabricator users can connect to without any extra work, and which can safely execute commands and apply appropriate permissions, and disable users when they are disabled in Phabricator and all that stuff. - Build out "sshd-exec" to do more thorough checks and setup, and delegate command execution to Workflows (they now exist, and did not when I originally built this stuff). - Convert @btrahan's conduit API script into a workflow and slightly simplify it (ConduitCall did not exist at the time it was written). The next steps here on the Repository side are to implement Workflows for Git, SVN and HG wire protocols. These will mostly just proxy the protocols, but also need to enforce permissions. So the approach will basically be: - Implement workflows for stuff like `git receive-pack`. - These workflows will implement enough of the underlying protocol to determine what resource the user is trying to access, and whether they want to read or write it. - They'll then do a permissons check, and kick the user out if they don't have permission to do whatever they are trying to do. - If the user does have permission, we just proxy the rest of the transaction. Next steps on the Conduit side are more simple: - Make ConduitClient understand "ssh://" URLs. Test Plan: Ran `sshd-exec --phabricator-ssh-user epriestley conduit differential.query`, etc. This will get a more comprehensive test once I set up sshd-vcs. Reviewers: btrahan, vrana Reviewed By: btrahan CC: aran Maniphest Tasks: T603, T550 Differential Revision: https://secure.phabricator.com/D4229
2012-12-19 20:08:07 +01:00
$root = dirname(dirname(dirname(__FILE__)));
require_once $root.'/scripts/__init_script__.php';
$ssh_log = PhabricatorSSHLog::getLog();
Implement SSHD glue and Conduit SSH endpoint Summary: - Build "sshd-auth" (for authentication) and "sshd-exec" (for command execution) binaries. These are callable by "sshd-vcs", located [[https://github.com/epriestley/sshd-vcs | in my account on GitHub]]. They are based on precursors [[https://github.com/epriestley/sshd-vcs-glue | here on GitHub]] which I deployed for TenXer about a year ago, so I have some confidence they at least basically work. - The problem this solves is that normally every user would need an account on a machine to connect to it, and/or their public keys would all need to be listed in `~/.authorized_keys`. This is a big pain in most installs. Software like Gitosis/Gitolite solve this problem by giving you an easy way to add public keys to `~/.authorized_keys`, but this is pretty gross. - Roughly, instead of looking in `~/.authorized_keys` when a user connects, the patched sshd instead runs `echo <public key> | sshd-auth`. The `sshd-auth` script looks up the public key and authorizes the matching user, if they exist. It also forces sshd to run `sshd-exec` instead of a normal shell. - `sshd-exec` receives the authenticated user and any command which was passed to ssh (like `git receive-pack`) and can route them appropriately. - Overall, this permits a single account to be set up on a server which all Phabricator users can connect to without any extra work, and which can safely execute commands and apply appropriate permissions, and disable users when they are disabled in Phabricator and all that stuff. - Build out "sshd-exec" to do more thorough checks and setup, and delegate command execution to Workflows (they now exist, and did not when I originally built this stuff). - Convert @btrahan's conduit API script into a workflow and slightly simplify it (ConduitCall did not exist at the time it was written). The next steps here on the Repository side are to implement Workflows for Git, SVN and HG wire protocols. These will mostly just proxy the protocols, but also need to enforce permissions. So the approach will basically be: - Implement workflows for stuff like `git receive-pack`. - These workflows will implement enough of the underlying protocol to determine what resource the user is trying to access, and whether they want to read or write it. - They'll then do a permissons check, and kick the user out if they don't have permission to do whatever they are trying to do. - If the user does have permission, we just proxy the rest of the transaction. Next steps on the Conduit side are more simple: - Make ConduitClient understand "ssh://" URLs. Test Plan: Ran `sshd-exec --phabricator-ssh-user epriestley conduit differential.query`, etc. This will get a more comprehensive test once I set up sshd-vcs. Reviewers: btrahan, vrana Reviewed By: btrahan CC: aran Maniphest Tasks: T603, T550 Differential Revision: https://secure.phabricator.com/D4229
2012-12-19 20:08:07 +01:00
$args = new PhutilArgumentParser($argv);
$args->setTagline(pht('execute SSH requests'));
Implement SSHD glue and Conduit SSH endpoint Summary: - Build "sshd-auth" (for authentication) and "sshd-exec" (for command execution) binaries. These are callable by "sshd-vcs", located [[https://github.com/epriestley/sshd-vcs | in my account on GitHub]]. They are based on precursors [[https://github.com/epriestley/sshd-vcs-glue | here on GitHub]] which I deployed for TenXer about a year ago, so I have some confidence they at least basically work. - The problem this solves is that normally every user would need an account on a machine to connect to it, and/or their public keys would all need to be listed in `~/.authorized_keys`. This is a big pain in most installs. Software like Gitosis/Gitolite solve this problem by giving you an easy way to add public keys to `~/.authorized_keys`, but this is pretty gross. - Roughly, instead of looking in `~/.authorized_keys` when a user connects, the patched sshd instead runs `echo <public key> | sshd-auth`. The `sshd-auth` script looks up the public key and authorizes the matching user, if they exist. It also forces sshd to run `sshd-exec` instead of a normal shell. - `sshd-exec` receives the authenticated user and any command which was passed to ssh (like `git receive-pack`) and can route them appropriately. - Overall, this permits a single account to be set up on a server which all Phabricator users can connect to without any extra work, and which can safely execute commands and apply appropriate permissions, and disable users when they are disabled in Phabricator and all that stuff. - Build out "sshd-exec" to do more thorough checks and setup, and delegate command execution to Workflows (they now exist, and did not when I originally built this stuff). - Convert @btrahan's conduit API script into a workflow and slightly simplify it (ConduitCall did not exist at the time it was written). The next steps here on the Repository side are to implement Workflows for Git, SVN and HG wire protocols. These will mostly just proxy the protocols, but also need to enforce permissions. So the approach will basically be: - Implement workflows for stuff like `git receive-pack`. - These workflows will implement enough of the underlying protocol to determine what resource the user is trying to access, and whether they want to read or write it. - They'll then do a permissons check, and kick the user out if they don't have permission to do whatever they are trying to do. - If the user does have permission, we just proxy the rest of the transaction. Next steps on the Conduit side are more simple: - Make ConduitClient understand "ssh://" URLs. Test Plan: Ran `sshd-exec --phabricator-ssh-user epriestley conduit differential.query`, etc. This will get a more comprehensive test once I set up sshd-vcs. Reviewers: btrahan, vrana Reviewed By: btrahan CC: aran Maniphest Tasks: T603, T550 Differential Revision: https://secure.phabricator.com/D4229
2012-12-19 20:08:07 +01:00
$args->setSynopsis(<<<EOSYNOPSIS
Prepare to route VCS connections through SSH Summary: Fixes T2229. This sets the stage for a patch similar to D7417, but for SSH. In particular, SSH 6.2 introduced an `AuthorizedKeysCommand` directive, which lets us do this in a mostly-reasonable way without needing users to patch sshd (if they have a recent enough version, at least). The way the `AuthorizedKeysCommand` works is that it gets run and produces an `authorized_keys`-style file fragment. This isn't ideal, because we have to dump every key into the result, but should be fine for most installs. The earlier patch against `sshd` passes the public key itself, which allows the script to just look up the key. We might use this eventually, since it can scale much better, so I haven't removed it. Generally, auth is split into two scripts now which mostly do the same thing: - `ssh-auth` is the AuthorizedKeysCommand auth, which takes nothing and dumps the whole keyfile. - `ssh-auth-key` is the slightly cleaner and more scalable (but patch-dependent) version, which takes the public key and dumps only matching options. I also reworked the argument parsing to be a bit more sane. Test Plan: This is somewhat-intentionally a bit obtuse since I don't really want anyone using it yet, but basically: - Copy `phabricator-ssh-hook.sh` to somewhere like `/usr/libexec/openssh/`, chown it `root` and chmod it `500`. - This script should probably also do a username check in the future. - Create a copy of `sshd_config` and fix the paths/etc. Point the KeyScript at your copy of the hook. - Start a copy of sshd (6.2 or newer) with `-f <your config file>` and maybe `-d -d -d` to foreground and debug. - Run `ssh -p 2222 localhost` or similar. Specifically, I did this setup and then ran a bunch of commands like: - `ssh host` (denied, no command) - `ssh host ls` (denied, not supported) - `echo '{}' | ssh host conduit conduit.ping` (works) Reviewers: btrahan Reviewed By: btrahan CC: hach-que, aran Maniphest Tasks: T2229, T2230 Differential Revision: https://secure.phabricator.com/D7419
2013-10-26 18:43:43 +02:00
**ssh-exec** --phabricator-ssh-user __user__ [--ssh-command __commmand__]
**ssh-exec** --phabricator-ssh-device __device__ [--ssh-command __commmand__]
Execute authenticated SSH requests. This script is normally invoked
via SSHD, but can be invoked manually for testing.
Implement SSHD glue and Conduit SSH endpoint Summary: - Build "sshd-auth" (for authentication) and "sshd-exec" (for command execution) binaries. These are callable by "sshd-vcs", located [[https://github.com/epriestley/sshd-vcs | in my account on GitHub]]. They are based on precursors [[https://github.com/epriestley/sshd-vcs-glue | here on GitHub]] which I deployed for TenXer about a year ago, so I have some confidence they at least basically work. - The problem this solves is that normally every user would need an account on a machine to connect to it, and/or their public keys would all need to be listed in `~/.authorized_keys`. This is a big pain in most installs. Software like Gitosis/Gitolite solve this problem by giving you an easy way to add public keys to `~/.authorized_keys`, but this is pretty gross. - Roughly, instead of looking in `~/.authorized_keys` when a user connects, the patched sshd instead runs `echo <public key> | sshd-auth`. The `sshd-auth` script looks up the public key and authorizes the matching user, if they exist. It also forces sshd to run `sshd-exec` instead of a normal shell. - `sshd-exec` receives the authenticated user and any command which was passed to ssh (like `git receive-pack`) and can route them appropriately. - Overall, this permits a single account to be set up on a server which all Phabricator users can connect to without any extra work, and which can safely execute commands and apply appropriate permissions, and disable users when they are disabled in Phabricator and all that stuff. - Build out "sshd-exec" to do more thorough checks and setup, and delegate command execution to Workflows (they now exist, and did not when I originally built this stuff). - Convert @btrahan's conduit API script into a workflow and slightly simplify it (ConduitCall did not exist at the time it was written). The next steps here on the Repository side are to implement Workflows for Git, SVN and HG wire protocols. These will mostly just proxy the protocols, but also need to enforce permissions. So the approach will basically be: - Implement workflows for stuff like `git receive-pack`. - These workflows will implement enough of the underlying protocol to determine what resource the user is trying to access, and whether they want to read or write it. - They'll then do a permissons check, and kick the user out if they don't have permission to do whatever they are trying to do. - If the user does have permission, we just proxy the rest of the transaction. Next steps on the Conduit side are more simple: - Make ConduitClient understand "ssh://" URLs. Test Plan: Ran `sshd-exec --phabricator-ssh-user epriestley conduit differential.query`, etc. This will get a more comprehensive test once I set up sshd-vcs. Reviewers: btrahan, vrana Reviewed By: btrahan CC: aran Maniphest Tasks: T603, T550 Differential Revision: https://secure.phabricator.com/D4229
2012-12-19 20:08:07 +01:00
EOSYNOPSIS
);
$args->parseStandardArguments();
Prepare to route VCS connections through SSH Summary: Fixes T2229. This sets the stage for a patch similar to D7417, but for SSH. In particular, SSH 6.2 introduced an `AuthorizedKeysCommand` directive, which lets us do this in a mostly-reasonable way without needing users to patch sshd (if they have a recent enough version, at least). The way the `AuthorizedKeysCommand` works is that it gets run and produces an `authorized_keys`-style file fragment. This isn't ideal, because we have to dump every key into the result, but should be fine for most installs. The earlier patch against `sshd` passes the public key itself, which allows the script to just look up the key. We might use this eventually, since it can scale much better, so I haven't removed it. Generally, auth is split into two scripts now which mostly do the same thing: - `ssh-auth` is the AuthorizedKeysCommand auth, which takes nothing and dumps the whole keyfile. - `ssh-auth-key` is the slightly cleaner and more scalable (but patch-dependent) version, which takes the public key and dumps only matching options. I also reworked the argument parsing to be a bit more sane. Test Plan: This is somewhat-intentionally a bit obtuse since I don't really want anyone using it yet, but basically: - Copy `phabricator-ssh-hook.sh` to somewhere like `/usr/libexec/openssh/`, chown it `root` and chmod it `500`. - This script should probably also do a username check in the future. - Create a copy of `sshd_config` and fix the paths/etc. Point the KeyScript at your copy of the hook. - Start a copy of sshd (6.2 or newer) with `-f <your config file>` and maybe `-d -d -d` to foreground and debug. - Run `ssh -p 2222 localhost` or similar. Specifically, I did this setup and then ran a bunch of commands like: - `ssh host` (denied, no command) - `ssh host ls` (denied, not supported) - `echo '{}' | ssh host conduit conduit.ping` (works) Reviewers: btrahan Reviewed By: btrahan CC: hach-que, aran Maniphest Tasks: T2229, T2230 Differential Revision: https://secure.phabricator.com/D7419
2013-10-26 18:43:43 +02:00
$args->parse(
Implement SSHD glue and Conduit SSH endpoint Summary: - Build "sshd-auth" (for authentication) and "sshd-exec" (for command execution) binaries. These are callable by "sshd-vcs", located [[https://github.com/epriestley/sshd-vcs | in my account on GitHub]]. They are based on precursors [[https://github.com/epriestley/sshd-vcs-glue | here on GitHub]] which I deployed for TenXer about a year ago, so I have some confidence they at least basically work. - The problem this solves is that normally every user would need an account on a machine to connect to it, and/or their public keys would all need to be listed in `~/.authorized_keys`. This is a big pain in most installs. Software like Gitosis/Gitolite solve this problem by giving you an easy way to add public keys to `~/.authorized_keys`, but this is pretty gross. - Roughly, instead of looking in `~/.authorized_keys` when a user connects, the patched sshd instead runs `echo <public key> | sshd-auth`. The `sshd-auth` script looks up the public key and authorizes the matching user, if they exist. It also forces sshd to run `sshd-exec` instead of a normal shell. - `sshd-exec` receives the authenticated user and any command which was passed to ssh (like `git receive-pack`) and can route them appropriately. - Overall, this permits a single account to be set up on a server which all Phabricator users can connect to without any extra work, and which can safely execute commands and apply appropriate permissions, and disable users when they are disabled in Phabricator and all that stuff. - Build out "sshd-exec" to do more thorough checks and setup, and delegate command execution to Workflows (they now exist, and did not when I originally built this stuff). - Convert @btrahan's conduit API script into a workflow and slightly simplify it (ConduitCall did not exist at the time it was written). The next steps here on the Repository side are to implement Workflows for Git, SVN and HG wire protocols. These will mostly just proxy the protocols, but also need to enforce permissions. So the approach will basically be: - Implement workflows for stuff like `git receive-pack`. - These workflows will implement enough of the underlying protocol to determine what resource the user is trying to access, and whether they want to read or write it. - They'll then do a permissons check, and kick the user out if they don't have permission to do whatever they are trying to do. - If the user does have permission, we just proxy the rest of the transaction. Next steps on the Conduit side are more simple: - Make ConduitClient understand "ssh://" URLs. Test Plan: Ran `sshd-exec --phabricator-ssh-user epriestley conduit differential.query`, etc. This will get a more comprehensive test once I set up sshd-vcs. Reviewers: btrahan, vrana Reviewed By: btrahan CC: aran Maniphest Tasks: T603, T550 Differential Revision: https://secure.phabricator.com/D4229
2012-12-19 20:08:07 +01:00
array(
array(
'name' => 'phabricator-ssh-user',
'param' => 'username',
'help' => pht(
'If the request authenticated with a user key, the name of the '.
'user.'),
),
array(
'name' => 'phabricator-ssh-device',
'param' => 'name',
'help' => pht(
'If the request authenticated with a device key, the name of the '.
'device.'),
),
array(
'name' => 'phabricator-ssh-key',
'param' => 'id',
'help' => pht(
'The ID of the SSH key which authenticated this request. This is '.
'used to allow logs to report when specific keys were used, to make '.
'it easier to manage credentials.'),
Implement SSHD glue and Conduit SSH endpoint Summary: - Build "sshd-auth" (for authentication) and "sshd-exec" (for command execution) binaries. These are callable by "sshd-vcs", located [[https://github.com/epriestley/sshd-vcs | in my account on GitHub]]. They are based on precursors [[https://github.com/epriestley/sshd-vcs-glue | here on GitHub]] which I deployed for TenXer about a year ago, so I have some confidence they at least basically work. - The problem this solves is that normally every user would need an account on a machine to connect to it, and/or their public keys would all need to be listed in `~/.authorized_keys`. This is a big pain in most installs. Software like Gitosis/Gitolite solve this problem by giving you an easy way to add public keys to `~/.authorized_keys`, but this is pretty gross. - Roughly, instead of looking in `~/.authorized_keys` when a user connects, the patched sshd instead runs `echo <public key> | sshd-auth`. The `sshd-auth` script looks up the public key and authorizes the matching user, if they exist. It also forces sshd to run `sshd-exec` instead of a normal shell. - `sshd-exec` receives the authenticated user and any command which was passed to ssh (like `git receive-pack`) and can route them appropriately. - Overall, this permits a single account to be set up on a server which all Phabricator users can connect to without any extra work, and which can safely execute commands and apply appropriate permissions, and disable users when they are disabled in Phabricator and all that stuff. - Build out "sshd-exec" to do more thorough checks and setup, and delegate command execution to Workflows (they now exist, and did not when I originally built this stuff). - Convert @btrahan's conduit API script into a workflow and slightly simplify it (ConduitCall did not exist at the time it was written). The next steps here on the Repository side are to implement Workflows for Git, SVN and HG wire protocols. These will mostly just proxy the protocols, but also need to enforce permissions. So the approach will basically be: - Implement workflows for stuff like `git receive-pack`. - These workflows will implement enough of the underlying protocol to determine what resource the user is trying to access, and whether they want to read or write it. - They'll then do a permissons check, and kick the user out if they don't have permission to do whatever they are trying to do. - If the user does have permission, we just proxy the rest of the transaction. Next steps on the Conduit side are more simple: - Make ConduitClient understand "ssh://" URLs. Test Plan: Ran `sshd-exec --phabricator-ssh-user epriestley conduit differential.query`, etc. This will get a more comprehensive test once I set up sshd-vcs. Reviewers: btrahan, vrana Reviewed By: btrahan CC: aran Maniphest Tasks: T603, T550 Differential Revision: https://secure.phabricator.com/D4229
2012-12-19 20:08:07 +01:00
),
Prepare to route VCS connections through SSH Summary: Fixes T2229. This sets the stage for a patch similar to D7417, but for SSH. In particular, SSH 6.2 introduced an `AuthorizedKeysCommand` directive, which lets us do this in a mostly-reasonable way without needing users to patch sshd (if they have a recent enough version, at least). The way the `AuthorizedKeysCommand` works is that it gets run and produces an `authorized_keys`-style file fragment. This isn't ideal, because we have to dump every key into the result, but should be fine for most installs. The earlier patch against `sshd` passes the public key itself, which allows the script to just look up the key. We might use this eventually, since it can scale much better, so I haven't removed it. Generally, auth is split into two scripts now which mostly do the same thing: - `ssh-auth` is the AuthorizedKeysCommand auth, which takes nothing and dumps the whole keyfile. - `ssh-auth-key` is the slightly cleaner and more scalable (but patch-dependent) version, which takes the public key and dumps only matching options. I also reworked the argument parsing to be a bit more sane. Test Plan: This is somewhat-intentionally a bit obtuse since I don't really want anyone using it yet, but basically: - Copy `phabricator-ssh-hook.sh` to somewhere like `/usr/libexec/openssh/`, chown it `root` and chmod it `500`. - This script should probably also do a username check in the future. - Create a copy of `sshd_config` and fix the paths/etc. Point the KeyScript at your copy of the hook. - Start a copy of sshd (6.2 or newer) with `-f <your config file>` and maybe `-d -d -d` to foreground and debug. - Run `ssh -p 2222 localhost` or similar. Specifically, I did this setup and then ran a bunch of commands like: - `ssh host` (denied, no command) - `ssh host ls` (denied, not supported) - `echo '{}' | ssh host conduit conduit.ping` (works) Reviewers: btrahan Reviewed By: btrahan CC: hach-que, aran Maniphest Tasks: T2229, T2230 Differential Revision: https://secure.phabricator.com/D7419
2013-10-26 18:43:43 +02:00
array(
'name' => 'ssh-command',
'param' => 'command',
'help' => pht(
'Provide a command to execute. This makes testing this script '.
'easier. When running normally, the command is read from the '.
'environment (%s), which is populated by sshd.',
'SSH_ORIGINAL_COMMAND'),
Prepare to route VCS connections through SSH Summary: Fixes T2229. This sets the stage for a patch similar to D7417, but for SSH. In particular, SSH 6.2 introduced an `AuthorizedKeysCommand` directive, which lets us do this in a mostly-reasonable way without needing users to patch sshd (if they have a recent enough version, at least). The way the `AuthorizedKeysCommand` works is that it gets run and produces an `authorized_keys`-style file fragment. This isn't ideal, because we have to dump every key into the result, but should be fine for most installs. The earlier patch against `sshd` passes the public key itself, which allows the script to just look up the key. We might use this eventually, since it can scale much better, so I haven't removed it. Generally, auth is split into two scripts now which mostly do the same thing: - `ssh-auth` is the AuthorizedKeysCommand auth, which takes nothing and dumps the whole keyfile. - `ssh-auth-key` is the slightly cleaner and more scalable (but patch-dependent) version, which takes the public key and dumps only matching options. I also reworked the argument parsing to be a bit more sane. Test Plan: This is somewhat-intentionally a bit obtuse since I don't really want anyone using it yet, but basically: - Copy `phabricator-ssh-hook.sh` to somewhere like `/usr/libexec/openssh/`, chown it `root` and chmod it `500`. - This script should probably also do a username check in the future. - Create a copy of `sshd_config` and fix the paths/etc. Point the KeyScript at your copy of the hook. - Start a copy of sshd (6.2 or newer) with `-f <your config file>` and maybe `-d -d -d` to foreground and debug. - Run `ssh -p 2222 localhost` or similar. Specifically, I did this setup and then ran a bunch of commands like: - `ssh host` (denied, no command) - `ssh host ls` (denied, not supported) - `echo '{}' | ssh host conduit conduit.ping` (works) Reviewers: btrahan Reviewed By: btrahan CC: hach-que, aran Maniphest Tasks: T2229, T2230 Differential Revision: https://secure.phabricator.com/D7419
2013-10-26 18:43:43 +02:00
),
Implement SSHD glue and Conduit SSH endpoint Summary: - Build "sshd-auth" (for authentication) and "sshd-exec" (for command execution) binaries. These are callable by "sshd-vcs", located [[https://github.com/epriestley/sshd-vcs | in my account on GitHub]]. They are based on precursors [[https://github.com/epriestley/sshd-vcs-glue | here on GitHub]] which I deployed for TenXer about a year ago, so I have some confidence they at least basically work. - The problem this solves is that normally every user would need an account on a machine to connect to it, and/or their public keys would all need to be listed in `~/.authorized_keys`. This is a big pain in most installs. Software like Gitosis/Gitolite solve this problem by giving you an easy way to add public keys to `~/.authorized_keys`, but this is pretty gross. - Roughly, instead of looking in `~/.authorized_keys` when a user connects, the patched sshd instead runs `echo <public key> | sshd-auth`. The `sshd-auth` script looks up the public key and authorizes the matching user, if they exist. It also forces sshd to run `sshd-exec` instead of a normal shell. - `sshd-exec` receives the authenticated user and any command which was passed to ssh (like `git receive-pack`) and can route them appropriately. - Overall, this permits a single account to be set up on a server which all Phabricator users can connect to without any extra work, and which can safely execute commands and apply appropriate permissions, and disable users when they are disabled in Phabricator and all that stuff. - Build out "sshd-exec" to do more thorough checks and setup, and delegate command execution to Workflows (they now exist, and did not when I originally built this stuff). - Convert @btrahan's conduit API script into a workflow and slightly simplify it (ConduitCall did not exist at the time it was written). The next steps here on the Repository side are to implement Workflows for Git, SVN and HG wire protocols. These will mostly just proxy the protocols, but also need to enforce permissions. So the approach will basically be: - Implement workflows for stuff like `git receive-pack`. - These workflows will implement enough of the underlying protocol to determine what resource the user is trying to access, and whether they want to read or write it. - They'll then do a permissons check, and kick the user out if they don't have permission to do whatever they are trying to do. - If the user does have permission, we just proxy the rest of the transaction. Next steps on the Conduit side are more simple: - Make ConduitClient understand "ssh://" URLs. Test Plan: Ran `sshd-exec --phabricator-ssh-user epriestley conduit differential.query`, etc. This will get a more comprehensive test once I set up sshd-vcs. Reviewers: btrahan, vrana Reviewed By: btrahan CC: aran Maniphest Tasks: T603, T550 Differential Revision: https://secure.phabricator.com/D4229
2012-12-19 20:08:07 +01:00
));
try {
$remote_address = null;
$ssh_client = getenv('SSH_CLIENT');
if ($ssh_client) {
// This has the format "<ip> <remote-port> <local-port>". Grab the IP.
$remote_address = head(explode(' ', $ssh_client));
$ssh_log->setData(
array(
'r' => $remote_address,
));
}
$key_id = $args->getArg('phabricator-ssh-key');
if ($key_id) {
$ssh_log->setData(
array(
'k' => $key_id,
));
}
Implement SSHD glue and Conduit SSH endpoint Summary: - Build "sshd-auth" (for authentication) and "sshd-exec" (for command execution) binaries. These are callable by "sshd-vcs", located [[https://github.com/epriestley/sshd-vcs | in my account on GitHub]]. They are based on precursors [[https://github.com/epriestley/sshd-vcs-glue | here on GitHub]] which I deployed for TenXer about a year ago, so I have some confidence they at least basically work. - The problem this solves is that normally every user would need an account on a machine to connect to it, and/or their public keys would all need to be listed in `~/.authorized_keys`. This is a big pain in most installs. Software like Gitosis/Gitolite solve this problem by giving you an easy way to add public keys to `~/.authorized_keys`, but this is pretty gross. - Roughly, instead of looking in `~/.authorized_keys` when a user connects, the patched sshd instead runs `echo <public key> | sshd-auth`. The `sshd-auth` script looks up the public key and authorizes the matching user, if they exist. It also forces sshd to run `sshd-exec` instead of a normal shell. - `sshd-exec` receives the authenticated user and any command which was passed to ssh (like `git receive-pack`) and can route them appropriately. - Overall, this permits a single account to be set up on a server which all Phabricator users can connect to without any extra work, and which can safely execute commands and apply appropriate permissions, and disable users when they are disabled in Phabricator and all that stuff. - Build out "sshd-exec" to do more thorough checks and setup, and delegate command execution to Workflows (they now exist, and did not when I originally built this stuff). - Convert @btrahan's conduit API script into a workflow and slightly simplify it (ConduitCall did not exist at the time it was written). The next steps here on the Repository side are to implement Workflows for Git, SVN and HG wire protocols. These will mostly just proxy the protocols, but also need to enforce permissions. So the approach will basically be: - Implement workflows for stuff like `git receive-pack`. - These workflows will implement enough of the underlying protocol to determine what resource the user is trying to access, and whether they want to read or write it. - They'll then do a permissons check, and kick the user out if they don't have permission to do whatever they are trying to do. - If the user does have permission, we just proxy the rest of the transaction. Next steps on the Conduit side are more simple: - Make ConduitClient understand "ssh://" URLs. Test Plan: Ran `sshd-exec --phabricator-ssh-user epriestley conduit differential.query`, etc. This will get a more comprehensive test once I set up sshd-vcs. Reviewers: btrahan, vrana Reviewed By: btrahan CC: aran Maniphest Tasks: T603, T550 Differential Revision: https://secure.phabricator.com/D4229
2012-12-19 20:08:07 +01:00
$user_name = $args->getArg('phabricator-ssh-user');
$device_name = $args->getArg('phabricator-ssh-device');
$user = null;
$device = null;
$is_cluster_request = false;
if ($user_name && $device_name) {
throw new Exception(
pht(
'The %s and %s flags are mutually exclusive. You can not '.
'authenticate as both a user ("%s") and a device ("%s"). '.
'Specify one or the other, but not both.',
'--phabricator-ssh-user',
'--phabricator-ssh-device',
$user_name,
$device_name));
} else if (strlen($user_name)) {
$user = id(new PhabricatorPeopleQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withUsernames(array($user_name))
->executeOne();
if (!$user) {
throw new Exception(
pht(
'Invalid username ("%s"). There is no user with this username.',
$user_name));
}
} else if (strlen($device_name)) {
if (!$remote_address) {
throw new Exception(
pht(
'Unable to identify remote address from the %s environment '.
'variable. Device authentication is accepted only from trusted '.
'sources.',
'SSH_CLIENT'));
}
if (!PhabricatorEnv::isClusterAddress($remote_address)) {
throw new Exception(
pht(
'This request originates from outside of the Phabricator cluster '.
'address range. Requests signed with a trusted device key must '.
'originate from trusted hosts.'));
}
$device = id(new AlmanacDeviceQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withNames(array($device_name))
->executeOne();
if (!$device) {
throw new Exception(
pht(
'Invalid device name ("%s"). There is no device with this name.',
$device->getName()));
}
// We're authenticated as a device, but we're going to read the user out of
// the command below.
$is_cluster_request = true;
} else {
throw new Exception(
pht(
'This script must be invoked with either the %s or %s flag.',
'--phabricator-ssh-user',
'--phabricator-ssh-device'));
}
if ($args->getArg('ssh-command')) {
$original_command = $args->getArg('ssh-command');
} else {
$original_command = getenv('SSH_ORIGINAL_COMMAND');
Implement SSHD glue and Conduit SSH endpoint Summary: - Build "sshd-auth" (for authentication) and "sshd-exec" (for command execution) binaries. These are callable by "sshd-vcs", located [[https://github.com/epriestley/sshd-vcs | in my account on GitHub]]. They are based on precursors [[https://github.com/epriestley/sshd-vcs-glue | here on GitHub]] which I deployed for TenXer about a year ago, so I have some confidence they at least basically work. - The problem this solves is that normally every user would need an account on a machine to connect to it, and/or their public keys would all need to be listed in `~/.authorized_keys`. This is a big pain in most installs. Software like Gitosis/Gitolite solve this problem by giving you an easy way to add public keys to `~/.authorized_keys`, but this is pretty gross. - Roughly, instead of looking in `~/.authorized_keys` when a user connects, the patched sshd instead runs `echo <public key> | sshd-auth`. The `sshd-auth` script looks up the public key and authorizes the matching user, if they exist. It also forces sshd to run `sshd-exec` instead of a normal shell. - `sshd-exec` receives the authenticated user and any command which was passed to ssh (like `git receive-pack`) and can route them appropriately. - Overall, this permits a single account to be set up on a server which all Phabricator users can connect to without any extra work, and which can safely execute commands and apply appropriate permissions, and disable users when they are disabled in Phabricator and all that stuff. - Build out "sshd-exec" to do more thorough checks and setup, and delegate command execution to Workflows (they now exist, and did not when I originally built this stuff). - Convert @btrahan's conduit API script into a workflow and slightly simplify it (ConduitCall did not exist at the time it was written). The next steps here on the Repository side are to implement Workflows for Git, SVN and HG wire protocols. These will mostly just proxy the protocols, but also need to enforce permissions. So the approach will basically be: - Implement workflows for stuff like `git receive-pack`. - These workflows will implement enough of the underlying protocol to determine what resource the user is trying to access, and whether they want to read or write it. - They'll then do a permissons check, and kick the user out if they don't have permission to do whatever they are trying to do. - If the user does have permission, we just proxy the rest of the transaction. Next steps on the Conduit side are more simple: - Make ConduitClient understand "ssh://" URLs. Test Plan: Ran `sshd-exec --phabricator-ssh-user epriestley conduit differential.query`, etc. This will get a more comprehensive test once I set up sshd-vcs. Reviewers: btrahan, vrana Reviewed By: btrahan CC: aran Maniphest Tasks: T603, T550 Differential Revision: https://secure.phabricator.com/D4229
2012-12-19 20:08:07 +01:00
}
$original_argv = id(new PhutilShellLexer())
->splitArguments($original_command);
if ($device) {
$act_as_name = array_shift($original_argv);
if (!preg_match('/^@/', $act_as_name)) {
throw new Exception(
pht(
'Commands executed by devices must identify an acting user in the '.
'first command argument. This request was not constructed '.
'properly.'));
}
$act_as_name = substr($act_as_name, 1);
$user = id(new PhabricatorPeopleQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withUsernames(array($act_as_name))
->executeOne();
if (!$user) {
throw new Exception(
pht(
'Device request identifies an acting user with an invalid '.
'username ("%s"). There is no user with this username.',
$act_as_name));
}
Implement SSHD glue and Conduit SSH endpoint Summary: - Build "sshd-auth" (for authentication) and "sshd-exec" (for command execution) binaries. These are callable by "sshd-vcs", located [[https://github.com/epriestley/sshd-vcs | in my account on GitHub]]. They are based on precursors [[https://github.com/epriestley/sshd-vcs-glue | here on GitHub]] which I deployed for TenXer about a year ago, so I have some confidence they at least basically work. - The problem this solves is that normally every user would need an account on a machine to connect to it, and/or their public keys would all need to be listed in `~/.authorized_keys`. This is a big pain in most installs. Software like Gitosis/Gitolite solve this problem by giving you an easy way to add public keys to `~/.authorized_keys`, but this is pretty gross. - Roughly, instead of looking in `~/.authorized_keys` when a user connects, the patched sshd instead runs `echo <public key> | sshd-auth`. The `sshd-auth` script looks up the public key and authorizes the matching user, if they exist. It also forces sshd to run `sshd-exec` instead of a normal shell. - `sshd-exec` receives the authenticated user and any command which was passed to ssh (like `git receive-pack`) and can route them appropriately. - Overall, this permits a single account to be set up on a server which all Phabricator users can connect to without any extra work, and which can safely execute commands and apply appropriate permissions, and disable users when they are disabled in Phabricator and all that stuff. - Build out "sshd-exec" to do more thorough checks and setup, and delegate command execution to Workflows (they now exist, and did not when I originally built this stuff). - Convert @btrahan's conduit API script into a workflow and slightly simplify it (ConduitCall did not exist at the time it was written). The next steps here on the Repository side are to implement Workflows for Git, SVN and HG wire protocols. These will mostly just proxy the protocols, but also need to enforce permissions. So the approach will basically be: - Implement workflows for stuff like `git receive-pack`. - These workflows will implement enough of the underlying protocol to determine what resource the user is trying to access, and whether they want to read or write it. - They'll then do a permissons check, and kick the user out if they don't have permission to do whatever they are trying to do. - If the user does have permission, we just proxy the rest of the transaction. Next steps on the Conduit side are more simple: - Make ConduitClient understand "ssh://" URLs. Test Plan: Ran `sshd-exec --phabricator-ssh-user epriestley conduit differential.query`, etc. This will get a more comprehensive test once I set up sshd-vcs. Reviewers: btrahan, vrana Reviewed By: btrahan CC: aran Maniphest Tasks: T603, T550 Differential Revision: https://secure.phabricator.com/D4229
2012-12-19 20:08:07 +01:00
}
$ssh_log->setData(
array(
'u' => $user->getUsername(),
'P' => $user->getPHID(),
));
Improve handling of email verification and "activated" accounts Summary: Small step forward which improves existing stuff or lays groudwork for future stuff: - Currently, to check for email verification, we have to single-query the email address on every page. Instead, denoramlize it into the user object. - Migrate all the existing users. - When the user verifies an email, mark them as `isEmailVerified` if the email is their primary email. - Just make the checks look at the `isEmailVerified` field. - Add a new check, `isUserActivated()`, to cover email-verified plus disabled. Currently, a non-verified-but-not-disabled user could theoretically use Conduit over SSH, if anyone deployed it. Tighten that up. - Add an `isApproved` flag, which is always true for now. In a future diff, I want to add a default-on admin approval queue for new accounts, to prevent configuration mistakes. The way it will work is: - When the queue is enabled, registering users are created with `isApproved = false`. - Admins are sent an email, "[Phabricator] New User Approval (alincoln)", telling them that a new user is waiting for approval. - They go to the web UI and approve the user. - Manually-created accounts are auto-approved. - The email will have instructions for disabling the queue. I think this queue will be helpful for new installs and give them peace of mind, and when you go to disable it we have a better opportunity to warn you about exactly what that means. Generally, I want to improve the default safety of registration, since if you just blindly coast through the path of least resistance right now your install ends up pretty open, and realistically few installs are on VPNs. Test Plan: - Ran migration, verified `isEmailVerified` populated correctly. - Created a new user, checked DB for verified (not verified). - Verified, checked DB (now verified). - Used Conduit, People, Diffusion. Reviewers: btrahan Reviewed By: btrahan CC: chad, aran Differential Revision: https://secure.phabricator.com/D7572
2013-11-12 23:37:04 +01:00
if (!$user->isUserActivated()) {
throw new Exception(
pht(
'Your account ("%s") is not activated. Visit the web interface '.
'for more information.',
$user->getUsername()));
Prepare to route VCS connections through SSH Summary: Fixes T2229. This sets the stage for a patch similar to D7417, but for SSH. In particular, SSH 6.2 introduced an `AuthorizedKeysCommand` directive, which lets us do this in a mostly-reasonable way without needing users to patch sshd (if they have a recent enough version, at least). The way the `AuthorizedKeysCommand` works is that it gets run and produces an `authorized_keys`-style file fragment. This isn't ideal, because we have to dump every key into the result, but should be fine for most installs. The earlier patch against `sshd` passes the public key itself, which allows the script to just look up the key. We might use this eventually, since it can scale much better, so I haven't removed it. Generally, auth is split into two scripts now which mostly do the same thing: - `ssh-auth` is the AuthorizedKeysCommand auth, which takes nothing and dumps the whole keyfile. - `ssh-auth-key` is the slightly cleaner and more scalable (but patch-dependent) version, which takes the public key and dumps only matching options. I also reworked the argument parsing to be a bit more sane. Test Plan: This is somewhat-intentionally a bit obtuse since I don't really want anyone using it yet, but basically: - Copy `phabricator-ssh-hook.sh` to somewhere like `/usr/libexec/openssh/`, chown it `root` and chmod it `500`. - This script should probably also do a username check in the future. - Create a copy of `sshd_config` and fix the paths/etc. Point the KeyScript at your copy of the hook. - Start a copy of sshd (6.2 or newer) with `-f <your config file>` and maybe `-d -d -d` to foreground and debug. - Run `ssh -p 2222 localhost` or similar. Specifically, I did this setup and then ran a bunch of commands like: - `ssh host` (denied, no command) - `ssh host ls` (denied, not supported) - `echo '{}' | ssh host conduit conduit.ping` (works) Reviewers: btrahan Reviewed By: btrahan CC: hach-que, aran Maniphest Tasks: T2229, T2230 Differential Revision: https://secure.phabricator.com/D7419
2013-10-26 18:43:43 +02:00
}
$workflows = id(new PhutilSymbolLoader())
->setAncestorClass('PhabricatorSSHWorkflow')
->loadObjects();
$workflow_names = mpull($workflows, 'getName', 'getName');
Prepare to route VCS connections through SSH Summary: Fixes T2229. This sets the stage for a patch similar to D7417, but for SSH. In particular, SSH 6.2 introduced an `AuthorizedKeysCommand` directive, which lets us do this in a mostly-reasonable way without needing users to patch sshd (if they have a recent enough version, at least). The way the `AuthorizedKeysCommand` works is that it gets run and produces an `authorized_keys`-style file fragment. This isn't ideal, because we have to dump every key into the result, but should be fine for most installs. The earlier patch against `sshd` passes the public key itself, which allows the script to just look up the key. We might use this eventually, since it can scale much better, so I haven't removed it. Generally, auth is split into two scripts now which mostly do the same thing: - `ssh-auth` is the AuthorizedKeysCommand auth, which takes nothing and dumps the whole keyfile. - `ssh-auth-key` is the slightly cleaner and more scalable (but patch-dependent) version, which takes the public key and dumps only matching options. I also reworked the argument parsing to be a bit more sane. Test Plan: This is somewhat-intentionally a bit obtuse since I don't really want anyone using it yet, but basically: - Copy `phabricator-ssh-hook.sh` to somewhere like `/usr/libexec/openssh/`, chown it `root` and chmod it `500`. - This script should probably also do a username check in the future. - Create a copy of `sshd_config` and fix the paths/etc. Point the KeyScript at your copy of the hook. - Start a copy of sshd (6.2 or newer) with `-f <your config file>` and maybe `-d -d -d` to foreground and debug. - Run `ssh -p 2222 localhost` or similar. Specifically, I did this setup and then ran a bunch of commands like: - `ssh host` (denied, no command) - `ssh host ls` (denied, not supported) - `echo '{}' | ssh host conduit conduit.ping` (works) Reviewers: btrahan Reviewed By: btrahan CC: hach-que, aran Maniphest Tasks: T2229, T2230 Differential Revision: https://secure.phabricator.com/D7419
2013-10-26 18:43:43 +02:00
if (!$original_argv) {
throw new Exception(
pht(
"Welcome to Phabricator.\n\n".
"You are logged in as %s.\n\n".
"You haven't specified a command to run. This means you're requesting ".
"an interactive shell, but Phabricator does not provide an ".
"interactive shell over SSH.\n\n".
"Usually, you should run a command like `%s` or `%s` ".
"rather than connecting directly with SSH.\n\n".
"Supported commands are: %s.",
$user->getUsername(),
'git clone',
'hg push',
implode(', ', $workflow_names)));
Prepare to route VCS connections through SSH Summary: Fixes T2229. This sets the stage for a patch similar to D7417, but for SSH. In particular, SSH 6.2 introduced an `AuthorizedKeysCommand` directive, which lets us do this in a mostly-reasonable way without needing users to patch sshd (if they have a recent enough version, at least). The way the `AuthorizedKeysCommand` works is that it gets run and produces an `authorized_keys`-style file fragment. This isn't ideal, because we have to dump every key into the result, but should be fine for most installs. The earlier patch against `sshd` passes the public key itself, which allows the script to just look up the key. We might use this eventually, since it can scale much better, so I haven't removed it. Generally, auth is split into two scripts now which mostly do the same thing: - `ssh-auth` is the AuthorizedKeysCommand auth, which takes nothing and dumps the whole keyfile. - `ssh-auth-key` is the slightly cleaner and more scalable (but patch-dependent) version, which takes the public key and dumps only matching options. I also reworked the argument parsing to be a bit more sane. Test Plan: This is somewhat-intentionally a bit obtuse since I don't really want anyone using it yet, but basically: - Copy `phabricator-ssh-hook.sh` to somewhere like `/usr/libexec/openssh/`, chown it `root` and chmod it `500`. - This script should probably also do a username check in the future. - Create a copy of `sshd_config` and fix the paths/etc. Point the KeyScript at your copy of the hook. - Start a copy of sshd (6.2 or newer) with `-f <your config file>` and maybe `-d -d -d` to foreground and debug. - Run `ssh -p 2222 localhost` or similar. Specifically, I did this setup and then ran a bunch of commands like: - `ssh host` (denied, no command) - `ssh host ls` (denied, not supported) - `echo '{}' | ssh host conduit conduit.ping` (works) Reviewers: btrahan Reviewed By: btrahan CC: hach-que, aran Maniphest Tasks: T2229, T2230 Differential Revision: https://secure.phabricator.com/D7419
2013-10-26 18:43:43 +02:00
}
$log_argv = implode(' ', $original_argv);
$log_argv = id(new PhutilUTF8StringTruncator())
->setMaximumCodepoints(128)
->truncateString($log_argv);
$ssh_log->setData(
array(
'C' => $original_argv[0],
'U' => $log_argv,
));
Prepare to route VCS connections through SSH Summary: Fixes T2229. This sets the stage for a patch similar to D7417, but for SSH. In particular, SSH 6.2 introduced an `AuthorizedKeysCommand` directive, which lets us do this in a mostly-reasonable way without needing users to patch sshd (if they have a recent enough version, at least). The way the `AuthorizedKeysCommand` works is that it gets run and produces an `authorized_keys`-style file fragment. This isn't ideal, because we have to dump every key into the result, but should be fine for most installs. The earlier patch against `sshd` passes the public key itself, which allows the script to just look up the key. We might use this eventually, since it can scale much better, so I haven't removed it. Generally, auth is split into two scripts now which mostly do the same thing: - `ssh-auth` is the AuthorizedKeysCommand auth, which takes nothing and dumps the whole keyfile. - `ssh-auth-key` is the slightly cleaner and more scalable (but patch-dependent) version, which takes the public key and dumps only matching options. I also reworked the argument parsing to be a bit more sane. Test Plan: This is somewhat-intentionally a bit obtuse since I don't really want anyone using it yet, but basically: - Copy `phabricator-ssh-hook.sh` to somewhere like `/usr/libexec/openssh/`, chown it `root` and chmod it `500`. - This script should probably also do a username check in the future. - Create a copy of `sshd_config` and fix the paths/etc. Point the KeyScript at your copy of the hook. - Start a copy of sshd (6.2 or newer) with `-f <your config file>` and maybe `-d -d -d` to foreground and debug. - Run `ssh -p 2222 localhost` or similar. Specifically, I did this setup and then ran a bunch of commands like: - `ssh host` (denied, no command) - `ssh host ls` (denied, not supported) - `echo '{}' | ssh host conduit conduit.ping` (works) Reviewers: btrahan Reviewed By: btrahan CC: hach-que, aran Maniphest Tasks: T2229, T2230 Differential Revision: https://secure.phabricator.com/D7419
2013-10-26 18:43:43 +02:00
$command = head($original_argv);
$parseable_argv = $original_argv;
array_unshift($parseable_argv, 'phabricator-ssh-exec');
$parsed_args = new PhutilArgumentParser($parseable_argv);
Prepare to route VCS connections through SSH Summary: Fixes T2229. This sets the stage for a patch similar to D7417, but for SSH. In particular, SSH 6.2 introduced an `AuthorizedKeysCommand` directive, which lets us do this in a mostly-reasonable way without needing users to patch sshd (if they have a recent enough version, at least). The way the `AuthorizedKeysCommand` works is that it gets run and produces an `authorized_keys`-style file fragment. This isn't ideal, because we have to dump every key into the result, but should be fine for most installs. The earlier patch against `sshd` passes the public key itself, which allows the script to just look up the key. We might use this eventually, since it can scale much better, so I haven't removed it. Generally, auth is split into two scripts now which mostly do the same thing: - `ssh-auth` is the AuthorizedKeysCommand auth, which takes nothing and dumps the whole keyfile. - `ssh-auth-key` is the slightly cleaner and more scalable (but patch-dependent) version, which takes the public key and dumps only matching options. I also reworked the argument parsing to be a bit more sane. Test Plan: This is somewhat-intentionally a bit obtuse since I don't really want anyone using it yet, but basically: - Copy `phabricator-ssh-hook.sh` to somewhere like `/usr/libexec/openssh/`, chown it `root` and chmod it `500`. - This script should probably also do a username check in the future. - Create a copy of `sshd_config` and fix the paths/etc. Point the KeyScript at your copy of the hook. - Start a copy of sshd (6.2 or newer) with `-f <your config file>` and maybe `-d -d -d` to foreground and debug. - Run `ssh -p 2222 localhost` or similar. Specifically, I did this setup and then ran a bunch of commands like: - `ssh host` (denied, no command) - `ssh host ls` (denied, not supported) - `echo '{}' | ssh host conduit conduit.ping` (works) Reviewers: btrahan Reviewed By: btrahan CC: hach-que, aran Maniphest Tasks: T2229, T2230 Differential Revision: https://secure.phabricator.com/D7419
2013-10-26 18:43:43 +02:00
if (empty($workflow_names[$command])) {
throw new Exception(pht('Invalid command.'));
Implement SSHD glue and Conduit SSH endpoint Summary: - Build "sshd-auth" (for authentication) and "sshd-exec" (for command execution) binaries. These are callable by "sshd-vcs", located [[https://github.com/epriestley/sshd-vcs | in my account on GitHub]]. They are based on precursors [[https://github.com/epriestley/sshd-vcs-glue | here on GitHub]] which I deployed for TenXer about a year ago, so I have some confidence they at least basically work. - The problem this solves is that normally every user would need an account on a machine to connect to it, and/or their public keys would all need to be listed in `~/.authorized_keys`. This is a big pain in most installs. Software like Gitosis/Gitolite solve this problem by giving you an easy way to add public keys to `~/.authorized_keys`, but this is pretty gross. - Roughly, instead of looking in `~/.authorized_keys` when a user connects, the patched sshd instead runs `echo <public key> | sshd-auth`. The `sshd-auth` script looks up the public key and authorizes the matching user, if they exist. It also forces sshd to run `sshd-exec` instead of a normal shell. - `sshd-exec` receives the authenticated user and any command which was passed to ssh (like `git receive-pack`) and can route them appropriately. - Overall, this permits a single account to be set up on a server which all Phabricator users can connect to without any extra work, and which can safely execute commands and apply appropriate permissions, and disable users when they are disabled in Phabricator and all that stuff. - Build out "sshd-exec" to do more thorough checks and setup, and delegate command execution to Workflows (they now exist, and did not when I originally built this stuff). - Convert @btrahan's conduit API script into a workflow and slightly simplify it (ConduitCall did not exist at the time it was written). The next steps here on the Repository side are to implement Workflows for Git, SVN and HG wire protocols. These will mostly just proxy the protocols, but also need to enforce permissions. So the approach will basically be: - Implement workflows for stuff like `git receive-pack`. - These workflows will implement enough of the underlying protocol to determine what resource the user is trying to access, and whether they want to read or write it. - They'll then do a permissons check, and kick the user out if they don't have permission to do whatever they are trying to do. - If the user does have permission, we just proxy the rest of the transaction. Next steps on the Conduit side are more simple: - Make ConduitClient understand "ssh://" URLs. Test Plan: Ran `sshd-exec --phabricator-ssh-user epriestley conduit differential.query`, etc. This will get a more comprehensive test once I set up sshd-vcs. Reviewers: btrahan, vrana Reviewed By: btrahan CC: aran Maniphest Tasks: T603, T550 Differential Revision: https://secure.phabricator.com/D4229
2012-12-19 20:08:07 +01:00
}
$workflow = $parsed_args->parseWorkflows($workflows);
Implement SSHD glue and Conduit SSH endpoint Summary: - Build "sshd-auth" (for authentication) and "sshd-exec" (for command execution) binaries. These are callable by "sshd-vcs", located [[https://github.com/epriestley/sshd-vcs | in my account on GitHub]]. They are based on precursors [[https://github.com/epriestley/sshd-vcs-glue | here on GitHub]] which I deployed for TenXer about a year ago, so I have some confidence they at least basically work. - The problem this solves is that normally every user would need an account on a machine to connect to it, and/or their public keys would all need to be listed in `~/.authorized_keys`. This is a big pain in most installs. Software like Gitosis/Gitolite solve this problem by giving you an easy way to add public keys to `~/.authorized_keys`, but this is pretty gross. - Roughly, instead of looking in `~/.authorized_keys` when a user connects, the patched sshd instead runs `echo <public key> | sshd-auth`. The `sshd-auth` script looks up the public key and authorizes the matching user, if they exist. It also forces sshd to run `sshd-exec` instead of a normal shell. - `sshd-exec` receives the authenticated user and any command which was passed to ssh (like `git receive-pack`) and can route them appropriately. - Overall, this permits a single account to be set up on a server which all Phabricator users can connect to without any extra work, and which can safely execute commands and apply appropriate permissions, and disable users when they are disabled in Phabricator and all that stuff. - Build out "sshd-exec" to do more thorough checks and setup, and delegate command execution to Workflows (they now exist, and did not when I originally built this stuff). - Convert @btrahan's conduit API script into a workflow and slightly simplify it (ConduitCall did not exist at the time it was written). The next steps here on the Repository side are to implement Workflows for Git, SVN and HG wire protocols. These will mostly just proxy the protocols, but also need to enforce permissions. So the approach will basically be: - Implement workflows for stuff like `git receive-pack`. - These workflows will implement enough of the underlying protocol to determine what resource the user is trying to access, and whether they want to read or write it. - They'll then do a permissons check, and kick the user out if they don't have permission to do whatever they are trying to do. - If the user does have permission, we just proxy the rest of the transaction. Next steps on the Conduit side are more simple: - Make ConduitClient understand "ssh://" URLs. Test Plan: Ran `sshd-exec --phabricator-ssh-user epriestley conduit differential.query`, etc. This will get a more comprehensive test once I set up sshd-vcs. Reviewers: btrahan, vrana Reviewed By: btrahan CC: aran Maniphest Tasks: T603, T550 Differential Revision: https://secure.phabricator.com/D4229
2012-12-19 20:08:07 +01:00
$workflow->setUser($user);
$workflow->setOriginalArguments($original_argv);
$workflow->setIsClusterRequest($is_cluster_request);
Implement SSHD glue and Conduit SSH endpoint Summary: - Build "sshd-auth" (for authentication) and "sshd-exec" (for command execution) binaries. These are callable by "sshd-vcs", located [[https://github.com/epriestley/sshd-vcs | in my account on GitHub]]. They are based on precursors [[https://github.com/epriestley/sshd-vcs-glue | here on GitHub]] which I deployed for TenXer about a year ago, so I have some confidence they at least basically work. - The problem this solves is that normally every user would need an account on a machine to connect to it, and/or their public keys would all need to be listed in `~/.authorized_keys`. This is a big pain in most installs. Software like Gitosis/Gitolite solve this problem by giving you an easy way to add public keys to `~/.authorized_keys`, but this is pretty gross. - Roughly, instead of looking in `~/.authorized_keys` when a user connects, the patched sshd instead runs `echo <public key> | sshd-auth`. The `sshd-auth` script looks up the public key and authorizes the matching user, if they exist. It also forces sshd to run `sshd-exec` instead of a normal shell. - `sshd-exec` receives the authenticated user and any command which was passed to ssh (like `git receive-pack`) and can route them appropriately. - Overall, this permits a single account to be set up on a server which all Phabricator users can connect to without any extra work, and which can safely execute commands and apply appropriate permissions, and disable users when they are disabled in Phabricator and all that stuff. - Build out "sshd-exec" to do more thorough checks and setup, and delegate command execution to Workflows (they now exist, and did not when I originally built this stuff). - Convert @btrahan's conduit API script into a workflow and slightly simplify it (ConduitCall did not exist at the time it was written). The next steps here on the Repository side are to implement Workflows for Git, SVN and HG wire protocols. These will mostly just proxy the protocols, but also need to enforce permissions. So the approach will basically be: - Implement workflows for stuff like `git receive-pack`. - These workflows will implement enough of the underlying protocol to determine what resource the user is trying to access, and whether they want to read or write it. - They'll then do a permissons check, and kick the user out if they don't have permission to do whatever they are trying to do. - If the user does have permission, we just proxy the rest of the transaction. Next steps on the Conduit side are more simple: - Make ConduitClient understand "ssh://" URLs. Test Plan: Ran `sshd-exec --phabricator-ssh-user epriestley conduit differential.query`, etc. This will get a more comprehensive test once I set up sshd-vcs. Reviewers: btrahan, vrana Reviewed By: btrahan CC: aran Maniphest Tasks: T603, T550 Differential Revision: https://secure.phabricator.com/D4229
2012-12-19 20:08:07 +01:00
$sock_stdin = fopen('php://stdin', 'r');
if (!$sock_stdin) {
throw new Exception(pht('Unable to open stdin.'));
Implement SSHD glue and Conduit SSH endpoint Summary: - Build "sshd-auth" (for authentication) and "sshd-exec" (for command execution) binaries. These are callable by "sshd-vcs", located [[https://github.com/epriestley/sshd-vcs | in my account on GitHub]]. They are based on precursors [[https://github.com/epriestley/sshd-vcs-glue | here on GitHub]] which I deployed for TenXer about a year ago, so I have some confidence they at least basically work. - The problem this solves is that normally every user would need an account on a machine to connect to it, and/or their public keys would all need to be listed in `~/.authorized_keys`. This is a big pain in most installs. Software like Gitosis/Gitolite solve this problem by giving you an easy way to add public keys to `~/.authorized_keys`, but this is pretty gross. - Roughly, instead of looking in `~/.authorized_keys` when a user connects, the patched sshd instead runs `echo <public key> | sshd-auth`. The `sshd-auth` script looks up the public key and authorizes the matching user, if they exist. It also forces sshd to run `sshd-exec` instead of a normal shell. - `sshd-exec` receives the authenticated user and any command which was passed to ssh (like `git receive-pack`) and can route them appropriately. - Overall, this permits a single account to be set up on a server which all Phabricator users can connect to without any extra work, and which can safely execute commands and apply appropriate permissions, and disable users when they are disabled in Phabricator and all that stuff. - Build out "sshd-exec" to do more thorough checks and setup, and delegate command execution to Workflows (they now exist, and did not when I originally built this stuff). - Convert @btrahan's conduit API script into a workflow and slightly simplify it (ConduitCall did not exist at the time it was written). The next steps here on the Repository side are to implement Workflows for Git, SVN and HG wire protocols. These will mostly just proxy the protocols, but also need to enforce permissions. So the approach will basically be: - Implement workflows for stuff like `git receive-pack`. - These workflows will implement enough of the underlying protocol to determine what resource the user is trying to access, and whether they want to read or write it. - They'll then do a permissons check, and kick the user out if they don't have permission to do whatever they are trying to do. - If the user does have permission, we just proxy the rest of the transaction. Next steps on the Conduit side are more simple: - Make ConduitClient understand "ssh://" URLs. Test Plan: Ran `sshd-exec --phabricator-ssh-user epriestley conduit differential.query`, etc. This will get a more comprehensive test once I set up sshd-vcs. Reviewers: btrahan, vrana Reviewed By: btrahan CC: aran Maniphest Tasks: T603, T550 Differential Revision: https://secure.phabricator.com/D4229
2012-12-19 20:08:07 +01:00
}
$sock_stdout = fopen('php://stdout', 'w');
if (!$sock_stdout) {
throw new Exception(pht('Unable to open stdout.'));
Implement SSHD glue and Conduit SSH endpoint Summary: - Build "sshd-auth" (for authentication) and "sshd-exec" (for command execution) binaries. These are callable by "sshd-vcs", located [[https://github.com/epriestley/sshd-vcs | in my account on GitHub]]. They are based on precursors [[https://github.com/epriestley/sshd-vcs-glue | here on GitHub]] which I deployed for TenXer about a year ago, so I have some confidence they at least basically work. - The problem this solves is that normally every user would need an account on a machine to connect to it, and/or their public keys would all need to be listed in `~/.authorized_keys`. This is a big pain in most installs. Software like Gitosis/Gitolite solve this problem by giving you an easy way to add public keys to `~/.authorized_keys`, but this is pretty gross. - Roughly, instead of looking in `~/.authorized_keys` when a user connects, the patched sshd instead runs `echo <public key> | sshd-auth`. The `sshd-auth` script looks up the public key and authorizes the matching user, if they exist. It also forces sshd to run `sshd-exec` instead of a normal shell. - `sshd-exec` receives the authenticated user and any command which was passed to ssh (like `git receive-pack`) and can route them appropriately. - Overall, this permits a single account to be set up on a server which all Phabricator users can connect to without any extra work, and which can safely execute commands and apply appropriate permissions, and disable users when they are disabled in Phabricator and all that stuff. - Build out "sshd-exec" to do more thorough checks and setup, and delegate command execution to Workflows (they now exist, and did not when I originally built this stuff). - Convert @btrahan's conduit API script into a workflow and slightly simplify it (ConduitCall did not exist at the time it was written). The next steps here on the Repository side are to implement Workflows for Git, SVN and HG wire protocols. These will mostly just proxy the protocols, but also need to enforce permissions. So the approach will basically be: - Implement workflows for stuff like `git receive-pack`. - These workflows will implement enough of the underlying protocol to determine what resource the user is trying to access, and whether they want to read or write it. - They'll then do a permissons check, and kick the user out if they don't have permission to do whatever they are trying to do. - If the user does have permission, we just proxy the rest of the transaction. Next steps on the Conduit side are more simple: - Make ConduitClient understand "ssh://" URLs. Test Plan: Ran `sshd-exec --phabricator-ssh-user epriestley conduit differential.query`, etc. This will get a more comprehensive test once I set up sshd-vcs. Reviewers: btrahan, vrana Reviewed By: btrahan CC: aran Maniphest Tasks: T603, T550 Differential Revision: https://secure.phabricator.com/D4229
2012-12-19 20:08:07 +01:00
}
$sock_stderr = fopen('php://stderr', 'w');
if (!$sock_stderr) {
throw new Exception(pht('Unable to open stderr.'));
}
Implement SSHD glue and Conduit SSH endpoint Summary: - Build "sshd-auth" (for authentication) and "sshd-exec" (for command execution) binaries. These are callable by "sshd-vcs", located [[https://github.com/epriestley/sshd-vcs | in my account on GitHub]]. They are based on precursors [[https://github.com/epriestley/sshd-vcs-glue | here on GitHub]] which I deployed for TenXer about a year ago, so I have some confidence they at least basically work. - The problem this solves is that normally every user would need an account on a machine to connect to it, and/or their public keys would all need to be listed in `~/.authorized_keys`. This is a big pain in most installs. Software like Gitosis/Gitolite solve this problem by giving you an easy way to add public keys to `~/.authorized_keys`, but this is pretty gross. - Roughly, instead of looking in `~/.authorized_keys` when a user connects, the patched sshd instead runs `echo <public key> | sshd-auth`. The `sshd-auth` script looks up the public key and authorizes the matching user, if they exist. It also forces sshd to run `sshd-exec` instead of a normal shell. - `sshd-exec` receives the authenticated user and any command which was passed to ssh (like `git receive-pack`) and can route them appropriately. - Overall, this permits a single account to be set up on a server which all Phabricator users can connect to without any extra work, and which can safely execute commands and apply appropriate permissions, and disable users when they are disabled in Phabricator and all that stuff. - Build out "sshd-exec" to do more thorough checks and setup, and delegate command execution to Workflows (they now exist, and did not when I originally built this stuff). - Convert @btrahan's conduit API script into a workflow and slightly simplify it (ConduitCall did not exist at the time it was written). The next steps here on the Repository side are to implement Workflows for Git, SVN and HG wire protocols. These will mostly just proxy the protocols, but also need to enforce permissions. So the approach will basically be: - Implement workflows for stuff like `git receive-pack`. - These workflows will implement enough of the underlying protocol to determine what resource the user is trying to access, and whether they want to read or write it. - They'll then do a permissons check, and kick the user out if they don't have permission to do whatever they are trying to do. - If the user does have permission, we just proxy the rest of the transaction. Next steps on the Conduit side are more simple: - Make ConduitClient understand "ssh://" URLs. Test Plan: Ran `sshd-exec --phabricator-ssh-user epriestley conduit differential.query`, etc. This will get a more comprehensive test once I set up sshd-vcs. Reviewers: btrahan, vrana Reviewed By: btrahan CC: aran Maniphest Tasks: T603, T550 Differential Revision: https://secure.phabricator.com/D4229
2012-12-19 20:08:07 +01:00
$socket_channel = new PhutilSocketChannel(
$sock_stdin,
$sock_stdout);
$error_channel = new PhutilSocketChannel(null, $sock_stderr);
Implement SSHD glue and Conduit SSH endpoint Summary: - Build "sshd-auth" (for authentication) and "sshd-exec" (for command execution) binaries. These are callable by "sshd-vcs", located [[https://github.com/epriestley/sshd-vcs | in my account on GitHub]]. They are based on precursors [[https://github.com/epriestley/sshd-vcs-glue | here on GitHub]] which I deployed for TenXer about a year ago, so I have some confidence they at least basically work. - The problem this solves is that normally every user would need an account on a machine to connect to it, and/or their public keys would all need to be listed in `~/.authorized_keys`. This is a big pain in most installs. Software like Gitosis/Gitolite solve this problem by giving you an easy way to add public keys to `~/.authorized_keys`, but this is pretty gross. - Roughly, instead of looking in `~/.authorized_keys` when a user connects, the patched sshd instead runs `echo <public key> | sshd-auth`. The `sshd-auth` script looks up the public key and authorizes the matching user, if they exist. It also forces sshd to run `sshd-exec` instead of a normal shell. - `sshd-exec` receives the authenticated user and any command which was passed to ssh (like `git receive-pack`) and can route them appropriately. - Overall, this permits a single account to be set up on a server which all Phabricator users can connect to without any extra work, and which can safely execute commands and apply appropriate permissions, and disable users when they are disabled in Phabricator and all that stuff. - Build out "sshd-exec" to do more thorough checks and setup, and delegate command execution to Workflows (they now exist, and did not when I originally built this stuff). - Convert @btrahan's conduit API script into a workflow and slightly simplify it (ConduitCall did not exist at the time it was written). The next steps here on the Repository side are to implement Workflows for Git, SVN and HG wire protocols. These will mostly just proxy the protocols, but also need to enforce permissions. So the approach will basically be: - Implement workflows for stuff like `git receive-pack`. - These workflows will implement enough of the underlying protocol to determine what resource the user is trying to access, and whether they want to read or write it. - They'll then do a permissons check, and kick the user out if they don't have permission to do whatever they are trying to do. - If the user does have permission, we just proxy the rest of the transaction. Next steps on the Conduit side are more simple: - Make ConduitClient understand "ssh://" URLs. Test Plan: Ran `sshd-exec --phabricator-ssh-user epriestley conduit differential.query`, etc. This will get a more comprehensive test once I set up sshd-vcs. Reviewers: btrahan, vrana Reviewed By: btrahan CC: aran Maniphest Tasks: T603, T550 Differential Revision: https://secure.phabricator.com/D4229
2012-12-19 20:08:07 +01:00
$metrics_channel = new PhutilMetricsChannel($socket_channel);
$workflow->setIOChannel($metrics_channel);
$workflow->setErrorChannel($error_channel);
Implement SSHD glue and Conduit SSH endpoint Summary: - Build "sshd-auth" (for authentication) and "sshd-exec" (for command execution) binaries. These are callable by "sshd-vcs", located [[https://github.com/epriestley/sshd-vcs | in my account on GitHub]]. They are based on precursors [[https://github.com/epriestley/sshd-vcs-glue | here on GitHub]] which I deployed for TenXer about a year ago, so I have some confidence they at least basically work. - The problem this solves is that normally every user would need an account on a machine to connect to it, and/or their public keys would all need to be listed in `~/.authorized_keys`. This is a big pain in most installs. Software like Gitosis/Gitolite solve this problem by giving you an easy way to add public keys to `~/.authorized_keys`, but this is pretty gross. - Roughly, instead of looking in `~/.authorized_keys` when a user connects, the patched sshd instead runs `echo <public key> | sshd-auth`. The `sshd-auth` script looks up the public key and authorizes the matching user, if they exist. It also forces sshd to run `sshd-exec` instead of a normal shell. - `sshd-exec` receives the authenticated user and any command which was passed to ssh (like `git receive-pack`) and can route them appropriately. - Overall, this permits a single account to be set up on a server which all Phabricator users can connect to without any extra work, and which can safely execute commands and apply appropriate permissions, and disable users when they are disabled in Phabricator and all that stuff. - Build out "sshd-exec" to do more thorough checks and setup, and delegate command execution to Workflows (they now exist, and did not when I originally built this stuff). - Convert @btrahan's conduit API script into a workflow and slightly simplify it (ConduitCall did not exist at the time it was written). The next steps here on the Repository side are to implement Workflows for Git, SVN and HG wire protocols. These will mostly just proxy the protocols, but also need to enforce permissions. So the approach will basically be: - Implement workflows for stuff like `git receive-pack`. - These workflows will implement enough of the underlying protocol to determine what resource the user is trying to access, and whether they want to read or write it. - They'll then do a permissons check, and kick the user out if they don't have permission to do whatever they are trying to do. - If the user does have permission, we just proxy the rest of the transaction. Next steps on the Conduit side are more simple: - Make ConduitClient understand "ssh://" URLs. Test Plan: Ran `sshd-exec --phabricator-ssh-user epriestley conduit differential.query`, etc. This will get a more comprehensive test once I set up sshd-vcs. Reviewers: btrahan, vrana Reviewed By: btrahan CC: aran Maniphest Tasks: T603, T550 Differential Revision: https://secure.phabricator.com/D4229
2012-12-19 20:08:07 +01:00
$rethrow = null;
try {
$err = $workflow->execute($parsed_args);
Implement SSHD glue and Conduit SSH endpoint Summary: - Build "sshd-auth" (for authentication) and "sshd-exec" (for command execution) binaries. These are callable by "sshd-vcs", located [[https://github.com/epriestley/sshd-vcs | in my account on GitHub]]. They are based on precursors [[https://github.com/epriestley/sshd-vcs-glue | here on GitHub]] which I deployed for TenXer about a year ago, so I have some confidence they at least basically work. - The problem this solves is that normally every user would need an account on a machine to connect to it, and/or their public keys would all need to be listed in `~/.authorized_keys`. This is a big pain in most installs. Software like Gitosis/Gitolite solve this problem by giving you an easy way to add public keys to `~/.authorized_keys`, but this is pretty gross. - Roughly, instead of looking in `~/.authorized_keys` when a user connects, the patched sshd instead runs `echo <public key> | sshd-auth`. The `sshd-auth` script looks up the public key and authorizes the matching user, if they exist. It also forces sshd to run `sshd-exec` instead of a normal shell. - `sshd-exec` receives the authenticated user and any command which was passed to ssh (like `git receive-pack`) and can route them appropriately. - Overall, this permits a single account to be set up on a server which all Phabricator users can connect to without any extra work, and which can safely execute commands and apply appropriate permissions, and disable users when they are disabled in Phabricator and all that stuff. - Build out "sshd-exec" to do more thorough checks and setup, and delegate command execution to Workflows (they now exist, and did not when I originally built this stuff). - Convert @btrahan's conduit API script into a workflow and slightly simplify it (ConduitCall did not exist at the time it was written). The next steps here on the Repository side are to implement Workflows for Git, SVN and HG wire protocols. These will mostly just proxy the protocols, but also need to enforce permissions. So the approach will basically be: - Implement workflows for stuff like `git receive-pack`. - These workflows will implement enough of the underlying protocol to determine what resource the user is trying to access, and whether they want to read or write it. - They'll then do a permissons check, and kick the user out if they don't have permission to do whatever they are trying to do. - If the user does have permission, we just proxy the rest of the transaction. Next steps on the Conduit side are more simple: - Make ConduitClient understand "ssh://" URLs. Test Plan: Ran `sshd-exec --phabricator-ssh-user epriestley conduit differential.query`, etc. This will get a more comprehensive test once I set up sshd-vcs. Reviewers: btrahan, vrana Reviewed By: btrahan CC: aran Maniphest Tasks: T603, T550 Differential Revision: https://secure.phabricator.com/D4229
2012-12-19 20:08:07 +01:00
$metrics_channel->flush();
$error_channel->flush();
} catch (Exception $ex) {
$rethrow = $ex;
}
// Always write this if we got as far as building a metrics channel.
$ssh_log->setData(
array(
'i' => $metrics_channel->getBytesRead(),
'o' => $metrics_channel->getBytesWritten(),
));
if ($rethrow) {
throw $rethrow;
}
Implement SSHD glue and Conduit SSH endpoint Summary: - Build "sshd-auth" (for authentication) and "sshd-exec" (for command execution) binaries. These are callable by "sshd-vcs", located [[https://github.com/epriestley/sshd-vcs | in my account on GitHub]]. They are based on precursors [[https://github.com/epriestley/sshd-vcs-glue | here on GitHub]] which I deployed for TenXer about a year ago, so I have some confidence they at least basically work. - The problem this solves is that normally every user would need an account on a machine to connect to it, and/or their public keys would all need to be listed in `~/.authorized_keys`. This is a big pain in most installs. Software like Gitosis/Gitolite solve this problem by giving you an easy way to add public keys to `~/.authorized_keys`, but this is pretty gross. - Roughly, instead of looking in `~/.authorized_keys` when a user connects, the patched sshd instead runs `echo <public key> | sshd-auth`. The `sshd-auth` script looks up the public key and authorizes the matching user, if they exist. It also forces sshd to run `sshd-exec` instead of a normal shell. - `sshd-exec` receives the authenticated user and any command which was passed to ssh (like `git receive-pack`) and can route them appropriately. - Overall, this permits a single account to be set up on a server which all Phabricator users can connect to without any extra work, and which can safely execute commands and apply appropriate permissions, and disable users when they are disabled in Phabricator and all that stuff. - Build out "sshd-exec" to do more thorough checks and setup, and delegate command execution to Workflows (they now exist, and did not when I originally built this stuff). - Convert @btrahan's conduit API script into a workflow and slightly simplify it (ConduitCall did not exist at the time it was written). The next steps here on the Repository side are to implement Workflows for Git, SVN and HG wire protocols. These will mostly just proxy the protocols, but also need to enforce permissions. So the approach will basically be: - Implement workflows for stuff like `git receive-pack`. - These workflows will implement enough of the underlying protocol to determine what resource the user is trying to access, and whether they want to read or write it. - They'll then do a permissons check, and kick the user out if they don't have permission to do whatever they are trying to do. - If the user does have permission, we just proxy the rest of the transaction. Next steps on the Conduit side are more simple: - Make ConduitClient understand "ssh://" URLs. Test Plan: Ran `sshd-exec --phabricator-ssh-user epriestley conduit differential.query`, etc. This will get a more comprehensive test once I set up sshd-vcs. Reviewers: btrahan, vrana Reviewed By: btrahan CC: aran Maniphest Tasks: T603, T550 Differential Revision: https://secure.phabricator.com/D4229
2012-12-19 20:08:07 +01:00
} catch (Exception $ex) {
fwrite(STDERR, "phabricator-ssh-exec: ".$ex->getMessage()."\n");
$err = 1;
Implement SSHD glue and Conduit SSH endpoint Summary: - Build "sshd-auth" (for authentication) and "sshd-exec" (for command execution) binaries. These are callable by "sshd-vcs", located [[https://github.com/epriestley/sshd-vcs | in my account on GitHub]]. They are based on precursors [[https://github.com/epriestley/sshd-vcs-glue | here on GitHub]] which I deployed for TenXer about a year ago, so I have some confidence they at least basically work. - The problem this solves is that normally every user would need an account on a machine to connect to it, and/or their public keys would all need to be listed in `~/.authorized_keys`. This is a big pain in most installs. Software like Gitosis/Gitolite solve this problem by giving you an easy way to add public keys to `~/.authorized_keys`, but this is pretty gross. - Roughly, instead of looking in `~/.authorized_keys` when a user connects, the patched sshd instead runs `echo <public key> | sshd-auth`. The `sshd-auth` script looks up the public key and authorizes the matching user, if they exist. It also forces sshd to run `sshd-exec` instead of a normal shell. - `sshd-exec` receives the authenticated user and any command which was passed to ssh (like `git receive-pack`) and can route them appropriately. - Overall, this permits a single account to be set up on a server which all Phabricator users can connect to without any extra work, and which can safely execute commands and apply appropriate permissions, and disable users when they are disabled in Phabricator and all that stuff. - Build out "sshd-exec" to do more thorough checks and setup, and delegate command execution to Workflows (they now exist, and did not when I originally built this stuff). - Convert @btrahan's conduit API script into a workflow and slightly simplify it (ConduitCall did not exist at the time it was written). The next steps here on the Repository side are to implement Workflows for Git, SVN and HG wire protocols. These will mostly just proxy the protocols, but also need to enforce permissions. So the approach will basically be: - Implement workflows for stuff like `git receive-pack`. - These workflows will implement enough of the underlying protocol to determine what resource the user is trying to access, and whether they want to read or write it. - They'll then do a permissons check, and kick the user out if they don't have permission to do whatever they are trying to do. - If the user does have permission, we just proxy the rest of the transaction. Next steps on the Conduit side are more simple: - Make ConduitClient understand "ssh://" URLs. Test Plan: Ran `sshd-exec --phabricator-ssh-user epriestley conduit differential.query`, etc. This will get a more comprehensive test once I set up sshd-vcs. Reviewers: btrahan, vrana Reviewed By: btrahan CC: aran Maniphest Tasks: T603, T550 Differential Revision: https://secure.phabricator.com/D4229
2012-12-19 20:08:07 +01:00
}
$ssh_log->setData(
array(
'c' => $err,
'T' => (int)(1000000 * (microtime(true) - $ssh_start_time)),
));
exit($err);