Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F15428712
D10262.id24763.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
16 KB
Referenced Files
None
Subscribers
None
D10262.id24763.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D10262: Implement `passphrase.query` for querying credentials
Attached
Detach File
Event Timeline
Log In to Comment