@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+134 -7
+2
src/__phutil_library_map__.php
··· 1883 1883 'PhabricatorAuthSSHKeyListController' => 'applications/auth/controller/PhabricatorAuthSSHKeyListController.php', 1884 1884 'PhabricatorAuthSSHKeyPHIDType' => 'applications/auth/phid/PhabricatorAuthSSHKeyPHIDType.php', 1885 1885 'PhabricatorAuthSSHKeyQuery' => 'applications/auth/query/PhabricatorAuthSSHKeyQuery.php', 1886 + 'PhabricatorAuthSSHKeyReplyHandler' => 'applications/auth/mail/PhabricatorAuthSSHKeyReplyHandler.php', 1886 1887 'PhabricatorAuthSSHKeySearchEngine' => 'applications/auth/query/PhabricatorAuthSSHKeySearchEngine.php', 1887 1888 'PhabricatorAuthSSHKeyTableView' => 'applications/auth/view/PhabricatorAuthSSHKeyTableView.php', 1888 1889 'PhabricatorAuthSSHKeyTransaction' => 'applications/auth/storage/PhabricatorAuthSSHKeyTransaction.php', ··· 6318 6319 'PhabricatorAuthSSHKeyListController' => 'PhabricatorAuthSSHKeyController', 6319 6320 'PhabricatorAuthSSHKeyPHIDType' => 'PhabricatorPHIDType', 6320 6321 'PhabricatorAuthSSHKeyQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 6322 + 'PhabricatorAuthSSHKeyReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 6321 6323 'PhabricatorAuthSSHKeySearchEngine' => 'PhabricatorApplicationSearchEngine', 6322 6324 'PhabricatorAuthSSHKeyTableView' => 'AphrontView', 6323 6325 'PhabricatorAuthSSHKeyTransaction' => 'PhabricatorApplicationTransaction',
+8
src/applications/almanac/storage/AlmanacDevice.php
··· 227 227 return $this->getName(); 228 228 } 229 229 230 + public function getSSHKeyNotifyPHIDs() { 231 + // Devices don't currently have anyone useful to notify about SSH key 232 + // edits, and they're usually a difficult vector to attack since you need 233 + // access to a cluster host. However, it would be nice to make them 234 + // subscribable at some point. 235 + return array(); 236 + } 237 + 230 238 231 239 /* -( PhabricatorDestructibleInterface )----------------------------------- */ 232 240
+24 -6
src/applications/auth/controller/PhabricatorAuthSSHKeyGenerateController.php
··· 36 36 37 37 $type = $public_key->getType(); 38 38 $body = $public_key->getBody(); 39 + $comment = pht('Generated'); 39 40 40 - $key 41 - ->setName($default_name) 42 - ->setKeyType($type) 43 - ->setKeyBody($body) 44 - ->setKeyComment(pht('Generated')) 45 - ->save(); 41 + $entire_key = "{$type} {$body} {$comment}"; 42 + 43 + $type_create = PhabricatorTransactions::TYPE_CREATE; 44 + $type_name = PhabricatorAuthSSHKeyTransaction::TYPE_NAME; 45 + $type_key = PhabricatorAuthSSHKeyTransaction::TYPE_KEY; 46 + 47 + $xactions = array(); 48 + 49 + $xactions[] = id(new PhabricatorAuthSSHKeyTransaction()) 50 + ->setTransactionType(PhabricatorTransactions::TYPE_CREATE); 51 + 52 + $xactions[] = id(new PhabricatorAuthSSHKeyTransaction()) 53 + ->setTransactionType($type_name) 54 + ->setNewValue($default_name); 55 + 56 + $xactions[] = id(new PhabricatorAuthSSHKeyTransaction()) 57 + ->setTransactionType($type_key) 58 + ->setNewValue($entire_key); 59 + 60 + $editor = id(new PhabricatorAuthSSHKeyEditor()) 61 + ->setActor($viewer) 62 + ->setContentSourceFromRequest($request) 63 + ->applyTransactions($key, $xactions); 46 64 47 65 // NOTE: We're disabling workflow on submit so the download works. We're 48 66 // disabling workflow on cancel so the page reloads, showing the new
+64
src/applications/auth/editor/PhabricatorAuthSSHKeyEditor.php
··· 177 177 } 178 178 179 179 180 + protected function shouldSendMail( 181 + PhabricatorLiskDAO $object, 182 + array $xactions) { 183 + return true; 184 + } 185 + 186 + protected function getMailSubjectPrefix() { 187 + return pht('[SSH Key]'); 188 + } 189 + 190 + protected function getMailThreadID(PhabricatorLiskDAO $object) { 191 + return 'ssh-key-'.$object->getPHID(); 192 + } 193 + 194 + protected function getMailTo(PhabricatorLiskDAO $object) { 195 + return $object->getObject()->getSSHKeyNotifyPHIDs(); 196 + } 197 + 198 + protected function getMailCC(PhabricatorLiskDAO $object) { 199 + return array(); 200 + } 201 + 202 + protected function buildReplyHandler(PhabricatorLiskDAO $object) { 203 + return id(new PhabricatorAuthSSHKeyReplyHandler()) 204 + ->setMailReceiver($object); 205 + } 206 + 207 + protected function buildMailTemplate(PhabricatorLiskDAO $object) { 208 + $id = $object->getID(); 209 + $name = $object->getName(); 210 + $phid = $object->getPHID(); 211 + 212 + $mail = id(new PhabricatorMetaMTAMail()) 213 + ->setSubject(pht('SSH Key %d: %s', $id, $name)) 214 + ->addHeader('Thread-Topic', $phid); 215 + 216 + // The primary value of this mail is alerting users to account compromises, 217 + // so force delivery. In particular, this mail should still be delievered 218 + // even if "self mail" is disabled. 219 + $mail->setForceDelivery(true); 220 + 221 + return $mail; 222 + } 223 + 224 + protected function buildMailBody( 225 + PhabricatorLiskDAO $object, 226 + array $xactions) { 227 + 228 + $body = parent::buildMailBody($object, $xactions); 229 + 230 + $body->addLinkSection( 231 + pht('SECURITY WARNING'), 232 + pht( 233 + 'If you do not recognize this change, it may indicate your account '. 234 + 'has been compromised.')); 235 + 236 + $detail_uri = $object->getURI(); 237 + $detail_uri = PhabricatorEnv::getProductionURI($detail_uri); 238 + 239 + $body->addLinkSection(pht('SSH KEY DETAIL'), $detail_uri); 240 + 241 + return $body; 242 + } 243 + 180 244 }
+17
src/applications/auth/mail/PhabricatorAuthSSHKeyReplyHandler.php
··· 1 + <?php 2 + 3 + final class PhabricatorAuthSSHKeyReplyHandler 4 + extends PhabricatorApplicationTransactionReplyHandler { 5 + 6 + public function validateMailReceiver($mail_receiver) { 7 + if (!($mail_receiver instanceof PhabricatorAuthSSHKey)) { 8 + throw new Exception( 9 + pht('Mail receiver is not a %s!', 'PhabricatorAuthSSHKey')); 10 + } 11 + } 12 + 13 + public function getObjectPrefix() { 14 + return 'SSHKEY'; 15 + } 16 + 17 + }
+2
src/applications/auth/sshkey/PhabricatorSSHPublicKeyInterface.php
··· 17 17 */ 18 18 public function getSSHKeyDefaultName(); 19 19 20 + public function getSSHKeyNotifyPHIDs(); 21 + 20 22 }
+7 -1
src/applications/auth/storage/PhabricatorAuthSSHKey.php
··· 70 70 return parent::save(); 71 71 } 72 72 73 + public function getMailKey() { 74 + // NOTE: We don't actually receive mail for these objects. It's OK for 75 + // the mail key to be predictable until we do. 76 + return PhabricatorHash::digestForIndex($this->getPHID()); 77 + } 78 + 73 79 public function toPublicKey() { 74 80 return PhabricatorAuthSSHPublicKey::newFromStoredKey($this); 75 81 } ··· 164 170 } 165 171 166 172 public function getApplicationTransactionTemplate() { 167 - return new PhabricatorAuthProviderConfigTransaction(); 173 + return new PhabricatorAuthSSHKeyTransaction(); 168 174 } 169 175 170 176 public function willRenderTimeline(
+4
src/applications/auth/storage/PhabricatorAuthSSHKeyTransaction.php
··· 26 26 $new = $this->getNewValue(); 27 27 28 28 switch ($this->getTransactionType()) { 29 + case PhabricatorTransactions::TYPE_CREATE: 30 + return pht( 31 + '%s created this key.', 32 + $this->renderHandleLink($author_phid)); 29 33 case self::TYPE_NAME: 30 34 return pht( 31 35 '%s renamed this key from "%s" to "%s".',
+6
src/applications/people/storage/PhabricatorUser.php
··· 1342 1342 return 'id_rsa_phabricator'; 1343 1343 } 1344 1344 1345 + public function getSSHKeyNotifyPHIDs() { 1346 + return array( 1347 + $this->getPHID(), 1348 + ); 1349 + } 1350 + 1345 1351 1346 1352 /* -( PhabricatorApplicationTransactionInterface )------------------------- */ 1347 1353