1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-19 05:12:41 +01:00

Send forced mail on SSH key edits

Summary:
Ref T10917. This cheats fairly heavily to generate SSH key mail:

  - Generate normal transaction mail.
  - Force it to go to the user.
  - Use `setForceDelivery()` to force it to actually be delivered.
  - Add some warning language to the mail body.

This doesn't move us much closer to Glorious Infrastructure for this whole class of events, but should do what it needs to for now and doesn't really require anything sketchy.

Test Plan: Created and edited SSH keys, got security notice mail.

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T10917

Differential Revision: https://secure.phabricator.com/D15948
This commit is contained in:
epriestley 2016-05-19 10:34:38 -07:00
parent da6b3de65c
commit 6f6ca0102d
9 changed files with 134 additions and 7 deletions

View file

@ -1883,6 +1883,7 @@ phutil_register_library_map(array(
'PhabricatorAuthSSHKeyListController' => 'applications/auth/controller/PhabricatorAuthSSHKeyListController.php',
'PhabricatorAuthSSHKeyPHIDType' => 'applications/auth/phid/PhabricatorAuthSSHKeyPHIDType.php',
'PhabricatorAuthSSHKeyQuery' => 'applications/auth/query/PhabricatorAuthSSHKeyQuery.php',
'PhabricatorAuthSSHKeyReplyHandler' => 'applications/auth/mail/PhabricatorAuthSSHKeyReplyHandler.php',
'PhabricatorAuthSSHKeySearchEngine' => 'applications/auth/query/PhabricatorAuthSSHKeySearchEngine.php',
'PhabricatorAuthSSHKeyTableView' => 'applications/auth/view/PhabricatorAuthSSHKeyTableView.php',
'PhabricatorAuthSSHKeyTransaction' => 'applications/auth/storage/PhabricatorAuthSSHKeyTransaction.php',
@ -6318,6 +6319,7 @@ phutil_register_library_map(array(
'PhabricatorAuthSSHKeyListController' => 'PhabricatorAuthSSHKeyController',
'PhabricatorAuthSSHKeyPHIDType' => 'PhabricatorPHIDType',
'PhabricatorAuthSSHKeyQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorAuthSSHKeyReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler',
'PhabricatorAuthSSHKeySearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhabricatorAuthSSHKeyTableView' => 'AphrontView',
'PhabricatorAuthSSHKeyTransaction' => 'PhabricatorApplicationTransaction',

View file

@ -227,6 +227,14 @@ final class AlmanacDevice
return $this->getName();
}
public function getSSHKeyNotifyPHIDs() {
// Devices don't currently have anyone useful to notify about SSH key
// edits, and they're usually a difficult vector to attack since you need
// access to a cluster host. However, it would be nice to make them
// subscribable at some point.
return array();
}
/* -( PhabricatorDestructibleInterface )----------------------------------- */

View file

@ -36,13 +36,31 @@ final class PhabricatorAuthSSHKeyGenerateController
$type = $public_key->getType();
$body = $public_key->getBody();
$comment = pht('Generated');
$key
->setName($default_name)
->setKeyType($type)
->setKeyBody($body)
->setKeyComment(pht('Generated'))
->save();
$entire_key = "{$type} {$body} {$comment}";
$type_create = PhabricatorTransactions::TYPE_CREATE;
$type_name = PhabricatorAuthSSHKeyTransaction::TYPE_NAME;
$type_key = PhabricatorAuthSSHKeyTransaction::TYPE_KEY;
$xactions = array();
$xactions[] = id(new PhabricatorAuthSSHKeyTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_CREATE);
$xactions[] = id(new PhabricatorAuthSSHKeyTransaction())
->setTransactionType($type_name)
->setNewValue($default_name);
$xactions[] = id(new PhabricatorAuthSSHKeyTransaction())
->setTransactionType($type_key)
->setNewValue($entire_key);
$editor = id(new PhabricatorAuthSSHKeyEditor())
->setActor($viewer)
->setContentSourceFromRequest($request)
->applyTransactions($key, $xactions);
// NOTE: We're disabling workflow on submit so the download works. We're
// disabling workflow on cancel so the page reloads, showing the new

View file

@ -177,4 +177,68 @@ final class PhabricatorAuthSSHKeyEditor
}
protected function shouldSendMail(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
protected function getMailSubjectPrefix() {
return pht('[SSH Key]');
}
protected function getMailThreadID(PhabricatorLiskDAO $object) {
return 'ssh-key-'.$object->getPHID();
}
protected function getMailTo(PhabricatorLiskDAO $object) {
return $object->getObject()->getSSHKeyNotifyPHIDs();
}
protected function getMailCC(PhabricatorLiskDAO $object) {
return array();
}
protected function buildReplyHandler(PhabricatorLiskDAO $object) {
return id(new PhabricatorAuthSSHKeyReplyHandler())
->setMailReceiver($object);
}
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
$id = $object->getID();
$name = $object->getName();
$phid = $object->getPHID();
$mail = id(new PhabricatorMetaMTAMail())
->setSubject(pht('SSH Key %d: %s', $id, $name))
->addHeader('Thread-Topic', $phid);
// The primary value of this mail is alerting users to account compromises,
// so force delivery. In particular, this mail should still be delievered
// even if "self mail" is disabled.
$mail->setForceDelivery(true);
return $mail;
}
protected function buildMailBody(
PhabricatorLiskDAO $object,
array $xactions) {
$body = parent::buildMailBody($object, $xactions);
$body->addLinkSection(
pht('SECURITY WARNING'),
pht(
'If you do not recognize this change, it may indicate your account '.
'has been compromised.'));
$detail_uri = $object->getURI();
$detail_uri = PhabricatorEnv::getProductionURI($detail_uri);
$body->addLinkSection(pht('SSH KEY DETAIL'), $detail_uri);
return $body;
}
}

View file

@ -0,0 +1,17 @@
<?php
final class PhabricatorAuthSSHKeyReplyHandler
extends PhabricatorApplicationTransactionReplyHandler {
public function validateMailReceiver($mail_receiver) {
if (!($mail_receiver instanceof PhabricatorAuthSSHKey)) {
throw new Exception(
pht('Mail receiver is not a %s!', 'PhabricatorAuthSSHKey'));
}
}
public function getObjectPrefix() {
return 'SSHKEY';
}
}

View file

@ -17,4 +17,6 @@ interface PhabricatorSSHPublicKeyInterface {
*/
public function getSSHKeyDefaultName();
public function getSSHKeyNotifyPHIDs();
}

View file

@ -70,6 +70,12 @@ final class PhabricatorAuthSSHKey
return parent::save();
}
public function getMailKey() {
// NOTE: We don't actually receive mail for these objects. It's OK for
// the mail key to be predictable until we do.
return PhabricatorHash::digestForIndex($this->getPHID());
}
public function toPublicKey() {
return PhabricatorAuthSSHPublicKey::newFromStoredKey($this);
}
@ -164,7 +170,7 @@ final class PhabricatorAuthSSHKey
}
public function getApplicationTransactionTemplate() {
return new PhabricatorAuthProviderConfigTransaction();
return new PhabricatorAuthSSHKeyTransaction();
}
public function willRenderTimeline(

View file

@ -26,6 +26,10 @@ final class PhabricatorAuthSSHKeyTransaction
$new = $this->getNewValue();
switch ($this->getTransactionType()) {
case PhabricatorTransactions::TYPE_CREATE:
return pht(
'%s created this key.',
$this->renderHandleLink($author_phid));
case self::TYPE_NAME:
return pht(
'%s renamed this key from "%s" to "%s".',

View file

@ -1342,6 +1342,12 @@ final class PhabricatorUser
return 'id_rsa_phabricator';
}
public function getSSHKeyNotifyPHIDs() {
return array(
$this->getPHID(),
);
}
/* -( PhabricatorApplicationTransactionInterface )------------------------- */