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
This commit is contained in:
@@ -4,25 +4,27 @@
|
||||
$root = dirname(dirname(dirname(__FILE__)));
|
||||
require_once $root.'/scripts/__init_script__.php';
|
||||
|
||||
$user_dao = new PhabricatorUser();
|
||||
$ssh_dao = new PhabricatorUserSSHKey();
|
||||
$conn_r = $user_dao->establishConnection('r');
|
||||
$keys = id(new PhabricatorAuthSSHKeyQuery())
|
||||
->setViewer(PhabricatorUser::getOmnipotentUser())
|
||||
->execute();
|
||||
|
||||
$rows = queryfx_all(
|
||||
$conn_r,
|
||||
'SELECT userName, keyBody, keyType FROM %T u JOIN %T ssh
|
||||
ON u.phid = ssh.userPHID',
|
||||
$user_dao->getTableName(),
|
||||
$ssh_dao->getTableName());
|
||||
foreach ($keys as $key => $ssh_key) {
|
||||
// For now, filter out any keys which don't belong to users. Eventually we
|
||||
// may allow devices to use this channel.
|
||||
if (!($ssh_key->getObject() instanceof PhabricatorUser)) {
|
||||
unset($keys[$key]);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$rows) {
|
||||
if (!$keys) {
|
||||
echo pht('No keys found.')."\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$bin = $root.'/bin/ssh-exec';
|
||||
foreach ($rows as $row) {
|
||||
$user = $row['userName'];
|
||||
foreach ($keys as $ssh_key) {
|
||||
$user = $ssh_key->getObject()->getUsername();
|
||||
|
||||
$cmd = csprintf('%s --phabricator-ssh-user %s', $bin, $user);
|
||||
// This is additional escaping for the SSH 'command="..."' string.
|
||||
@@ -30,13 +32,12 @@ foreach ($rows as $row) {
|
||||
|
||||
// Strip out newlines and other nonsense from the key type and key body.
|
||||
|
||||
$type = $row['keyType'];
|
||||
$type = $ssh_key->getKeyType();
|
||||
$type = preg_replace('@[\x00-\x20]+@', '', $type);
|
||||
|
||||
$key = $row['keyBody'];
|
||||
$key = $ssh_key->getKeyBody();
|
||||
$key = preg_replace('@[\x00-\x20]+@', '', $key);
|
||||
|
||||
|
||||
$options = array(
|
||||
'command="'.$cmd.'"',
|
||||
'no-port-forwarding',
|
||||
|
||||
Reference in New Issue
Block a user