diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index ce51bae323..00a543804b 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -947,6 +947,7 @@ phutil_register_library_map(array( 'PackageDeleteMail' => 'applications/owners/mail/PackageDeleteMail.php', 'PackageMail' => 'applications/owners/mail/PackageMail.php', 'PackageModifyMail' => 'applications/owners/mail/PackageModifyMail.php', + 'PassphraseAbstractKey' => 'applications/passphrase/keys/PassphraseAbstractKey.php', 'PassphraseController' => 'applications/passphrase/controller/PassphraseController.php', 'PassphraseCredential' => 'applications/passphrase/storage/PassphraseCredential.php', 'PassphraseCredentialControl' => 'applications/passphrase/view/PassphraseCredentialControl.php', @@ -968,6 +969,8 @@ phutil_register_library_map(array( 'PassphraseCredentialViewController' => 'applications/passphrase/controller/PassphraseCredentialViewController.php', 'PassphraseDAO' => 'applications/passphrase/storage/PassphraseDAO.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', 'PasteCapabilityDefaultView' => 'applications/paste/capability/PasteCapabilityDefaultView.php', 'PasteCreateMailReceiver' => 'applications/paste/mail/PasteCreateMailReceiver.php', @@ -3330,6 +3333,7 @@ phutil_register_library_map(array( 'PackageDeleteMail' => 'PackageMail', 'PackageMail' => 'PhabricatorMail', 'PackageModifyMail' => 'PackageMail', + 'PassphraseAbstractKey' => 'Phobject', 'PassphraseController' => 'PhabricatorController', 'PassphraseCredential' => array( @@ -3359,6 +3363,8 @@ phutil_register_library_map(array( 'PassphraseCredentialViewController' => 'PassphraseController', 'PassphraseDAO' => 'PhabricatorLiskDAO', 'PassphrasePHIDTypeCredential' => 'PhabricatorPHIDType', + 'PassphrasePasswordKey' => 'PassphraseAbstractKey', + 'PassphraseSSHKey' => 'PassphraseAbstractKey', 'PassphraseSecret' => 'PassphraseDAO', 'PasteCapabilityDefaultView' => 'PhabricatorPolicyCapability', 'PasteCreateMailReceiver' => 'PhabricatorMailReceiver', diff --git a/src/applications/passphrase/credentialtype/PassphraseCredentialTypePassword.php b/src/applications/passphrase/credentialtype/PassphraseCredentialTypePassword.php index 47da20d84f..7f3ef9e6e1 100644 --- a/src/applications/passphrase/credentialtype/PassphraseCredentialTypePassword.php +++ b/src/applications/passphrase/credentialtype/PassphraseCredentialTypePassword.php @@ -3,12 +3,15 @@ final class PassphraseCredentialTypePassword extends PassphraseCredentialType { + const CREDENTIAL_TYPE = 'password'; + const PROVIDES_TYPE = 'provides/password'; + public function getCredentialType() { - return 'password'; + return self::CREDENTIAL_TYPE; } public function getProvidesType() { - return 'provides/password'; + return self::PROVIDES_TYPE; } public function getCredentialTypeName() { diff --git a/src/applications/passphrase/credentialtype/PassphraseCredentialTypeSSHPrivateKey.php b/src/applications/passphrase/credentialtype/PassphraseCredentialTypeSSHPrivateKey.php index 5d8af08966..5c7c684eb8 100644 --- a/src/applications/passphrase/credentialtype/PassphraseCredentialTypeSSHPrivateKey.php +++ b/src/applications/passphrase/credentialtype/PassphraseCredentialTypeSSHPrivateKey.php @@ -3,8 +3,10 @@ abstract class PassphraseCredentialTypeSSHPrivateKey extends PassphraseCredentialType { + const PROVIDES_TYPE = 'provides/ssh-key-file'; + final public function getProvidesType() { - return 'provides/ssh-key-file'; + return self::PROVIDES_TYPE; } } diff --git a/src/applications/passphrase/credentialtype/PassphraseCredentialTypeSSHPrivateKeyFile.php b/src/applications/passphrase/credentialtype/PassphraseCredentialTypeSSHPrivateKeyFile.php index 1d93e24be8..35154c16ec 100644 --- a/src/applications/passphrase/credentialtype/PassphraseCredentialTypeSSHPrivateKeyFile.php +++ b/src/applications/passphrase/credentialtype/PassphraseCredentialTypeSSHPrivateKeyFile.php @@ -3,8 +3,10 @@ final class PassphraseCredentialTypeSSHPrivateKeyFile extends PassphraseCredentialTypeSSHPrivateKey { + const CREDENTIAL_TYPE = 'ssh-key-file'; + public function getCredentialType() { - return 'ssh-key-file'; + return self::CREDENTIAL_TYPE; } public function getCredentialTypeName() { diff --git a/src/applications/passphrase/credentialtype/PassphraseCredentialTypeSSHPrivateKeyText.php b/src/applications/passphrase/credentialtype/PassphraseCredentialTypeSSHPrivateKeyText.php index 9cc03dccc6..4211b0b927 100644 --- a/src/applications/passphrase/credentialtype/PassphraseCredentialTypeSSHPrivateKeyText.php +++ b/src/applications/passphrase/credentialtype/PassphraseCredentialTypeSSHPrivateKeyText.php @@ -3,8 +3,10 @@ final class PassphraseCredentialTypeSSHPrivateKeyText extends PassphraseCredentialTypeSSHPrivateKey { + const CREDENTIAL_TYPE = 'ssh-key-text'; + public function getCredentialType() { - return 'ssh-key-text'; + return self::CREDENTIAL_TYPE; } public function getCredentialTypeName() { diff --git a/src/applications/passphrase/keys/PassphraseAbstractKey.php b/src/applications/passphrase/keys/PassphraseAbstractKey.php new file mode 100644 index 0000000000..76cba1b39e --- /dev/null +++ b/src/applications/passphrase/keys/PassphraseAbstractKey.php @@ -0,0 +1,66 @@ +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()); + } + +} diff --git a/src/applications/passphrase/keys/PassphrasePasswordKey.php b/src/applications/passphrase/keys/PassphrasePasswordKey.php new file mode 100644 index 0000000000..f30a76cb67 --- /dev/null +++ b/src/applications/passphrase/keys/PassphrasePasswordKey.php @@ -0,0 +1,17 @@ +loadAndValidateFromPHID( + $phid, + $viewer, + PassphraseCredentialTypePassword::PROVIDES_TYPE); + } + + public function getPasswordEnvelope() { + return $this->requireCredential()->getSecret(); + } + +} diff --git a/src/applications/passphrase/keys/PassphraseSSHKey.php b/src/applications/passphrase/keys/PassphraseSSHKey.php new file mode 100644 index 0000000000..4ba5025b98 --- /dev/null +++ b/src/applications/passphrase/keys/PassphraseSSHKey.php @@ -0,0 +1,40 @@ +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(); + } + +}