1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-23 23:32:40 +01:00
phorge-phorge/scripts/ssh/ssh-auth.php

78 lines
1.9 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
$root = dirname(dirname(dirname(__FILE__)));
require_once $root.'/scripts/__init_script__.php';
Add a query/policy layer on top of SSH keys for Almanac Summary: Ref T5833. Currently, SSH keys are associated only with users, and are a bit un-modern. I want to let Almanac Devices have SSH keys so devices in a cluster can identify to one another. For example, with hosted installs, initialization will go something like this: - A request comes in for `company.phacility.com`. - A SiteSource (from D10787) makes a Conduit call to Almanac on the master install to check if `company` is a valid install and pull config if it is. - This call can be signed with an SSH key which identifies a trusted Almanac Device. In the cluster case, a web host can make an authenticated call to a repository host with similar key signing. To move toward this, put a proper Query class on top of SSH key access (this diff). In following diffs, I'll: - Rename `userPHID` to `objectPHID`. - Move this to the `auth` database. - Provide UI for device/key association. An alternative approach would be to build some kind of special token layer in Conduit, but I think that would be a lot harder to manage in the hosting case. This gives us a more direct attack on trusting requests from machines and recognizing machines as first (well, sort of second-class) actors without needing things like fake user accounts. Test Plan: - Added and removed SSH keys. - Added and removed SSH keys from a bot account. - Tried to edit an unonwned SSH key (denied). - Ran `bin/ssh-auth`, got sensible output. - Ran `bin/ssh-auth-key`, got sensible output. Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Maniphest Tasks: T5833 Differential Revision: https://secure.phabricator.com/D10790
2014-11-06 21:37:02 +01:00
$keys = id(new PhabricatorAuthSSHKeyQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
Deactivate SSH keys instead of destroying them completely Summary: Ref T10917. Currently, when you delete an SSH key, we really truly delete it forever. This isn't very consistent with other applications, but we built this stuff a long time ago before we were as rigorous about retaining data and making it auditable. In partiular, destroying data isn't good for auditing after security issues, since it means we can't show you logs of any changes an attacker might have made to your keys. To prepare to improve this, stop destoying data. This will allow later changes to become transaction-oriented and show normal transaction logs. The tricky part here is that we have a `UNIQUE KEY` on the public key part of the key. Instead, I changed this to `UNIQUE (key, isActive)`, where `isActive` is a nullable boolean column. This works because MySQL does not enforce "unique" if part of the key is `NULL`. So you can't have two rows with `("A", 1)`, but you can have as many rows as you want with `("A", null)`. This lets us keep the "each key may only be active for one user/object" rule without requiring us to delete any data. Test Plan: - Ran schema changes. - Viewed public keys. - Tried to add a duplicate key, got rejected (already associated with another object). - Deleted SSH key. - Verified that the key was no longer actually deleted from the database, just marked inactive (in future changes, I'll update the UI to be more clear about this). - Uploaded a new copy of the same public key, worked fine (no duplicate key rejection). - Tried to upload yet another copy, got rejected. - Generated a new keypair. - Tried to upload a duplicate to an Almanac device, got rejected. - Generated a new pair for a device. - Trusted a device key. - Untrusted a device key. - "Deleted" a device key. - Tried to trust a deleted device key, got "inactive" message. - Ran `bin/ssh-auth`, got good output with unique keys. - Ran `cat ~/.ssh/id_rsa.pub | ./bin/ssh-auth-key`, got good output with one key. - Used `auth.querypublickeys` Conduit method to query keys, got good active keys. Reviewers: chad Reviewed By: chad Maniphest Tasks: T10917 Differential Revision: https://secure.phabricator.com/D15943
2016-05-18 18:32:50 +02:00
->withIsActive(true)
Add a query/policy layer on top of SSH keys for Almanac Summary: Ref T5833. Currently, SSH keys are associated only with users, and are a bit un-modern. I want to let Almanac Devices have SSH keys so devices in a cluster can identify to one another. For example, with hosted installs, initialization will go something like this: - A request comes in for `company.phacility.com`. - A SiteSource (from D10787) makes a Conduit call to Almanac on the master install to check if `company` is a valid install and pull config if it is. - This call can be signed with an SSH key which identifies a trusted Almanac Device. In the cluster case, a web host can make an authenticated call to a repository host with similar key signing. To move toward this, put a proper Query class on top of SSH key access (this diff). In following diffs, I'll: - Rename `userPHID` to `objectPHID`. - Move this to the `auth` database. - Provide UI for device/key association. An alternative approach would be to build some kind of special token layer in Conduit, but I think that would be a lot harder to manage in the hosting case. This gives us a more direct attack on trusting requests from machines and recognizing machines as first (well, sort of second-class) actors without needing things like fake user accounts. Test Plan: - Added and removed SSH keys. - Added and removed SSH keys from a bot account. - Tried to edit an unonwned SSH key (denied). - Ran `bin/ssh-auth`, got sensible output. - Ran `bin/ssh-auth-key`, got sensible output. Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Maniphest Tasks: T5833 Differential Revision: https://secure.phabricator.com/D10790
2014-11-06 21:37:02 +01:00
->execute();
if (!$keys) {
echo pht('No keys found.')."\n";
exit(1);
}
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
$bin = $root.'/bin/ssh-exec';
Add a query/policy layer on top of SSH keys for Almanac Summary: Ref T5833. Currently, SSH keys are associated only with users, and are a bit un-modern. I want to let Almanac Devices have SSH keys so devices in a cluster can identify to one another. For example, with hosted installs, initialization will go something like this: - A request comes in for `company.phacility.com`. - A SiteSource (from D10787) makes a Conduit call to Almanac on the master install to check if `company` is a valid install and pull config if it is. - This call can be signed with an SSH key which identifies a trusted Almanac Device. In the cluster case, a web host can make an authenticated call to a repository host with similar key signing. To move toward this, put a proper Query class on top of SSH key access (this diff). In following diffs, I'll: - Rename `userPHID` to `objectPHID`. - Move this to the `auth` database. - Provide UI for device/key association. An alternative approach would be to build some kind of special token layer in Conduit, but I think that would be a lot harder to manage in the hosting case. This gives us a more direct attack on trusting requests from machines and recognizing machines as first (well, sort of second-class) actors without needing things like fake user accounts. Test Plan: - Added and removed SSH keys. - Added and removed SSH keys from a bot account. - Tried to edit an unonwned SSH key (denied). - Ran `bin/ssh-auth`, got sensible output. - Ran `bin/ssh-auth-key`, got sensible output. Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Maniphest Tasks: T5833 Differential Revision: https://secure.phabricator.com/D10790
2014-11-06 21:37:02 +01:00
foreach ($keys as $ssh_key) {
$key_argv = array();
$object = $ssh_key->getObject();
if ($object instanceof PhabricatorUser) {
$key_argv[] = '--phabricator-ssh-user';
$key_argv[] = $object->getUsername();
} else if ($object instanceof AlmanacDevice) {
if (!$ssh_key->getIsTrusted()) {
// If this key is not a trusted device key, don't allow SSH
// authentication.
continue;
}
$key_argv[] = '--phabricator-ssh-device';
$key_argv[] = $object->getName();
} else {
// We don't know what sort of key this is; don't permit SSH auth.
continue;
}
$key_argv[] = '--phabricator-ssh-key';
$key_argv[] = $ssh_key->getID();
$cmd = csprintf('%s %Ls', $bin, $key_argv);
$instance = PhabricatorEnv::getEnvConfig('cluster.instance');
if (strlen($instance)) {
$cmd = csprintf('PHABRICATOR_INSTANCE=%s %C', $instance, $cmd);
}
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
// This is additional escaping for the SSH 'command="..."' string.
$cmd = addcslashes($cmd, '"\\');
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
// Strip out newlines and other nonsense from the key type and key body.
Add a query/policy layer on top of SSH keys for Almanac Summary: Ref T5833. Currently, SSH keys are associated only with users, and are a bit un-modern. I want to let Almanac Devices have SSH keys so devices in a cluster can identify to one another. For example, with hosted installs, initialization will go something like this: - A request comes in for `company.phacility.com`. - A SiteSource (from D10787) makes a Conduit call to Almanac on the master install to check if `company` is a valid install and pull config if it is. - This call can be signed with an SSH key which identifies a trusted Almanac Device. In the cluster case, a web host can make an authenticated call to a repository host with similar key signing. To move toward this, put a proper Query class on top of SSH key access (this diff). In following diffs, I'll: - Rename `userPHID` to `objectPHID`. - Move this to the `auth` database. - Provide UI for device/key association. An alternative approach would be to build some kind of special token layer in Conduit, but I think that would be a lot harder to manage in the hosting case. This gives us a more direct attack on trusting requests from machines and recognizing machines as first (well, sort of second-class) actors without needing things like fake user accounts. Test Plan: - Added and removed SSH keys. - Added and removed SSH keys from a bot account. - Tried to edit an unonwned SSH key (denied). - Ran `bin/ssh-auth`, got sensible output. - Ran `bin/ssh-auth-key`, got sensible output. Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Maniphest Tasks: T5833 Differential Revision: https://secure.phabricator.com/D10790
2014-11-06 21:37:02 +01:00
$type = $ssh_key->getKeyType();
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
$type = preg_replace('@[\x00-\x20]+@', '', $type);
if (!strlen($type)) {
continue;
}
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
Add a query/policy layer on top of SSH keys for Almanac Summary: Ref T5833. Currently, SSH keys are associated only with users, and are a bit un-modern. I want to let Almanac Devices have SSH keys so devices in a cluster can identify to one another. For example, with hosted installs, initialization will go something like this: - A request comes in for `company.phacility.com`. - A SiteSource (from D10787) makes a Conduit call to Almanac on the master install to check if `company` is a valid install and pull config if it is. - This call can be signed with an SSH key which identifies a trusted Almanac Device. In the cluster case, a web host can make an authenticated call to a repository host with similar key signing. To move toward this, put a proper Query class on top of SSH key access (this diff). In following diffs, I'll: - Rename `userPHID` to `objectPHID`. - Move this to the `auth` database. - Provide UI for device/key association. An alternative approach would be to build some kind of special token layer in Conduit, but I think that would be a lot harder to manage in the hosting case. This gives us a more direct attack on trusting requests from machines and recognizing machines as first (well, sort of second-class) actors without needing things like fake user accounts. Test Plan: - Added and removed SSH keys. - Added and removed SSH keys from a bot account. - Tried to edit an unonwned SSH key (denied). - Ran `bin/ssh-auth`, got sensible output. - Ran `bin/ssh-auth-key`, got sensible output. Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Maniphest Tasks: T5833 Differential Revision: https://secure.phabricator.com/D10790
2014-11-06 21:37:02 +01:00
$key = $ssh_key->getKeyBody();
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
$key = preg_replace('@[\x00-\x20]+@', '', $key);
if (!strlen($key)) {
continue;
}
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
$options = array(
'command="'.$cmd.'"',
'no-port-forwarding',
'no-X11-forwarding',
'no-agent-forwarding',
'no-pty',
);
$options = implode(',', $options);
$lines[] = $options.' '.$type.' '.$key."\n";
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
echo implode('', $lines);
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
exit(0);