Page MenuHomePhabricator

D10262.id24763.diff
No OneTemporary

D10262.id24763.diff

diff --git a/resources/sql/autopatches/20140814.passphrasecredentialconduit.sql b/resources/sql/autopatches/20140814.passphrasecredentialconduit.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20140814.passphrasecredentialconduit.sql
@@ -0,0 +1,2 @@
+ALTER TABLE {$NAMESPACE}_passphrase.passphrase_credential
+ ADD COLUMN allowConduit BOOL NOT NULL DEFAULT 0;
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -1034,8 +1034,10 @@
'PackageMail' => 'applications/owners/mail/PackageMail.php',
'PackageModifyMail' => 'applications/owners/mail/PackageModifyMail.php',
'PassphraseAbstractKey' => 'applications/passphrase/keys/PassphraseAbstractKey.php',
+ 'PassphraseConduitAPIMethod' => 'applications/passphrase/conduit/PassphraseConduitAPIMethod.php',
'PassphraseController' => 'applications/passphrase/controller/PassphraseController.php',
'PassphraseCredential' => 'applications/passphrase/storage/PassphraseCredential.php',
+ 'PassphraseCredentialConduitController' => 'applications/passphrase/controller/PassphraseCredentialConduitController.php',
'PassphraseCredentialControl' => 'applications/passphrase/view/PassphraseCredentialControl.php',
'PassphraseCredentialCreateController' => 'applications/passphrase/controller/PassphraseCredentialCreateController.php',
'PassphraseCredentialDestroyController' => 'applications/passphrase/controller/PassphraseCredentialDestroyController.php',
@@ -1059,6 +1061,7 @@
'PassphraseCredentialViewController' => 'applications/passphrase/controller/PassphraseCredentialViewController.php',
'PassphraseDAO' => 'applications/passphrase/storage/PassphraseDAO.php',
'PassphrasePasswordKey' => 'applications/passphrase/keys/PassphrasePasswordKey.php',
+ 'PassphraseQueryConduitAPIMethod' => 'applications/passphrase/conduit/PassphraseQueryConduitAPIMethod.php',
'PassphraseRemarkupRule' => 'applications/passphrase/remarkup/PassphraseRemarkupRule.php',
'PassphraseSSHKey' => 'applications/passphrase/keys/PassphraseSSHKey.php',
'PassphraseSecret' => 'applications/passphrase/storage/PassphraseSecret.php',
@@ -3839,12 +3842,14 @@
'PackageMail' => 'PhabricatorMail',
'PackageModifyMail' => 'PackageMail',
'PassphraseAbstractKey' => 'Phobject',
+ 'PassphraseConduitAPIMethod' => 'ConduitAPIMethod',
'PassphraseController' => 'PhabricatorController',
'PassphraseCredential' => array(
'PassphraseDAO',
'PhabricatorPolicyInterface',
'PhabricatorDestructibleInterface',
),
+ 'PassphraseCredentialConduitController' => 'PassphraseController',
'PassphraseCredentialControl' => 'AphrontFormControl',
'PassphraseCredentialCreateController' => 'PassphraseController',
'PassphraseCredentialDestroyController' => 'PassphraseController',
@@ -3868,6 +3873,7 @@
'PassphraseCredentialViewController' => 'PassphraseController',
'PassphraseDAO' => 'PhabricatorLiskDAO',
'PassphrasePasswordKey' => 'PassphraseAbstractKey',
+ 'PassphraseQueryConduitAPIMethod' => 'PassphraseConduitAPIMethod',
'PassphraseRemarkupRule' => 'PhabricatorObjectRemarkupRule',
'PassphraseSSHKey' => 'PassphraseAbstractKey',
'PassphraseSecret' => 'PassphraseDAO',
diff --git a/src/applications/passphrase/application/PhabricatorPassphraseApplication.php b/src/applications/passphrase/application/PhabricatorPassphraseApplication.php
--- a/src/applications/passphrase/application/PhabricatorPassphraseApplication.php
+++ b/src/applications/passphrase/application/PhabricatorPassphraseApplication.php
@@ -46,6 +46,7 @@
'reveal/(?P<id>\d+)/' => 'PassphraseCredentialRevealController',
'public/(?P<id>\d+)/' => 'PassphraseCredentialPublicController',
'lock/(?P<id>\d+)/' => 'PassphraseCredentialLockController',
+ 'conduit/(?P<id>\d+)/' => 'PassphraseCredentialConduitController',
));
}
diff --git a/src/applications/passphrase/conduit/PassphraseConduitAPIMethod.php b/src/applications/passphrase/conduit/PassphraseConduitAPIMethod.php
new file mode 100644
--- /dev/null
+++ b/src/applications/passphrase/conduit/PassphraseConduitAPIMethod.php
@@ -0,0 +1,10 @@
+<?php
+
+abstract class PassphraseConduitAPIMethod extends ConduitAPIMethod {
+
+ final public function getApplication() {
+ return PhabricatorApplication::getByClass(
+ 'PhabricatorPassphraseApplication');
+ }
+
+}
diff --git a/src/applications/passphrase/conduit/PassphraseQueryConduitAPIMethod.php b/src/applications/passphrase/conduit/PassphraseQueryConduitAPIMethod.php
new file mode 100644
--- /dev/null
+++ b/src/applications/passphrase/conduit/PassphraseQueryConduitAPIMethod.php
@@ -0,0 +1,123 @@
+<?php
+
+final class PassphraseQueryConduitAPIMethod
+ extends PassphraseConduitAPIMethod {
+
+ public function getAPIMethodName() {
+ return 'passphrase.query';
+ }
+
+ public function getMethodDescription() {
+ return pht('Query credentials.');
+ }
+
+ public function defineParamTypes() {
+ return array(
+ 'ids' => 'optional list<int>',
+ 'phids' => 'optional list<phid>',
+ 'needSecrets' => 'optional bool',
+ 'needPublicKeys' => 'optional bool',
+ ) + $this->getPagerParamTypes();
+ }
+
+ public function defineReturnType() {
+ return 'list<dict>';
+ }
+
+ public function defineErrorTypes() {
+ return array();
+ }
+
+ protected function execute(ConduitAPIRequest $request) {
+ $query = id(new PassphraseCredentialQuery())
+ ->setViewer($request->getUser());
+
+ if ($request->getValue('ids')) {
+ $query->withIDs($request->getValue('ids'));
+ }
+
+ if ($request->getValue('phids')) {
+ $query->withPHIDs($request->getValue('phids'));
+ }
+
+ if ($request->getValue('needSecrets')) {
+ $query->needSecrets(true);
+ }
+
+ $pager = $this->newPager($request);
+ $credentials = $query->executeWithCursorPager($pager);
+
+ $results = array();
+ foreach ($credentials as $credential) {
+ $type = PassphraseCredentialType::getTypeByConstant(
+ $credential->getCredentialType());
+ if (!$type) {
+ continue;
+ }
+
+ $public_key = null;
+ if ($request->getValue('needPublicKeys') && $type->hasPublicKey()) {
+ $public_key = $type->getPublicKey(
+ $request->getUser(),
+ $credential);
+ }
+
+ $secret = null;
+ if ($request->getValue('needSecrets')) {
+ if ($credential->getAllowConduit()) {
+ $secret = $credential->getSecret()->openEnvelope();
+ }
+ }
+
+ $material = array();
+ switch ($credential->getCredentialType()) {
+ case PassphraseCredentialTypeSSHPrivateKeyFile::CREDENTIAL_TYPE:
+ if ($secret) {
+ $material['file'] = $secret;
+ }
+ if ($public_key) {
+ $material['publicKey'] = $public_key;
+ }
+ break;
+ case PassphraseCredentialTypeSSHPrivateKeyText::CREDENTIAL_TYPE:
+ if ($secret) {
+ $material['privateKey'] = $secret;
+ }
+ if ($public_key) {
+ $material['publicKey'] = $public_key;
+ }
+ break;
+ case PassphraseCredentialTypePassword::CREDENTIAL_TYPE:
+ if ($secret) {
+ $material['password'] = $secret;
+ }
+ break;
+ }
+
+ if (!$credential->getAllowConduit()) {
+ $material['noAPIAccess'] = pht(
+ 'This credential\'s private material '.
+ 'is not accessible via API calls.');
+ }
+
+ $results[$credential->getPHID()] = array(
+ 'id' => $credential->getID(),
+ 'phid' => $credential->getPHID(),
+ 'type' => $credential->getCredentialType(),
+ 'name' => $credential->getName(),
+ 'uri' =>
+ PhabricatorEnv::getProductionURI('/'.$credential->getMonogram()),
+ 'monogram' => $credential->getMonogram(),
+ 'username' => $credential->getUsername(),
+ 'material' => $material,
+ );
+ }
+
+ $result = array(
+ 'data' => $results,
+ );
+
+ return $this->addPagerResults($result, $pager);
+ }
+
+}
diff --git a/src/applications/passphrase/controller/PassphraseCredentialConduitController.php b/src/applications/passphrase/controller/PassphraseCredentialConduitController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/passphrase/controller/PassphraseCredentialConduitController.php
@@ -0,0 +1,81 @@
+<?php
+
+final class PassphraseCredentialConduitController
+ extends PassphraseController {
+
+ private $id;
+
+ public function willProcessRequest(array $data) {
+ $this->id = $data['id'];
+ }
+
+ public function processRequest() {
+ $request = $this->getRequest();
+ $viewer = $request->getUser();
+
+ $credential = id(new PassphraseCredentialQuery())
+ ->setViewer($viewer)
+ ->withIDs(array($this->id))
+ ->requireCapabilities(
+ array(
+ PhabricatorPolicyCapability::CAN_VIEW,
+ PhabricatorPolicyCapability::CAN_EDIT,
+ ))
+ ->executeOne();
+ if (!$credential) {
+ return new Aphront404Response();
+ }
+
+ $view_uri = '/K'.$credential->getID();
+
+ $token = id(new PhabricatorAuthSessionEngine())->requireHighSecuritySession(
+ $viewer,
+ $request,
+ $view_uri);
+
+ $type = PassphraseCredentialType::getTypeByConstant(
+ $credential->getCredentialType());
+ if (!$type) {
+ throw new Exception(pht('Credential has invalid type "%s"!', $type));
+ }
+
+ if ($request->isFormPost()) {
+ $xactions = array();
+ $xactions[] = id(new PassphraseCredentialTransaction())
+ ->setTransactionType(PassphraseCredentialTransaction::TYPE_CONDUIT)
+ ->setNewValue(!$credential->getAllowConduit());
+
+ $editor = id(new PassphraseCredentialTransactionEditor())
+ ->setActor($viewer)
+ ->setContinueOnMissingFields(true)
+ ->setContentSourceFromRequest($request)
+ ->applyTransactions($credential, $xactions);
+
+ return id(new AphrontRedirectResponse())->setURI($view_uri);
+ }
+
+ if ($credential->getAllowConduit()) {
+ return $this->newDialog()
+ ->setTitle(pht('Prevent Conduit access?'))
+ ->appendChild(
+ pht(
+ 'This credential and its secret will no longer be able '.
+ 'to be retrieved using the `passphrase.query` method '.
+ 'in Conduit.'))
+ ->addSubmitButton(pht('Prevent Conduit Access'))
+ ->addCancelButton($view_uri);
+ } else {
+ return $this->newDialog()
+ ->setTitle(pht('Allow Conduit access?'))
+ ->appendChild(
+ pht(
+ 'This credential will be able to be retrieved via the Conduit '.
+ 'API by users who have access to this credential. You should '.
+ 'only enable this for credentials which need to be accessed '.
+ 'programmatically (such as from build agents).'))
+ ->addSubmitButton(pht('Allow Conduit Access'))
+ ->addCancelButton($view_uri);
+ }
+ }
+
+}
diff --git a/src/applications/passphrase/controller/PassphraseCredentialViewController.php b/src/applications/passphrase/controller/PassphraseCredentialViewController.php
--- a/src/applications/passphrase/controller/PassphraseCredentialViewController.php
+++ b/src/applications/passphrase/controller/PassphraseCredentialViewController.php
@@ -93,6 +93,15 @@
$credential_lock_icon = 'fa-unlock';
}
+ $allow_conduit = $credential->getAllowConduit();
+ if ($allow_conduit) {
+ $credential_conduit_text = pht('Prevent Conduit Access');
+ $credential_conduit_icon = 'fa-ban';
+ } else {
+ $credential_conduit_text = pht('Allow Conduit Access');
+ $credential_conduit_icon = 'fa-wrench';
+ }
+
$actions = id(new PhabricatorActionListView())
->setObjectURI('/K'.$id)
->setUser($viewer);
@@ -138,6 +147,13 @@
$actions->addAction(
id(new PhabricatorActionView())
+ ->setName($credential_conduit_text)
+ ->setIcon($credential_conduit_icon)
+ ->setHref($this->getApplicationURI("conduit/{$id}/"))
+ ->setWorkflow(true));
+
+ $actions->addAction(
+ id(new PhabricatorActionView())
->setName($credential_lock_text)
->setIcon($credential_lock_icon)
->setHref($this->getApplicationURI("lock/{$id}/"))
diff --git a/src/applications/passphrase/editor/PassphraseCredentialTransactionEditor.php b/src/applications/passphrase/editor/PassphraseCredentialTransactionEditor.php
--- a/src/applications/passphrase/editor/PassphraseCredentialTransactionEditor.php
+++ b/src/applications/passphrase/editor/PassphraseCredentialTransactionEditor.php
@@ -24,6 +24,7 @@
$types[] = PassphraseCredentialTransaction::TYPE_DESTROY;
$types[] = PassphraseCredentialTransaction::TYPE_LOOKEDATSECRET;
$types[] = PassphraseCredentialTransaction::TYPE_LOCK;
+ $types[] = PassphraseCredentialTransaction::TYPE_CONDUIT;
return $types;
}
@@ -47,6 +48,8 @@
return (int)$object->getIsDestroyed();
case PassphraseCredentialTransaction::TYPE_LOCK:
return (int)$object->getIsLocked();
+ case PassphraseCredentialTransaction::TYPE_CONDUIT:
+ return (int)$object->getAllowConduit();
case PassphraseCredentialTransaction::TYPE_LOOKEDATSECRET:
return null;
}
@@ -67,6 +70,8 @@
case PassphraseCredentialTransaction::TYPE_DESTROY:
case PassphraseCredentialTransaction::TYPE_LOCK:
return (int)$xaction->getNewValue();
+ case PassphraseCredentialTransaction::TYPE_CONDUIT:
+ return (int)$xaction->getNewValue();
}
return parent::getCustomTransactionNewValue($object, $xaction);
}
@@ -114,6 +119,9 @@
case PassphraseCredentialTransaction::TYPE_LOCK:
$object->setIsLocked((int)$xaction->getNewValue());
return;
+ case PassphraseCredentialTransaction::TYPE_CONDUIT:
+ $object->setAllowConduit((int)$xaction->getNewValue());
+ return;
}
return parent::applyCustomInternalTransaction($object, $xaction);
@@ -131,6 +139,7 @@
case PassphraseCredentialTransaction::TYPE_DESTROY:
case PassphraseCredentialTransaction::TYPE_LOOKEDATSECRET:
case PassphraseCredentialTransaction::TYPE_LOCK:
+ case PassphraseCredentialTransaction::TYPE_CONDUIT:
case PhabricatorTransactions::TYPE_VIEW_POLICY:
case PhabricatorTransactions::TYPE_EDIT_POLICY:
return;
diff --git a/src/applications/passphrase/query/PassphraseCredentialQuery.php b/src/applications/passphrase/query/PassphraseCredentialQuery.php
--- a/src/applications/passphrase/query/PassphraseCredentialQuery.php
+++ b/src/applications/passphrase/query/PassphraseCredentialQuery.php
@@ -8,6 +8,7 @@
private $credentialTypes;
private $providesTypes;
private $isDestroyed;
+ private $allowConduit;
private $needSecrets;
@@ -36,6 +37,11 @@
return $this;
}
+ public function withAllowConduit($allow_conduit) {
+ $this->allowConduit = $allow_conduit;
+ return $this;
+ }
+
public function needSecrets($need_secrets) {
$this->needSecrets = $need_secrets;
return $this;
@@ -127,6 +133,13 @@
(int)$this->isDestroyed);
}
+ if ($this->allowConduit !== null) {
+ $where[] = qsprintf(
+ $conn_r,
+ 'allowConduit = %d',
+ (int)$this->allowConduit);
+ }
+
return $this->formatWhereClause($where);
}
diff --git a/src/applications/passphrase/storage/PassphraseCredential.php b/src/applications/passphrase/storage/PassphraseCredential.php
--- a/src/applications/passphrase/storage/PassphraseCredential.php
+++ b/src/applications/passphrase/storage/PassphraseCredential.php
@@ -14,6 +14,7 @@
protected $secretID;
protected $isDestroyed;
protected $isLocked = 0;
+ protected $allowConduit = 0;
private $secret = self::ATTACHABLE;
diff --git a/src/applications/passphrase/storage/PassphraseCredentialTransaction.php b/src/applications/passphrase/storage/PassphraseCredentialTransaction.php
--- a/src/applications/passphrase/storage/PassphraseCredentialTransaction.php
+++ b/src/applications/passphrase/storage/PassphraseCredentialTransaction.php
@@ -10,6 +10,7 @@
const TYPE_DESTROY = 'passphrase:destroy';
const TYPE_LOOKEDATSECRET = 'passphrase:lookedAtSecret';
const TYPE_LOCK = 'passphrase:lock';
+ const TYPE_CONDUIT = 'passphrase:conduit';
public function getApplicationName() {
return 'passphrase';
@@ -91,6 +92,17 @@
return pht(
'%s locked this credential.',
$this->renderHandleLink($author_phid));
+ case self::TYPE_CONDUIT:
+ if ($old) {
+ return pht(
+ '%s disallowed Conduit API access to this credential.',
+ $this->renderHandleLink($author_phid));
+ } else {
+ return pht(
+ '%s allowed Conduit API access to this credential.',
+ $this->renderHandleLink($author_phid));
+ }
+ break;
}
return parent::getTitle();

File Metadata

Mime Type
text/plain
Expires
Mon, Mar 24, 9:50 PM (6 d, 12 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7382865
Default Alt Text
D10262.id24763.diff (16 KB)

Event Timeline