Open History to see the last commit
1import { generateKeyPair, SignJWT } from "jose";
2import { expect, it, vi } from "vite-plus/test";
3import { authorizeCacheWrite, authorizeTelemetry } from "./telemetryAuth.ts";
4import { authorize, ISSUER } from "../vendor/vite-plus-remote-cache-cloudflare/src/auth.ts";
5
6it("accepts signed stacked PR telemetry without granting cache writes or trusting another repository", async () => {
7 vi.useFakeTimers({ toFake: ["Date"] });
8 vi.setSystemTime(1_000_000);
9 try {
10 const { publicKey, privateKey } = await generateKeyPair("RS256");
11 const scope = {
12 scope_id: "t3code",
13 endpoint: "https://cache.example/projects/t3code",
14 repository_id: "123",
15 repository_owner_id: "456",
16 branch: "refs/heads/main",
17 policy_version: 1,
18 writes_enabled: 0,
19 pull_requests: 0,
20 };
21 const token = async (repository_id: string, audience = scope.endpoint) =>
22 new SignJWT({
23 repository_id,
24 repository_owner_id: "456",
25 repository_visibility: "public",
26 event_name: "pull_request",
27 ref: "refs/pull/42/merge",
28 ref_type: "branch",
29 base_ref: "feature/parent",
30 actor: "maria",
31 })
32 .setProtectedHeader({ alg: "RS256", kid: "test" })
33 .setIssuer(ISSUER)
34 .setAudience(audience)
35 .setIssuedAt(1000)
36 .setNotBefore(1000)
37 .setExpirationTime(1600)
38 .sign(privateKey);
39 const request = (token: string) =>
40 new Request(scope.endpoint, { headers: { Authorization: `Bearer ${token}` } });
41 const keys = async () => publicKey;
42 const valid = request(await token("123"));
43 const allowed = {
44 ...scope,
45 writes_enabled: 1,
46 pull_requests: 1,
47 branch: "refs/heads/feature/parent",
48 };
49 expect(
50 await authorizeCacheWrite(
51 request(await token("123", "https://ci-reader:secret@cache.example/projects/t3code")),
52 allowed,
53 keys,
54 ),
55 ).toMatchObject({ repository_id: "123" });
56 await expect(
57 authorizeCacheWrite(
58 request(await token("123", "https://ci-reader:secret@other.example/projects/t3code")),
59 allowed,
60 keys,
61 ),
62 ).rejects.toMatchObject({ status: 403 });
63 expect(await authorizeTelemetry(valid, scope, keys)).toBe("github/maria");
64 await expect(
65 authorizeCacheWrite(valid, { ...allowed, pull_requests: 0 }, keys),
66 ).rejects.toMatchObject({ status: 403 });
67 await expect(
68 authorizeCacheWrite(valid, { ...allowed, branch: "refs/heads/main" }, keys),
69 ).rejects.toMatchObject({ status: 403 });
70 await expect(authorize(valid, scope, keys)).rejects.toMatchObject({ status: 403 });
71 await expect(authorizeCacheWrite(valid, scope, keys)).rejects.toMatchObject({ status: 403 });
72 expect(await authorizeCacheWrite(valid, allowed, keys)).toMatchObject({
73 repository_id: "123",
74 });
75 await expect(
76 authorizeCacheWrite(request(await token("another-repo")), allowed, keys),
77 ).rejects.toMatchObject({ status: 403 });
78 await expect(
79 authorizeTelemetry(request(await token("another-repo")), scope, keys),
80 ).rejects.toMatchObject({ status: 403 });
81 } finally {
82 vi.useRealTimers();
83 }
84});