Skip to content

Commit e8e8934

Browse files
committed
feat(github-upload-public-key): customize key name
1 parent e08093c commit e8e8934

4 files changed

Lines changed: 85 additions & 14 deletions

File tree

‎registry/coder/modules/github-upload-public-key/README.md‎

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,24 @@ Templates that utilize Github External Auth can automatically ensure that the Co
1414
module "github-upload-public-key" {
1515
count = data.coder_workspace.me.start_count
1616
source = "registry.coder.com/coder/github-upload-public-key/coder"
17-
version = "1.0.32"
17+
version = "1.1.0"
1818
agent_id = coder_agent.main.id
1919
}
2020
```
2121

22+
By default, GitHub displays the uploaded key as `<Coder access URL> Workspaces`.
23+
Set `key_name` to give workspaces a recognizable name:
24+
25+
```tf
26+
module "github-upload-public-key" {
27+
count = data.coder_workspace.me.start_count
28+
source = "registry.coder.com/coder/github-upload-public-key/coder"
29+
version = "1.1.0"
30+
agent_id = coder_agent.main.id
31+
key_name = "ACME Coder Workspaces"
32+
}
33+
```
34+
2235
## Requirements
2336

2437
This module requires `curl` and `jq` to be installed inside your workspace.
@@ -47,7 +60,7 @@ data "coder_external_auth" "github" {
4760
module "github-upload-public-key" {
4861
count = data.coder_workspace.me.start_count
4962
source = "registry.coder.com/coder/github-upload-public-key/coder"
50-
version = "1.0.32"
63+
version = "1.1.0"
5164
agent_id = coder_agent.main.id
5265
external_auth_id = data.coder_external_auth.github.id
5366
}

‎registry/coder/modules/github-upload-public-key/main.test.ts‎

Lines changed: 50 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ const setupContainer = async (
3939
image = "lorello/alpine-bash",
4040
vars: Record<string, string> = {},
4141
) => {
42-
const server = setupServer();
42+
const { server, uploadedKeys } = setupServer();
4343
const state = await runTerraformApply(import.meta.dir, {
4444
agent_id: "foo",
4545
...vars,
@@ -54,12 +54,13 @@ const setupContainer = async (
5454
await removeContainer(id);
5555
});
5656

57-
return { id, instance, server };
57+
return { id, instance, server, uploadedKeys };
5858
};
5959

6060
const setupServer = () => {
61-
const fakeGithubHost = serve({
62-
fetch: (req) => {
61+
const uploadedKeys: { key: string; title: string }[] = [];
62+
const server = serve({
63+
fetch: async (req) => {
6364
const url = new URL(req.url);
6465
if (url.pathname === "/api/v2/users/me/gitsshkey") {
6566
return createJSONResponse({
@@ -69,6 +70,9 @@ const setupServer = () => {
6970

7071
if (url.pathname === "/user/keys") {
7172
if (req.method === "POST") {
73+
uploadedKeys.push(
74+
(await req.json()) as { key: string; title: string },
75+
);
7276
return createJSONResponse(
7377
{
7478
key: "created",
@@ -107,7 +111,7 @@ const setupServer = () => {
107111
port: 0,
108112
});
109113

110-
return fakeGithubHost;
114+
return { server, uploadedKeys };
111115
};
112116

113117
setDefaultTimeout(30 * 1000);
@@ -122,7 +126,7 @@ describe("github-upload-public-key", () => {
122126
});
123127

124128
it("creates new key if one does not exist", async () => {
125-
const { instance, id, server } = await setupContainer();
129+
const { instance, id, server, uploadedKeys } = await setupContainer();
126130
await writeCoder(id, "echo foo");
127131

128132
const url = server.url.toString().slice(0, -1);
@@ -140,6 +144,46 @@ describe("github-upload-public-key", () => {
140144
"Your Coder public key has been added to GitHub!",
141145
);
142146
expect(exec.exitCode).toBe(0);
147+
expect(uploadedKeys).toEqual([
148+
{
149+
key: "exists",
150+
title: `${url} Workspaces`,
151+
},
152+
]);
153+
});
154+
155+
it("uses a custom key name as data", async () => {
156+
const keyName = 'Coder "Devbox" $(touch /tmp/coder-key-name-injected)';
157+
const { instance, id, server, uploadedKeys } = await setupContainer(
158+
undefined,
159+
{ key_name: keyName },
160+
);
161+
await writeCoder(id, "echo foo");
162+
163+
const url = server.url.toString().slice(0, -1);
164+
const exec = await execContainer(id, [
165+
"env",
166+
`CODER_ACCESS_URL=${url}`,
167+
`GITHUB_API_URL=${url}`,
168+
"CODER_OWNER_SESSION_TOKEN=foo",
169+
"CODER_EXTERNAL_AUTH_ID=github",
170+
"bash",
171+
"-c",
172+
instance.script,
173+
]);
174+
expect(exec.stdout).toContain(
175+
"Your Coder public key has been added to GitHub!",
176+
);
177+
expect(exec.exitCode).toBe(0);
178+
expect(uploadedKeys).toEqual([{ key: "exists", title: keyName }]);
179+
180+
const injectionCheck = await execContainer(id, [
181+
"test",
182+
"!",
183+
"-e",
184+
"/tmp/coder-key-name-injected",
185+
]);
186+
expect(injectionCheck.exitCode).toBe(0);
143187
});
144188

145189
it("does nothing if one already exists", async () => {

‎registry/coder/modules/github-upload-public-key/main.tf‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@ variable "github_api_url" {
2626
default = "https://api.github.com"
2727
}
2828

29+
variable "key_name" {
30+
description = "The title assigned to the uploaded SSH key in GitHub. Defaults to '<Coder access URL> Workspaces'."
31+
type = string
32+
default = null
33+
}
34+
2935
data "coder_workspace" "me" {}
3036
data "coder_workspace_owner" "me" {}
3137

@@ -36,8 +42,9 @@ resource "coder_script" "github_upload_public_key" {
3642
CODER_ACCESS_URL : data.coder_workspace.me.access_url,
3743
CODER_EXTERNAL_AUTH_ID : var.external_auth_id,
3844
GITHUB_API_URL : var.github_api_url,
45+
CODER_PUBLIC_KEY_NAME_B64 : base64encode(var.key_name == null ? "" : var.key_name),
3946
})
4047
display_name = "Github Upload Public Key"
4148
icon = "/icon/github.svg"
4249
run_on_start = true
43-
}
50+
}

‎registry/coder/modules/github-upload-public-key/run.sh‎

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ if [ -z "$GITHUB_API_URL" ]; then
3333
fi
3434

3535
echo "Fetching GitHub token..."
36-
GITHUB_TOKEN=$(coder external-auth access-token $CODER_EXTERNAL_AUTH_ID)
36+
GITHUB_TOKEN=$(coder external-auth access-token "$CODER_EXTERNAL_AUTH_ID")
3737
if [ $? -ne 0 ]; then
3838
printf "Authenticate with Github to automatically upload Coder public key:\n$GITHUB_TOKEN\n"
3939
exit 1
@@ -68,7 +68,7 @@ GITHUB_KEYS_RESPONSE=$(
6868
-H "Accept: application/vnd.github+json" \
6969
-H "Authorization: Bearer $GITHUB_TOKEN" \
7070
-H "X-GitHub-Api-Version: 2022-11-28" \
71-
$GITHUB_API_URL/user/keys
71+
"$GITHUB_API_URL/user/keys"
7272
)
7373
GITHUB_KEYS_RESPONSE_STATUS=$(tail -n1 <<< "$GITHUB_KEYS_RESPONSE")
7474
GITHUB_KEYS_RESPONSE_BODY=$(sed \$d <<< "$GITHUB_KEYS_RESPONSE")
@@ -87,16 +87,23 @@ if [ "$PUBLIC_KEY" = "$GITHUB_MATCH" ]; then
8787
fi
8888

8989
echo "Your Coder public key is not in GitHub. Adding it now..."
90-
CODER_PUBLIC_KEY_NAME="$CODER_ACCESS_URL Workspaces"
90+
CODER_PUBLIC_KEY_NAME=$(jq -rn --arg value "${CODER_PUBLIC_KEY_NAME_B64}" '$value | @base64d')
91+
if [ -z "$CODER_PUBLIC_KEY_NAME" ]; then
92+
CODER_PUBLIC_KEY_NAME="$CODER_ACCESS_URL Workspaces"
93+
fi
94+
UPLOAD_BODY=$(jq -cn \
95+
--arg title "$CODER_PUBLIC_KEY_NAME" \
96+
--arg key "$PUBLIC_KEY" \
97+
'{title: $title, key: $key}')
9198
UPLOAD_RESPONSE=$(
9299
curl -L -s \
93100
-X POST \
94101
-w "\n%%{http_code}" \
95102
-H "Accept: application/vnd.github+json" \
96103
-H "Authorization: Bearer $GITHUB_TOKEN" \
97104
-H "X-GitHub-Api-Version: 2022-11-28" \
98-
$GITHUB_API_URL/user/keys \
99-
-d "{\"title\":\"$CODER_PUBLIC_KEY_NAME\",\"key\":\"$PUBLIC_KEY\"}"
105+
"$GITHUB_API_URL/user/keys" \
106+
--data "$UPLOAD_BODY"
100107
)
101108
UPLOAD_RESPONSE_STATUS=$(tail -n1 <<< "$UPLOAD_RESPONSE")
102109
UPLOAD_RESPONSE_BODY=$(sed \$d <<< "$UPLOAD_RESPONSE")

0 commit comments

Comments
 (0)