@@ -10,16 +10,17 @@ tags: [helper, integration, vault, jwt, oidc]
10
10
11
11
# Hashicorp Vault Integration (JWT)
12
12
13
- This module lets you authenticate with [ Hashicorp Vault] ( https://www.vaultproject.io/ ) in your Coder workspaces by reusing the [ OIDC] ( https://coder.com/docs/admin/users/oidc-auth ) access token from Coder's OIDC authentication method. This requires configuring the Vault [ JWT/OIDC] ( https://developer.hashicorp.com/vault/docs/auth/jwt#configuration ) auth method.
13
+ This module lets you authenticate with [ Hashicorp Vault] ( https://www.vaultproject.io/ ) in your Coder workspaces by reusing the [ OIDC] ( https://coder.com/docs/admin/users/oidc-auth ) access token from Coder's OIDC authentication method or another source of jwt token . This requires configuring the Vault [ JWT/OIDC] ( https://developer.hashicorp.com/vault/docs/auth/jwt#configuration ) auth method.
14
14
15
15
``` tf
16
16
module "vault" {
17
- count = data.coder_workspace.me.start_count
18
- source = "registry.coder.com/modules/vault-jwt/coder"
19
- version = "1.0.31"
20
- agent_id = coder_agent.example.id
21
- vault_addr = "https://vault.example.com"
22
- vault_jwt_role = "coder" # The Vault role to use for authentication
17
+ count = data.coder_workspace.me.start_count
18
+ source = "registry.coder.com/modules/vault-jwt/coder"
19
+ version = "1.1.0"
20
+ agent_id = coder_agent.example.id
21
+ vault_addr = "https://vault.example.com"
22
+ vault_jwt_role = "coder" # The Vault role to use for authentication
23
+ vault_jwt_token = "eyJhbGciOiJIUzI1N..." # optional, if not present, defaults to user's oidc authentication token
23
24
}
24
25
```
25
26
@@ -79,3 +80,106 @@ module "vault" {
79
80
vault_cli_version = "1.17.5"
80
81
}
81
82
```
83
+
84
+ ### Use a custom JWT token
85
+
86
+ ``` tf
87
+
88
+ terraform {
89
+ required_providers {
90
+ jwt = {
91
+ source = "geektheripper/jwt"
92
+ version = "1.1.4"
93
+ }
94
+ time = {
95
+ source = "hashicorp/time"
96
+ version = "0.11.1"
97
+ }
98
+ }
99
+ }
100
+
101
+
102
+ resource "jwt_signed_token" "vault" {
103
+ count = data.coder_workspace.me.start_count
104
+ algorithm = "RS256"
105
+ # `openssl genrsa -out key.pem 4096` and `openssl rsa -in key.pem -pubout > pub.pem` to generate keys
106
+ key = file("key.pem")
107
+ claims_json = jsonencode({
108
+ iss = "https://code.example.com"
109
+ sub = "${data.coder_workspace.me.id}"
110
+ aud = "https://vault.example.com"
111
+ iat = provider::time::rfc3339_parse(plantimestamp()).unix
112
+ # Uncomment to set an expiry on the JWT token(default 3600 seconds).
113
+ # workspace will need to be restarted to generate a new token if it expires
114
+ #exp = provider::time::rfc3339_parse(timeadd(timestamp(), 3600)).unix agent = coder_agent.main.id
115
+ provisioner = data.coder_provisioner.main.id
116
+ provisioner_arch = data.coder_provisioner.main.arch
117
+ provisioner_os = data.coder_provisioner.main.os
118
+
119
+ workspace = data.coder_workspace.me.id
120
+ workspace_url = data.coder_workspace.me.access_url
121
+ workspace_port = data.coder_workspace.me.access_port
122
+ workspace_name = data.coder_workspace.me.name
123
+ template = data.coder_workspace.me.template_id
124
+ template_name = data.coder_workspace.me.template_name
125
+ template_version = data.coder_workspace.me.template_version
126
+ owner = data.coder_workspace_owner.me.id
127
+ owner_name = data.coder_workspace_owner.me.name
128
+ owner_email = data.coder_workspace_owner.me.email
129
+ owner_login_type = data.coder_workspace_owner.me.login_type
130
+ owner_groups = data.coder_workspace_owner.me.groups
131
+ })
132
+ }
133
+
134
+ module "vault" {
135
+ count = data.coder_workspace.me.start_count
136
+ source = "registry.coder.com/modules/vault-jwt/coder"
137
+ version = "1.1.0"
138
+ agent_id = coder_agent.example.id
139
+ vault_addr = "https://vault.example.com"
140
+ vault_jwt_role = "coder" # The Vault role to use for authentication
141
+ vault_jwt_token = jwt_signed_token.vault[0].token
142
+ }
143
+ ```
144
+
145
+ #### Example Vault JWT role
146
+
147
+ ``` shell
148
+ vault write auth/JWT_MOUNT/role/workspace - << EOF
149
+ {
150
+ "user_claim": "sub",
151
+ "bound_audiences": "https://vault.example.com",
152
+ "role_type": "jwt",
153
+ "ttl": "1h",
154
+ "claim_mappings": {
155
+ "owner": "owner",
156
+ "owner_email": "owner_email",
157
+ "owner_login_type": "owner_login_type",
158
+ "owner_name": "owner_name",
159
+ "provisioner": "provisioner",
160
+ "provisioner_arch": "provisioner_arch",
161
+ "provisioner_os": "provisioner_os",
162
+ "sub": "sub",
163
+ "template": "template",
164
+ "template_name": "template_name",
165
+ "template_version": "template_version",
166
+ "workspace": "workspace",
167
+ "workspace_name": "workspace_name",
168
+ "workspace_id": "workspace_id"
169
+ }
170
+ }
171
+ EOF
172
+ ```
173
+
174
+ #### Example workspace access Vault policy
175
+
176
+ ``` tf
177
+ path "kv/data/app/coder/{{identity.entity.aliases.<MOUNT_ACCESSOR>.metadata.owner_name}}/{{identity.entity.aliases.<MOUNT_ACCESSOR>.metadata.workspace_name}}" {
178
+ capabilities = ["create", "read", "update", "delete", "list", "subscribe"]
179
+ subscribe_event_types = ["*"]
180
+ }
181
+ path "kv/metadata/app/coder/{{identity.entity.aliases.<MOUNT_ACCESSOR>.metadata.owner_name}}/{{identity.entity.aliases.<MOUNT_ACCESSOR>.metadata.workspace_name}}" {
182
+ capabilities = ["create", "read", "update", "delete", "list", "subscribe"]
183
+ subscribe_event_types = ["*"]
184
+ }
185
+ ```
0 commit comments