@microagi/alchemy-gcp 0.7.0 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +39 -0
- package/lib/ArtifactRegistry/Operations.d.ts +2 -2
- package/lib/ArtifactRegistry/Operations.d.ts.map +1 -1
- package/lib/ArtifactRegistry/Repository.d.ts +1 -1
- package/lib/ArtifactRegistry/Validation.d.ts.map +1 -1
- package/lib/Auth/AuthProvider.d.ts.map +1 -1
- package/lib/Auth/AuthProvider.js.map +1 -1
- package/lib/Auth/Credentials.d.ts +1 -1
- package/lib/Auth/Credentials.d.ts.map +1 -1
- package/lib/CloudResourceManager/Project.d.ts +1 -1
- package/lib/CloudResourceManager/ProjectIamMember.d.ts.map +1 -1
- package/lib/Compute/Address.d.ts +1 -1
- package/lib/Compute/Firewall.d.ts +1 -1
- package/lib/Compute/ForwardingRule.d.ts +1 -1
- package/lib/Compute/GlobalAddress.d.ts +1 -1
- package/lib/Compute/Network.d.ts +1 -1
- package/lib/Compute/Network.d.ts.map +1 -1
- package/lib/Compute/Operations.d.ts +4 -4
- package/lib/Compute/Operations.d.ts.map +1 -1
- package/lib/Compute/Subnetwork.d.ts +1 -1
- package/lib/Compute/SubnetworkIamMember.d.ts.map +1 -1
- package/lib/Container/Cluster.d.ts +1 -1
- package/lib/Container/NodePool.d.ts +11 -1
- package/lib/Container/NodePool.d.ts.map +1 -1
- package/lib/Container/NodePool.js +4 -0
- package/lib/Container/NodePool.js.map +1 -1
- package/lib/Container/Operations.d.ts +2 -2
- package/lib/Container/Operations.d.ts.map +1 -1
- package/lib/Iam/ServiceAccount.d.ts +104 -0
- package/lib/Iam/ServiceAccount.d.ts.map +1 -0
- package/lib/Iam/ServiceAccount.js +255 -0
- package/lib/Iam/ServiceAccount.js.map +1 -0
- package/lib/Iam/ServiceAccountIamMember.d.ts +49 -0
- package/lib/Iam/ServiceAccountIamMember.d.ts.map +1 -0
- package/lib/Iam/ServiceAccountIamMember.js +50 -0
- package/lib/Iam/ServiceAccountIamMember.js.map +1 -0
- package/lib/Iam/ServiceAccountKey.d.ts +72 -0
- package/lib/Iam/ServiceAccountKey.d.ts.map +1 -0
- package/lib/Iam/ServiceAccountKey.js +164 -0
- package/lib/Iam/ServiceAccountKey.js.map +1 -0
- package/lib/Iam/index.d.ts +6 -0
- package/lib/Iam/index.d.ts.map +1 -0
- package/lib/Iam/index.js +4 -0
- package/lib/Iam/index.js.map +1 -0
- package/lib/Kubernetes/KubernetesManifest.d.ts +1 -1
- package/lib/Kubernetes/Secret.d.ts +1 -1
- package/lib/Kubernetes/client.d.ts.map +1 -1
- package/lib/Kubernetes/connection.d.ts.map +1 -1
- package/lib/ManagedLustre/Instance.d.ts +1 -1
- package/lib/Providers.d.ts +1 -1
- package/lib/Providers.d.ts.map +1 -1
- package/lib/Providers.js +7 -1
- package/lib/Providers.js.map +1 -1
- package/lib/Run/IamMember.d.ts.map +1 -1
- package/lib/Run/IamSync.d.ts.map +1 -1
- package/lib/Run/Job.d.ts +1 -1
- package/lib/Run/Operations.d.ts +2 -2
- package/lib/Run/Operations.d.ts.map +1 -1
- package/lib/Run/Service.d.ts +1 -1
- package/lib/Run/Validation.d.ts.map +1 -1
- package/lib/Sqladmin/Instance.d.ts +1 -1
- package/lib/Sqladmin/Operations.d.ts +2 -2
- package/lib/Sqladmin/Operations.d.ts.map +1 -1
- package/lib/Sqladmin/Types.d.ts.map +1 -1
- package/lib/Sqladmin/Validation.d.ts.map +1 -1
- package/lib/Storage/Bucket.d.ts +117 -0
- package/lib/Storage/Bucket.d.ts.map +1 -0
- package/lib/Storage/Bucket.js +239 -0
- package/lib/Storage/Bucket.js.map +1 -0
- package/lib/Storage/BucketIamMember.d.ts +29 -0
- package/lib/Storage/BucketIamMember.d.ts.map +1 -0
- package/lib/Storage/BucketIamMember.js +26 -0
- package/lib/Storage/BucketIamMember.js.map +1 -0
- package/lib/Storage/index.d.ts +4 -0
- package/lib/Storage/index.d.ts.map +1 -0
- package/lib/Storage/index.js +3 -0
- package/lib/Storage/index.js.map +1 -0
- package/lib/Tags.d.ts.map +1 -1
- package/lib/index.d.ts +2 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -0
- package/lib/index.js.map +1 -1
- package/package.json +3 -3
- package/src/Container/NodePool.ts +12 -0
- package/src/Iam/ServiceAccount.ts +450 -0
- package/src/Iam/ServiceAccountIamMember.ts +56 -0
- package/src/Iam/ServiceAccountKey.ts +284 -0
- package/src/Iam/index.ts +8 -0
- package/src/Providers.ts +18 -0
- package/src/Storage/Bucket.ts +439 -0
- package/src/Storage/BucketIamMember.ts +33 -0
- package/src/Storage/index.ts +10 -0
- package/src/index.ts +2 -0
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
import { ConfigError } from "@distilled.cloud/gcp";
|
|
2
|
+
import * as iam from "@distilled.cloud/gcp/unstable/iam-v1";
|
|
3
|
+
import { Resource } from "alchemy";
|
|
4
|
+
import { Unowned } from "alchemy/AdoptPolicy";
|
|
5
|
+
import { isResolved } from "alchemy/Diff";
|
|
6
|
+
import * as Provider from "alchemy/Provider";
|
|
7
|
+
import { diffTags } from "alchemy/Tags";
|
|
8
|
+
import * as Duration from "effect/Duration";
|
|
9
|
+
import * as Effect from "effect/Effect";
|
|
10
|
+
import * as Schedule from "effect/Schedule";
|
|
11
|
+
import { descriptionHasAlchemyMarker, gcpAlchemyDescription, stripAlchemyMarker, } from "../Tags.js";
|
|
12
|
+
export const ServiceAccount = Resource("GCP.ServiceAccount");
|
|
13
|
+
const toAttributes = (sa) => {
|
|
14
|
+
const accountId = (sa.email ?? "").split("@")[0];
|
|
15
|
+
return {
|
|
16
|
+
name: sa.name ?? "",
|
|
17
|
+
email: sa.email ?? "",
|
|
18
|
+
uniqueId: sa.uniqueId ?? "",
|
|
19
|
+
projectId: sa.projectId ?? "",
|
|
20
|
+
accountId,
|
|
21
|
+
displayName: sa.displayName,
|
|
22
|
+
description: stripAlchemyMarker(sa.description),
|
|
23
|
+
disabled: sa.disabled ?? false,
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
export const ServiceAccountProvider = () => Provider.effect(ServiceAccount, Effect.gen(function* () {
|
|
27
|
+
const getProjectsServiceAccounts = yield* iam.getProjectsServiceAccounts;
|
|
28
|
+
const createProjectsServiceAccounts = yield* iam.createProjectsServiceAccounts;
|
|
29
|
+
const patchProjectsServiceAccounts = yield* iam.patchProjectsServiceAccounts;
|
|
30
|
+
const deleteProjectsServiceAccounts = yield* iam.deleteProjectsServiceAccounts;
|
|
31
|
+
const listProjectsServiceAccounts = yield* iam.listProjectsServiceAccounts;
|
|
32
|
+
const getIamPolicyProjectsServiceAccounts = yield* iam.getIamPolicyProjectsServiceAccounts;
|
|
33
|
+
const setIamPolicyProjectsServiceAccounts = yield* iam.setIamPolicyProjectsServiceAccounts;
|
|
34
|
+
const resourceName = (projectId, accountId) => `projects/${projectId}/serviceAccounts/${accountId}`;
|
|
35
|
+
const observeServiceAccount = (projectId, accountId) => getProjectsServiceAccounts({
|
|
36
|
+
name: resourceName(projectId, accountId),
|
|
37
|
+
}).pipe(
|
|
38
|
+
// GSAs that don't exist OR that the caller can't see both
|
|
39
|
+
// collapse to "absent" — same 403→missing pattern as the
|
|
40
|
+
// project observer.
|
|
41
|
+
Effect.catchTag("NotFound", () => Effect.succeed(undefined)), Effect.catchTag("Forbidden", () => Effect.succeed(undefined)));
|
|
42
|
+
const requireServiceAccount = (projectId, accountId, context) => observeServiceAccount(projectId, accountId).pipe(Effect.flatMap((sa) => sa
|
|
43
|
+
? Effect.succeed(sa)
|
|
44
|
+
: Effect.fail(new ConfigError({
|
|
45
|
+
message: `ServiceAccount ${accountId} in project ${projectId} ${context}.`,
|
|
46
|
+
}))));
|
|
47
|
+
// List-page scan for cold recovery. Alchemy marker in the
|
|
48
|
+
// description field identifies our GSAs; the page boundary is
|
|
49
|
+
// arbitrary — we still need to page through to find any marker
|
|
50
|
+
// that happens to fall past the first page.
|
|
51
|
+
const findByAlchemyMarker = Effect.fn(function* (id, projectId) {
|
|
52
|
+
let pageToken;
|
|
53
|
+
// Up to 100 pages × 100 items per page = 10000 GSAs; well past
|
|
54
|
+
// any realistic project size. If we ever exceed that we should
|
|
55
|
+
// cap and warn rather than silently miss matches.
|
|
56
|
+
for (let i = 0; i < 100; i++) {
|
|
57
|
+
const page = yield* listProjectsServiceAccounts({
|
|
58
|
+
name: `projects/${projectId}`,
|
|
59
|
+
...(pageToken ? { pageToken } : {}),
|
|
60
|
+
pageSize: 100,
|
|
61
|
+
});
|
|
62
|
+
for (const sa of page.accounts ?? []) {
|
|
63
|
+
if (yield* descriptionHasAlchemyMarker(id, sa.description)) {
|
|
64
|
+
return sa;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
pageToken = page.nextPageToken;
|
|
68
|
+
if (!pageToken)
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
return undefined;
|
|
72
|
+
});
|
|
73
|
+
// Sync mutable fields: displayName + description. Both use
|
|
74
|
+
// `updateMask` so we only PATCH what actually changed. Diff
|
|
75
|
+
// against OBSERVED state, not `olds`, so adoption converges
|
|
76
|
+
// correctly when a foreign description is on the GSA.
|
|
77
|
+
const syncMutable = Effect.fn(function* (observed, desired) {
|
|
78
|
+
const updateMaskFields = [];
|
|
79
|
+
if (desired.displayName !== observed.displayName) {
|
|
80
|
+
updateMaskFields.push("display_name");
|
|
81
|
+
}
|
|
82
|
+
const descDiff = diffTags({ description: observed.description ?? "" }, { description: desired.descriptionWithMarker });
|
|
83
|
+
if (descDiff.removed.length > 0 ||
|
|
84
|
+
descDiff.upsert.length > 0) {
|
|
85
|
+
updateMaskFields.push("description");
|
|
86
|
+
}
|
|
87
|
+
if (updateMaskFields.length === 0)
|
|
88
|
+
return observed;
|
|
89
|
+
return yield* patchProjectsServiceAccounts({
|
|
90
|
+
name: observed.name,
|
|
91
|
+
body: {
|
|
92
|
+
updateMask: updateMaskFields.join(","),
|
|
93
|
+
serviceAccount: {
|
|
94
|
+
displayName: desired.displayName,
|
|
95
|
+
description: desired.descriptionWithMarker,
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
// Apply merged IAM bindings as a single setIamPolicy. Same
|
|
101
|
+
// foreign-binding preservation + etag-retry pattern as the
|
|
102
|
+
// Project's `syncIam` — see `src/CloudResourceManager/Project.ts:421-474`.
|
|
103
|
+
const syncIam = (args) => Effect.gen(function* () {
|
|
104
|
+
const desiredByRole = new Map();
|
|
105
|
+
for (const b of args.bindings) {
|
|
106
|
+
for (const ib of b.data.iamBindings) {
|
|
107
|
+
const set = desiredByRole.get(ib.role) ?? new Set();
|
|
108
|
+
for (const m of ib.members)
|
|
109
|
+
set.add(m);
|
|
110
|
+
desiredByRole.set(ib.role, set);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (desiredByRole.size === 0)
|
|
114
|
+
return;
|
|
115
|
+
const current = yield* getIamPolicyProjectsServiceAccounts({
|
|
116
|
+
resource: args.resourceName,
|
|
117
|
+
"options.requestedPolicyVersion": 3,
|
|
118
|
+
});
|
|
119
|
+
const existingBindings = (current.bindings ?? []).map((b) => ({
|
|
120
|
+
...b,
|
|
121
|
+
members: [...(b.members ?? [])],
|
|
122
|
+
}));
|
|
123
|
+
let mutated = false;
|
|
124
|
+
for (const [role, members] of desiredByRole) {
|
|
125
|
+
let existing = existingBindings.find((b) => b.role === role && !b.condition);
|
|
126
|
+
if (!existing) {
|
|
127
|
+
existing = { role, members: [] };
|
|
128
|
+
existingBindings.push(existing);
|
|
129
|
+
}
|
|
130
|
+
const merged = new Set([...(existing.members ?? []), ...members]);
|
|
131
|
+
if (merged.size !== (existing.members?.length ?? 0))
|
|
132
|
+
mutated = true;
|
|
133
|
+
existing.members = [...merged];
|
|
134
|
+
}
|
|
135
|
+
if (!mutated)
|
|
136
|
+
return;
|
|
137
|
+
yield* setIamPolicyProjectsServiceAccounts({
|
|
138
|
+
resource: args.resourceName,
|
|
139
|
+
body: {
|
|
140
|
+
policy: { ...current, bindings: existingBindings, version: 3 },
|
|
141
|
+
},
|
|
142
|
+
});
|
|
143
|
+
}).pipe(Effect.retry({
|
|
144
|
+
schedule: Schedule.exponential(Duration.seconds(2)).pipe(Schedule.both(Schedule.recurs(8))),
|
|
145
|
+
}));
|
|
146
|
+
return {
|
|
147
|
+
// Stable identity: accountId + project; both immutable; either
|
|
148
|
+
// change → replace. The server-assigned uniqueId is also stable
|
|
149
|
+
// for the lifetime of the GSA (re-create gets a different one).
|
|
150
|
+
stables: ["accountId", "projectId", "uniqueId", "name", "email"],
|
|
151
|
+
diff: Effect.fn(function* ({ id, news, olds = {}, output }) {
|
|
152
|
+
if (!isResolved(news))
|
|
153
|
+
return undefined;
|
|
154
|
+
// Replace ONLY when a prior identity is actually known AND differs.
|
|
155
|
+
// A partial/adopted state can lack the persisted accountId/projectId
|
|
156
|
+
// (an adoption that never persisted full Attributes leaves
|
|
157
|
+
// output.projectId === "" / undefined). Treating that "unknown" as a
|
|
158
|
+
// replace spuriously deletes+recreates a live, correctly-named GSA
|
|
159
|
+
// (and churns its uniqueId → breaks Workload-Identity bindings).
|
|
160
|
+
// When the prior identity is absent, fall through to reconcile, which
|
|
161
|
+
// observes the live resource and re-persists its Attributes. The
|
|
162
|
+
// truthiness guard covers both `undefined` and the `""` toAttributes
|
|
163
|
+
// default; a genuine accountId/project change still has a non-empty
|
|
164
|
+
// prior value to compare against, so real replacements are unaffected.
|
|
165
|
+
// `||` (not `??`): toAttributes persists `accountId`/`projectId` as
|
|
166
|
+
// `""` when absent, and an empty string must fall through to `olds`
|
|
167
|
+
// (the previous Props) rather than mask it — otherwise a genuine
|
|
168
|
+
// identity change with an empty `output` but a populated `olds` would
|
|
169
|
+
// skip the replace and adopt/create at the new identity without
|
|
170
|
+
// deleting the old GSA.
|
|
171
|
+
const priorAccount = output?.accountId || olds.accountId;
|
|
172
|
+
const priorProject = output?.projectId || olds.project;
|
|
173
|
+
if ((priorAccount && news.accountId !== priorAccount) ||
|
|
174
|
+
(priorProject && news.project !== priorProject)) {
|
|
175
|
+
return { action: "replace" };
|
|
176
|
+
}
|
|
177
|
+
return undefined;
|
|
178
|
+
}),
|
|
179
|
+
reconcile: Effect.fn(function* ({ id, news, bindings }) {
|
|
180
|
+
const descriptionWithMarker = yield* gcpAlchemyDescription(id, news.description);
|
|
181
|
+
// 1. Observe — cloud state is authoritative. A second
|
|
182
|
+
// scan-by-marker covers the cold-recovery case where
|
|
183
|
+
// persisted `output`/`olds` lost the uniqueId after
|
|
184
|
+
// state loss. We prefer the direct-by-name probe first
|
|
185
|
+
// (cheap) and fall back to the scan only when direct
|
|
186
|
+
// observation returned `undefined`.
|
|
187
|
+
let observed = yield* observeServiceAccount(news.project, news.accountId);
|
|
188
|
+
if (!observed) {
|
|
189
|
+
observed = yield* findByAlchemyMarker(id, news.project);
|
|
190
|
+
}
|
|
191
|
+
// 2. Ensure — create if missing. createProjectsServiceAccounts
|
|
192
|
+
// is synchronous (returns the SA, not an LRO). Conflict
|
|
193
|
+
// covers a peer reconciler race — re-observe.
|
|
194
|
+
if (!observed) {
|
|
195
|
+
observed = yield* createProjectsServiceAccounts({
|
|
196
|
+
name: `projects/${news.project}`,
|
|
197
|
+
body: {
|
|
198
|
+
accountId: news.accountId,
|
|
199
|
+
serviceAccount: {
|
|
200
|
+
displayName: news.displayName,
|
|
201
|
+
description: descriptionWithMarker,
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
}).pipe(Effect.catchTag("Conflict", () => Effect.succeed(undefined)));
|
|
205
|
+
if (!observed) {
|
|
206
|
+
observed = yield* requireServiceAccount(news.project, news.accountId, "did not appear after create");
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
// 3. Sync mutable fields against OBSERVED state.
|
|
210
|
+
const synced = yield* syncMutable(observed, {
|
|
211
|
+
displayName: news.displayName ?? observed.displayName,
|
|
212
|
+
descriptionWithMarker,
|
|
213
|
+
descriptionUserOnly: news.description,
|
|
214
|
+
});
|
|
215
|
+
// 4. Sync IAM bindings (Workload Identity, impersonators, …).
|
|
216
|
+
// Single setIamPolicy on the GSA with merged bindings;
|
|
217
|
+
// foreign roles preserved. Etag-retried internally.
|
|
218
|
+
yield* syncIam({
|
|
219
|
+
resourceName: synced.name,
|
|
220
|
+
bindings,
|
|
221
|
+
});
|
|
222
|
+
return toAttributes(synced);
|
|
223
|
+
}),
|
|
224
|
+
delete: Effect.fn(function* ({ output }) {
|
|
225
|
+
// Synchronous delete — Empty response, no LRO. NotFound
|
|
226
|
+
// means the GSA was already deleted (or never existed in our
|
|
227
|
+
// scope); both are idempotent successes.
|
|
228
|
+
yield* deleteProjectsServiceAccounts({
|
|
229
|
+
name: output.name,
|
|
230
|
+
}).pipe(Effect.catchTag("NotFound", () => Effect.void), Effect.catchTag("Forbidden", () => Effect.void));
|
|
231
|
+
}),
|
|
232
|
+
read: Effect.fn(function* ({ id, output, olds }) {
|
|
233
|
+
// Direct-by-name probe when we have any handle on the
|
|
234
|
+
// accountId. Falls back to a project-wide scan-by-marker
|
|
235
|
+
// for cold recovery after state loss.
|
|
236
|
+
const accountId = output?.accountId ?? olds?.accountId;
|
|
237
|
+
const projectId = output?.projectId ?? olds?.project;
|
|
238
|
+
let observed;
|
|
239
|
+
if (accountId && projectId) {
|
|
240
|
+
observed = yield* observeServiceAccount(projectId, accountId);
|
|
241
|
+
}
|
|
242
|
+
if (!observed && projectId) {
|
|
243
|
+
observed = yield* findByAlchemyMarker(id, projectId);
|
|
244
|
+
}
|
|
245
|
+
if (!observed)
|
|
246
|
+
return undefined;
|
|
247
|
+
const attrs = toAttributes(observed);
|
|
248
|
+
// Adoption gate via description marker (see Tags.ts §description).
|
|
249
|
+
return (yield* descriptionHasAlchemyMarker(id, observed.description))
|
|
250
|
+
? attrs
|
|
251
|
+
: Unowned(attrs);
|
|
252
|
+
}),
|
|
253
|
+
};
|
|
254
|
+
}));
|
|
255
|
+
//# sourceMappingURL=ServiceAccount.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ServiceAccount.js","sourceRoot":"","sources":["../../src/Iam/ServiceAccount.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect";
|
|
2
|
+
import type { ServiceAccount } from "./ServiceAccount.ts";
|
|
3
|
+
/**
|
|
4
|
+
* Bind a single `(role, member)` IAM grant onto a {@link ServiceAccount}.
|
|
5
|
+
*
|
|
6
|
+
* This is a **target-side binding** — it records the grant onto the
|
|
7
|
+
* GSA's binding bag (`stack.bindings[gsa]`); the ServiceAccount
|
|
8
|
+
* provider's `reconcile` later merges all such bindings (across all
|
|
9
|
+
* callers, including parallel ones from different stack stages) into
|
|
10
|
+
* a single `setIamPolicy` call on the GSA. Same pattern as
|
|
11
|
+
* `projectIamMember` / `subnetworkIamMember`.
|
|
12
|
+
*
|
|
13
|
+
* Identity for dedup: the rendered SID is `IamMember(<gsa>, <key>)`.
|
|
14
|
+
* The engine collapses binds by SID, so callers MUST supply a
|
|
15
|
+
* stack-unique `key` per (gsa, role, member) triple — otherwise a
|
|
16
|
+
* later bind silently overwrites an earlier one with the same key.
|
|
17
|
+
*
|
|
18
|
+
* The reason `key` exists: `member` is usually an `Output<string>`
|
|
19
|
+
* (e.g. `Output.interpolate\`...${cluster.projectId}...\``), and
|
|
20
|
+
* `Output` expressions stringify by their AST shape, not by the
|
|
21
|
+
* eventual value. Two interpolations of the same shape but different
|
|
22
|
+
* literal templates render the same SID. `key` sidesteps that by
|
|
23
|
+
* forcing a static, caller-supplied label into the SID.
|
|
24
|
+
*
|
|
25
|
+
* Use this for the "Pulumi `gcp.serviceAccount.IAMMember`" pattern:
|
|
26
|
+
* authoritative-for-(role, member)-tuple, additive (does not displace
|
|
27
|
+
* other members on the same role).
|
|
28
|
+
*
|
|
29
|
+
* @example Workload Identity binding for one cluster
|
|
30
|
+
* ```typescript
|
|
31
|
+
* yield* GCP.serviceAccountIamMember(gsa, "ClusterA-WorkloadIdentity", {
|
|
32
|
+
* role: "roles/iam.workloadIdentityUser",
|
|
33
|
+
* member: `serviceAccount:${clusterA.projectId}.svc.id.goog[researchers/build]`,
|
|
34
|
+
* });
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* @example Same GSA, second cluster (separate key → distinct SID)
|
|
38
|
+
* ```typescript
|
|
39
|
+
* yield* GCP.serviceAccountIamMember(gsa, "ClusterB-WorkloadIdentity", {
|
|
40
|
+
* role: "roles/iam.workloadIdentityUser",
|
|
41
|
+
* member: `serviceAccount:${clusterB.projectId}.svc.id.goog[researchers/build]`,
|
|
42
|
+
* });
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export declare const serviceAccountIamMember: (gsa: ServiceAccount, key: string, args: {
|
|
46
|
+
role: string;
|
|
47
|
+
member: string;
|
|
48
|
+
}) => Effect.Effect<void>;
|
|
49
|
+
//# sourceMappingURL=ServiceAccountIamMember.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ServiceAccountIamMember.d.ts","sourceRoot":"","sources":["../../src/Iam/ServiceAccountIamMember.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,eAAO,MAAM,uBAAuB,QAC7B,cAAc,OACd,MAAM,QACL;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,KACrC,MAAM,CAAC,MAAM,CAAC,IAAI,CAMiB,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bind a single `(role, member)` IAM grant onto a {@link ServiceAccount}.
|
|
3
|
+
*
|
|
4
|
+
* This is a **target-side binding** — it records the grant onto the
|
|
5
|
+
* GSA's binding bag (`stack.bindings[gsa]`); the ServiceAccount
|
|
6
|
+
* provider's `reconcile` later merges all such bindings (across all
|
|
7
|
+
* callers, including parallel ones from different stack stages) into
|
|
8
|
+
* a single `setIamPolicy` call on the GSA. Same pattern as
|
|
9
|
+
* `projectIamMember` / `subnetworkIamMember`.
|
|
10
|
+
*
|
|
11
|
+
* Identity for dedup: the rendered SID is `IamMember(<gsa>, <key>)`.
|
|
12
|
+
* The engine collapses binds by SID, so callers MUST supply a
|
|
13
|
+
* stack-unique `key` per (gsa, role, member) triple — otherwise a
|
|
14
|
+
* later bind silently overwrites an earlier one with the same key.
|
|
15
|
+
*
|
|
16
|
+
* The reason `key` exists: `member` is usually an `Output<string>`
|
|
17
|
+
* (e.g. `Output.interpolate\`...${cluster.projectId}...\``), and
|
|
18
|
+
* `Output` expressions stringify by their AST shape, not by the
|
|
19
|
+
* eventual value. Two interpolations of the same shape but different
|
|
20
|
+
* literal templates render the same SID. `key` sidesteps that by
|
|
21
|
+
* forcing a static, caller-supplied label into the SID.
|
|
22
|
+
*
|
|
23
|
+
* Use this for the "Pulumi `gcp.serviceAccount.IAMMember`" pattern:
|
|
24
|
+
* authoritative-for-(role, member)-tuple, additive (does not displace
|
|
25
|
+
* other members on the same role).
|
|
26
|
+
*
|
|
27
|
+
* @example Workload Identity binding for one cluster
|
|
28
|
+
* ```typescript
|
|
29
|
+
* yield* GCP.serviceAccountIamMember(gsa, "ClusterA-WorkloadIdentity", {
|
|
30
|
+
* role: "roles/iam.workloadIdentityUser",
|
|
31
|
+
* member: `serviceAccount:${clusterA.projectId}.svc.id.goog[researchers/build]`,
|
|
32
|
+
* });
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* @example Same GSA, second cluster (separate key → distinct SID)
|
|
36
|
+
* ```typescript
|
|
37
|
+
* yield* GCP.serviceAccountIamMember(gsa, "ClusterB-WorkloadIdentity", {
|
|
38
|
+
* role: "roles/iam.workloadIdentityUser",
|
|
39
|
+
* member: `serviceAccount:${clusterB.projectId}.svc.id.goog[researchers/build]`,
|
|
40
|
+
* });
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
export const serviceAccountIamMember = (gsa, key, args) =>
|
|
44
|
+
// Tagged-template `.bind` records into the target's binding bag.
|
|
45
|
+
// ServiceAccount's reconcile sees `bindings: ResourceBinding<…>[]`
|
|
46
|
+
// and merges all entries by role into one setIamPolicy call.
|
|
47
|
+
gsa.bind `IamMember(${gsa}, ${key})`({
|
|
48
|
+
iamBindings: [{ role: args.role, members: [args.member] }],
|
|
49
|
+
});
|
|
50
|
+
//# sourceMappingURL=ServiceAccountIamMember.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ServiceAccountIamMember.js","sourceRoot":"","sources":["../../src/Iam/ServiceAccountIamMember.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CACrC,GAAmB,EACnB,GAAW,EACX,IAAsC,EACjB,EAAE;AACvB,iEAAiE;AACjE,mEAAmE;AACnE,6DAA6D;AAC7D,GAAG,CAAC,IAAI,CAAA,aAAa,GAAG,KAAK,GAAG,GAAG,CAAC;IAClC,WAAW,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;CAC3D,CAAmC,CAAC"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { Resource } from "alchemy";
|
|
2
|
+
import * as Provider from "alchemy/Provider";
|
|
3
|
+
import type * as GCP from "../Providers.ts";
|
|
4
|
+
/**
|
|
5
|
+
* A user-managed service account key (JSON credentials file). Lives
|
|
6
|
+
* under a {@link import("./ServiceAccount.ts").ServiceAccount} and
|
|
7
|
+
* produces a `privateKeyData` field (base64-encoded JSON key file)
|
|
8
|
+
* available ONLY on create — `get`/`list` never return it.
|
|
9
|
+
*
|
|
10
|
+
* The `privateKeyData` attribute is marked stable so the engine
|
|
11
|
+
* preserves it across reconciles (it cannot be re-read from the API).
|
|
12
|
+
* On cold recovery (state loss), if the key exists but
|
|
13
|
+
* `privateKeyData` is absent from state, the old key is deleted and a
|
|
14
|
+
* new one is created so the `privateKeyData` is re-obtained.
|
|
15
|
+
*
|
|
16
|
+
* SA keys carry no labels or description, so adoption cannot be gated
|
|
17
|
+
* by marker — the SA itself is alchemy-owned, and the key is managed
|
|
18
|
+
* exclusively through this resource.
|
|
19
|
+
*
|
|
20
|
+
* @section Creating a ServiceAccountKey
|
|
21
|
+
* @example Mint a JSON key for a GSA
|
|
22
|
+
* ```typescript
|
|
23
|
+
* const key = yield* GCP.ServiceAccountKey("TempBucketKey", {
|
|
24
|
+
* serviceAccount: sa.name, // projects/{p}/serviceAccounts/{email}
|
|
25
|
+
* });
|
|
26
|
+
* // key.privateKeyData is the base64-encoded JSON key file
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export type ServiceAccountKeyProps = {
|
|
30
|
+
/**
|
|
31
|
+
* The resource name of the parent service account, in the format
|
|
32
|
+
* `projects/{PROJECT_ID}/serviceAccounts/{EMAIL_ADDRESS}`.
|
|
33
|
+
* Immutable — changing it triggers a replacement (the key is
|
|
34
|
+
* scoped to the SA).
|
|
35
|
+
*/
|
|
36
|
+
serviceAccount: string;
|
|
37
|
+
/**
|
|
38
|
+
* Key algorithm. Defaults to `KEY_ALG_RSA_2048`. Immutable after
|
|
39
|
+
* create.
|
|
40
|
+
*/
|
|
41
|
+
keyAlgorithm?: "KEY_ALG_RSA_2048" | "KEY_ALG_RSA_1024";
|
|
42
|
+
/**
|
|
43
|
+
* Output format for the private key. Defaults to
|
|
44
|
+
* `TYPE_GOOGLE_CREDENTIALS_FILE` (the Google Credentials JSON
|
|
45
|
+
* format usable by gcloud, gsutil, and the gcsfuse CSI driver).
|
|
46
|
+
*/
|
|
47
|
+
privateKeyType?: "TYPE_GOOGLE_CREDENTIALS_FILE" | "TYPE_PKCS12_FILE";
|
|
48
|
+
};
|
|
49
|
+
export type ServiceAccountKey = Resource<"GCP.ServiceAccountKey", ServiceAccountKeyProps, {
|
|
50
|
+
/** Full resource name: `projects/{p}/serviceAccounts/{email}/keys/{keyId}`. */
|
|
51
|
+
name: string;
|
|
52
|
+
/**
|
|
53
|
+
* Base64-encoded private key data (JSON key file). Only available
|
|
54
|
+
* on create — not returned by `get`/`list`. Preserved in alchemy
|
|
55
|
+
* state; on state loss the old key is deleted + a new one is
|
|
56
|
+
* created to re-obtain it.
|
|
57
|
+
*/
|
|
58
|
+
privateKeyData: string | undefined;
|
|
59
|
+
/** Key algorithm used. */
|
|
60
|
+
keyAlgorithm: string | undefined;
|
|
61
|
+
/** Key type: `USER_MANAGED` or `SYSTEM_MANAGED`. */
|
|
62
|
+
keyType: string | undefined;
|
|
63
|
+
/** Key origin: `USER_PROVIDED` or `GOOGLE_PROVIDED`. */
|
|
64
|
+
keyOrigin: string | undefined;
|
|
65
|
+
/** Timestamp after which the key is valid (RFC 3339). */
|
|
66
|
+
validAfterTime: string | undefined;
|
|
67
|
+
/** Whether the key is disabled. */
|
|
68
|
+
disabled: boolean | undefined;
|
|
69
|
+
}, never, GCP.Providers>;
|
|
70
|
+
export declare const ServiceAccountKey: import("alchemy").ResourceClass<ServiceAccountKey>;
|
|
71
|
+
export declare const ServiceAccountKeyProvider: () => import("effect/Layer").Layer<Provider.Provider<ServiceAccountKey>, never, import("@distilled.cloud/gcp").Credentials | import("effect/unstable/http/HttpClient").HttpClient>;
|
|
72
|
+
//# sourceMappingURL=ServiceAccountKey.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ServiceAccountKey.d.ts","sourceRoot":"","sources":["../../src/Iam/ServiceAccountKey.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnC,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAE7C,OAAO,KAAK,KAAK,GAAG,MAAM,iBAAiB,CAAC;AAE5C;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC;;;;;OAKG;IACH,cAAc,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,YAAY,CAAC,EAAE,kBAAkB,GAAG,kBAAkB,CAAC;IACvD;;;;OAIG;IACH,cAAc,CAAC,EAAE,8BAA8B,GAAG,kBAAkB,CAAC;CACtE,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,QAAQ,CACtC,uBAAuB,EACvB,sBAAsB,EACtB;IACE,+EAA+E;IAC/E,IAAI,EAAE,MAAM,CAAC;IACb;;;;;OAKG;IACH,cAAc,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,0BAA0B;IAC1B,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,oDAAoD;IACpD,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,wDAAwD;IACxD,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,yDAAyD;IACzD,cAAc,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,mCAAmC;IACnC,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;CAC/B,EACD,KAAK,EACL,GAAG,CAAC,SAAS,CACd,CAAC;AAEF,eAAO,MAAM,iBAAiB,oDAE7B,CAAC;AAYF,eAAO,MAAM,yBAAyB,oLA2LnC,CAAC"}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { ConfigError } from "@distilled.cloud/gcp";
|
|
2
|
+
import * as iam from "@distilled.cloud/gcp/unstable/iam-v1";
|
|
3
|
+
import { Resource } from "alchemy";
|
|
4
|
+
import { isResolved } from "alchemy/Diff";
|
|
5
|
+
import * as Provider from "alchemy/Provider";
|
|
6
|
+
import * as Effect from "effect/Effect";
|
|
7
|
+
export const ServiceAccountKey = Resource("GCP.ServiceAccountKey");
|
|
8
|
+
const toAttributes = (k) => ({
|
|
9
|
+
name: k.name ?? "",
|
|
10
|
+
privateKeyData: k.privateKeyData,
|
|
11
|
+
keyAlgorithm: k.keyAlgorithm,
|
|
12
|
+
keyType: k.keyType,
|
|
13
|
+
keyOrigin: k.keyOrigin,
|
|
14
|
+
validAfterTime: k.validAfterTime,
|
|
15
|
+
disabled: k.disabled,
|
|
16
|
+
});
|
|
17
|
+
export const ServiceAccountKeyProvider = () => Provider.effect(ServiceAccountKey, Effect.gen(function* () {
|
|
18
|
+
const createProjectsServiceAccountsKeys = yield* iam.createProjectsServiceAccountsKeys;
|
|
19
|
+
const deleteProjectsServiceAccountsKeys = yield* iam.deleteProjectsServiceAccountsKeys;
|
|
20
|
+
const listProjectsServiceAccountsKeys = yield* iam.listProjectsServiceAccountsKeys;
|
|
21
|
+
const getProjectsServiceAccountsKeys = yield* iam.getProjectsServiceAccountsKeys;
|
|
22
|
+
// Find a user-managed key by name (direct probe).
|
|
23
|
+
// NotFound → undefined (key doesn't exist). Forbidden is NOT
|
|
24
|
+
// swallowed — if the caller lacks permission to read this key,
|
|
25
|
+
// propagating the error is safer than treating it as "missing"
|
|
26
|
+
// and potentially creating a duplicate on the SA.
|
|
27
|
+
const observeKey = (keyName) => getProjectsServiceAccountsKeys({
|
|
28
|
+
name: keyName,
|
|
29
|
+
publicKeyType: "TYPE_GOOGLE_CREDENTIALS_FILE",
|
|
30
|
+
}).pipe(Effect.catchTag("NotFound", () => Effect.succeed(undefined)));
|
|
31
|
+
// List all user-managed keys for the SA. Used for cold recovery
|
|
32
|
+
// when the key name is not in state. Returns the first
|
|
33
|
+
// user-managed key found (the SA is dedicated to this resource,
|
|
34
|
+
// so there should be at most one user-managed key).
|
|
35
|
+
const findUserManagedKey = Effect.fn(function* (serviceAccount) {
|
|
36
|
+
const page = yield* listProjectsServiceAccountsKeys({
|
|
37
|
+
name: serviceAccount,
|
|
38
|
+
keyTypes: "USER_MANAGED",
|
|
39
|
+
});
|
|
40
|
+
const keys = page.keys ?? [];
|
|
41
|
+
if (keys.length === 0)
|
|
42
|
+
return undefined;
|
|
43
|
+
if (keys.length === 1)
|
|
44
|
+
return keys[0];
|
|
45
|
+
// Multiple user-managed keys — GCP allows multiple keys per
|
|
46
|
+
// SA, so creating another would silently succeed (not
|
|
47
|
+
// Conflict as an earlier comment assumed). Surface an error
|
|
48
|
+
// so the user cleans up the extra keys and re-runs.
|
|
49
|
+
return yield* Effect.fail(new ConfigError({
|
|
50
|
+
message: `Service account ${serviceAccount} has ${keys.length} user-managed keys; ` +
|
|
51
|
+
`cannot determine which to adopt. Delete the extra keys and re-run.`,
|
|
52
|
+
}));
|
|
53
|
+
});
|
|
54
|
+
return {
|
|
55
|
+
// privateKeyData is stable: it's set on create and never
|
|
56
|
+
// changes. The engine preserves it across reconciles and
|
|
57
|
+
// does not use it for drift detection.
|
|
58
|
+
stables: ["name", "privateKeyData", "keyAlgorithm", "keyType"],
|
|
59
|
+
diff: Effect.fn(function* ({ news, olds = {} }) {
|
|
60
|
+
if (!isResolved(news))
|
|
61
|
+
return undefined;
|
|
62
|
+
const priorSa = olds.serviceAccount;
|
|
63
|
+
const priorKeyAlgorithm = olds.keyAlgorithm;
|
|
64
|
+
const priorPrivateKeyType = olds.privateKeyType;
|
|
65
|
+
if ((priorSa && news.serviceAccount !== priorSa) ||
|
|
66
|
+
(priorKeyAlgorithm && news.keyAlgorithm !== priorKeyAlgorithm) ||
|
|
67
|
+
(priorPrivateKeyType &&
|
|
68
|
+
news.privateKeyType !== priorPrivateKeyType)) {
|
|
69
|
+
return { action: "replace" };
|
|
70
|
+
}
|
|
71
|
+
return undefined;
|
|
72
|
+
}),
|
|
73
|
+
reconcile: Effect.fn(function* ({ id, news, output }) {
|
|
74
|
+
// 1. Observe — check if the key exists by name (from
|
|
75
|
+
// state output). Fall back to listing user-managed
|
|
76
|
+
// keys for cold recovery.
|
|
77
|
+
const keyName = output?.name;
|
|
78
|
+
let observed;
|
|
79
|
+
if (keyName) {
|
|
80
|
+
observed = yield* observeKey(keyName);
|
|
81
|
+
}
|
|
82
|
+
if (!observed) {
|
|
83
|
+
observed = yield* findUserManagedKey(news.serviceAccount);
|
|
84
|
+
}
|
|
85
|
+
// 2. Ensure — create if missing. If the key exists but
|
|
86
|
+
// privateKeyData is not in state (state loss), delete
|
|
87
|
+
// the old key and create a new one so privateKeyData is
|
|
88
|
+
// re-obtained.
|
|
89
|
+
if (!observed) {
|
|
90
|
+
const created = yield* createProjectsServiceAccountsKeys({
|
|
91
|
+
name: news.serviceAccount,
|
|
92
|
+
body: {
|
|
93
|
+
privateKeyType: news.privateKeyType ?? "TYPE_GOOGLE_CREDENTIALS_FILE",
|
|
94
|
+
keyAlgorithm: news.keyAlgorithm ?? "KEY_ALG_RSA_2048",
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
return toAttributes(created);
|
|
98
|
+
}
|
|
99
|
+
// Key exists. If it is the same key we created before, preserve
|
|
100
|
+
// privateKeyData from state. If the name differs, the key was
|
|
101
|
+
// swapped out-of-band — fall through to delete + recreate so
|
|
102
|
+
// privateKeyData matches the live key.
|
|
103
|
+
if (output?.privateKeyData && observed.name === output.name) {
|
|
104
|
+
return {
|
|
105
|
+
...toAttributes(observed),
|
|
106
|
+
privateKeyData: output.privateKeyData,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
// privateKeyData is missing from state. Only delete + recreate
|
|
110
|
+
// when we can PROVE the observed key is ours: output.name must
|
|
111
|
+
// be set and match. SA keys carry no labels, so on cold recovery
|
|
112
|
+
// (output undefined) a found key might be pre-existing or
|
|
113
|
+
// manually rotated — deleting it would destroy someone else's
|
|
114
|
+
// credentials. Fail instead and ask the user to clean up.
|
|
115
|
+
if (output?.name && observed.name === output.name) {
|
|
116
|
+
yield* deleteProjectsServiceAccountsKeys({
|
|
117
|
+
name: observed.name,
|
|
118
|
+
}).pipe(Effect.catchTag("NotFound", () => Effect.void));
|
|
119
|
+
const created = yield* createProjectsServiceAccountsKeys({
|
|
120
|
+
name: news.serviceAccount,
|
|
121
|
+
body: {
|
|
122
|
+
privateKeyType: news.privateKeyType ?? "TYPE_GOOGLE_CREDENTIALS_FILE",
|
|
123
|
+
keyAlgorithm: news.keyAlgorithm ?? "KEY_ALG_RSA_2048",
|
|
124
|
+
},
|
|
125
|
+
});
|
|
126
|
+
return toAttributes(created);
|
|
127
|
+
}
|
|
128
|
+
// Key exists but we can't prove ownership. Don't delete it.
|
|
129
|
+
return yield* Effect.fail(new ConfigError({
|
|
130
|
+
message: `Service account key ${observed.name} exists on ${news.serviceAccount} ` +
|
|
131
|
+
`but cannot be verified as ours (no matching state). ` +
|
|
132
|
+
`Delete it manually and re-run to create a fresh key.`,
|
|
133
|
+
}));
|
|
134
|
+
}),
|
|
135
|
+
delete: Effect.fn(function* ({ output }) {
|
|
136
|
+
yield* deleteProjectsServiceAccountsKeys({
|
|
137
|
+
name: output.name,
|
|
138
|
+
}).pipe(Effect.catchTag("NotFound", () => Effect.void), Effect.catchTag("Forbidden", () => Effect.void));
|
|
139
|
+
}),
|
|
140
|
+
read: Effect.fn(function* ({ id, output, olds }) {
|
|
141
|
+
const keyName = output?.name;
|
|
142
|
+
const serviceAccount = olds.serviceAccount;
|
|
143
|
+
let observed;
|
|
144
|
+
if (keyName) {
|
|
145
|
+
observed = yield* observeKey(keyName);
|
|
146
|
+
}
|
|
147
|
+
if (!observed && serviceAccount) {
|
|
148
|
+
observed = yield* findUserManagedKey(serviceAccount);
|
|
149
|
+
}
|
|
150
|
+
if (!observed)
|
|
151
|
+
return undefined;
|
|
152
|
+
// privateKeyData is not available from get/list — preserve it
|
|
153
|
+
// from state output only when it still describes this key.
|
|
154
|
+
const privateKeyData = output?.name && observed.name === output.name
|
|
155
|
+
? output.privateKeyData
|
|
156
|
+
: undefined;
|
|
157
|
+
return {
|
|
158
|
+
...toAttributes(observed),
|
|
159
|
+
privateKeyData,
|
|
160
|
+
};
|
|
161
|
+
}),
|
|
162
|
+
};
|
|
163
|
+
}));
|
|
164
|
+
//# sourceMappingURL=ServiceAccountKey.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ServiceAccountKey.js","sourceRoot":"","sources":["../../src/Iam/ServiceAccountKey.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { ServiceAccount, ServiceAccountProvider } from "./ServiceAccount.ts";
|
|
2
|
+
export type { ServiceAccountProps } from "./ServiceAccount.ts";
|
|
3
|
+
export * from "./ServiceAccountIamMember.ts";
|
|
4
|
+
export { ServiceAccountKey, ServiceAccountKeyProvider, } from "./ServiceAccountKey.ts";
|
|
5
|
+
export type { ServiceAccountKeyProps } from "./ServiceAccountKey.ts";
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/Iam/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAC7E,YAAY,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC/D,cAAc,8BAA8B,CAAC;AAC7C,OAAO,EACL,iBAAiB,EACjB,yBAAyB,GAC1B,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC"}
|