feat: add enable/disable support for user secrets (#27537)

Users can now disable a secret to stop it from being injected into
workspaces without deleting it, and re-enable it later. Disabled secrets
stay visible and editable everywhere they already appear.

An enabled secret must have at least one injection target; a secret with
no target can be stored only while disabled. Existing target-less secrets
are migrated to disabled to preserve current behavior.

Support spans the REST API, SDK, CLI, dashboard, and audit log.
This commit is contained in:
Zach
2026-07-28 09:58:33 -06:00
committed by GitHub
parent 3c61a9a939
commit 85984ff142
56 changed files with 1391 additions and 186 deletions
+28 -22
View File
@@ -5117,6 +5117,7 @@ This is required on creation to enable a user-flow of validating a template work
```json
{
"description": "string",
"enabled": true,
"env_name": "string",
"file_path": "string",
"name": "string",
@@ -5126,13 +5127,14 @@ This is required on creation to enable a user-flow of validating a template work
### Properties
| Name | Type | Required | Restrictions | Description |
|---------------|--------|----------|--------------|-------------|
| `description` | string | false | | |
| `env_name` | string | false | | |
| `file_path` | string | false | | |
| `name` | string | false | | |
| `value` | string | false | | |
| Name | Type | Required | Restrictions | Description |
|---------------|---------|----------|--------------|-------------|
| `description` | string | false | | |
| `enabled` | boolean | false | | |
| `env_name` | string | false | | |
| `file_path` | string | false | | |
| `name` | string | false | | |
| `value` | string | false | | |
## codersdk.CreateUserSkillRequest
@@ -13833,6 +13835,7 @@ If the schedule is empty, the user will be updated to use the default schedule.|
```json
{
"description": "string",
"enabled": true,
"env_name": "string",
"file_path": "string",
"value": "string"
@@ -13841,12 +13844,13 @@ If the schedule is empty, the user will be updated to use the default schedule.|
### Properties
| Name | Type | Required | Restrictions | Description |
|---------------|--------|----------|--------------|-------------|
| `description` | string | false | | |
| `env_name` | string | false | | |
| `file_path` | string | false | | |
| `value` | string | false | | |
| Name | Type | Required | Restrictions | Description |
|---------------|---------|----------|--------------|-------------|
| `description` | string | false | | |
| `enabled` | boolean | false | | |
| `env_name` | string | false | | |
| `file_path` | string | false | | |
| `value` | string | false | | |
## codersdk.UpdateUserSkillRequest
@@ -14532,6 +14536,7 @@ If the schedule is empty, the user will be updated to use the default schedule.|
{
"created_at": "2019-08-24T14:15:22Z",
"description": "string",
"enabled": true,
"env_name": "string",
"file_path": "string",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
@@ -14542,15 +14547,16 @@ If the schedule is empty, the user will be updated to use the default schedule.|
### Properties
| Name | Type | Required | Restrictions | Description |
|---------------|--------|----------|--------------|-------------|
| `created_at` | string | false | | |
| `description` | string | false | | |
| `env_name` | string | false | | |
| `file_path` | string | false | | |
| `id` | string | false | | |
| `name` | string | false | | |
| `updated_at` | string | false | | |
| Name | Type | Required | Restrictions | Description |
|---------------|---------|----------|--------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `created_at` | string | false | | |
| `description` | string | false | | |
| `enabled` | boolean | false | | Enabled controls whether the secret is injected into workspaces. Disabled secrets remain visible and editable, but are not added to the agent manifest, so they are not exposed as environment variables or written to secret files. |
| `env_name` | string | false | | |
| `file_path` | string | false | | |
| `id` | string | false | | |
| `name` | string | false | | |
| `updated_at` | string | false | | |
## codersdk.UserSkill
+29 -20
View File
@@ -28,6 +28,7 @@ curl -X GET http://coder-server:8080/api/v2/users/{user}/secrets \
{
"created_at": "2019-08-24T14:15:22Z",
"description": "string",
"enabled": true,
"env_name": "string",
"file_path": "string",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
@@ -47,16 +48,17 @@ curl -X GET http://coder-server:8080/api/v2/users/{user}/secrets \
Status Code **200**
| Name | Type | Required | Restrictions | Description |
|-----------------|-------------------|----------|--------------|-------------|
| `[array item]` | array | false | | |
| `» created_at` | string(date-time) | false | | |
| `» description` | string | false | | |
| `» env_name` | string | false | | |
| `» file_path` | string | false | | |
| `» id` | string(uuid) | false | | |
| `» name` | string | false | | |
| `» updated_at` | string(date-time) | false | | |
| Name | Type | Required | Restrictions | Description |
|-----------------|-------------------|----------|--------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `[array item]` | array | false | | |
| `» created_at` | string(date-time) | false | | |
| `» description` | string | false | | |
| `» enabled` | boolean | false | | Enabled controls whether the secret is injected into workspaces. Disabled secrets remain visible and editable, but are not added to the agent manifest, so they are not exposed as environment variables or written to secret files. |
| `» env_name` | string | false | | |
| `» file_path` | string | false | | |
| `» id` | string(uuid) | false | | |
| `» name` | string | false | | |
| `» updated_at` | string(date-time) | false | | |
To perform this operation, you must be authenticated. [Learn more](authentication.md).
@@ -79,6 +81,7 @@ curl -X POST http://coder-server:8080/api/v2/users/{user}/secrets \
```json
{
"description": "string",
"enabled": true,
"env_name": "string",
"file_path": "string",
"name": "string",
@@ -101,6 +104,7 @@ curl -X POST http://coder-server:8080/api/v2/users/{user}/secrets \
{
"created_at": "2019-08-24T14:15:22Z",
"description": "string",
"enabled": true,
"env_name": "string",
"file_path": "string",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
@@ -156,6 +160,7 @@ curl -X POST http://coder-server:8080/api/v2/users/{user}/secrets/batch \
{
"created_at": "2019-08-24T14:15:22Z",
"description": "string",
"enabled": true,
"env_name": "string",
"file_path": "string",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
@@ -178,16 +183,17 @@ curl -X POST http://coder-server:8080/api/v2/users/{user}/secrets/batch \
Status Code **201**
| Name | Type | Required | Restrictions | Description |
|-----------------|-------------------|----------|--------------|-------------|
| `[array item]` | array | false | | |
| `» created_at` | string(date-time) | false | | |
| `» description` | string | false | | |
| `» env_name` | string | false | | |
| `» file_path` | string | false | | |
| `» id` | string(uuid) | false | | |
| `» name` | string | false | | |
| `» updated_at` | string(date-time) | false | | |
| Name | Type | Required | Restrictions | Description |
|-----------------|-------------------|----------|--------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `[array item]` | array | false | | |
| `» created_at` | string(date-time) | false | | |
| `» description` | string | false | | |
| `» enabled` | boolean | false | | Enabled controls whether the secret is injected into workspaces. Disabled secrets remain visible and editable, but are not added to the agent manifest, so they are not exposed as environment variables or written to secret files. |
| `» env_name` | string | false | | |
| `» file_path` | string | false | | |
| `» id` | string(uuid) | false | | |
| `» name` | string | false | | |
| `» updated_at` | string(date-time) | false | | |
To perform this operation, you must be authenticated. [Learn more](authentication.md).
@@ -219,6 +225,7 @@ curl -X GET http://coder-server:8080/api/v2/users/{user}/secrets/{name} \
{
"created_at": "2019-08-24T14:15:22Z",
"description": "string",
"enabled": true,
"env_name": "string",
"file_path": "string",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
@@ -281,6 +288,7 @@ curl -X PATCH http://coder-server:8080/api/v2/users/{user}/secrets/{name} \
```json
{
"description": "string",
"enabled": true,
"env_name": "string",
"file_path": "string",
"value": "string"
@@ -303,6 +311,7 @@ curl -X PATCH http://coder-server:8080/api/v2/users/{user}/secrets/{name} \
{
"created_at": "2019-08-24T14:15:22Z",
"description": "string",
"enabled": true,
"env_name": "string",
"file_path": "string",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
+8 -6
View File
@@ -39,9 +39,11 @@ coder secret
## Subcommands
| Name | Purpose |
|-------------------------------------------|-----------------------------------|
| [<code>create</code>](./secret_create.md) | Create a secret |
| [<code>update</code>](./secret_update.md) | Update a secret |
| [<code>list</code>](./secret_list.md) | List secrets, or show one by name |
| [<code>delete</code>](./secret_delete.md) | Delete a secret |
| Name | Purpose |
|---------------------------------------------|---------------------------------------------------|
| [<code>create</code>](./secret_create.md) | Create a secret |
| [<code>update</code>](./secret_update.md) | Update a secret |
| [<code>enable</code>](./secret_enable.md) | Enable a secret so it is injected into workspaces |
| [<code>disable</code>](./secret_disable.md) | Disable a secret without removing it |
| [<code>list</code>](./secret_list.md) | List secrets, or show one by name |
| [<code>delete</code>](./secret_delete.md) | Delete a secret |
+9
View File
@@ -48,3 +48,12 @@ Name of the workspace environment variable that this secret will set.
| Type | <code>string</code> |
Workspace file path where this secret will be written. Must start with ~/ or /.
### --enabled
| | |
|---------|-------------------|
| Type | <code>bool</code> |
| Default | <code>true</code> |
Whether the secret is injected into workspaces. An enabled secret must set --env or --file; pass --enabled=false to store a secret without injecting it.
+10
View File
@@ -0,0 +1,10 @@
<!-- DO NOT EDIT | GENERATED CONTENT -->
# secret disable
Disable a secret without removing it
## Usage
```console
coder secret disable <name>
```
+10
View File
@@ -0,0 +1,10 @@
<!-- DO NOT EDIT | GENERATED CONTENT -->
# secret enable
Enable a secret so it is injected into workspaces
## Usage
```console
coder secret enable <name>
```
+4 -4
View File
@@ -23,10 +23,10 @@ Secret values are omitted from the output.
### -c, --column
| | |
|---------|---------------------------------------------------------------|
| Type | <code>[created\|name\|updated\|env\|file\|description]</code> |
| Default | <code>name,created,updated,env,file,description</code> |
| | |
|---------|------------------------------------------------------------------------|
| Type | <code>[created\|name\|updated\|env\|file\|enabled\|description]</code> |
| Default | <code>name,created,updated,env,file,enabled,description</code> |
Columns to display in table output.
+9 -1
View File
@@ -12,7 +12,7 @@ coder secret update [flags] <name>
## Description
```console
At least one of --value, --description, --env, or --file must be specified. Provide the secret value by at most one of --value or non-interactive stdin (pipe or redirect).
At least one of --value, --description, --env, --file, or --enabled must be specified. Provide the secret value by at most one of --value or non-interactive stdin (pipe or redirect).
```
## Options
@@ -48,3 +48,11 @@ Name of the workspace environment variable that this secret will set. Pass an em
| Type | <code>string</code> |
Workspace file path where this secret will be written. Must start with ~/ or /. Pass an empty string to clear it.
### --enabled
| | |
|------|-------------------|
| Type | <code>bool</code> |
Whether the secret is injected into workspaces. An enabled secret must keep at least one of --env or --file; pass --enabled=false to stop injecting it without deleting it.