Skip to content

Commit 970d792

Browse files
committed
chore: enable SBOM and containerd support in Docker builds
Added SBOM (Software Bill of Materials) generation during Docker build to enhance traceability. Refer to Docker documentation on SBOM: docs.docker.com/build/metadata/attestations/sbom Updated Docker build scripts to use BuildKit for provenance and SBOM support: docs.docker.com/build/metadata/attestations Configured Docker daemon to support the Containerd snapshotter feature to improve performance: docs.docker.com/engine/storage/containerd
1 parent 26832cb commit 970d792

File tree

62 files changed

+169
-179
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+169
-179
lines changed

.github/workflows/ci.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ jobs:
259259
- name: Install Protoc
260260
run: |
261261
mkdir -p /tmp/proto
262-
pushd /tmp/proto
262+
build /tmp/proto
263263
curl -L -o protoc.zip https://github.com/protocolbuffers/protobuf/releases/download/v23.4/protoc-23.4-linux-x86_64.zip
264264
unzip protoc.zip
265265
cp -r ./bin/* /usr/local/bin

.github/workflows/release.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,7 @@ jobs:
361361
file: scripts/Dockerfile.base
362362
platforms: linux/amd64,linux/arm64,linux/arm/v7
363363
provenance: true
364+
sbom: true
364365
pull: true
365366
no-cache: true
366367
push: true
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
{
2-
"registry-mirrors": ["https://mirror.gcr.io"]
2+
"registry-mirrors": ["https://mirror.gcr.io"],
3+
"features": {
4+
"containerd-snapshotter": true
5+
}
36
}

dogfood/contents/zed/main.tf

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ data "coder_workspace" "me" {}
2020

2121
resource "coder_app" "zed" {
2222
agent_id = var.agent_id
23-
display_name = "Zed Editor"
23+
display_name = "Zed"
2424
slug = "zed"
2525
icon = "/icon/zed.svg"
2626
external = true
27-
url = "zed://ssh/coder.${lower(data.coder_workspace.me.name)}/${var.folder}"
27+
url = "zed://ssh/${lower(data.coder_workspace.me.name)}.coder/${var.folder}"
2828
}

enterprise/coderd/groups.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,8 +167,6 @@ func (api *API) patchGroup(rw http.ResponseWriter, r *http.Request) {
167167
})
168168
return
169169
}
170-
// TODO: It would be nice to enforce this at the schema level
171-
// but unfortunately our org_members table does not have an ID.
172170
_, err := database.ExpectOne(api.Database.OrganizationMembers(ctx, database.OrganizationMembersParams{
173171
OrganizationID: group.OrganizationID,
174172
UserID: uuid.MustParse(id),

scripts/build_docker.sh

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,9 +122,11 @@ export DOCKER_BUILDKIT=1
122122
base_image="$DEFAULT_BASE"
123123
if [[ "$build_base" != "" ]]; then
124124
log "--- Building base Docker image for $arch ($build_base)"
125-
docker build \
125+
docker buildx build \
126126
--platform "$arch" \
127127
--tag "$build_base" \
128+
--provenance true \
129+
--sbom true \
128130
--no-cache \
129131
-f Dockerfile.base \
130132
. 1>&2

site/e2e/constants.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@ export const defaultPassword = "SomeSecurePassword!";
2020

2121
// Credentials for users
2222
export const users = {
23-
admin: {
24-
username: "admin",
23+
owner: {
24+
username: "owner",
2525
password: defaultPassword,
26-
email: "admin@coder.com",
26+
email: "owner@coder.com",
2727
},
2828
templateAdmin: {
2929
username: "template-admin",
@@ -41,7 +41,7 @@ export const users = {
4141
username: "auditor",
4242
password: defaultPassword,
4343
email: "auditor@coder.com",
44-
roles: ["Template Admin", "Auditor"],
44+
roles: ["Auditor"],
4545
},
4646
member: {
4747
username: "member",

site/e2e/helpers.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ export type LoginOptions = {
6767
password: string;
6868
};
6969

70-
export async function login(page: Page, options: LoginOptions = users.admin) {
70+
export async function login(page: Page, options: LoginOptions = users.owner) {
7171
const ctx = page.context();
7272
// biome-ignore lint/suspicious/noExplicitAny: reset the current user
7373
(ctx as any)[Symbol.for("currentUser")] = undefined;

site/e2e/setup/addUsersAndLicense.spec.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,16 @@ test("setup deployment", async ({ page }) => {
1616
}
1717

1818
// Setup first user
19-
await page.getByLabel(Language.emailLabel).fill(users.admin.email);
20-
await page.getByLabel(Language.passwordLabel).fill(users.admin.password);
19+
await page.getByLabel(Language.emailLabel).fill(users.owner.email);
20+
await page.getByLabel(Language.passwordLabel).fill(users.owner.password);
2121
await page.getByTestId("create").click();
2222

2323
await expectUrl(page).toHavePathName("/workspaces");
2424
await page.getByTestId("button-select-template").isVisible();
2525

2626
for (const user of Object.values(users)) {
2727
// Already created as first user
28-
if (user.username === "admin") {
28+
if (user.username === "owner") {
2929
continue;
3030
}
3131

site/e2e/tests/auditLogs.spec.ts

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,62 +13,63 @@ test.describe.configure({ mode: "parallel" });
1313

1414
test.beforeEach(async ({ page }) => {
1515
beforeCoderTest(page);
16-
await login(page, users.auditor);
1716
});
1817

19-
async function resetSearch(page: Page) {
18+
async function resetSearch(page: Page, username: string) {
2019
const clearButton = page.getByLabel("Clear search");
2120
if (await clearButton.isVisible()) {
2221
await clearButton.click();
2322
}
2423

2524
// Filter by the auditor test user to prevent race conditions
26-
const user = currentUser(page);
2725
await expect(page.getByText("All users")).toBeVisible();
28-
await page.getByPlaceholder("Search...").fill(`username:${user.username}`);
26+
await page.getByPlaceholder("Search...").fill(`username:${username}`);
2927
await expect(page.getByText("All users")).not.toBeVisible();
3028
}
3129

3230
test("logins are logged", async ({ page }) => {
3331
requiresLicense();
3432

3533
// Go to the audit history
34+
await login(page, users.auditor);
3635
await page.goto("/audit");
36+
const username = users.auditor.username;
3737

3838
const user = currentUser(page);
39-
const loginMessage = `${user.username} logged in`;
39+
const loginMessage = `${username} logged in`;
4040
// Make sure those things we did all actually show up
41-
await resetSearch(page);
41+
await resetSearch(page, username);
4242
await expect(page.getByText(loginMessage).first()).toBeVisible();
4343
});
4444

4545
test("creating templates and workspaces is logged", async ({ page }) => {
4646
requiresLicense();
4747

4848
// Do some stuff that should show up in the audit logs
49+
await login(page, users.templateAdmin);
50+
const username = users.templateAdmin.username;
4951
const templateName = await createTemplate(page);
5052
const workspaceName = await createWorkspace(page, templateName);
5153

5254
// Go to the audit history
55+
await login(page, users.auditor);
5356
await page.goto("/audit");
5457

55-
const user = currentUser(page);
56-
5758
// Make sure those things we did all actually show up
58-
await resetSearch(page);
59+
await resetSearch(page, username);
5960
await expect(
60-
page.getByText(`${user.username} created template ${templateName}`),
61+
page.getByText(`${username} created template ${templateName}`),
6162
).toBeVisible();
6263
await expect(
63-
page.getByText(`${user.username} created workspace ${workspaceName}`),
64+
page.getByText(`${username} created workspace ${workspaceName}`),
6465
).toBeVisible();
6566
await expect(
66-
page.getByText(`${user.username} started workspace ${workspaceName}`),
67+
page.getByText(`${username} started workspace ${workspaceName}`),
6768
).toBeVisible();
6869

6970
// Make sure we can inspect the details of the log item
7071
const createdWorkspace = page.locator(".MuiTableRow-root", {
71-
hasText: `${user.username} created workspace ${workspaceName}`,
72+
hasText: `${username} created workspace ${workspaceName}`,
7273
});
7374
await createdWorkspace.getByLabel("open-dropdown").click();
7475
await expect(
@@ -83,18 +84,19 @@ test("inspecting and filtering audit logs", async ({ page }) => {
8384
requiresLicense();
8485

8586
// Do some stuff that should show up in the audit logs
87+
await login(page, users.templateAdmin);
88+
const username = users.templateAdmin.username;
8689
const templateName = await createTemplate(page);
8790
const workspaceName = await createWorkspace(page, templateName);
8891

8992
// Go to the audit history
93+
await login(page, users.auditor);
9094
await page.goto("/audit");
91-
92-
const user = currentUser(page);
93-
const loginMessage = `${user.username} logged in`;
94-
const startedWorkspaceMessage = `${user.username} started workspace ${workspaceName}`;
95+
const loginMessage = `${username} logged in`;
96+
const startedWorkspaceMessage = `${username} started workspace ${workspaceName}`;
9597

9698
// Filter by resource type
97-
await resetSearch(page);
99+
await resetSearch(page, username);
98100
await page.getByText("All resource types").click();
99101
const workspaceBuildsOption = page.getByText("Workspace Build");
100102
await workspaceBuildsOption.scrollIntoViewIfNeeded({ timeout: 5000 });
@@ -107,7 +109,7 @@ test("inspecting and filtering audit logs", async ({ page }) => {
107109
await expect(page.getByText("All resource types")).toBeVisible();
108110

109111
// Filter by action type
110-
await resetSearch(page);
112+
await resetSearch(page, username);
111113
await page.getByText("All actions").click();
112114
await page.getByText("Login", { exact: true }).click();
113115
// Logins should be visible

0 commit comments

Comments
 (0)