|
| 1 | +--- |
| 2 | +title: "Using the Secret Manager CLI" |
| 3 | +description: How to manage CI secrets using the Secret Manager CLI tool. |
| 4 | +--- |
| 5 | + |
| 6 | +This page provides an overview of the Secret Manager CLI — a tool for managing CI secrets — and covers its core commands, usage patterns, and capabilities. |
| 7 | + |
| 8 | +# What is the Secret Manager CLI? |
| 9 | + |
| 10 | +The Secret Manager CLI is the primary way to manage secrets used in CI workflows. It is a command-line tool that runs locally, allowing users to: |
| 11 | + |
| 12 | +- Create new secrets |
| 13 | +- List, delete and update existing secrets |
| 14 | +- Retrieve authentication information for the service account tied to a secret collection |
| 15 | + |
| 16 | +{{< alert title="Note" color="info" >}} |
| 17 | +In the future, we may provide a GUI (e.g., a web interface), |
| 18 | +but currently, the CLI is the only interface available. |
| 19 | +{{< / alert >}} |
| 20 | + |
| 21 | +## Prerequisites |
| 22 | + |
| 23 | +Before using the Secret Manager CLI, make sure you have the following installed: |
| 24 | + |
| 25 | +- [**gcloud CLI**](https://cloud.google.com/sdk/gcloud) – Required for authentication with Google Cloud, where CI secrets are stored. |
| 26 | +- **Python 3** – Required for running the tool. |
| 27 | + |
| 28 | +## Initial setup |
| 29 | + |
| 30 | +To start using the Secret Manager CLI: |
| 31 | + |
| 32 | +1. Clone the [openshift/release](https://github.com/openshift/release) GitHub repository locally. |
| 33 | + |
| 34 | +2. Run the CLI via the wrapper script located at `hack/secret-manager.sh`. For example: |
| 35 | + |
| 36 | + ```sh |
| 37 | + ./secret-manager.sh login |
| 38 | + ``` |
| 39 | + |
| 40 | + To make this easier, we recommend setting an alias: |
| 41 | + |
| 42 | + ```sh |
| 43 | + alias sm="./<path-to-release-repo>/hack/secret-manager.sh" |
| 44 | + ``` |
| 45 | + |
| 46 | + You can then use the tool like this: |
| 47 | + |
| 48 | + ```sh |
| 49 | + sm login |
| 50 | + ``` |
| 51 | + |
| 52 | +3. The first command you need to run is `login`. This will open a browser window and authenticate you through Red Hat SSO. |
| 53 | + You only need to log in once unless you explicitly log out of your `gcloud` account. |
| 54 | + |
| 55 | + Once authenticated, you can use all supported commands (`create`, `list`, `update`, etc.). |
| 56 | + |
| 57 | +## Understanding secret collections and groups |
| 58 | + |
| 59 | +Secrets are organized in a three-level hierarchy that controls access and organization: |
| 60 | + |
| 61 | +- **Collection** (top level): A logical grouping that defines ownership and access control. Access to collections is granted to Rover groups – not individuals. |
| 62 | +- **Group** (middle level): A subdivision within a collection that organizes related secrets together (e.g., `aws`, `gcp`, or nested like `ibmcloud/config`). Group names use forward slashes (`/`) for hierarchy. |
| 63 | +- **Secret/Field** (bottom level): The actual secret name (e.g., `username`, `password`, `api-token`). |
| 64 | + |
| 65 | +**Example hierarchy:** |
| 66 | +``` |
| 67 | +my-collection/ # Collection |
| 68 | +├── aws/ # Group |
| 69 | +│ ├── access-key-id # Secret (field) |
| 70 | +│ └── secret-access-key # Secret (field) |
| 71 | +└── gcp/config/ # Nested group |
| 72 | + └── credentials.json # Secret (field) |
| 73 | +``` |
| 74 | + |
| 75 | +**How secrets are referenced in CI configs:** |
| 76 | + |
| 77 | +In your CI configuration files (`ci-operator/config/` or step registry), you reference secrets using the collection and group: |
| 78 | + |
| 79 | +```yaml |
| 80 | +credentials: |
| 81 | +- collection: my-collection |
| 82 | + group: aws |
| 83 | + mount_path: /tmp/aws-creds |
| 84 | +``` |
| 85 | +
|
| 86 | +This automatically mounts all fields in `my-collection/aws/` to the specified path. |
| 87 | + |
| 88 | +Permissions are based on the **email address associated with your Rover group**. |
| 89 | + |
| 90 | +To use a collection (or create a new one), your Rover group must be added to [this configuration file](https://github.com/openshift/release/tree/master/core-services/sync-rover-groups/_config.yaml) in the `openshift/release` repo. |
| 91 | + |
| 92 | +### Adding a New Secret Collection |
| 93 | + |
| 94 | +To give the `abc` rover group access to a collection called `my-collection`, update the [configuration file](https://github.com/openshift/release/tree/master/core-services/sync-rover-groups/_config.yaml) like this: |
| 95 | + |
| 96 | +```yaml |
| 97 | +groups: |
| 98 | + abc: |
| 99 | + secret_collections: |
| 100 | + - my-collection |
| 101 | +``` |
| 102 | + |
| 103 | +- A collection can belong to multiple groups. |
| 104 | +- A group can own multiple collections. |
| 105 | + |
| 106 | +After your PR is merged, a postsubmit job (TODO: add job link) will run to sync the changes. Once that job completes successfully, your group will have full access to manage secrets in that collection. |
| 107 | + |
| 108 | +# Common tasks |
| 109 | + |
| 110 | +In the following command examples we use `sm` as standing for `./hack/secret-manager.sh` for brevity. |
| 111 | + |
| 112 | +Also see [commands cheat sheet](#commands-cheat-sheet) for quick reference. |
| 113 | + |
| 114 | +## Creating a new secret |
| 115 | + |
| 116 | +{{< alert title="Note" color="info" >}} |
| 117 | +A secret must belong to both a [collection and a group](#understanding-secret-collections-and-groups). |
| 118 | +Before creating a new secret, make sure you have access to the target collection, or [create a new collection](#adding-a-new-secret-collection). |
| 119 | +{{< / alert >}} |
| 120 | + |
| 121 | +To create a new secret, specify the collection and the secret path in `group/field` format: |
| 122 | + |
| 123 | +```sh |
| 124 | +sm create -c my-collection aws/access-key-id --from-file=./credentials.json |
| 125 | +``` |
| 126 | + |
| 127 | +This creates a secret at the path `my-collection/aws/access-key-id`. |
| 128 | + |
| 129 | +**Secret path format:** The positional argument uses forward slashes to separate group and field: |
| 130 | +- Simple: `aws/password` (group: `aws`, field: `password`) |
| 131 | +- Nested: `ibmcloud/config/credentials.json` (group: `ibmcloud/config`, field: `credentials.json`) |
| 132 | + |
| 133 | +After executing this command, you’ll be prompted to enter some metadata. |
| 134 | +These metadata help us track ownership and manage secrets effectively. |
| 135 | +These fields are mandatory. If something doesn’t apply, enter `none`. |
| 136 | +You’ll be asked to provide: |
| 137 | + |
| 138 | +- **Jira project**: The JIRA project used by your team (e.g. ART for issues.redhat.com/browse/ART). This helps Test Platform track incidents related to the secret. |
| 139 | +- **Rotation information**: A short explanation of how the secret is rotated. This helps future team members maintain token rotation. Do not include sensitive information -- focus on the process or tools used. |
| 140 | +- **Request information**: Context for why this secret was created (e.g. links to tickets, documentation, chat threads). This helps others know who to contact if issues arise. Do not include sensitive data. |
| 141 | + |
| 142 | +After you enter the metadata, a secret at `my-collection/aws/access-key-id` will be created with the contents of `credentials.json`. |
| 143 | + |
| 144 | +Once created, the secret is immediately available for use in CI jobs. |
| 145 | + |
| 146 | +{{< alert title="Note" color="info" >}} |
| 147 | +We encourage users to automate secret rotation using the dedicated write-only service account provided for each collection. [Learn more](#getting-the-service-account-associated-with-a-collection). |
| 148 | +{{< /alert >}} |
| 149 | + |
| 150 | +### Creating a secret from a literal string |
| 151 | + |
| 152 | +You can also create a secret from the contents of a literal string value using the `--from-literal` option: |
| 153 | + |
| 154 | +```sh |
| 155 | +sm create -c my-collection aws/api-token --from-literal="secret value" |
| 156 | +``` |
| 157 | + |
| 158 | +For additional details about the `create` command, run: |
| 159 | + |
| 160 | +```sh |
| 161 | +sm create --help |
| 162 | +``` |
| 163 | + |
| 164 | +## Listing secrets, rover groups, and collections |
| 165 | + |
| 166 | +You can use the `list` command to inspect what secrets, rover groups, and collections exist. This is often the first step before creating, updating, or deleting a secret. |
| 167 | + |
| 168 | +You can also add the `-o json` option to the commands below to output the data in JSON format (useful for scripting or automation). |
| 169 | + |
| 170 | +### Listing all secrets in a collection |
| 171 | + |
| 172 | +To list all secrets within a collection, run: |
| 173 | + |
| 174 | +```sh |
| 175 | +sm list -c my-collection |
| 176 | +``` |
| 177 | + |
| 178 | +This displays all secrets in `group/field` format, organized by group: |
| 179 | + |
| 180 | +``` |
| 181 | +aws/access-key-id |
| 182 | +aws/secret-access-key |
| 183 | +
|
| 184 | +gcp/credentials.json |
| 185 | +
|
| 186 | +ibmcloud/config/api-key |
| 187 | +``` |
| 188 | + |
| 189 | +### Listing all secret collections for a Rover group |
| 190 | + |
| 191 | +To list all collections your Rover group has access to, run: |
| 192 | + |
| 193 | +```sh |
| 194 | +sm list --rover-group=my-rover-group |
| 195 | +``` |
| 196 | + |
| 197 | +This lists all collections configured for the `my-rover-group` Rover group, as defined in [the configuration file](https://github.com/openshift/release/tree/master/core-services/sync-rover-groups/_config.yaml). |
| 198 | + |
| 199 | +{{< alert title="Note" color="info" >}} |
| 200 | +`--rover-group` refers to your **Rover group** (for access control), which is different from **secret groups** (the organizational hierarchy within collections like `aws`, `gcp`, etc.). |
| 201 | +{{< / alert >}} |
| 202 | + |
| 203 | +### Listing all secret collections |
| 204 | + |
| 205 | +If no options are provided, `sm list` prints *all configured collections* across all groups: |
| 206 | + |
| 207 | +```sh |
| 208 | +sm list |
| 209 | +``` |
| 210 | + |
| 211 | +This is useful for general exploration, especially if you're unsure of the collection or group names. |
| 212 | + |
| 213 | +## Updating a secret |
| 214 | + |
| 215 | +To change the contents of a secret that already exists, use the `update` command. |
| 216 | +You can provide new secret data either from a file or directly as a literal string. |
| 217 | +The update takes effect immediately, and the new secret value will be used the next time a new instance of a CI job references it. |
| 218 | + |
| 219 | +{{< alert title="Note" color="info" >}} |
| 220 | +You can only update secrets in collections you have access to. To check which secret collections you have access to, use `sm list --rover-group=<my-rover-group>` or see [the configuration file](https://github.com/openshift/release/tree/master/core-services/sync-rover-groups/_config.yaml). |
| 221 | +{{< / alert >}} |
| 222 | + |
| 223 | +### Updating a secret from file |
| 224 | + |
| 225 | +To update the contents of a secret with data from a file: |
| 226 | + |
| 227 | +```sh |
| 228 | +sm update -c my-collection aws/access-key-id --from-file=./new-creds.json |
| 229 | +``` |
| 230 | + |
| 231 | +### Updating a secret from a literal string |
| 232 | + |
| 233 | +To update the contents of a secret with a plain string value: |
| 234 | + |
| 235 | +```sh |
| 236 | +sm update -c my-collection aws/api-token --from-literal="new secret value" |
| 237 | +``` |
| 238 | + |
| 239 | +For more details, run: |
| 240 | + |
| 241 | +```sh |
| 242 | +sm update --help |
| 243 | +``` |
| 244 | + |
| 245 | +## Deleting a secret |
| 246 | + |
| 247 | +To remove a secret from a collection, use the `delete` command. |
| 248 | + |
| 249 | +{{< alert title="Note" color="info" >}} |
| 250 | +You can only delete secrets in collections you have access to. To check which secret collections you have access to, use `sm list --rover-group=<my-rover-group>` or see [the configuration file](https://github.com/openshift/release/tree/master/core-services/sync-rover-groups/_config.yaml). |
| 251 | +{{< / alert >}} |
| 252 | + |
| 253 | +### Example |
| 254 | + |
| 255 | +To delete a secret from a collection: |
| 256 | + |
| 257 | +```sh |
| 258 | +sm delete -c my-collection aws/access-key-id |
| 259 | +``` |
| 260 | + |
| 261 | +For more details, run: |
| 262 | + |
| 263 | +```sh |
| 264 | +sm delete --help |
| 265 | +``` |
| 266 | + |
| 267 | +## Getting the service account associated with a collection |
| 268 | + |
| 269 | +Each secret collection has a dedicated write-only service account associated with it. This service account is intended for automating secret rotation (e.g., by setting up a scheduled job in your team). |
| 270 | + |
| 271 | +This service account: |
| 272 | + |
| 273 | +- Can create, update, and delete secrets in the collection. |
| 274 | +- Cannot read secrets — this is by design, to protect sensitive data. |
| 275 | + |
| 276 | +To retrieve the authentication credentials (in JSON format) for this service account, run: |
| 277 | + |
| 278 | +```sh |
| 279 | +sm get-sa -c my-collection |
| 280 | +``` |
| 281 | + |
| 282 | +This command does not create a new service account — it simply returns the credentials for the one already associated with the specified collection. You can use these credentials to configure a script or automation tool that rotates secrets on a regular basis. |
| 283 | + |
| 284 | +# Troubleshooting |
| 285 | + |
| 286 | +TODO |
| 287 | + |
| 288 | +# Commands cheat sheet |
| 289 | + |
| 290 | +In the following examples, `sm` stands for `./hack/secret-manager.sh`. |
| 291 | + |
| 292 | +> **Note:** Each command also supports short flag versions (e.g. `-c` instead of `--collection`). |
| 293 | +> Run `<command> --help` to see all available options and shortcuts. |
| 294 | + |
| 295 | +## Help |
| 296 | + |
| 297 | +- `sm --help` |
| 298 | + Show the list of available commands. |
| 299 | +- `sm <command> --help` |
| 300 | + Show detailed help for a specific command (e.g. `sm create --help`). |
| 301 | + |
| 302 | +## Getting started |
| 303 | + |
| 304 | +- `sm login` |
| 305 | + Authorize into Google Cloud using Red Hat SSO. |
| 306 | + |
| 307 | +## Create a new secret |
| 308 | + |
| 309 | +### From file |
| 310 | + |
| 311 | +- `sm create -c my-collection aws/my-secret --from-file ./path/to/file` |
| 312 | + Create a secret from file contents. |
| 313 | + |
| 314 | +### From literal string |
| 315 | + |
| 316 | +- `sm create -c my-collection aws/my-secret --from-literal "secret value"` |
| 317 | + Create a secret from a literal string value. |
| 318 | + |
| 319 | +## Update a Secret |
| 320 | + |
| 321 | +### From File |
| 322 | + |
| 323 | +- `sm update -c my-collection aws/my-secret --from-file ./path/to/file` |
| 324 | + Update a secret using a new file. |
| 325 | + |
| 326 | +### From Literal String |
| 327 | + |
| 328 | +- `sm update -c my-collection aws/my-secret --from-literal "new value"` |
| 329 | + Update a secret with a new literal string. |
| 330 | + |
| 331 | +## Delete a Secret |
| 332 | + |
| 333 | +- `sm delete -c my-collection aws/my-secret` |
| 334 | + Delete a secret from a collection. |
| 335 | + |
| 336 | +## List |
| 337 | + |
| 338 | +- `sm list -c my-collection` |
| 339 | + List all secrets in a collection (displayed in `group/field` format). |
| 340 | +- `sm list --rover-group my-rover-group` |
| 341 | + List all secret collections accessible by a Rover group. |
| 342 | +- `sm list` |
| 343 | + List all secret collections. |
| 344 | + |
| 345 | +## Get Service Account |
| 346 | + |
| 347 | +- `sm get-sa -c my-collection` |
| 348 | + Retrieve credentials for the service account associated with the collection. |
0 commit comments