Issue 104: Create service that tracks SSH key usage

master
Nathan Adams 2016-04-30 17:14:41 -05:00
parent c16adf0a89
commit ac5ced20a7
6 changed files with 116 additions and 10 deletions

View File

@ -27,7 +27,7 @@ import subprocess
SCRIPTDIR = os.path.abspath(__file__).rsplit(os.path.sep, 1)[0]
GITSERVEPHP = '%s/gitserve.php' % SCRIPTDIR
process = subprocess.Popen(['php', GITSERVEPHP, sys.argv[1]],
process = subprocess.Popen(['php', GITSERVEPHP, sys.argv[1], sys.argv[2]],
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
output = str.encode("\n").join(process.communicate()).strip()
status = process.wait()

View File

@ -54,6 +54,30 @@ class IDF_Key extends Pluf_Model
'blank' => false,
'verbose' => __('public key'),
),
'last_used' =>
array(
'type' => 'Pluf_DB_Field_Datetime',
'blank' => true,
'verbose' => __('last used date'),
'index' => true,
'help_text' => 'Date of when key was last used',
),
'creation_dtime' =>
array(
'type' => 'Pluf_DB_Field_Datetime',
'blank' => true,
'verbose' => __('creation date'),
'index' => true,
'help_text' => 'Date of addition',
),
'ipaddress' =>
array(
'type' => 'Pluf_DB_Field_Varchar',
'blank' => false,
'editable' => false,
'verbose' => __('ipaddress'),
'help_text' => __('IP address that was last connected with this key'),
),
);
// WARNING: Not using getSqlTable on the Pluf_User object to
// avoid recursion.
@ -155,6 +179,10 @@ class IDF_Key extends Pluf_Model
$params = array('key' => $this, 'created' => $create);
Pluf_Signal::send('IDF_Key::postSave',
'IDF_Key', $params);
if ($create) {
$this->creation_dtime = gmdate('Y-m-d H:i:s');
}
}
function preDelete()

View File

@ -0,0 +1,47 @@
<?php
function IDF_Migrations_34GitSSHTracking_up()
{
$table = Pluf::factory('IDF_Key')->getSqlTable();
$sql = array();
$sql["MySQL"] = <<<EOD
ALTER TABLE `$table`
ADD COLUMN `last_used` DATETIME NOT NULL AFTER `content`,
ADD COLUMN `creation_dtime` DATETIME NOT NULL AFTER `last_used`,
ADD COLUMN `ipaddress` VARCHAR(255) NOT NULL AFTER `creation_dtime`,
ADD INDEX `last_used` (`last_used`),
ADD INDEX `creation_dtime` (`creation_dtime`);
UPDATE indefero_idf_keys SET creation_dtime = '2016-04-30 03:19:54';
EOD;
$db = Pluf::db();
$engine = Pluf::f('db_engine');
$db->execute($sql[$engine]);
}
function IDF_Migrations_34GitSSHTracking_down()
{
$table = Pluf::factory('IDF_Key')->getSqlTable();
$sql = array();
$sql["MySQL"] = <<<EOD
ALTER TABLE `$table`
DROP COLUMN `last_used` DATETIME NOT NULL AFTER `content`,
DROP COLUMN `creation_dtime` DATETIME NOT NULL AFTER `last_used`,
DROP COLUMN `ipaddress` VARCHAR(255) NOT NULL AFTER `creation_dtime`,
DROP INDEX `last_used` (`last_used`),
DROP INDEX `creation_dtime` (`creation_dtime`);
EOD;
$db = Pluf::db();
$engine = Pluf::f('db_engine');
$db->execute($sql[$engine]);
}

View File

@ -29,7 +29,7 @@ class IDF_Plugin_SyncGit_Cron
/**
* Template for the SSH key.
*/
public $template = 'command="python %s %s",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty %s';
public $template = 'command="python %s %s %s",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty %s';
/**
* Synchronize.
@ -56,7 +56,7 @@ class IDF_Plugin_SyncGit_Cron
}
if ($key_type == 'ssh' and preg_match('/^[a-zA-Z][a-zA-Z0-9_.-]*(@[a-zA-Z][a-zA-Z0-9.-]*)?$/', $key->login)) {
$content = trim(str_replace(array("\n", "\r"), '', $key->content));
$out .= sprintf($template, $cmd, $key->login, $content)."\n";
$out .= sprintf($template, $cmd, $key->login, $key->id, $content)."\n";
}
}
$out = "# indefero start" . PHP_EOL . $out . "# indefero end" . PHP_EOL;

View File

@ -107,10 +107,11 @@ class IDF_Plugin_SyncGit_Serve
*/
public static function main($argv, $env)
{
if (count($argv) != 2) {
self::fatalError('Missing argument USER.');
if (count($argv) != 3) {
self::fatalError('Missing argument USER and SSH key id.');
}
$username = $argv[1];
$keyId = $argv[2];
umask(0022);
if (!isset($env['SSH_ORIGINAL_COMMAND'])) {
self::fatalError('Need SSH_ORIGINAL_COMMAND in environment.');
@ -120,6 +121,12 @@ class IDF_Plugin_SyncGit_Serve
$serve = new IDF_Plugin_SyncGit_Serve();
try {
$new_cmd = $serve->serve($username, $cmd);
if ($keyId) {
$key = Pluf::factory('IDF_Key', $keyId);
$key->ipaddress = explode(" ", $_SERVER["SSH_CLIENT"])[0];
$key->last_used = gmdate('Y-m-d H:i:s');
$key->update();
}
} catch (Exception $e) {
self::fatalError($e->getMessage());
}

View File

@ -147,11 +147,35 @@
{if count($keys)}
<table summary=" " class="recent-issues">
<tr><th colspan="2">{trans 'Your Current Public Keys'}</th></tr>
{foreach $keys as $key}<tr><td>
<span class="mono">{$key.showCompact()}</span></td><td> <form class="star" method="post" action="{url 'IDF_Views_User::deleteKey', array($key.id)}"><input type="image" src="{media '/idf/img/trash.png'}" name="submit" value="{trans 'Delete this key'}" /></form>
</td>
</tr>{/foreach}
<tr>
<th colspan="5">{trans 'Your Current Public Keys'}</th>
</tr>
<tr>
<th>Key</th>
<th>Key Added</th>
<th>Key Last Used</th>
<th>Last IP</th>
<th>Delete</th>
</tr>
{foreach $keys as $key}
<tr>
<td>
<span class="mono">{$key.showCompact()}</span>
</td>
<td width="13%" style="text-align: center">
<span title="{$key.creation_dtime}">{$key.creation_dtime|date}</span>
</td>
<td width="16%">
<span title="{$key.last_used|date:"%Y-%m-%d %H:%M:%S"}">{$key.last_used|dateago}</span>
</td>
<td>
{$key.ipaddress}
</td>
<td>
<form class="star" method="post" action="{url 'IDF_Views_User::deleteKey', array($key.id)}"><input type="image" src="{media '/idf/img/trash.png'}" name="submit" value="{trans 'Delete this key'}" /></form>
</td>
</tr>
{/foreach}
</table>
{/if}
{if count($mailaddrs)>1}