diff --git a/.gitignore b/.gitignore --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,8 @@ /conf/local/local.json /conf/local/ENVIRONMENT /conf/local/VERSION +/conf/local/HOSTKEY +/conf/local/HOSTID # Impact Font /resources/font/impact.ttf diff --git a/bin/almanac b/bin/almanac new file mode 120000 --- /dev/null +++ b/bin/almanac @@ -0,0 +1 @@ +../scripts/almanac/manage_almanac.php \ No newline at end of file diff --git a/resources/sql/autopatches/20140902.almanacauthorizedhost.1.sql b/resources/sql/autopatches/20140902.almanacauthorizedhost.1.sql new file mode 100644 --- /dev/null +++ b/resources/sql/autopatches/20140902.almanacauthorizedhost.1.sql @@ -0,0 +1,6 @@ +CREATE TABLE {$NAMESPACE}_almanac.almanac_authorizedhost ( + id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, + publicKey LONGTEXT NOT NULL, + dateCreated INT UNSIGNED NOT NULL, + dateModified INT UNSIGNED NOT NULL +) ENGINE=InnoDB, COLLATE utf8_general_ci; diff --git a/scripts/almanac/manage_almanac.php b/scripts/almanac/manage_almanac.php new file mode 100755 --- /dev/null +++ b/scripts/almanac/manage_almanac.php @@ -0,0 +1,21 @@ +#!/usr/bin/env php +setTagline('manage host directory'); +$args->setSynopsis(<<parseStandardArguments(); + +$workflows = id(new PhutilSymbolLoader()) + ->setAncestorClass('AlmanacManagementWorkflow') + ->loadObjects(); +$workflows[] = new PhutilHelpArgumentWorkflow(); +$args->parseWorkflows($workflows); 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 @@ -9,6 +9,10 @@ phutil_register_library_map(array( '__library_version__' => 2, 'class' => array( + 'AlmanacAuthorizedHost' => 'applications/almanac/storage/AlmanacAuthorizedHost.php', + 'AlmanacDAO' => 'applications/almanac/storage/AlmanacDAO.php', + 'AlmanacManagementRegisterWorkflow' => 'applications/almanac/management/AlmanacManagementRegisterWorkflow.php', + 'AlmanacManagementWorkflow' => 'applications/almanac/management/AlmanacManagementWorkflow.php', 'Aphront304Response' => 'aphront/response/Aphront304Response.php', 'Aphront400Response' => 'aphront/response/Aphront400Response.php', 'Aphront403Response' => 'aphront/response/Aphront403Response.php', @@ -1091,6 +1095,7 @@ 'PhabricatorActionListView' => 'view/layout/PhabricatorActionListView.php', 'PhabricatorActionView' => 'view/layout/PhabricatorActionView.php', 'PhabricatorAllCapsTranslation' => 'infrastructure/internationalization/translation/PhabricatorAllCapsTranslation.php', + 'PhabricatorAlmanacApplication' => 'applications/almanac/application/PhabricatorAlmanacApplication.php', 'PhabricatorAmazonAuthProvider' => 'applications/auth/provider/PhabricatorAmazonAuthProvider.php', 'PhabricatorAnchorView' => 'view/layout/PhabricatorAnchorView.php', 'PhabricatorAphlictManagementBuildWorkflow' => 'applications/aphlict/management/PhabricatorAphlictManagementBuildWorkflow.php', @@ -2778,6 +2783,10 @@ 'require_celerity_resource' => 'infrastructure/celerity/api.php', ), 'xmap' => array( + 'AlmanacAuthorizedHost' => 'AlmanacDAO', + 'AlmanacDAO' => 'PhabricatorLiskDAO', + 'AlmanacManagementRegisterWorkflow' => 'AlmanacManagementWorkflow', + 'AlmanacManagementWorkflow' => 'PhabricatorManagementWorkflow', 'Aphront304Response' => 'AphrontResponse', 'Aphront400Response' => 'AphrontResponse', 'Aphront403Response' => 'AphrontHTMLResponse', @@ -3912,6 +3921,7 @@ 'PhabricatorActionListView' => 'AphrontView', 'PhabricatorActionView' => 'AphrontView', 'PhabricatorAllCapsTranslation' => 'PhabricatorTranslation', + 'PhabricatorAlmanacApplication' => 'PhabricatorApplication', 'PhabricatorAmazonAuthProvider' => 'PhabricatorOAuth2AuthProvider', 'PhabricatorAnchorView' => 'AphrontView', 'PhabricatorAphlictManagementBuildWorkflow' => 'PhabricatorAphlictManagementWorkflow', diff --git a/src/applications/almanac/application/PhabricatorAlmanacApplication.php b/src/applications/almanac/application/PhabricatorAlmanacApplication.php new file mode 100644 --- /dev/null +++ b/src/applications/almanac/application/PhabricatorAlmanacApplication.php @@ -0,0 +1,41 @@ +setName('register') + ->setSynopsis('Register this host for authorized Conduit access.') + ->setArguments(array()); + } + + public function execute(PhutilArgumentParser $args) { + $console = PhutilConsole::getConsole(); + + if (Filesystem::pathExists($this->getHostPrivateKeyPath())) { + throw new Exception( + 'This host already has a private key for Conduit access.'); + } + + $pair = PhabricatorSSHKeyGenerator::generateKeypair(); + list($public_key, $private_key) = $pair; + + $host = id(new AlmanacAuthorizedHost()) + ->setPublicKey($public_key) + ->save(); + + Filesystem::writeFile( + $this->getHostPrivateKeyPath(), + $private_key); + + Filesystem::writeFile( + $this->getHostIDPath(), + $host->getID()); + + $console->writeOut("Registered as authorized host %d.\n", $host->getID()); + } + + private function getHostPrivateKeyPath() { + $root = dirname(phutil_get_library_root('phabricator')); + $path = $root.'/conf/local/HOSTKEY'; + return $path; + } + + private function getHostIDPath() { + $root = dirname(phutil_get_library_root('phabricator')); + $path = $root.'/conf/local/HOSTID'; + return $path; + } + +} diff --git a/src/applications/almanac/management/AlmanacManagementWorkflow.php b/src/applications/almanac/management/AlmanacManagementWorkflow.php new file mode 100644 --- /dev/null +++ b/src/applications/almanac/management/AlmanacManagementWorkflow.php @@ -0,0 +1,6 @@ + array(), 'db.dashboard' => array(), 'db.system' => array(), + 'db.almanac' => array(), '0000.legacy.sql' => array( 'legacy' => 0, ),