Skip to content

Commit fa0fe79

Browse files
committed
feat(agent): add api_key_scope to control agent token permissions
Change-Id: I90dd87756b47b589bf0a363e22de70d2cffd44fa Signed-off-by: Thomas Kosiewski <tk@coder.com>
1 parent 21147bf commit fa0fe79

File tree

8 files changed

+128
-13
lines changed

8 files changed

+128
-13
lines changed

.envrc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
if ! has nix_direnv_version || ! nix_direnv_version 3.0.6; then
2+
source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/3.0.6/direnvrc" "sha256-RYcUJaRMf8oF5LznDrlCXbkOQrywm0HDv1VjYGaJGdM="
3+
fi
4+
5+
nix_direnv_manual_reload
6+
7+
use flake .

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,6 @@ website/vendor
3636

3737
# Binary
3838
terraform-provider-coder
39+
40+
# direnv
41+
.direnv

docs/resources/agent.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,10 @@ data "coder_workspace" "me" {
1717
}
1818
1919
resource "coder_agent" "dev" {
20-
os = "linux"
21-
arch = "amd64"
22-
dir = "/workspace"
20+
os = "linux"
21+
arch = "amd64"
22+
dir = "/workspace"
23+
api_key_scope = "all"
2324
display_apps {
2425
vscode = true
2526
vscode_insiders = false
@@ -71,6 +72,7 @@ resource "kubernetes_pod" "dev" {
7172

7273
### Optional
7374

75+
- `api_key_scope` (String) Controls what API routes the agent token can access. Options: 'all' (full access) or 'no_user_data' (blocks /external-auth, /gitsshkey, and /gitauth routes)
7476
- `auth` (String) The authentication type the agent will use. Must be one of: `"token"`, `"google-instance-identity"`, `"aws-instance-identity"`, `"azure-instance-identity"`.
7577
- `connection_timeout` (Number) Time in seconds until the agent is marked as timed out when a connection with the server cannot be established. A value of zero never marks the agent as timed out.
7678
- `dir` (String) The starting directory when a user creates a shell session. Defaults to `"$HOME"`.

examples/resources/coder_agent/resource.tf

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ data "coder_workspace" "me" {
22
}
33

44
resource "coder_agent" "dev" {
5-
os = "linux"
6-
arch = "amd64"
7-
dir = "/workspace"
5+
os = "linux"
6+
arch = "amd64"
7+
dir = "/workspace"
8+
api_key_scope = "all"
89
display_apps {
910
vscode = true
1011
vscode_insiders = false

flake.lock

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

flake.nix

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
description = "Terraform provider for Coder";
33

44
inputs = {
5-
nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
5+
nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11";
66
flake-utils.url = "github:numtide/flake-utils";
77
};
88

9-
outputs = { self, nixpkgs, flake-utils, ... }:
9+
outputs = { nixpkgs, flake-utils, ... }:
1010
flake-utils.lib.eachDefaultSystem (system:
1111
let
1212
pkgs = import nixpkgs {
@@ -21,7 +21,7 @@
2121
name = "devShell";
2222
buildInputs = with pkgs; [
2323
terraform
24-
go_1_20
24+
go_1_24
2525
];
2626
};
2727
}

provider/agent.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,17 @@ func agentResource() *schema.Resource {
8080
return nil
8181
},
8282
Schema: map[string]*schema.Schema{
83+
"api_key_scope": {
84+
Type: schema.TypeString,
85+
Optional: true,
86+
Default: "all",
87+
ForceNew: true,
88+
Description: "Controls what API routes the agent token can access. Options: 'all' (full access) or 'no_user_data' (blocks /external-auth, /gitsshkey, and /gitauth routes)",
89+
ValidateFunc: validation.StringInSlice([]string{
90+
"all",
91+
"no_user_data",
92+
}, false),
93+
},
8394
"init_script": {
8495
Type: schema.TypeString,
8596
Computed: true,

provider/agent_test.go

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -709,5 +709,96 @@ func TestAgent_DisplayApps(t *testing.T) {
709709
}},
710710
})
711711
})
712+
}
713+
714+
// TestAgent_APIKeyScope tests valid states/transitions and invalid values for api_key_scope.
715+
func TestAgent_APIKeyScope(t *testing.T) {
716+
t.Parallel()
717+
718+
t.Run("ValidTransitions", func(t *testing.T) {
719+
t.Parallel()
720+
721+
resourceName := "coder_agent.test_scope_valid"
712722

723+
resource.Test(t, resource.TestCase{
724+
ProviderFactories: coderFactory(),
725+
IsUnitTest: true,
726+
Steps: []resource.TestStep{
727+
// Step 1: Default value
728+
{
729+
Config: `
730+
provider "coder" {
731+
url = "https://example.com"
732+
}
733+
resource "coder_agent" "test_scope_valid" {
734+
os = "linux"
735+
arch = "amd64"
736+
# api_key_scope is omitted, should default to "default"
737+
}
738+
`,
739+
Check: resource.ComposeTestCheckFunc(
740+
resource.TestCheckResourceAttr(resourceName, "api_key_scope", "all"),
741+
),
742+
},
743+
// Step 2: Explicit "default"
744+
{
745+
Config: `
746+
provider "coder" {
747+
url = "https://example.com"
748+
}
749+
resource "coder_agent" "test_scope_valid" {
750+
os = "linux"
751+
arch = "amd64"
752+
api_key_scope = "all"
753+
}
754+
`,
755+
Check: resource.ComposeTestCheckFunc(
756+
resource.TestCheckResourceAttr(resourceName, "api_key_scope", "all"),
757+
),
758+
},
759+
// Step 3: Explicit "no_user_data"
760+
{
761+
Config: `
762+
provider "coder" {
763+
url = "https://example.com"
764+
}
765+
resource "coder_agent" "test_scope_valid" {
766+
os = "linux"
767+
arch = "amd64"
768+
api_key_scope = "no_user_data"
769+
}
770+
`,
771+
Check: resource.ComposeTestCheckFunc(
772+
resource.TestCheckResourceAttr(resourceName, "api_key_scope", "no_user_data"),
773+
),
774+
},
775+
},
776+
})
777+
})
778+
779+
t.Run("InvalidValue", func(t *testing.T) {
780+
t.Parallel()
781+
782+
resource.Test(t, resource.TestCase{
783+
ProviderFactories: coderFactory(),
784+
IsUnitTest: true,
785+
Steps: []resource.TestStep{
786+
// Step 1: Invalid value check
787+
{
788+
Config: `
789+
provider "coder" {
790+
url = "https://example.com"
791+
}
792+
resource "coder_agent" "test_scope_invalid" { // Use unique name
793+
os = "linux"
794+
arch = "amd64"
795+
api_key_scope = "invalid-scope"
796+
}
797+
`,
798+
ExpectError: regexp.MustCompile(`expected api_key_scope to be one of \["all" "no_user_data"\], got invalid-scope`),
799+
PlanOnly: true,
800+
},
801+
},
802+
})
803+
})
713804
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy