@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Document how to register cluster devices with Almanac

Summary:
Ref T4292. This is a required step in configuring a cluster: document and explain it.

Previously `bin/almanac register` could //also// add and trust keys. I've removed this capability since I think it's needless and complicated. If there's some real use for it eventually, we could add a `bin/almanac add-key` or whatever. The workflow is simpler and has better guard rails that point you in the correct direction now.

Test Plan:
- Read documentation.
- Ran `bin/almanac` with various good/bad flags.

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T4292

Differential Revision: https://secure.phabricator.com/D15795

+298 -63
+56 -63
src/applications/almanac/management/AlmanacManagementRegisterWorkflow.php
··· 20 20 'help' => pht('Path to a private key for the host.'), 21 21 ), 22 22 array( 23 - 'name' => 'allow-key-reuse', 24 - 'help' => pht( 25 - 'Register even if another host is already registered with this '. 26 - 'keypair. This is an advanced featuer which allows a pool of '. 27 - 'devices to share credentials.'), 28 - ), 29 - array( 30 23 'name' => 'identify-as', 31 24 'param' => 'name', 32 25 'help' => pht( ··· 36 29 array( 37 30 'name' => 'force', 38 31 'help' => pht( 39 - 'Register this host even if keys already exist.'), 32 + 'Register this host even if keys already exist on disk.'), 40 33 ), 41 34 )); 42 35 } 43 36 44 37 public function execute(PhutilArgumentParser $args) { 45 - $console = PhutilConsole::getConsole(); 38 + $viewer = $this->getViewer(); 46 39 47 40 $device_name = $args->getArg('device'); 48 41 if (!strlen($device_name)) { ··· 51 44 } 52 45 53 46 $device = id(new AlmanacDeviceQuery()) 54 - ->setViewer($this->getViewer()) 47 + ->setViewer($viewer) 55 48 ->withNames(array($device_name)) 56 49 ->executeOne(); 57 50 if (!$device) { 58 51 throw new PhutilArgumentUsageException( 59 52 pht('No such device "%s" exists!', $device_name)); 53 + } 54 + 55 + $identify_as = $args->getArg('identify-as'); 56 + 57 + $raw_device = $device_name; 58 + if (strlen($identify_as)) { 59 + $raw_device = $identify_as; 60 + } 61 + 62 + $identity_device = id(new AlmanacDeviceQuery()) 63 + ->setViewer($viewer) 64 + ->withNames(array($raw_device)) 65 + ->executeOne(); 66 + if (!$identity_device) { 67 + throw new PhutilArgumentUsageException( 68 + pht( 69 + 'No such device "%s" exists!', $raw_device)); 60 70 } 61 71 62 72 $private_key_path = $args->getArg('private-key'); ··· 67 77 68 78 if (!Filesystem::pathExists($private_key_path)) { 69 79 throw new PhutilArgumentUsageException( 70 - pht('Private key "%s" does not exist!', $private_key_path)); 80 + pht('No private key exists at path "%s"!', $private_key_path)); 71 81 } 72 82 73 83 $raw_private_key = Filesystem::readFile($private_key_path); ··· 85 95 if ($err) { 86 96 throw new PhutilArgumentUsageException( 87 97 pht( 88 - 'Unable to change ownership of a file to daemon user "%s". Run '. 89 - 'this command as %s or root.', 98 + 'Unable to change ownership of an identity file to daemon user '. 99 + '"%s". Run this command as %s or root.', 90 100 $phd_user, 91 101 $phd_user)); 92 102 } ··· 133 143 ->withKeys(array($key_object)) 134 144 ->executeOne(); 135 145 136 - if ($public_key) { 137 - if ($public_key->getObjectPHID() !== $device->getPHID()) { 138 - throw new PhutilArgumentUsageException( 139 - pht( 140 - 'The public key corresponding to the given private key is '. 141 - 'already associated with an object other than the specified '. 142 - 'device. You can not use a single private key to identify '. 143 - 'multiple devices or users.')); 144 - } else if (!$public_key->getIsTrusted()) { 145 - throw new PhutilArgumentUsageException( 146 - pht( 147 - 'The public key corresponding to the given private key is '. 148 - 'already associated with the device, but is not trusted. '. 149 - 'Registering this key would trust the other entities which '. 150 - 'hold it. Use a unique key, or explicitly enable trust for the '. 151 - 'current key.')); 152 - } else if (!$args->getArg('allow-key-reuse')) { 153 - throw new PhutilArgumentUsageException( 154 - pht( 155 - 'The public key corresponding to the given private key is '. 156 - 'already associated with the device. If you do not want to '. 157 - 'use a unique key, use --allow-key-reuse to permit '. 158 - 'reassociation.')); 159 - } 160 - } else { 161 - $public_key = id(new PhabricatorAuthSSHKey()) 162 - ->setObjectPHID($device->getPHID()) 163 - ->attachObject($device) 164 - ->setName($device->getSSHKeyDefaultName()) 165 - ->setKeyType($key_object->getType()) 166 - ->setKeyBody($key_object->getBody()) 167 - ->setKeyComment(pht('Registered')) 168 - ->setIsTrusted(1); 146 + if (!$public_key) { 147 + throw new PhutilArgumentUsageException( 148 + pht( 149 + 'The public key corresponding to the given private key is not '. 150 + 'yet known to Phabricator. Associate the public key with an '. 151 + 'Almanac device in the web interface before registering hosts '. 152 + 'with it.')); 153 + } 154 + 155 + if ($public_key->getObjectPHID() !== $device->getPHID()) { 156 + $public_phid = $public_key->getObjectPHID(); 157 + $public_handles = $viewer->loadHandles(array($public_phid)); 158 + $public_handle = $public_handles[$public_phid]; 159 + 160 + throw new PhutilArgumentUsageException( 161 + pht( 162 + 'The public key corresponding to the given private key is already '. 163 + 'associated with an object ("%s") other than the specified '. 164 + 'device ("%s"). You can not use a single private key to identify '. 165 + 'multiple devices or users.', 166 + $public_handle->getFullName(), 167 + $device->getName())); 169 168 } 170 169 170 + if (!$public_key->getIsTrusted()) { 171 + throw new PhutilArgumentUsageException( 172 + pht( 173 + 'The public key corresponding to the given private key is '. 174 + 'properly associated with the device, but is not yet trusted. '. 175 + 'Trust this key before registering devices with it.')); 176 + } 171 177 172 - $console->writeOut( 178 + echo tsprintf( 173 179 "%s\n", 174 180 pht('Installing public key...')); 175 181 ··· 179 185 Filesystem::writeFile($tmp_public, $raw_public_key); 180 186 execx('mv -f %s %s', $tmp_public, $stored_public_path); 181 187 182 - $console->writeOut( 188 + echo tsprintf( 183 189 "%s\n", 184 190 pht('Installing private key...')); 185 191 execx('mv -f %s %s', $tmp_private, $stored_private_path); 186 192 187 - $raw_device = $device_name; 188 - $identify_as = $args->getArg('identify-as'); 189 - if (strlen($identify_as)) { 190 - $raw_device = $identify_as; 191 - } 192 - 193 - $console->writeOut( 193 + echo tsprintf( 194 194 "%s\n", 195 195 pht('Installing device %s...', $raw_device)); 196 196 ··· 202 202 Filesystem::writeFile($tmp_device, $raw_device); 203 203 execx('mv -f %s %s', $tmp_device, $stored_device_path); 204 204 205 - if (!$public_key->getID()) { 206 - $console->writeOut( 207 - "%s\n", 208 - pht('Registering device key...')); 209 - $public_key->save(); 210 - } 211 - 212 - $console->writeOut( 205 + echo tsprintf( 213 206 "**<bg:green> %s </bg>** %s\n", 214 207 pht('HOST REGISTERED'), 215 208 pht(
+242
src/docs/user/cluster/cluster_devices.diviner
··· 1 + @title Cluster: Devices 2 + @group cluster 3 + 4 + Guide to configuring hosts to act as cluster devices. 5 + 6 + Cluster Context 7 + =============== 8 + 9 + This document describes a step in configuring Phabricator to run on 10 + multiple hosts in a cluster configuration. This is an advanced feature. For 11 + more information on clustering, see @{article:Clustering Introduction}. 12 + 13 + In this context, device configuration is mostly relevant to configuring 14 + repository services in a cluster. You can find more details about this in 15 + @{article:Cluster: Repositories}. 16 + 17 + 18 + Overview 19 + ======== 20 + 21 + Some cluster services need to be able to authenticate themselves and interact 22 + with other services. For example, two repository hosts holding copies of the 23 + same repository must be able to fetch changes from one another, even if the 24 + repository is private. 25 + 26 + Within a cluster, devices authenticate using SSH keys. Some operations happen 27 + over SSH (using keys in a normal way, as you would when running `ssh` from the 28 + command line), while others happen over HTTP (using SSH keys to sign requests). 29 + 30 + Before hosts can authenticate to one another, you need to configure the 31 + credentials so other devices know the keys can be trusted. Beyond establishing 32 + trust, this configuration will establish //device identity//, so each host 33 + knows which device it is explicitly. 34 + 35 + Today, this is primarily necessary when configuring repository clusters. 36 + 37 + 38 + Using Almanac 39 + ============= 40 + 41 + The tool Phabricator uses to manage cluster devices is the **Almanac** 42 + application, and most configuration will occur through the application's web 43 + UI. If you are not familiar with it, see @{article:Almanac User Guide} first. 44 + This document assumes you are familiar with Almanac concepts. 45 + 46 + 47 + What Lies Ahead 48 + =============== 49 + 50 + Here's a brief overview of the steps required to register cluster devices. The 51 + remainder of this document walks through these points in more detail. 52 + 53 + - Create an Almanac device record for each device. 54 + - Generate, add, and trust SSH keys if necessary. 55 + - Install Phabricator on the host. 56 + - Use `bin/almanac register` from the host to register it as a device. 57 + 58 + See below for guidance on each of these steps. 59 + 60 + 61 + Individual vs Shared Keys 62 + ========================= 63 + 64 + Before getting started, you should choose how you plan to manage device SSH 65 + keys. Trust and device identity are handled separately, and there are two ways 66 + to set up SSH keys so that devices can authenticate with one another: 67 + 68 + - you can generate a unique SSH key for each device; or 69 + - you can generate one SSH key and share it across multiple devices. 70 + 71 + Using **unique keys** allows the tools to do some more sanity/safety checks and 72 + makes it a bit more difficult to misconfigure things, but you'll have to do 73 + more work managing the actual keys. This may be a better choice if you are 74 + setting up a small cluster (2-3 devices) for the first time. 75 + 76 + Using **shared keys** makes key management easier but safety checks won't be 77 + able to catch a few kinds of mistakes. This may be a better choice if you are 78 + setting up a larger cluster, plan to expand the cluster later, or have 79 + experience with Phabricator clustering. 80 + 81 + Because all cluster keys are all-powerful, there is no material difference 82 + between these methods from a security or trust viewpoint. Unique keys are just 83 + potentially easier to administrate at small scales, while shared keys are 84 + easier at larger scales. 85 + 86 + 87 + Create Almanac Device Records 88 + ============================= 89 + 90 + For each host you plan to make part of a Phabricator cluster, go to the 91 + {nav Almanac} application and create a **device** record. For guidance on this 92 + application, see @{article:Almanac User Guide}. 93 + 94 + Add **interfaces** to each device record so Phabricator can tell how to 95 + connect to these hosts. Normally, you'll add one HTTP interface (usually on 96 + port 80) and one SSH interface (often on port 22) to each device: 97 + 98 + For example, if you are building a two-host repository cluster, you may end 99 + up with records that look like these: 100 + 101 + - Device: `repo001.mycompany.net` 102 + - Interface: `123.0.0.1:22` 103 + - Interface: `123.0.0.1:80` 104 + - Device: `repo002.mycopmany.net` 105 + - Interface: `123.0.0.2:22` 106 + - Interface: `123.0.0.2:80` 107 + 108 + Note that these hosts will normally run two `sshd` ports: the standard `sshd` 109 + which you connect to to operate and administrate the host, and the special 110 + Phabricator `sshd` that you connect to to clone and push repositories. 111 + 112 + You should specify the Phabricator `sshd` port, **not** the standard `sshd` 113 + port. 114 + 115 + If you're using **unique** SSH keys for each device, continue to the next step. 116 + 117 + If you're using **shared** SSH keys, create a third device with no interfaces, 118 + like `keywarden.mycompany.net`. This device will just be used as a container to 119 + hold the trusted SSH key and is not a real device. 120 + 121 + NOTE: Do **not** create a **service** record yet. Today, service records become 122 + active immediately once they are created, and you haven't set things up yet. 123 + 124 + 125 + Generate and Trust SSH Keys 126 + =========================== 127 + 128 + Next, you need to generate or upload SSH keys and mark them as trusted. Marking 129 + a key as trusted gives it tremendous power. 130 + 131 + If you're using **unique** SSH keys, upload or generate a key for each 132 + individual device from the device detail screen in the Almanac web UI. Save the 133 + private keys for the next step. 134 + 135 + If you're using a **shared** SSH key, upload or generate a single key for 136 + the keywarden device from the device detail screen in the Almanac web UI. 137 + Save the private key for the next step. 138 + 139 + Regardless of how many keys you generated, take the key IDs from the tables 140 + in the web UI and run this command from the command line for each key, to mark 141 + each key as trusted: 142 + 143 + ``` 144 + phabricator/ $ ./bin/almanac trust-key --id <key-id-1> 145 + phabricator/ $ ./bin/almanac trust-key --id <key-id-2> 146 + ... 147 + ``` 148 + 149 + The warnings this command emits are serious. The private keys are now trusted, 150 + and allow any user or device possessing them to sign requests that bypass 151 + policy checks without requiring additional credentials. Guard them carefully! 152 + 153 + If you need to revoke trust for a key later, use `untrust-key`: 154 + 155 + ``` 156 + phabricator/ $ ./bin/almanac untrust-key --id <key-id> 157 + ``` 158 + 159 + Once the keys are trusted, continue to the next step. 160 + 161 + 162 + Install Phabricator 163 + =================== 164 + 165 + If you haven't already, install Phabricator on each device you plan to enroll 166 + in the cluster. Cluster repository devices must provide services over both HTTP 167 + and SSH, so you need to install and configure both a webserver and a 168 + Phabricator `sshd` on these hosts. 169 + 170 + Generally, you will follow whatever process you otherwise use when installing 171 + Phabricator. 172 + 173 + NOTE: Do not start the daemons on the new devices yet. They won't work properly 174 + until you've finished configuring things. 175 + 176 + Once Phabricator is installed, you can enroll the devices in the cluster by 177 + registering them. 178 + 179 + 180 + Register Devices 181 + ================ 182 + 183 + To register a host as an Almanac device, use `bin/almanac register`. 184 + 185 + If you are using **unique** keys, run it like this: 186 + 187 + ``` 188 + $ ./bin/almanac register \ 189 + --device <device> \ 190 + --private-key <key> 191 + ``` 192 + 193 + For example, you might run this command on `repo001` when using unique keys: 194 + 195 + ``` 196 + $ ./bin/almanac register \ 197 + --device repo001.mycompany.net \ 198 + --private-key /path/to/private.key 199 + ``` 200 + 201 + If you are using a **shared** key, this will be a little more complicated 202 + because you need to override some checks that are intended to prevent mistakes. 203 + Use the `--identify-as` flag to choose a device identity: 204 + 205 + ``` 206 + $ ./bin/almanac register \ 207 + --device <keywarden-device> \ 208 + --private-key <key> \ 209 + --identify-as <actual-device> 210 + ``` 211 + 212 + For example, you might run this command on `repo001` when using a shared key: 213 + 214 + ``` 215 + $ ./bin/almanac register 216 + --device keywarden.mycompany.net \ 217 + --private-key /path/to/private-key \ 218 + --identify-as repo001.mycompany.net 219 + ``` 220 + 221 + In particular, note that `--device` is always the **trusted** device associated 222 + with the trusted key. The `--identify-as` flag allows several different hosts 223 + to share the same key but still identify as different devices. 224 + 225 + The overall effect of the `bin/almanac` command is to copy identity and key 226 + files into `phabricator/conf/keys/`. You can inspect the results by examining 227 + that directory. The helper script just catches potential mistakes and makes 228 + sure the process is completed correctly. 229 + 230 + Note that a copy of the active private key is stored in the `conf/keys/` 231 + directory permanently. 232 + 233 + 234 + Next Steps 235 + ========== 236 + 237 + Now that devices are registered, you can build cluster services from them. 238 + Return to the relevant cluster service documentation to continue: 239 + 240 + - build repository clusters with @{article:Cluster: Repositories}; 241 + - return to @{article:Clustering Introduction}; or 242 + - review the Almanac application with @{article:Almanac User Guide}.