mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-30 01:10:58 +01:00
Add "PassphraseKey" classes for code which needs to actually use credentials
Summary: Ref T4122. These classes provide typed, checked access to credentials, so you can say "give me this password, and throw if anything is funky". Test Plan: Used in next revision. Reviewers: btrahan Reviewed By: btrahan CC: aran Maniphest Tasks: T4122 Differential Revision: https://secure.phabricator.com/D7625
This commit is contained in:
parent
572567b85d
commit
61b26255bb
8 changed files with 143 additions and 5 deletions
|
@ -947,6 +947,7 @@ phutil_register_library_map(array(
|
||||||
'PackageDeleteMail' => 'applications/owners/mail/PackageDeleteMail.php',
|
'PackageDeleteMail' => 'applications/owners/mail/PackageDeleteMail.php',
|
||||||
'PackageMail' => 'applications/owners/mail/PackageMail.php',
|
'PackageMail' => 'applications/owners/mail/PackageMail.php',
|
||||||
'PackageModifyMail' => 'applications/owners/mail/PackageModifyMail.php',
|
'PackageModifyMail' => 'applications/owners/mail/PackageModifyMail.php',
|
||||||
|
'PassphraseAbstractKey' => 'applications/passphrase/keys/PassphraseAbstractKey.php',
|
||||||
'PassphraseController' => 'applications/passphrase/controller/PassphraseController.php',
|
'PassphraseController' => 'applications/passphrase/controller/PassphraseController.php',
|
||||||
'PassphraseCredential' => 'applications/passphrase/storage/PassphraseCredential.php',
|
'PassphraseCredential' => 'applications/passphrase/storage/PassphraseCredential.php',
|
||||||
'PassphraseCredentialControl' => 'applications/passphrase/view/PassphraseCredentialControl.php',
|
'PassphraseCredentialControl' => 'applications/passphrase/view/PassphraseCredentialControl.php',
|
||||||
|
@ -968,6 +969,8 @@ phutil_register_library_map(array(
|
||||||
'PassphraseCredentialViewController' => 'applications/passphrase/controller/PassphraseCredentialViewController.php',
|
'PassphraseCredentialViewController' => 'applications/passphrase/controller/PassphraseCredentialViewController.php',
|
||||||
'PassphraseDAO' => 'applications/passphrase/storage/PassphraseDAO.php',
|
'PassphraseDAO' => 'applications/passphrase/storage/PassphraseDAO.php',
|
||||||
'PassphrasePHIDTypeCredential' => 'applications/passphrase/phid/PassphrasePHIDTypeCredential.php',
|
'PassphrasePHIDTypeCredential' => 'applications/passphrase/phid/PassphrasePHIDTypeCredential.php',
|
||||||
|
'PassphrasePasswordKey' => 'applications/passphrase/keys/PassphrasePasswordKey.php',
|
||||||
|
'PassphraseSSHKey' => 'applications/passphrase/keys/PassphraseSSHKey.php',
|
||||||
'PassphraseSecret' => 'applications/passphrase/storage/PassphraseSecret.php',
|
'PassphraseSecret' => 'applications/passphrase/storage/PassphraseSecret.php',
|
||||||
'PasteCapabilityDefaultView' => 'applications/paste/capability/PasteCapabilityDefaultView.php',
|
'PasteCapabilityDefaultView' => 'applications/paste/capability/PasteCapabilityDefaultView.php',
|
||||||
'PasteCreateMailReceiver' => 'applications/paste/mail/PasteCreateMailReceiver.php',
|
'PasteCreateMailReceiver' => 'applications/paste/mail/PasteCreateMailReceiver.php',
|
||||||
|
@ -3330,6 +3333,7 @@ phutil_register_library_map(array(
|
||||||
'PackageDeleteMail' => 'PackageMail',
|
'PackageDeleteMail' => 'PackageMail',
|
||||||
'PackageMail' => 'PhabricatorMail',
|
'PackageMail' => 'PhabricatorMail',
|
||||||
'PackageModifyMail' => 'PackageMail',
|
'PackageModifyMail' => 'PackageMail',
|
||||||
|
'PassphraseAbstractKey' => 'Phobject',
|
||||||
'PassphraseController' => 'PhabricatorController',
|
'PassphraseController' => 'PhabricatorController',
|
||||||
'PassphraseCredential' =>
|
'PassphraseCredential' =>
|
||||||
array(
|
array(
|
||||||
|
@ -3359,6 +3363,8 @@ phutil_register_library_map(array(
|
||||||
'PassphraseCredentialViewController' => 'PassphraseController',
|
'PassphraseCredentialViewController' => 'PassphraseController',
|
||||||
'PassphraseDAO' => 'PhabricatorLiskDAO',
|
'PassphraseDAO' => 'PhabricatorLiskDAO',
|
||||||
'PassphrasePHIDTypeCredential' => 'PhabricatorPHIDType',
|
'PassphrasePHIDTypeCredential' => 'PhabricatorPHIDType',
|
||||||
|
'PassphrasePasswordKey' => 'PassphraseAbstractKey',
|
||||||
|
'PassphraseSSHKey' => 'PassphraseAbstractKey',
|
||||||
'PassphraseSecret' => 'PassphraseDAO',
|
'PassphraseSecret' => 'PassphraseDAO',
|
||||||
'PasteCapabilityDefaultView' => 'PhabricatorPolicyCapability',
|
'PasteCapabilityDefaultView' => 'PhabricatorPolicyCapability',
|
||||||
'PasteCreateMailReceiver' => 'PhabricatorMailReceiver',
|
'PasteCreateMailReceiver' => 'PhabricatorMailReceiver',
|
||||||
|
|
|
@ -3,12 +3,15 @@
|
||||||
final class PassphraseCredentialTypePassword
|
final class PassphraseCredentialTypePassword
|
||||||
extends PassphraseCredentialType {
|
extends PassphraseCredentialType {
|
||||||
|
|
||||||
|
const CREDENTIAL_TYPE = 'password';
|
||||||
|
const PROVIDES_TYPE = 'provides/password';
|
||||||
|
|
||||||
public function getCredentialType() {
|
public function getCredentialType() {
|
||||||
return 'password';
|
return self::CREDENTIAL_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getProvidesType() {
|
public function getProvidesType() {
|
||||||
return 'provides/password';
|
return self::PROVIDES_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getCredentialTypeName() {
|
public function getCredentialTypeName() {
|
||||||
|
|
|
@ -3,8 +3,10 @@
|
||||||
abstract class PassphraseCredentialTypeSSHPrivateKey
|
abstract class PassphraseCredentialTypeSSHPrivateKey
|
||||||
extends PassphraseCredentialType {
|
extends PassphraseCredentialType {
|
||||||
|
|
||||||
|
const PROVIDES_TYPE = 'provides/ssh-key-file';
|
||||||
|
|
||||||
final public function getProvidesType() {
|
final public function getProvidesType() {
|
||||||
return 'provides/ssh-key-file';
|
return self::PROVIDES_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,10 @@
|
||||||
final class PassphraseCredentialTypeSSHPrivateKeyFile
|
final class PassphraseCredentialTypeSSHPrivateKeyFile
|
||||||
extends PassphraseCredentialTypeSSHPrivateKey {
|
extends PassphraseCredentialTypeSSHPrivateKey {
|
||||||
|
|
||||||
|
const CREDENTIAL_TYPE = 'ssh-key-file';
|
||||||
|
|
||||||
public function getCredentialType() {
|
public function getCredentialType() {
|
||||||
return 'ssh-key-file';
|
return self::CREDENTIAL_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getCredentialTypeName() {
|
public function getCredentialTypeName() {
|
||||||
|
|
|
@ -3,8 +3,10 @@
|
||||||
final class PassphraseCredentialTypeSSHPrivateKeyText
|
final class PassphraseCredentialTypeSSHPrivateKeyText
|
||||||
extends PassphraseCredentialTypeSSHPrivateKey {
|
extends PassphraseCredentialTypeSSHPrivateKey {
|
||||||
|
|
||||||
|
const CREDENTIAL_TYPE = 'ssh-key-text';
|
||||||
|
|
||||||
public function getCredentialType() {
|
public function getCredentialType() {
|
||||||
return 'ssh-key-text';
|
return self::CREDENTIAL_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getCredentialTypeName() {
|
public function getCredentialTypeName() {
|
||||||
|
|
66
src/applications/passphrase/keys/PassphraseAbstractKey.php
Normal file
66
src/applications/passphrase/keys/PassphraseAbstractKey.php
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
abstract class PassphraseAbstractKey extends Phobject {
|
||||||
|
|
||||||
|
private $credential;
|
||||||
|
|
||||||
|
protected function requireCredential() {
|
||||||
|
if (!$this->credential) {
|
||||||
|
throw new Exception(pht("Credential is required!"));
|
||||||
|
}
|
||||||
|
return $this->credential;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function loadCredential(
|
||||||
|
$phid,
|
||||||
|
PhabricatorUser $viewer) {
|
||||||
|
|
||||||
|
$credential = id(new PassphraseCredentialQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->withPHIDs(array($phid))
|
||||||
|
->needSecrets(true)
|
||||||
|
->executeOne();
|
||||||
|
|
||||||
|
if (!$credential) {
|
||||||
|
throw new Exception(pht('Failed to load credential "%s"!', $phid));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $credential;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function validateCredential(
|
||||||
|
PassphraseCredential $credential,
|
||||||
|
$provides_type) {
|
||||||
|
|
||||||
|
$type = $credential->getCredentialType();
|
||||||
|
if ($type->getProvides() !== $provides_type) {
|
||||||
|
throw new Exception(
|
||||||
|
pht(
|
||||||
|
'Credential "%s" must provide "%s", but provides "%s"!',
|
||||||
|
'K'.$credential->getID(),
|
||||||
|
$provides_type,
|
||||||
|
$type->getProvides()));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function loadAndValidateFromPHID(
|
||||||
|
$phid,
|
||||||
|
PhabricatorUser $viewer,
|
||||||
|
$type) {
|
||||||
|
|
||||||
|
$credential = $this->loadCredential($phid, $viewer);
|
||||||
|
|
||||||
|
$this->validateCredential($credential, $type);
|
||||||
|
|
||||||
|
$this->credential = $credential;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getUsernameEnvelope() {
|
||||||
|
$credential = $this->requireCredential();
|
||||||
|
return new PhutilOpaqueEnvelope($credential->getUsername());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
17
src/applications/passphrase/keys/PassphrasePasswordKey.php
Normal file
17
src/applications/passphrase/keys/PassphrasePasswordKey.php
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PassphrasePasswordKey extends PassphraseAbstractKey {
|
||||||
|
|
||||||
|
public static function loadFromPHID($phid, PhabricatorUser $viewer) {
|
||||||
|
$key = new PassphraseSSHKey();
|
||||||
|
return $key->loadAndValidateFromPHID(
|
||||||
|
$phid,
|
||||||
|
$viewer,
|
||||||
|
PassphraseCredentialTypePassword::PROVIDES_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPasswordEnvelope() {
|
||||||
|
return $this->requireCredential()->getSecret();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
40
src/applications/passphrase/keys/PassphraseSSHKey.php
Normal file
40
src/applications/passphrase/keys/PassphraseSSHKey.php
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PassphraseSSHKey extends PassphraseAbstractKey {
|
||||||
|
|
||||||
|
private $keyFile;
|
||||||
|
|
||||||
|
public static function loadFromPHID($phid, PhabricatorUser $viewer) {
|
||||||
|
$key = new PassphraseSSHKey();
|
||||||
|
return $key->loadAndValidateFromPHID(
|
||||||
|
$phid,
|
||||||
|
$viewer,
|
||||||
|
PassphraseCredentialTypeSSHPrivateKey::PROVIDES_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getKeyfileEnvelope() {
|
||||||
|
$credential = $this->requireCredential();
|
||||||
|
|
||||||
|
$text_type = PassphraseCredentialTypeSSHPrivateKeyText::CREDENTIAL_TYPE;
|
||||||
|
if ($credential->getCredentialType() == $text_type) {
|
||||||
|
// If the credential stores key text, write it out to a temporary file
|
||||||
|
// so we can pass it to `ssh`.
|
||||||
|
if (!$this->keyFile) {
|
||||||
|
$temporary_file = new TempFile('passphrase-ssh-key');
|
||||||
|
|
||||||
|
Filesystem::changePermissions($temporary_file, 0600);
|
||||||
|
|
||||||
|
Filesystem::writeFile(
|
||||||
|
$temporary_file,
|
||||||
|
$credential->getSecret()->openEnvelope());
|
||||||
|
|
||||||
|
$this->keyFile = $temporary_file;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new PhutilOpaqueEnvelope((string)$this->keyFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $credential->getSecret();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue