1import * as GCP from "@/GCP";
2import * as Test from "@/Test/Alchemy";
3import * as securityposture from "@distilled.cloud/gcp/securityposture_v1";
4import { expect } from "alchemy-test";
5import * as Effect from "effect/Effect";
6import {
7 logLevel,
8 organization,
9 runLifecycle,
10 updatedPolicySets,
11 waitUntilPostureGone,
12} from "./common.ts";
13
14const { test } = Test.make({ providers: GCP.providers() });
15
16test.provider.skipIf(!runLifecycle)(
17 "getOrganizationsLocationsPostures on a missing posture fails with a typed tag",
18 (stack) =>
19 Effect.gen(function* () {
20 yield* stack.destroy();
21
22 const error = yield* Effect.flip(
23 securityposture.getOrganizationsLocationsPostures({
24 name: `${organization}/locations/global/postures/alchemy-missing`,
25 }),
26 );
27 expect(error._tag).toEqual("NotFound");
28
29 yield* stack.destroy();
30 }).pipe(logLevel),
31 {
32 tags: ["provider:gcp", "provider:gcp:securityposture", "live"],
33 timeout: 90_000,
34 },
35);
36
37test.provider.skipIf(!runLifecycle)(
38 "create, update, and delete a posture",
39 (stack) =>
40 Effect.gen(function* () {
41 yield* stack.destroy();
42
43 const created = yield* stack.deploy(
44 Effect.gen(function* () {
45 return yield* GCP.SecurityPosture.Posture("Baseline", {
46 organization,
47 description: "staging baseline",
48 annotations: { env: "test" },
49 });
50 }),
51 );
52
53 expect(created.postureId).toEqual(expect.any(String));
54 expect(created.organization).toEqual(organization);
55 expect(created.location).toEqual("global");
56 expect(created.name).toEqual(
57 `${organization}/locations/global/postures/${created.postureId}`,
58 );
59 expect(created.state).toEqual("DRAFT");
60 expect(created.description).toEqual("staging baseline");
61 expect(created.annotations).toMatchObject({ env: "test" });
62 expect(created.policySets.length).toBeGreaterThan(0);
63 expect(created.revisionId).toEqual(expect.any(String));
64
65 const fetched = yield* securityposture.getOrganizationsLocationsPostures({
66 name: created.name,
67 });
68 expect(fetched.name).toEqual(created.name);
69 expect(fetched.annotations?.env).toEqual("test");
70 expect(fetched.annotations?.["alchemy-id"]).toEqual(expect.any(String));
71
72 const updated = yield* stack.deploy(
73 Effect.gen(function* () {
74 return yield* GCP.SecurityPosture.Posture("Baseline", {
75 organization,
76 postureId: created.postureId,
77 description: "updated baseline",
78 annotations: { env: "prod" },
79 policySets: updatedPolicySets,
80 });
81 }),
82 );
83
84 expect(updated.name).toEqual(created.name);
85 expect(updated.description).toEqual("updated baseline");
86 expect(updated.policySets.map((set) => set.policySetId)).toContain(
87 "alchemy",
88 );
89 expect(
90 updated.policySets[0]?.policies?.map((policy) => policy.policyId),
91 ).toEqual(["alchemy-sha", "alchemy-sha-2"]);
92
93 yield* stack.destroy();
94
95 const gone = yield* waitUntilPostureGone(created.name);
96 expect(gone).toEqual("gone");
97 }).pipe(logLevel),
98 {
99 tags: ["provider:gcp", "provider:gcp:securityposture", "live"],
100 timeout: 90_000,
101 },
102);