|
3 | 3 | > [!CAUTION] |
4 | 4 | > This is a work in progress. You are welcome to try it out, and contribute, |
5 | 5 | > but it should not be considered stable or production-ready. |
| 6 | +
|
| 7 | +`cfa-eng` is a CLI tool for Code for America engineering teams. It manages AWS |
| 8 | +bastion host connections, named profiles, and OpenTofu infrastructure operations. |
| 9 | + |
| 10 | +## Requirements |
| 11 | + |
| 12 | +- Ruby 3.3+ |
| 13 | +- [AWS CLI](https://aws.amazon.com/cli/) with the |
| 14 | + [Session Manager plugin](https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager-working-with-install-plugin.html) |
| 15 | +- [Doppler CLI](https://docs.doppler.com/docs/install-cli) (for `tofu` commands) |
| 16 | +- [OpenTofu](https://opentofu.org/docs/intro/install/) (for `tofu` commands) |
| 17 | + |
| 18 | +## Installation |
| 19 | + |
| 20 | +```bash |
| 21 | +gem install cfa-eng-cli |
| 22 | +``` |
| 23 | + |
| 24 | +Or add it to your `Gemfile`: |
| 25 | + |
| 26 | +```ruby |
| 27 | +gem 'cfa-eng-cli' |
| 28 | +``` |
| 29 | + |
| 30 | +## Configuration |
| 31 | + |
| 32 | +`cfa-eng` uses **profiles** to store named sets of connection settings. Most |
| 33 | +commands require a profile, specified with `--profile` or the `CFA_PROFILE` |
| 34 | +environment variable. |
| 35 | + |
| 36 | +```bash |
| 37 | +export CFA_PROFILE=my-app |
| 38 | +``` |
| 39 | + |
| 40 | +Profile files are stored as YAML in `~/.codeforamerica/profiles/`. |
| 41 | + |
| 42 | +<!-- cspell:ignore codeforamerica --> |
| 43 | + |
| 44 | +## Commands |
| 45 | + |
| 46 | +### `profile` — Manage profiles |
| 47 | + |
| 48 | +#### `profile create` |
| 49 | + |
| 50 | +Creates a new profile. All fields can be supplied as options; any omitted fields |
| 51 | +are prompted for interactively. |
| 52 | + |
| 53 | +```bash |
| 54 | +cfa-eng profile create |
| 55 | +cfa-eng profile create --name my-app --project snap --environment staging \ |
| 56 | + --aws-profile shared-services-dev --region us-east-1 |
| 57 | +``` |
| 58 | + |
| 59 | +| Option | Description | |
| 60 | +|---|---| |
| 61 | +| `--name` | Profile name | |
| 62 | +| `--project` | Project name | |
| 63 | +| `--environment` | Deployment environment (e.g. `staging`, `production`) | |
| 64 | +| `--aws-profile` | AWS CLI profile to use for credentials | |
| 65 | +| `--region` | Primary AWS region (default: `us-east-1`) | |
| 66 | +| `--doppler-project` | Doppler project for secrets (default: `shared-services`) | |
| 67 | +| `--doppler-environment` | Doppler environment prefix used for config names, e.g. `infra` produces configs like `infra_dev`, `infra_prod`, `infra_<env>` (default: `infra`) | |
| 68 | + |
| 69 | +#### `profile list` |
| 70 | + |
| 71 | +Lists all saved profiles. |
| 72 | + |
| 73 | +```bash |
| 74 | +cfa-eng profile list |
| 75 | +``` |
| 76 | + |
| 77 | +#### `profile delete PROFILE` |
| 78 | + |
| 79 | +Deletes a profile. Prompts for confirmation unless `--yes` is given. |
| 80 | + |
| 81 | +```bash |
| 82 | +cfa-eng profile delete my-app |
| 83 | +cfa-eng profile delete my-app --yes |
| 84 | +``` |
| 85 | + |
| 86 | +#### `profile rename PROFILE NAME` |
| 87 | + |
| 88 | +Renames a profile. Prompts for confirmation unless `--yes` is given. |
| 89 | + |
| 90 | +```bash |
| 91 | +cfa-eng profile rename my-app my-renamed-app |
| 92 | +cfa-eng profile rename my-app my-renamed-app --yes |
| 93 | +``` |
| 94 | + |
| 95 | +--- |
| 96 | + |
| 97 | +### `bastion` — Connect to bastion hosts |
| 98 | + |
| 99 | +The `bastion` commands connect to AWS bastion hosts via SSM Session Manager port |
| 100 | +forwarding. A profile is required for all bastion commands. |
| 101 | + |
| 102 | +All `bastion` commands accept: |
| 103 | + |
| 104 | +| Option | Description | |
| 105 | +|---|---| |
| 106 | +| `--profile NAME` | Profile to use (default: `$CFA_PROFILE`) | |
| 107 | + |
| 108 | +#### `bastion create-tunnel` |
| 109 | + |
| 110 | +Adds a tunnel configuration to a profile. Prompts interactively for tunnel |
| 111 | +settings. |
| 112 | + |
| 113 | +```bash |
| 114 | +cfa-eng bastion create-tunnel --profile my-app |
| 115 | +``` |
| 116 | + |
| 117 | +#### `bastion delete-tunnel NAME` |
| 118 | + |
| 119 | +Removes a named tunnel configuration from a profile. |
| 120 | + |
| 121 | +```bash |
| 122 | +cfa-eng bastion delete-tunnel my-db --profile my-app |
| 123 | +``` |
| 124 | + |
| 125 | +#### `bastion tunnel` |
| 126 | + |
| 127 | +Opens an SSH tunnel through the bastion to a remote host using a saved tunnel |
| 128 | +configuration. |
| 129 | + |
| 130 | +```bash |
| 131 | +cfa-eng bastion tunnel --name my-db --profile my-app |
| 132 | +``` |
| 133 | + |
| 134 | +| Option | Description | |
| 135 | +|---|---| |
| 136 | +| `--name` | Name of the tunnel configuration to use | |
| 137 | + |
| 138 | +--- |
| 139 | + |
| 140 | +### `tofu` — Run OpenTofu operations |
| 141 | + |
| 142 | +The `tofu` commands wrap common OpenTofu operations. They automatically fetch |
| 143 | +secrets from Doppler, select the appropriate AWS profile for the environment, |
| 144 | +and run `tofu init` before each operation. |
| 145 | + |
| 146 | +A profile is required for all `tofu` commands and supplies the environment, |
| 147 | +AWS credentials, project name, and Doppler project. |
| 148 | + |
| 149 | +All `tofu` commands accept: |
| 150 | + |
| 151 | +| Option | Description | |
| 152 | +|---|---| |
| 153 | +| `--profile NAME` | Profile to use (default: `$CFA_PROFILE`) | |
| 154 | + |
| 155 | +These commands must be run from the root of an OpenTofu repository (a directory |
| 156 | +containing `tofu/configs/`). |
| 157 | + |
| 158 | +#### `tofu plan CONFIG` |
| 159 | + |
| 160 | +Runs `tofu plan -concise` for the given configuration layer. |
| 161 | + |
| 162 | +```bash |
| 163 | +cfa-eng tofu plan foundation --profile my-app |
| 164 | +cfa-eng tofu plan application --profile my-app --args="-out tfplan" |
| 165 | +``` |
| 166 | + |
| 167 | +| Option | Description | |
| 168 | +|---|---| |
| 169 | +| `--args STRING` | Extra arguments forwarded to `tofu plan` | |
| 170 | + |
| 171 | +#### `tofu apply CONFIG` |
| 172 | + |
| 173 | +Runs `tofu apply` for the given configuration layer. |
| 174 | + |
| 175 | +```bash |
| 176 | +cfa-eng tofu apply foundation --profile my-app |
| 177 | +cfa-eng tofu apply application --profile my-app --args="-auto-approve" |
| 178 | +``` |
| 179 | + |
| 180 | +| Option | Description | |
| 181 | +|---|---| |
| 182 | +| `--args STRING` | Extra arguments forwarded to `tofu apply` | |
| 183 | + |
| 184 | +#### `tofu destroy CONFIG` |
| 185 | + |
| 186 | +Runs `tofu destroy` for the given configuration layer. |
| 187 | + |
| 188 | +```bash |
| 189 | +cfa-eng tofu destroy application --profile my-app |
| 190 | +``` |
| 191 | + |
| 192 | +| Option | Description | |
| 193 | +|---|---| |
| 194 | +| `--args STRING` | Extra arguments forwarded to `tofu destroy` | |
| 195 | + |
| 196 | +#### `tofu output CONFIG` |
| 197 | + |
| 198 | +Shows the outputs for the given configuration layer. |
| 199 | + |
| 200 | +```bash |
| 201 | +cfa-eng tofu output foundation --profile my-app |
| 202 | +cfa-eng tofu output foundation --profile my-app --args="-json" |
| 203 | +``` |
| 204 | + |
| 205 | +| Option | Description | |
| 206 | +|---|---| |
| 207 | +| `--args STRING` | Extra arguments forwarded to `tofu output` | |
| 208 | + |
| 209 | +#### `tofu force-unlock CONFIG LOCK_ID` |
| 210 | + |
| 211 | +Force-unlocks a stuck state lock for the given configuration layer. Prompts for |
| 212 | +confirmation before proceeding. Does not fetch Doppler secrets. |
| 213 | + |
| 214 | +```bash |
| 215 | +cfa-eng tofu force-unlock foundation abc-1234-5678 --profile my-app |
| 216 | +``` |
| 217 | + |
| 218 | +> [!WARNING] |
| 219 | +> Only use this if you are certain the lock is stale. Unlocking while another |
| 220 | +> operation is in progress will corrupt state. |
| 221 | +
|
| 222 | +#### `tofu bootstrap` |
| 223 | + |
| 224 | +Bootstraps the remote S3 state backend for a new environment. If the state |
| 225 | +bucket does not yet exist, it applies the `foundation` configuration with a |
| 226 | +local backend first and then migrates state to S3. |
| 227 | + |
| 228 | +```bash |
| 229 | +cfa-eng tofu bootstrap --profile my-app |
| 230 | +``` |
| 231 | + |
| 232 | +> [!NOTE] |
| 233 | +> `tofu bootstrap` always operates on `tofu/configs/foundation`. |
| 234 | +
|
| 235 | +### AWS profile selection |
| 236 | + |
| 237 | +For `tofu` commands, the AWS profile is taken from the saved profile's |
| 238 | +`aws_profile` field. If no `aws_profile` is stored in the profile, the CLI |
| 239 | +selects a default based on the environment: |
| 240 | + |
| 241 | +| Environment | Default AWS profile | |
| 242 | +|---|---| |
| 243 | +| `production` | `shared-services-prod` | |
| 244 | +| All others | `shared-services-dev` | |
| 245 | + |
| 246 | +A red warning is printed before any operation targeting `production`. |
0 commit comments