@pipeline-builder/pipeline-core 3.1.0

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.
Files changed (54) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +32 -0
  3. package/lib/config/app-config.d.ts +81 -0
  4. package/lib/config/app-config.js +151 -0
  5. package/lib/config/billing-config.d.ts +17 -0
  6. package/lib/config/billing-config.js +95 -0
  7. package/lib/config/config-types.d.ts +213 -0
  8. package/lib/config/config-types.js +5 -0
  9. package/lib/config/infrastructure-config.d.ts +55 -0
  10. package/lib/config/infrastructure-config.js +200 -0
  11. package/lib/config/server-config.d.ts +53 -0
  12. package/lib/config/server-config.js +180 -0
  13. package/lib/core/artifact-manager.d.ts +62 -0
  14. package/lib/core/artifact-manager.js +86 -0
  15. package/lib/core/id-generator.d.ts +26 -0
  16. package/lib/core/id-generator.js +44 -0
  17. package/lib/core/metadata-builder.d.ts +13 -0
  18. package/lib/core/metadata-builder.js +81 -0
  19. package/lib/core/network-types.d.ts +200 -0
  20. package/lib/core/network-types.js +5 -0
  21. package/lib/core/network.d.ts +20 -0
  22. package/lib/core/network.js +84 -0
  23. package/lib/core/pipeline-helpers.d.ts +53 -0
  24. package/lib/core/pipeline-helpers.js +273 -0
  25. package/lib/core/pipeline-types.d.ts +136 -0
  26. package/lib/core/pipeline-types.js +140 -0
  27. package/lib/core/role-types.d.ts +254 -0
  28. package/lib/core/role-types.js +5 -0
  29. package/lib/core/role.d.ts +14 -0
  30. package/lib/core/role.js +118 -0
  31. package/lib/core/security-group-types.d.ts +84 -0
  32. package/lib/core/security-group-types.js +5 -0
  33. package/lib/core/security-group.d.ts +14 -0
  34. package/lib/core/security-group.js +34 -0
  35. package/lib/handlers/plugin-lookup-handler.d.ts +32 -0
  36. package/lib/handlers/plugin-lookup-handler.js +313 -0
  37. package/lib/handlers/pnpm-lock.yaml +12 -0
  38. package/lib/index.d.ts +54 -0
  39. package/lib/index.js +112 -0
  40. package/lib/pipeline/pipeline-builder.d.ts +82 -0
  41. package/lib/pipeline/pipeline-builder.js +292 -0
  42. package/lib/pipeline/pipeline-configuration.d.ts +72 -0
  43. package/lib/pipeline/pipeline-configuration.js +196 -0
  44. package/lib/pipeline/plugin-lookup.d.ts +100 -0
  45. package/lib/pipeline/plugin-lookup.js +247 -0
  46. package/lib/pipeline/source-builder.d.ts +47 -0
  47. package/lib/pipeline/source-builder.js +111 -0
  48. package/lib/pipeline/source-types.d.ts +191 -0
  49. package/lib/pipeline/source-types.js +5 -0
  50. package/lib/pipeline/stage-builder.d.ts +71 -0
  51. package/lib/pipeline/stage-builder.js +118 -0
  52. package/lib/pipeline/step-types.d.ts +307 -0
  53. package/lib/pipeline/step-types.js +5 -0
  54. package/package.json +137 -0
@@ -0,0 +1,254 @@
1
+ /**
2
+ * Role configuration using an IAM role ARN
3
+ *
4
+ * Looks up an existing IAM role by its ARN via `Role.fromRoleArn`.
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * const role: RoleArnConfig = {
9
+ * type: 'roleArn',
10
+ * options: {
11
+ * roleArn: 'arn:aws:iam::123456789012:role/MyPipelineRole',
12
+ * }
13
+ * };
14
+ * ```
15
+ */
16
+ export interface RoleArnConfig {
17
+ readonly type: 'roleArn';
18
+ readonly options: RoleArnOptions;
19
+ }
20
+ /**
21
+ * Role configuration using an IAM role name
22
+ *
23
+ * Looks up an existing IAM role by its name via `Role.fromRoleName`.
24
+ *
25
+ * @example
26
+ * ```typescript
27
+ * const role: RoleNameConfig = {
28
+ * type: 'roleName',
29
+ * options: {
30
+ * roleName: 'MyPipelineRole',
31
+ * }
32
+ * };
33
+ * ```
34
+ */
35
+ export interface RoleNameConfig {
36
+ readonly type: 'roleName';
37
+ readonly options: RoleNameOptions;
38
+ }
39
+ /**
40
+ * Configuration options for role lookup by ARN
41
+ */
42
+ export interface RoleArnOptions {
43
+ /**
44
+ * Full ARN of the IAM role
45
+ * @example 'arn:aws:iam::123456789012:role/MyPipelineRole'
46
+ */
47
+ readonly roleArn: string;
48
+ /**
49
+ * Whether the imported role can be modified by attaching policy resources to it.
50
+ * Set to false if you know the role is already configured correctly and
51
+ * want to avoid additional API calls during synthesis.
52
+ * @default true
53
+ */
54
+ readonly mutable?: boolean;
55
+ }
56
+ /**
57
+ * Configuration options for role lookup by name
58
+ */
59
+ export interface RoleNameOptions {
60
+ /**
61
+ * Name of the IAM role
62
+ * @example 'MyPipelineRole'
63
+ */
64
+ readonly roleName: string;
65
+ /**
66
+ * Whether the imported role can be modified by attaching policy resources to it.
67
+ * Set to false if you know the role is already configured correctly and
68
+ * want to avoid additional API calls during synthesis.
69
+ * @default true
70
+ */
71
+ readonly mutable?: boolean;
72
+ }
73
+ /**
74
+ * Role configuration that creates a new IAM role with CodeBuild service principal
75
+ * and minimal CloudWatch Logs permissions.
76
+ *
77
+ * **Important:** This role type uses `codebuild.amazonaws.com` as the trust principal.
78
+ * It is intended for CodeBuild project roles only — do NOT use it as the pipeline-level
79
+ * role (`BuilderProps.role`), which requires `codepipeline.amazonaws.com`. For the
80
+ * pipeline role, use `roleArn` or `roleName` to reference a pre-configured role,
81
+ * or omit `role` entirely to let CDK auto-create one with the correct principal.
82
+ *
83
+ * @example
84
+ * ```typescript
85
+ * const role: CodeBuildDefaultRoleConfig = {
86
+ * type: 'codeBuildDefault',
87
+ * options: {},
88
+ * };
89
+ * ```
90
+ */
91
+ export interface CodeBuildDefaultRoleConfig {
92
+ readonly type: 'codeBuildDefault';
93
+ readonly options: CodeBuildDefaultRoleOptions;
94
+ }
95
+ /**
96
+ * Configuration options for creating a CodeBuild service role
97
+ */
98
+ export interface CodeBuildDefaultRoleOptions {
99
+ /**
100
+ * Optional custom role name.
101
+ * When omitted, CDK generates a unique name.
102
+ */
103
+ readonly roleName?: string;
104
+ }
105
+ /**
106
+ * Role configuration using an OIDC identity provider for federated role assumption.
107
+ *
108
+ * Creates a new IAM role that trusts an OpenID Connect provider (e.g. GitHub Actions,
109
+ * GitLab CI, Bitbucket Pipelines) instead of requiring a static role ARN.
110
+ *
111
+ * Provide either `providerArn` to reference an existing OIDC provider,
112
+ * or `issuer` + `clientIds` to create a new one.
113
+ *
114
+ * @example
115
+ * ```typescript
116
+ * // Reference an existing OIDC provider
117
+ * const role: OidcRoleConfig = {
118
+ * type: 'oidc',
119
+ * options: {
120
+ * providerArn: 'arn:aws:iam::123456789012:oidc-provider/token.actions.githubusercontent.com',
121
+ * conditions: {
122
+ * 'token.actions.githubusercontent.com:sub': 'repo:my-org/my-repo:ref:refs/heads/main',
123
+ * },
124
+ * },
125
+ * };
126
+ *
127
+ * // Create a new OIDC provider inline (GitHub Actions)
128
+ * const role: OidcRoleConfig = {
129
+ * type: 'oidc',
130
+ * options: {
131
+ * issuer: 'https://token.actions.githubusercontent.com',
132
+ * clientIds: ['sts.amazonaws.com'],
133
+ * thumbprints: ['6938fd4d98bab03faadb97b34396831e3780aea1'],
134
+ * conditions: {
135
+ * 'token.actions.githubusercontent.com:sub': 'repo:my-org/my-repo:ref:refs/heads/main',
136
+ * },
137
+ * },
138
+ * };
139
+ * ```
140
+ */
141
+ export interface OidcRoleConfig {
142
+ readonly type: 'oidc';
143
+ readonly options: OidcRoleOptions;
144
+ }
145
+ /**
146
+ * Configuration options for OIDC federated role assumption.
147
+ */
148
+ export interface OidcRoleOptions {
149
+ /**
150
+ * ARN of an existing IAM OIDC identity provider.
151
+ * Mutually exclusive with `issuer`.
152
+ * @example 'arn:aws:iam::123456789012:oidc-provider/token.actions.githubusercontent.com'
153
+ */
154
+ readonly providerArn?: string;
155
+ /**
156
+ * OIDC issuer URL for creating a new provider.
157
+ * Mutually exclusive with `providerArn`.
158
+ * @example 'https://token.actions.githubusercontent.com'
159
+ */
160
+ readonly issuer?: string;
161
+ /**
162
+ * Client IDs (audiences) trusted by the OIDC provider.
163
+ * Required when using `issuer` to create a new provider.
164
+ * @example ['sts.amazonaws.com']
165
+ */
166
+ readonly clientIds?: string[];
167
+ /**
168
+ * TLS certificate thumbprints for the OIDC provider.
169
+ * Required when using `issuer` to create a new provider.
170
+ */
171
+ readonly thumbprints?: string[];
172
+ /**
173
+ * StringEquals conditions for the assume-role trust policy.
174
+ * Keys are the condition claim, values are the expected claim value(s).
175
+ * @example { 'token.actions.githubusercontent.com:sub': 'repo:my-org/my-repo:ref:refs/heads/main' }
176
+ */
177
+ readonly conditions?: Record<string, string | string[]>;
178
+ /**
179
+ * StringLike conditions for wildcard matching in the trust policy.
180
+ * @example { 'token.actions.githubusercontent.com:sub': 'repo:my-org/*' }
181
+ */
182
+ readonly conditionsLike?: Record<string, string | string[]>;
183
+ /**
184
+ * Optional custom role name.
185
+ * When omitted, CDK generates a unique name.
186
+ */
187
+ readonly roleName?: string;
188
+ /**
189
+ * Optional description for the IAM role.
190
+ * Appears in the AWS console and API responses.
191
+ * @example 'OIDC role for GitHub Actions CI/CD pipeline'
192
+ */
193
+ readonly description?: string;
194
+ /**
195
+ * Maximum session duration in seconds for the assumed role.
196
+ * Controls how long the temporary credentials remain valid.
197
+ * Must be between 3600 (1 hour) and 43200 (12 hours).
198
+ * @default 3600 (1 hour, AWS default)
199
+ */
200
+ readonly maxSessionDuration?: number;
201
+ /**
202
+ * ARN of an IAM permissions boundary to attach to the role.
203
+ * Required in many enterprise AWS environments to limit maximum permissions.
204
+ * @example 'arn:aws:iam::123456789012:policy/DeveloperBoundary'
205
+ */
206
+ readonly permissionsBoundaryArn?: string;
207
+ /**
208
+ * Optional managed policy ARNs to attach to the role.
209
+ */
210
+ readonly managedPolicyArns?: string[];
211
+ /**
212
+ * Inline IAM policy statements to attach to the role.
213
+ * Each entry defines an IAM policy statement with effect, actions, and resources.
214
+ *
215
+ * @example
216
+ * ```typescript
217
+ * policyStatements: [
218
+ * { actions: ['s3:GetObject'], resources: ['arn:aws:s3:::my-bucket/*'] },
219
+ * { actions: ['logs:CreateLogGroup', 'logs:PutLogEvents'], resources: ['*'] },
220
+ * ]
221
+ * ```
222
+ */
223
+ readonly policyStatements?: OidcPolicyStatement[];
224
+ }
225
+ /**
226
+ * An inline IAM policy statement for OIDC roles.
227
+ */
228
+ export interface OidcPolicyStatement {
229
+ /**
230
+ * IAM effect. Defaults to 'Allow'.
231
+ */
232
+ readonly effect?: 'Allow' | 'Deny';
233
+ /**
234
+ * IAM actions (e.g. 's3:GetObject', 'logs:*').
235
+ */
236
+ readonly actions: string[];
237
+ /**
238
+ * IAM resource ARNs this statement applies to.
239
+ */
240
+ readonly resources: string[];
241
+ }
242
+ /**
243
+ * Union type of all supported role configurations.
244
+ *
245
+ * Used at the pipeline level (`BuilderProps.role`) to specify the IAM role
246
+ * for the CodePipeline construct.
247
+ *
248
+ * Each variant resolves to a CDK `IRole`:
249
+ * - RoleArnConfig: Role looked up by ARN
250
+ * - RoleNameConfig: Role looked up by name
251
+ * - CodeBuildDefaultRoleConfig: Creates a new role with CodeBuild trust + CloudWatch Logs
252
+ * - OidcRoleConfig: Creates a new role with OIDC federated trust (no static ARN needed)
253
+ */
254
+ export type RoleConfig = RoleArnConfig | RoleNameConfig | CodeBuildDefaultRoleConfig | OidcRoleConfig;
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ // Copyright 2026 Pipeline Builder Contributors
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm9sZS10eXBlcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb3JlL3JvbGUtdHlwZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0MiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuLyoqXG4gKiBSb2xlIGNvbmZpZ3VyYXRpb24gdXNpbmcgYW4gSUFNIHJvbGUgQVJOXG4gKlxuICogTG9va3MgdXAgYW4gZXhpc3RpbmcgSUFNIHJvbGUgYnkgaXRzIEFSTiB2aWEgYFJvbGUuZnJvbVJvbGVBcm5gLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBjb25zdCByb2xlOiBSb2xlQXJuQ29uZmlnID0ge1xuICogICB0eXBlOiAncm9sZUFybicsXG4gKiAgIG9wdGlvbnM6IHtcbiAqICAgICByb2xlQXJuOiAnYXJuOmF3czppYW06OjEyMzQ1Njc4OTAxMjpyb2xlL015UGlwZWxpbmVSb2xlJyxcbiAqICAgfVxuICogfTtcbiAqIGBgYFxuICovXG5leHBvcnQgaW50ZXJmYWNlIFJvbGVBcm5Db25maWcge1xuICByZWFkb25seSB0eXBlOiAncm9sZUFybic7XG4gIHJlYWRvbmx5IG9wdGlvbnM6IFJvbGVBcm5PcHRpb25zO1xufVxuXG4vKipcbiAqIFJvbGUgY29uZmlndXJhdGlvbiB1c2luZyBhbiBJQU0gcm9sZSBuYW1lXG4gKlxuICogTG9va3MgdXAgYW4gZXhpc3RpbmcgSUFNIHJvbGUgYnkgaXRzIG5hbWUgdmlhIGBSb2xlLmZyb21Sb2xlTmFtZWAuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGNvbnN0IHJvbGU6IFJvbGVOYW1lQ29uZmlnID0ge1xuICogICB0eXBlOiAncm9sZU5hbWUnLFxuICogICBvcHRpb25zOiB7XG4gKiAgICAgcm9sZU5hbWU6ICdNeVBpcGVsaW5lUm9sZScsXG4gKiAgIH1cbiAqIH07XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBSb2xlTmFtZUNvbmZpZyB7XG4gIHJlYWRvbmx5IHR5cGU6ICdyb2xlTmFtZSc7XG4gIHJlYWRvbmx5IG9wdGlvbnM6IFJvbGVOYW1lT3B0aW9ucztcbn1cblxuLyoqXG4gKiBDb25maWd1cmF0aW9uIG9wdGlvbnMgZm9yIHJvbGUgbG9va3VwIGJ5IEFSTlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFJvbGVBcm5PcHRpb25zIHtcbiAgLyoqXG4gICAqIEZ1bGwgQVJOIG9mIHRoZSBJQU0gcm9sZVxuICAgKiBAZXhhbXBsZSAnYXJuOmF3czppYW06OjEyMzQ1Njc4OTAxMjpyb2xlL015UGlwZWxpbmVSb2xlJ1xuICAgKi9cbiAgcmVhZG9ubHkgcm9sZUFybjogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRoZSBpbXBvcnRlZCByb2xlIGNhbiBiZSBtb2RpZmllZCBieSBhdHRhY2hpbmcgcG9saWN5IHJlc291cmNlcyB0byBpdC5cbiAgICogU2V0IHRvIGZhbHNlIGlmIHlvdSBrbm93IHRoZSByb2xlIGlzIGFscmVhZHkgY29uZmlndXJlZCBjb3JyZWN0bHkgYW5kXG4gICAqIHdhbnQgdG8gYXZvaWQgYWRkaXRpb25hbCBBUEkgY2FsbHMgZHVyaW5nIHN5bnRoZXNpcy5cbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKi9cbiAgcmVhZG9ubHkgbXV0YWJsZT86IGJvb2xlYW47XG59XG5cbi8qKlxuICogQ29uZmlndXJhdGlvbiBvcHRpb25zIGZvciByb2xlIGxvb2t1cCBieSBuYW1lXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUm9sZU5hbWVPcHRpb25zIHtcbiAgLyoqXG4gICAqIE5hbWUgb2YgdGhlIElBTSByb2xlXG4gICAqIEBleGFtcGxlICdNeVBpcGVsaW5lUm9sZSdcbiAgICovXG4gIHJlYWRvbmx5IHJvbGVOYW1lOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdGhlIGltcG9ydGVkIHJvbGUgY2FuIGJlIG1vZGlmaWVkIGJ5IGF0dGFjaGluZyBwb2xpY3kgcmVzb3VyY2VzIHRvIGl0LlxuICAgKiBTZXQgdG8gZmFsc2UgaWYgeW91IGtub3cgdGhlIHJvbGUgaXMgYWxyZWFkeSBjb25maWd1cmVkIGNvcnJlY3RseSBhbmRcbiAgICogd2FudCB0byBhdm9pZCBhZGRpdGlvbmFsIEFQSSBjYWxscyBkdXJpbmcgc3ludGhlc2lzLlxuICAgKiBAZGVmYXVsdCB0cnVlXG4gICAqL1xuICByZWFkb25seSBtdXRhYmxlPzogYm9vbGVhbjtcbn1cblxuLyoqXG4gKiBSb2xlIGNvbmZpZ3VyYXRpb24gdGhhdCBjcmVhdGVzIGEgbmV3IElBTSByb2xlIHdpdGggQ29kZUJ1aWxkIHNlcnZpY2UgcHJpbmNpcGFsXG4gKiBhbmQgbWluaW1hbCBDbG91ZFdhdGNoIExvZ3MgcGVybWlzc2lvbnMuXG4gKlxuICogKipJbXBvcnRhbnQ6KiogVGhpcyByb2xlIHR5cGUgdXNlcyBgY29kZWJ1aWxkLmFtYXpvbmF3cy5jb21gIGFzIHRoZSB0cnVzdCBwcmluY2lwYWwuXG4gKiBJdCBpcyBpbnRlbmRlZCBmb3IgQ29kZUJ1aWxkIHByb2plY3Qgcm9sZXMgb25seSDigJQgZG8gTk9UIHVzZSBpdCBhcyB0aGUgcGlwZWxpbmUtbGV2ZWxcbiAqIHJvbGUgKGBCdWlsZGVyUHJvcHMucm9sZWApLCB3aGljaCByZXF1aXJlcyBgY29kZXBpcGVsaW5lLmFtYXpvbmF3cy5jb21gLiBGb3IgdGhlXG4gKiBwaXBlbGluZSByb2xlLCB1c2UgYHJvbGVBcm5gIG9yIGByb2xlTmFtZWAgdG8gcmVmZXJlbmNlIGEgcHJlLWNvbmZpZ3VyZWQgcm9sZSxcbiAqIG9yIG9taXQgYHJvbGVgIGVudGlyZWx5IHRvIGxldCBDREsgYXV0by1jcmVhdGUgb25lIHdpdGggdGhlIGNvcnJlY3QgcHJpbmNpcGFsLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBjb25zdCByb2xlOiBDb2RlQnVpbGREZWZhdWx0Um9sZUNvbmZpZyA9IHtcbiAqICAgdHlwZTogJ2NvZGVCdWlsZERlZmF1bHQnLFxuICogICBvcHRpb25zOiB7fSxcbiAqIH07XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBDb2RlQnVpbGREZWZhdWx0Um9sZUNvbmZpZyB7XG4gIHJlYWRvbmx5IHR5cGU6ICdjb2RlQnVpbGREZWZhdWx0JztcbiAgcmVhZG9ubHkgb3B0aW9uczogQ29kZUJ1aWxkRGVmYXVsdFJvbGVPcHRpb25zO1xufVxuXG4vKipcbiAqIENvbmZpZ3VyYXRpb24gb3B0aW9ucyBmb3IgY3JlYXRpbmcgYSBDb2RlQnVpbGQgc2VydmljZSByb2xlXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQ29kZUJ1aWxkRGVmYXVsdFJvbGVPcHRpb25zIHtcbiAgLyoqXG4gICAqIE9wdGlvbmFsIGN1c3RvbSByb2xlIG5hbWUuXG4gICAqIFdoZW4gb21pdHRlZCwgQ0RLIGdlbmVyYXRlcyBhIHVuaXF1ZSBuYW1lLlxuICAgKi9cbiAgcmVhZG9ubHkgcm9sZU5hbWU/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogUm9sZSBjb25maWd1cmF0aW9uIHVzaW5nIGFuIE9JREMgaWRlbnRpdHkgcHJvdmlkZXIgZm9yIGZlZGVyYXRlZCByb2xlIGFzc3VtcHRpb24uXG4gKlxuICogQ3JlYXRlcyBhIG5ldyBJQU0gcm9sZSB0aGF0IHRydXN0cyBhbiBPcGVuSUQgQ29ubmVjdCBwcm92aWRlciAoZS5nLiBHaXRIdWIgQWN0aW9ucyxcbiAqIEdpdExhYiBDSSwgQml0YnVja2V0IFBpcGVsaW5lcykgaW5zdGVhZCBvZiByZXF1aXJpbmcgYSBzdGF0aWMgcm9sZSBBUk4uXG4gKlxuICogUHJvdmlkZSBlaXRoZXIgYHByb3ZpZGVyQXJuYCB0byByZWZlcmVuY2UgYW4gZXhpc3RpbmcgT0lEQyBwcm92aWRlcixcbiAqIG9yIGBpc3N1ZXJgICsgYGNsaWVudElkc2AgdG8gY3JlYXRlIGEgbmV3IG9uZS5cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogLy8gUmVmZXJlbmNlIGFuIGV4aXN0aW5nIE9JREMgcHJvdmlkZXJcbiAqIGNvbnN0IHJvbGU6IE9pZGNSb2xlQ29uZmlnID0ge1xuICogICB0eXBlOiAnb2lkYycsXG4gKiAgIG9wdGlvbnM6IHtcbiAqICAgICBwcm92aWRlckFybjogJ2Fybjphd3M6aWFtOjoxMjM0NTY3ODkwMTI6b2lkYy1wcm92aWRlci90b2tlbi5hY3Rpb25zLmdpdGh1YnVzZXJjb250ZW50LmNvbScsXG4gKiAgICAgY29uZGl0aW9uczoge1xuICogICAgICAgJ3Rva2VuLmFjdGlvbnMuZ2l0aHVidXNlcmNvbnRlbnQuY29tOnN1Yic6ICdyZXBvOm15LW9yZy9teS1yZXBvOnJlZjpyZWZzL2hlYWRzL21haW4nLFxuICogICAgIH0sXG4gKiAgIH0sXG4gKiB9O1xuICpcbiAqIC8vIENyZWF0ZSBhIG5ldyBPSURDIHByb3ZpZGVyIGlubGluZSAoR2l0SHViIEFjdGlvbnMpXG4gKiBjb25zdCByb2xlOiBPaWRjUm9sZUNvbmZpZyA9IHtcbiAqICAgdHlwZTogJ29pZGMnLFxuICogICBvcHRpb25zOiB7XG4gKiAgICAgaXNzdWVyOiAnaHR0cHM6Ly90b2tlbi5hY3Rpb25zLmdpdGh1YnVzZXJjb250ZW50LmNvbScsXG4gKiAgICAgY2xpZW50SWRzOiBbJ3N0cy5hbWF6b25hd3MuY29tJ10sXG4gKiAgICAgdGh1bWJwcmludHM6IFsnNjkzOGZkNGQ5OGJhYjAzZmFhZGI5N2IzNDM5NjgzMWUzNzgwYWVhMSddLFxuICogICAgIGNvbmRpdGlvbnM6IHtcbiAqICAgICAgICd0b2tlbi5hY3Rpb25zLmdpdGh1YnVzZXJjb250ZW50LmNvbTpzdWInOiAncmVwbzpteS1vcmcvbXktcmVwbzpyZWY6cmVmcy9oZWFkcy9tYWluJyxcbiAqICAgICB9LFxuICogICB9LFxuICogfTtcbiAqIGBgYFxuICovXG5leHBvcnQgaW50ZXJmYWNlIE9pZGNSb2xlQ29uZmlnIHtcbiAgcmVhZG9ubHkgdHlwZTogJ29pZGMnO1xuICByZWFkb25seSBvcHRpb25zOiBPaWRjUm9sZU9wdGlvbnM7XG59XG5cbi8qKlxuICogQ29uZmlndXJhdGlvbiBvcHRpb25zIGZvciBPSURDIGZlZGVyYXRlZCByb2xlIGFzc3VtcHRpb24uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgT2lkY1JvbGVPcHRpb25zIHtcbiAgLyoqXG4gICAqIEFSTiBvZiBhbiBleGlzdGluZyBJQU0gT0lEQyBpZGVudGl0eSBwcm92aWRlci5cbiAgICogTXV0dWFsbHkgZXhjbHVzaXZlIHdpdGggYGlzc3VlcmAuXG4gICAqIEBleGFtcGxlICdhcm46YXdzOmlhbTo6MTIzNDU2Nzg5MDEyOm9pZGMtcHJvdmlkZXIvdG9rZW4uYWN0aW9ucy5naXRodWJ1c2VyY29udGVudC5jb20nXG4gICAqL1xuICByZWFkb25seSBwcm92aWRlckFybj86IHN0cmluZztcblxuICAvKipcbiAgICogT0lEQyBpc3N1ZXIgVVJMIGZvciBjcmVhdGluZyBhIG5ldyBwcm92aWRlci5cbiAgICogTXV0dWFsbHkgZXhjbHVzaXZlIHdpdGggYHByb3ZpZGVyQXJuYC5cbiAgICogQGV4YW1wbGUgJ2h0dHBzOi8vdG9rZW4uYWN0aW9ucy5naXRodWJ1c2VyY29udGVudC5jb20nXG4gICAqL1xuICByZWFkb25seSBpc3N1ZXI/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIENsaWVudCBJRHMgKGF1ZGllbmNlcykgdHJ1c3RlZCBieSB0aGUgT0lEQyBwcm92aWRlci5cbiAgICogUmVxdWlyZWQgd2hlbiB1c2luZyBgaXNzdWVyYCB0byBjcmVhdGUgYSBuZXcgcHJvdmlkZXIuXG4gICAqIEBleGFtcGxlIFsnc3RzLmFtYXpvbmF3cy5jb20nXVxuICAgKi9cbiAgcmVhZG9ubHkgY2xpZW50SWRzPzogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIFRMUyBjZXJ0aWZpY2F0ZSB0aHVtYnByaW50cyBmb3IgdGhlIE9JREMgcHJvdmlkZXIuXG4gICAqIFJlcXVpcmVkIHdoZW4gdXNpbmcgYGlzc3VlcmAgdG8gY3JlYXRlIGEgbmV3IHByb3ZpZGVyLlxuICAgKi9cbiAgcmVhZG9ubHkgdGh1bWJwcmludHM/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogU3RyaW5nRXF1YWxzIGNvbmRpdGlvbnMgZm9yIHRoZSBhc3N1bWUtcm9sZSB0cnVzdCBwb2xpY3kuXG4gICAqIEtleXMgYXJlIHRoZSBjb25kaXRpb24gY2xhaW0sIHZhbHVlcyBhcmUgdGhlIGV4cGVjdGVkIGNsYWltIHZhbHVlKHMpLlxuICAgKiBAZXhhbXBsZSB7ICd0b2tlbi5hY3Rpb25zLmdpdGh1YnVzZXJjb250ZW50LmNvbTpzdWInOiAncmVwbzpteS1vcmcvbXktcmVwbzpyZWY6cmVmcy9oZWFkcy9tYWluJyB9XG4gICAqL1xuICByZWFkb25seSBjb25kaXRpb25zPzogUmVjb3JkPHN0cmluZywgc3RyaW5nIHwgc3RyaW5nW10+O1xuXG4gIC8qKlxuICAgKiBTdHJpbmdMaWtlIGNvbmRpdGlvbnMgZm9yIHdpbGRjYXJkIG1hdGNoaW5nIGluIHRoZSB0cnVzdCBwb2xpY3kuXG4gICAqIEBleGFtcGxlIHsgJ3Rva2VuLmFjdGlvbnMuZ2l0aHVidXNlcmNvbnRlbnQuY29tOnN1Yic6ICdyZXBvOm15LW9yZy8qJyB9XG4gICAqL1xuICByZWFkb25seSBjb25kaXRpb25zTGlrZT86IFJlY29yZDxzdHJpbmcsIHN0cmluZyB8IHN0cmluZ1tdPjtcblxuICAvKipcbiAgICogT3B0aW9uYWwgY3VzdG9tIHJvbGUgbmFtZS5cbiAgICogV2hlbiBvbWl0dGVkLCBDREsgZ2VuZXJhdGVzIGEgdW5pcXVlIG5hbWUuXG4gICAqL1xuICByZWFkb25seSByb2xlTmFtZT86IHN0cmluZztcblxuICAvKipcbiAgICogT3B0aW9uYWwgZGVzY3JpcHRpb24gZm9yIHRoZSBJQU0gcm9sZS5cbiAgICogQXBwZWFycyBpbiB0aGUgQVdTIGNvbnNvbGUgYW5kIEFQSSByZXNwb25zZXMuXG4gICAqIEBleGFtcGxlICdPSURDIHJvbGUgZm9yIEdpdEh1YiBBY3Rpb25zIENJL0NEIHBpcGVsaW5lJ1xuICAgKi9cbiAgcmVhZG9ubHkgZGVzY3JpcHRpb24/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIE1heGltdW0gc2Vzc2lvbiBkdXJhdGlvbiBpbiBzZWNvbmRzIGZvciB0aGUgYXNzdW1lZCByb2xlLlxuICAgKiBDb250cm9scyBob3cgbG9uZyB0aGUgdGVtcG9yYXJ5IGNyZWRlbnRpYWxzIHJlbWFpbiB2YWxpZC5cbiAgICogTXVzdCBiZSBiZXR3ZWVuIDM2MDAgKDEgaG91cikgYW5kIDQzMjAwICgxMiBob3VycykuXG4gICAqIEBkZWZhdWx0IDM2MDAgKDEgaG91ciwgQVdTIGRlZmF1bHQpXG4gICAqL1xuICByZWFkb25seSBtYXhTZXNzaW9uRHVyYXRpb24/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIEFSTiBvZiBhbiBJQU0gcGVybWlzc2lvbnMgYm91bmRhcnkgdG8gYXR0YWNoIHRvIHRoZSByb2xlLlxuICAgKiBSZXF1aXJlZCBpbiBtYW55IGVudGVycHJpc2UgQVdTIGVudmlyb25tZW50cyB0byBsaW1pdCBtYXhpbXVtIHBlcm1pc3Npb25zLlxuICAgKiBAZXhhbXBsZSAnYXJuOmF3czppYW06OjEyMzQ1Njc4OTAxMjpwb2xpY3kvRGV2ZWxvcGVyQm91bmRhcnknXG4gICAqL1xuICByZWFkb25seSBwZXJtaXNzaW9uc0JvdW5kYXJ5QXJuPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBPcHRpb25hbCBtYW5hZ2VkIHBvbGljeSBBUk5zIHRvIGF0dGFjaCB0byB0aGUgcm9sZS5cbiAgICovXG4gIHJlYWRvbmx5IG1hbmFnZWRQb2xpY3lBcm5zPzogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIElubGluZSBJQU0gcG9saWN5IHN0YXRlbWVudHMgdG8gYXR0YWNoIHRvIHRoZSByb2xlLlxuICAgKiBFYWNoIGVudHJ5IGRlZmluZXMgYW4gSUFNIHBvbGljeSBzdGF0ZW1lbnQgd2l0aCBlZmZlY3QsIGFjdGlvbnMsIGFuZCByZXNvdXJjZXMuXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogcG9saWN5U3RhdGVtZW50czogW1xuICAgKiAgIHsgYWN0aW9uczogWydzMzpHZXRPYmplY3QnXSwgcmVzb3VyY2VzOiBbJ2Fybjphd3M6czM6OjpteS1idWNrZXQvKiddIH0sXG4gICAqICAgeyBhY3Rpb25zOiBbJ2xvZ3M6Q3JlYXRlTG9nR3JvdXAnLCAnbG9nczpQdXRMb2dFdmVudHMnXSwgcmVzb3VyY2VzOiBbJyonXSB9LFxuICAgKiBdXG4gICAqIGBgYFxuICAgKi9cbiAgcmVhZG9ubHkgcG9saWN5U3RhdGVtZW50cz86IE9pZGNQb2xpY3lTdGF0ZW1lbnRbXTtcbn1cblxuLyoqXG4gKiBBbiBpbmxpbmUgSUFNIHBvbGljeSBzdGF0ZW1lbnQgZm9yIE9JREMgcm9sZXMuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgT2lkY1BvbGljeVN0YXRlbWVudCB7XG4gIC8qKlxuICAgKiBJQU0gZWZmZWN0LiBEZWZhdWx0cyB0byAnQWxsb3cnLlxuICAgKi9cbiAgcmVhZG9ubHkgZWZmZWN0PzogJ0FsbG93JyB8ICdEZW55JztcblxuICAvKipcbiAgICogSUFNIGFjdGlvbnMgKGUuZy4gJ3MzOkdldE9iamVjdCcsICdsb2dzOionKS5cbiAgICovXG4gIHJlYWRvbmx5IGFjdGlvbnM6IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBJQU0gcmVzb3VyY2UgQVJOcyB0aGlzIHN0YXRlbWVudCBhcHBsaWVzIHRvLlxuICAgKi9cbiAgcmVhZG9ubHkgcmVzb3VyY2VzOiBzdHJpbmdbXTtcbn1cblxuLyoqXG4gKiBVbmlvbiB0eXBlIG9mIGFsbCBzdXBwb3J0ZWQgcm9sZSBjb25maWd1cmF0aW9ucy5cbiAqXG4gKiBVc2VkIGF0IHRoZSBwaXBlbGluZSBsZXZlbCAoYEJ1aWxkZXJQcm9wcy5yb2xlYCkgdG8gc3BlY2lmeSB0aGUgSUFNIHJvbGVcbiAqIGZvciB0aGUgQ29kZVBpcGVsaW5lIGNvbnN0cnVjdC5cbiAqXG4gKiBFYWNoIHZhcmlhbnQgcmVzb2x2ZXMgdG8gYSBDREsgYElSb2xlYDpcbiAqIC0gUm9sZUFybkNvbmZpZzogUm9sZSBsb29rZWQgdXAgYnkgQVJOXG4gKiAtIFJvbGVOYW1lQ29uZmlnOiBSb2xlIGxvb2tlZCB1cCBieSBuYW1lXG4gKiAtIENvZGVCdWlsZERlZmF1bHRSb2xlQ29uZmlnOiBDcmVhdGVzIGEgbmV3IHJvbGUgd2l0aCBDb2RlQnVpbGQgdHJ1c3QgKyBDbG91ZFdhdGNoIExvZ3NcbiAqIC0gT2lkY1JvbGVDb25maWc6IENyZWF0ZXMgYSBuZXcgcm9sZSB3aXRoIE9JREMgZmVkZXJhdGVkIHRydXN0IChubyBzdGF0aWMgQVJOIG5lZWRlZClcbiAqL1xuZXhwb3J0IHR5cGUgUm9sZUNvbmZpZyA9IFJvbGVBcm5Db25maWcgfCBSb2xlTmFtZUNvbmZpZyB8IENvZGVCdWlsZERlZmF1bHRSb2xlQ29uZmlnIHwgT2lkY1JvbGVDb25maWc7XG4iXX0=
@@ -0,0 +1,14 @@
1
+ import { IRole } from 'aws-cdk-lib/aws-iam';
2
+ import { Construct } from 'constructs';
3
+ import { UniqueId } from './id-generator';
4
+ import type { RoleConfig } from './role-types';
5
+ /**
6
+ * Resolve a RoleConfig into a CDK IRole.
7
+ * Uses discriminated union narrowing to delegate to the appropriate CDK lookup.
8
+ *
9
+ * @param scope - CDK construct scope
10
+ * @param id - UniqueId instance for generating unique construct IDs
11
+ * @param config - Role configuration to resolve
12
+ * @returns Resolved CDK IRole ready to pass to CodePipeline
13
+ */
14
+ export declare function resolveRole(scope: Construct, id: UniqueId, config: RoleConfig): IRole;
@@ -0,0 +1,118 @@
1
+ "use strict";
2
+ // Copyright 2026 Pipeline Builder Contributors
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.resolveRole = resolveRole;
6
+ const aws_cdk_lib_1 = require("aws-cdk-lib");
7
+ const aws_iam_1 = require("aws-cdk-lib/aws-iam");
8
+ const app_config_1 = require("../config/app-config");
9
+ /**
10
+ * Resolve a RoleConfig into a CDK IRole.
11
+ * Uses discriminated union narrowing to delegate to the appropriate CDK lookup.
12
+ *
13
+ * @param scope - CDK construct scope
14
+ * @param id - UniqueId instance for generating unique construct IDs
15
+ * @param config - Role configuration to resolve
16
+ * @returns Resolved CDK IRole ready to pass to CodePipeline
17
+ */
18
+ function resolveRole(scope, id, config) {
19
+ switch (config.type) {
20
+ case 'roleArn':
21
+ return aws_iam_1.Role.fromRoleArn(scope, id.generate('role:arn'), config.options.roleArn, {
22
+ mutable: config.options.mutable,
23
+ });
24
+ case 'roleName':
25
+ return aws_iam_1.Role.fromRoleName(scope, id.generate('role:name'), config.options.roleName, {
26
+ mutable: config.options.mutable,
27
+ });
28
+ case 'codeBuildDefault':
29
+ return createCodeBuildDefaultRole(scope, id, config.options);
30
+ case 'oidc':
31
+ return createOidcRole(scope, id, config.options);
32
+ default: {
33
+ const _exhaustive = config;
34
+ throw new Error(`Unknown role config type: ${_exhaustive.type}`);
35
+ }
36
+ }
37
+ }
38
+ /**
39
+ * Creates a new IAM role with CodeBuild service principal and CloudWatch Logs permissions.
40
+ */
41
+ function createCodeBuildDefaultRole(scope, id, options) {
42
+ const role = new aws_iam_1.Role(scope, id.generate('role:codebuild'), {
43
+ assumedBy: new aws_iam_1.ServicePrincipal('codebuild.amazonaws.com'),
44
+ ...(options.roleName && { roleName: options.roleName }),
45
+ });
46
+ const stack = aws_cdk_lib_1.Stack.of(scope);
47
+ const logGroupPrefix = app_config_1.Config.get('aws').logging.groupName;
48
+ // Derive ARN pattern from the configured log group name (strip trailing segment for wildcard)
49
+ const logGroupPattern = logGroupPrefix.replace(/\/[^/]*$/, '/*');
50
+ role.addToPolicy(new aws_iam_1.PolicyStatement({
51
+ effect: aws_iam_1.Effect.ALLOW,
52
+ actions: [
53
+ 'logs:CreateLogGroup',
54
+ 'logs:CreateLogStream',
55
+ 'logs:PutLogEvents',
56
+ ],
57
+ resources: [
58
+ `arn:aws:logs:${stack.region}:${stack.account}:log-group:${logGroupPattern}:*`,
59
+ ],
60
+ }));
61
+ return role;
62
+ }
63
+ /**
64
+ * Creates a new IAM role with an OIDC federated trust principal.
65
+ *
66
+ * Supports either referencing an existing OIDC provider by ARN
67
+ * or creating a new one from issuer URL + client IDs.
68
+ */
69
+ function createOidcRole(scope, id, options) {
70
+ if (options.providerArn && options.issuer) {
71
+ throw new Error('OIDC role config must specify either providerArn or issuer, not both');
72
+ }
73
+ let provider;
74
+ if (options.providerArn) {
75
+ provider = aws_iam_1.OpenIdConnectProvider.fromOpenIdConnectProviderArn(scope, id.generate('oidc:provider'), options.providerArn);
76
+ }
77
+ else if (options.issuer) {
78
+ provider = new aws_iam_1.OpenIdConnectProvider(scope, id.generate('oidc:provider'), {
79
+ url: options.issuer,
80
+ clientIds: options.clientIds ?? ['sts.amazonaws.com'],
81
+ thumbprints: options.thumbprints,
82
+ });
83
+ }
84
+ else {
85
+ throw new Error('OIDC role config requires either providerArn or issuer');
86
+ }
87
+ const principal = new aws_iam_1.OpenIdConnectPrincipal(provider, {
88
+ ...(options.conditions && { StringEquals: options.conditions }),
89
+ ...(options.conditionsLike && { StringLike: options.conditionsLike }),
90
+ });
91
+ const role = new aws_iam_1.Role(scope, id.generate('role:oidc'), {
92
+ assumedBy: principal,
93
+ ...(options.roleName && { roleName: options.roleName }),
94
+ ...(options.description && { description: options.description }),
95
+ ...(options.maxSessionDuration && {
96
+ maxSessionDuration: aws_cdk_lib_1.Duration.seconds(options.maxSessionDuration),
97
+ }),
98
+ ...(options.permissionsBoundaryArn && {
99
+ permissionsBoundary: aws_iam_1.ManagedPolicy.fromManagedPolicyArn(scope, id.generate('oidc:boundary'), options.permissionsBoundaryArn),
100
+ }),
101
+ });
102
+ if (options.managedPolicyArns) {
103
+ for (const arn of options.managedPolicyArns) {
104
+ role.addManagedPolicy(aws_iam_1.ManagedPolicy.fromManagedPolicyArn(scope, id.generate('oidc:policy'), arn));
105
+ }
106
+ }
107
+ if (options.policyStatements) {
108
+ for (const stmt of options.policyStatements) {
109
+ role.addToPolicy(new aws_iam_1.PolicyStatement({
110
+ effect: stmt.effect === 'Deny' ? aws_iam_1.Effect.DENY : aws_iam_1.Effect.ALLOW,
111
+ actions: stmt.actions,
112
+ resources: stmt.resources,
113
+ }));
114
+ }
115
+ }
116
+ return role;
117
+ }
118
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm9sZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb3JlL3JvbGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7O0FBNEJ0QyxrQ0F1QkM7QUFqREQsNkNBQThDO0FBQzlDLGlEQVU2QjtBQUk3QixxREFBOEM7QUFFOUM7Ozs7Ozs7O0dBUUc7QUFDSCxTQUFnQixXQUFXLENBQ3pCLEtBQWdCLEVBQ2hCLEVBQVksRUFDWixNQUFrQjtJQUVsQixRQUFRLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUNwQixLQUFLLFNBQVM7WUFDWixPQUFPLGNBQUksQ0FBQyxXQUFXLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLEVBQUUsTUFBTSxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUU7Z0JBQzlFLE9BQU8sRUFBRSxNQUFNLENBQUMsT0FBTyxDQUFDLE9BQU87YUFDaEMsQ0FBQyxDQUFDO1FBQ0wsS0FBSyxVQUFVO1lBQ2IsT0FBTyxjQUFJLENBQUMsWUFBWSxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxPQUFPLENBQUMsUUFBUSxFQUFFO2dCQUNqRixPQUFPLEVBQUUsTUFBTSxDQUFDLE9BQU8sQ0FBQyxPQUFPO2FBQ2hDLENBQUMsQ0FBQztRQUNMLEtBQUssa0JBQWtCO1lBQ3JCLE9BQU8sMEJBQTBCLENBQUMsS0FBSyxFQUFFLEVBQUUsRUFBRSxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDL0QsS0FBSyxNQUFNO1lBQ1QsT0FBTyxjQUFjLENBQUMsS0FBSyxFQUFFLEVBQUUsRUFBRSxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDbkQsT0FBTyxDQUFDLENBQUMsQ0FBQztZQUNSLE1BQU0sV0FBVyxHQUFVLE1BQU0sQ0FBQztZQUNsQyxNQUFNLElBQUksS0FBSyxDQUFDLDZCQUE4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QUFDLEtBQUs7Z0JBQzNELE9BQU8sRUFBRSxJQUFJLENBQUMsT0FBTztnQkFDckIsU0FBUyxFQUFFLElBQUksQ0FBQyxTQUFTO2FBQzFCLENBQUMsQ0FDSCxDQUFDO1FBQ0osQ0FBQztJQUNILENBQUM7SUFFRCxPQUFPLElBQUksQ0FBQztBQUNkLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuaW1wb3J0IHsgRHVyYXRpb24sIFN0YWNrIH0gZnJvbSAnYXdzLWNkay1saWInO1xuaW1wb3J0IHtcbiAgRWZmZWN0LFxuICBJT3BlbklkQ29ubmVjdFByb3ZpZGVyLFxuICBJUm9sZSxcbiAgTWFuYWdlZFBvbGljeSxcbiAgT3BlbklkQ29ubmVjdFByaW5jaXBhbCxcbiAgT3BlbklkQ29ubmVjdFByb3ZpZGVyLFxuICBQb2xpY3lTdGF0ZW1lbnQsXG4gIFJvbGUsXG4gIFNlcnZpY2VQcmluY2lwYWwsXG59IGZyb20gJ2F3cy1jZGstbGliL2F3cy1pYW0nO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgeyBVbmlxdWVJZCB9IGZyb20gJy4vaWQtZ2VuZXJhdG9yJztcbmltcG9ydCB0eXBlIHsgQ29kZUJ1aWxkRGVmYXVsdFJvbGVPcHRpb25zLCBPaWRjUm9sZU9wdGlvbnMsIFJvbGVDb25maWcgfSBmcm9tICcuL3JvbGUtdHlwZXMnO1xuaW1wb3J0IHsgQ29uZmlnIH0gZnJvbSAnLi4vY29uZmlnL2FwcC1jb25maWcnO1xuXG4vKipcbiAqIFJlc29sdmUgYSBSb2xlQ29uZmlnIGludG8gYSBDREsgSVJvbGUuXG4gKiBVc2VzIGRpc2NyaW1pbmF0ZWQgdW5pb24gbmFycm93aW5nIHRvIGRlbGVnYXRlIHRvIHRoZSBhcHByb3ByaWF0ZSBDREsgbG9va3VwLlxuICpcbiAqIEBwYXJhbSBzY29wZSAtIENESyBjb25zdHJ1Y3Qgc2NvcGVcbiAqIEBwYXJhbSBpZCAtIFVuaXF1ZUlkIGluc3RhbmNlIGZvciBnZW5lcmF0aW5nIHVuaXF1ZSBjb25zdHJ1Y3QgSURzXG4gKiBAcGFyYW0gY29uZmlnIC0gUm9sZSBjb25maWd1cmF0aW9uIHRvIHJlc29sdmVcbiAqIEByZXR1cm5zIFJlc29sdmVkIENESyBJUm9sZSByZWFkeSB0byBwYXNzIHRvIENvZGVQaXBlbGluZVxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVzb2x2ZVJvbGUoXG4gIHNjb3BlOiBDb25zdHJ1Y3QsXG4gIGlkOiBVbmlxdWVJZCxcbiAgY29uZmlnOiBSb2xlQ29uZmlnLFxuKTogSVJvbGUge1xuICBzd2l0Y2ggKGNvbmZpZy50eXBlKSB7XG4gICAgY2FzZSAncm9sZUFybic6XG4gICAgICByZXR1cm4gUm9sZS5mcm9tUm9sZUFybihzY29wZSwgaWQuZ2VuZXJhdGUoJ3JvbGU6YXJuJyksIGNvbmZpZy5vcHRpb25zLnJvbGVBcm4sIHtcbiAgICAgICAgbXV0YWJsZTogY29uZmlnLm9wdGlvbnMubXV0YWJsZSxcbiAgICAgIH0pO1xuICAgIGNhc2UgJ3JvbGVOYW1lJzpcbiAgICAgIHJldHVybiBSb2xlLmZyb21Sb2xlTmFtZShzY29wZSwgaWQuZ2VuZXJhdGUoJ3JvbGU6bmFtZScpLCBjb25maWcub3B0aW9ucy5yb2xlTmFtZSwge1xuICAgICAgICBtdXRhYmxlOiBjb25maWcub3B0aW9ucy5tdXRhYmxlLFxuICAgICAgfSk7XG4gICAgY2FzZSAnY29kZUJ1aWxkRGVmYXVsdCc6XG4gICAgICByZXR1cm4gY3JlYXRlQ29kZUJ1aWxkRGVmYXVsdFJvbGUoc2NvcGUsIGlkLCBjb25maWcub3B0aW9ucyk7XG4gICAgY2FzZSAnb2lkYyc6XG4gICAgICByZXR1cm4gY3JlYXRlT2lkY1JvbGUoc2NvcGUsIGlkLCBjb25maWcub3B0aW9ucyk7XG4gICAgZGVmYXVsdDoge1xuICAgICAgY29uc3QgX2V4aGF1c3RpdmU6IG5ldmVyID0gY29uZmlnO1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmtub3duIHJvbGUgY29uZmlnIHR5cGU6ICR7KF9leGhhdXN0aXZlIGFzIFJvbGVDb25maWcpLnR5cGV9YCk7XG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogQ3JlYXRlcyBhIG5ldyBJQU0gcm9sZSB3aXRoIENvZGVCdWlsZCBzZXJ2aWNlIHByaW5jaXBhbCBhbmQgQ2xvdWRXYXRjaCBMb2dzIHBlcm1pc3Npb25zLlxuICovXG5mdW5jdGlvbiBjcmVhdGVDb2RlQnVpbGREZWZhdWx0Um9sZShcbiAgc2NvcGU6IENvbnN0cnVjdCxcbiAgaWQ6IFVuaXF1ZUlkLFxuICBvcHRpb25zOiBDb2RlQnVpbGREZWZhdWx0Um9sZU9wdGlvbnMsXG4pOiBJUm9sZSB7XG4gIGNvbnN0IHJvbGUgPSBuZXcgUm9sZShzY29wZSwgaWQuZ2VuZXJhdGUoJ3JvbGU6Y29kZWJ1aWxkJyksIHtcbiAgICBhc3N1bWVkQnk6IG5ldyBTZXJ2aWNlUHJpbmNpcGFsKCdjb2RlYnVpbGQuYW1hem9uYXdzLmNvbScpLFxuICAgIC4uLihvcHRpb25zLnJvbGVOYW1lICYmIHsgcm9sZU5hbWU6IG9wdGlvbnMucm9sZU5hbWUgfSksXG4gIH0pO1xuXG4gIGNvbnN0IHN0YWNrID0gU3RhY2sub2Yoc2NvcGUpO1xuICBjb25zdCBsb2dHcm91cFByZWZpeCA9IENvbmZpZy5nZXQoJ2F3cycpLmxvZ2dpbmcuZ3JvdXBOYW1lO1xuICAvLyBEZXJpdmUgQVJOIHBhdHRlcm4gZnJvbSB0aGUgY29uZmlndXJlZCBsb2cgZ3JvdXAgbmFtZSAoc3RyaXAgdHJhaWxpbmcgc2VnbWVudCBmb3Igd2lsZGNhcmQpXG4gIGNvbnN0IGxvZ0dyb3VwUGF0dGVybiA9IGxvZ0dyb3VwUHJlZml4LnJlcGxhY2UoL1xcL1teL10qJC8sICcvKicpO1xuICByb2xlLmFkZFRvUG9saWN5KFxuICAgIG5ldyBQb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgZWZmZWN0OiBFZmZlY3QuQUxMT1csXG4gICAgICBhY3Rpb25zOiBbXG4gICAgICAgICdsb2dzOkNyZWF0ZUxvZ0dyb3VwJyxcbiAgICAgICAgJ2xvZ3M6Q3JlYXRlTG9nU3RyZWFtJyxcbiAgICAgICAgJ2xvZ3M6UHV0TG9nRXZlbnRzJyxcbiAgICAgIF0sXG4gICAgICByZXNvdXJjZXM6IFtcbiAgICAgICAgYGFybjphd3M6bG9nczoke3N0YWNrLnJlZ2lvbn06JHtzdGFjay5hY2NvdW50fTpsb2ctZ3JvdXA6JHtsb2dHcm91cFBhdHRlcm59OipgLFxuICAgICAgXSxcbiAgICB9KSxcbiAgKTtcblxuICByZXR1cm4gcm9sZTtcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgbmV3IElBTSByb2xlIHdpdGggYW4gT0lEQyBmZWRlcmF0ZWQgdHJ1c3QgcHJpbmNpcGFsLlxuICpcbiAqIFN1cHBvcnRzIGVpdGhlciByZWZlcmVuY2luZyBhbiBleGlzdGluZyBPSURDIHByb3ZpZGVyIGJ5IEFSTlxuICogb3IgY3JlYXRpbmcgYSBuZXcgb25lIGZyb20gaXNzdWVyIFVSTCArIGNsaWVudCBJRHMuXG4gKi9cbmZ1bmN0aW9uIGNyZWF0ZU9pZGNSb2xlKFxuICBzY29wZTogQ29uc3RydWN0LFxuICBpZDogVW5pcXVlSWQsXG4gIG9wdGlvbnM6IE9pZGNSb2xlT3B0aW9ucyxcbik6IElSb2xlIHtcbiAgaWYgKG9wdGlvbnMucHJvdmlkZXJBcm4gJiYgb3B0aW9ucy5pc3N1ZXIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ09JREMgcm9sZSBjb25maWcgbXVzdCBzcGVjaWZ5IGVpdGhlciBwcm92aWRlckFybiBvciBpc3N1ZXIsIG5vdCBib3RoJyk7XG4gIH1cblxuICBsZXQgcHJvdmlkZXI6IElPcGVuSWRDb25uZWN0UHJvdmlkZXI7XG5cbiAgaWYgKG9wdGlvbnMucHJvdmlkZXJBcm4pIHtcbiAgICBwcm92aWRlciA9IE9wZW5JZENvbm5lY3RQcm92aWRlci5mcm9tT3BlbklkQ29ubmVjdFByb3ZpZGVyQXJuKFxuICAgICAgc2NvcGUsXG4gICAgICBpZC5nZW5lcmF0ZSgnb2lkYzpwcm92aWRlcicpLFxuICAgICAgb3B0aW9ucy5wcm92aWRlckFybixcbiAgICApO1xuICB9IGVsc2UgaWYgKG9wdGlvbnMuaXNzdWVyKSB7XG4gICAgcHJvdmlkZXIgPSBuZXcgT3BlbklkQ29ubmVjdFByb3ZpZGVyKHNjb3BlLCBpZC5nZW5lcmF0ZSgnb2lkYzpwcm92aWRlcicpLCB7XG4gICAgICB1cmw6IG9wdGlvbnMuaXNzdWVyLFxuICAgICAgY2xpZW50SWRzOiBvcHRpb25zLmNsaWVudElkcyA/PyBbJ3N0cy5hbWF6b25hd3MuY29tJ10sXG4gICAgICB0aHVtYnByaW50czogb3B0aW9ucy50aHVtYnByaW50cyxcbiAgICB9KTtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ09JREMgcm9sZSBjb25maWcgcmVxdWlyZXMgZWl0aGVyIHByb3ZpZGVyQXJuIG9yIGlzc3VlcicpO1xuICB9XG5cbiAgY29uc3QgcHJpbmNpcGFsID0gbmV3IE9wZW5JZENvbm5lY3RQcmluY2lwYWwocHJvdmlkZXIsIHtcbiAgICAuLi4ob3B0aW9ucy5jb25kaXRpb25zICYmIHsgU3RyaW5nRXF1YWxzOiBvcHRpb25zLmNvbmRpdGlvbnMgfSksXG4gICAgLi4uKG9wdGlvbnMuY29uZGl0aW9uc0xpa2UgJiYgeyBTdHJpbmdMaWtlOiBvcHRpb25zLmNvbmRpdGlvbnNMaWtlIH0pLFxuICB9KTtcblxuICBjb25zdCByb2xlID0gbmV3IFJvbGUoc2NvcGUsIGlkLmdlbmVyYXRlKCdyb2xlOm9pZGMnKSwge1xuICAgIGFzc3VtZWRCeTogcHJpbmNpcGFsLFxuICAgIC4uLihvcHRpb25zLnJvbGVOYW1lICYmIHsgcm9sZU5hbWU6IG9wdGlvbnMucm9sZU5hbWUgfSksXG4gICAgLi4uKG9wdGlvbnMuZGVzY3JpcHRpb24gJiYgeyBkZXNjcmlwdGlvbjogb3B0aW9ucy5kZXNjcmlwdGlvbiB9KSxcbiAgICAuLi4ob3B0aW9ucy5tYXhTZXNzaW9uRHVyYXRpb24gJiYge1xuICAgICAgbWF4U2Vzc2lvbkR1cmF0aW9uOiBEdXJhdGlvbi5zZWNvbmRzKG9wdGlvbnMubWF4U2Vzc2lvbkR1cmF0aW9uKSxcbiAgICB9KSxcbiAgICAuLi4ob3B0aW9ucy5wZXJtaXNzaW9uc0JvdW5kYXJ5QXJuICYmIHtcbiAgICAgIHBlcm1pc3Npb25zQm91bmRhcnk6IE1hbmFnZWRQb2xpY3kuZnJvbU1hbmFnZWRQb2xpY3lBcm4oXG4gICAgICAgIHNjb3BlLFxuICAgICAgICBpZC5nZW5lcmF0ZSgnb2lkYzpib3VuZGFyeScpLFxuICAgICAgICBvcHRpb25zLnBlcm1pc3Npb25zQm91bmRhcnlBcm4sXG4gICAgICApLFxuICAgIH0pLFxuICB9KTtcblxuICBpZiAob3B0aW9ucy5tYW5hZ2VkUG9saWN5QXJucykge1xuICAgIGZvciAoY29uc3QgYXJuIG9mIG9wdGlvbnMubWFuYWdlZFBvbGljeUFybnMpIHtcbiAgICAgIHJvbGUuYWRkTWFuYWdlZFBvbGljeShNYW5hZ2VkUG9saWN5LmZyb21NYW5hZ2VkUG9saWN5QXJuKHNjb3BlLCBpZC5nZW5lcmF0ZSgnb2lkYzpwb2xpY3knKSwgYXJuKSk7XG4gICAgfVxuICB9XG5cbiAgaWYgKG9wdGlvbnMucG9saWN5U3RhdGVtZW50cykge1xuICAgIGZvciAoY29uc3Qgc3RtdCBvZiBvcHRpb25zLnBvbGljeVN0YXRlbWVudHMpIHtcbiAgICAgIHJvbGUuYWRkVG9Qb2xpY3koXG4gICAgICAgIG5ldyBQb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICAgIGVmZmVjdDogc3RtdC5lZmZlY3QgPT09ICdEZW55JyA/IEVmZmVjdC5ERU5ZIDogRWZmZWN0LkFMTE9XLFxuICAgICAgICAgIGFjdGlvbnM6IHN0bXQuYWN0aW9ucyxcbiAgICAgICAgICByZXNvdXJjZXM6IHN0bXQucmVzb3VyY2VzLFxuICAgICAgICB9KSxcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJvbGU7XG59XG4iXX0=
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Security group configuration using explicit security group IDs
3
+ *
4
+ * Looks up existing security groups by their IDs via `SecurityGroup.fromSecurityGroupId`.
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * const sg: SecurityGroupIdsConfig = {
9
+ * type: 'securityGroupIds',
10
+ * options: {
11
+ * securityGroupIds: ['sg-12345678', 'sg-87654321'],
12
+ * }
13
+ * };
14
+ * ```
15
+ */
16
+ export interface SecurityGroupIdsConfig {
17
+ readonly type: 'securityGroupIds';
18
+ readonly options: SecurityGroupIdsOptions;
19
+ }
20
+ /**
21
+ * Security group configuration using name-based lookup
22
+ *
23
+ * Looks up an existing security group by name and VPC ID
24
+ * via `SecurityGroup.fromLookupByName`.
25
+ *
26
+ * @example
27
+ * ```typescript
28
+ * const sg: SecurityGroupLookupConfig = {
29
+ * type: 'securityGroupLookup',
30
+ * options: {
31
+ * securityGroupName: 'my-codebuild-sg',
32
+ * vpcId: 'vpc-0a1b2c3d4e5f6a7b8',
33
+ * }
34
+ * };
35
+ * ```
36
+ */
37
+ export interface SecurityGroupLookupConfig {
38
+ readonly type: 'securityGroupLookup';
39
+ readonly options: SecurityGroupLookupOptions;
40
+ }
41
+ /**
42
+ * Configuration options for security group lookup by IDs
43
+ */
44
+ export interface SecurityGroupIdsOptions {
45
+ /**
46
+ * List of security group IDs
47
+ * @example ['sg-12345678', 'sg-87654321']
48
+ */
49
+ readonly securityGroupIds: string[];
50
+ /**
51
+ * Whether the imported security groups can be modified by attaching
52
+ * ingress/egress rules. Set to false to avoid additional API calls
53
+ * during synthesis.
54
+ * @default true
55
+ */
56
+ readonly mutable?: boolean;
57
+ }
58
+ /**
59
+ * Configuration options for security group lookup by name
60
+ */
61
+ export interface SecurityGroupLookupOptions {
62
+ /**
63
+ * Name of the security group to look up
64
+ * @example 'my-codebuild-sg'
65
+ */
66
+ readonly securityGroupName: string;
67
+ /**
68
+ * VPC ID that contains the security group.
69
+ * Required for name-based lookup.
70
+ * @example 'vpc-0a1b2c3d4e5f6a7b8'
71
+ */
72
+ readonly vpcId: string;
73
+ }
74
+ /**
75
+ * Union type of all supported security group configurations.
76
+ *
77
+ * Used at the pipeline level (`CodeBuildDefaults.securityGroups`) to specify
78
+ * security groups for CodeBuild actions.
79
+ *
80
+ * Each variant resolves to CDK `ISecurityGroup[]`:
81
+ * - SecurityGroupIdsConfig: Security groups looked up by IDs
82
+ * - SecurityGroupLookupConfig: Security group looked up by name + VPC
83
+ */
84
+ export type SecurityGroupConfig = SecurityGroupIdsConfig | SecurityGroupLookupConfig;
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ // Copyright 2026 Pipeline Builder Contributors
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VjdXJpdHktZ3JvdXAtdHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29yZS9zZWN1cml0eS1ncm91cC10eXBlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsK0NBQStDO0FBQy9DLHNDQUFzQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG4vKipcbiAqIFNlY3VyaXR5IGdyb3VwIGNvbmZpZ3VyYXRpb24gdXNpbmcgZXhwbGljaXQgc2VjdXJpdHkgZ3JvdXAgSURzXG4gKlxuICogTG9va3MgdXAgZXhpc3Rpbmcgc2VjdXJpdHkgZ3JvdXBzIGJ5IHRoZWlyIElEcyB2aWEgYFNlY3VyaXR5R3JvdXAuZnJvbVNlY3VyaXR5R3JvdXBJZGAuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGNvbnN0IHNnOiBTZWN1cml0eUdyb3VwSWRzQ29uZmlnID0ge1xuICogICB0eXBlOiAnc2VjdXJpdHlHcm91cElkcycsXG4gKiAgIG9wdGlvbnM6IHtcbiAqICAgICBzZWN1cml0eUdyb3VwSWRzOiBbJ3NnLTEyMzQ1Njc4JywgJ3NnLTg3NjU0MzIxJ10sXG4gKiAgIH1cbiAqIH07XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTZWN1cml0eUdyb3VwSWRzQ29uZmlnIHtcbiAgcmVhZG9ubHkgdHlwZTogJ3NlY3VyaXR5R3JvdXBJZHMnO1xuICByZWFkb25seSBvcHRpb25zOiBTZWN1cml0eUdyb3VwSWRzT3B0aW9ucztcbn1cblxuLyoqXG4gKiBTZWN1cml0eSBncm91cCBjb25maWd1cmF0aW9uIHVzaW5nIG5hbWUtYmFzZWQgbG9va3VwXG4gKlxuICogTG9va3MgdXAgYW4gZXhpc3Rpbmcgc2VjdXJpdHkgZ3JvdXAgYnkgbmFtZSBhbmQgVlBDIElEXG4gKiB2aWEgYFNlY3VyaXR5R3JvdXAuZnJvbUxvb2t1cEJ5TmFtZWAuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGNvbnN0IHNnOiBTZWN1cml0eUdyb3VwTG9va3VwQ29uZmlnID0ge1xuICogICB0eXBlOiAnc2VjdXJpdHlHcm91cExvb2t1cCcsXG4gKiAgIG9wdGlvbnM6IHtcbiAqICAgICBzZWN1cml0eUdyb3VwTmFtZTogJ215LWNvZGVidWlsZC1zZycsXG4gKiAgICAgdnBjSWQ6ICd2cGMtMGExYjJjM2Q0ZTVmNmE3YjgnLFxuICogICB9XG4gKiB9O1xuICogYGBgXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU2VjdXJpdHlHcm91cExvb2t1cENvbmZpZyB7XG4gIHJlYWRvbmx5IHR5cGU6ICdzZWN1cml0eUdyb3VwTG9va3VwJztcbiAgcmVhZG9ubHkgb3B0aW9uczogU2VjdXJpdHlHcm91cExvb2t1cE9wdGlvbnM7XG59XG5cbi8qKlxuICogQ29uZmlndXJhdGlvbiBvcHRpb25zIGZvciBzZWN1cml0eSBncm91cCBsb29rdXAgYnkgSURzXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU2VjdXJpdHlHcm91cElkc09wdGlvbnMge1xuICAvKipcbiAgICogTGlzdCBvZiBzZWN1cml0eSBncm91cCBJRHNcbiAgICogQGV4YW1wbGUgWydzZy0xMjM0NTY3OCcsICdzZy04NzY1NDMyMSddXG4gICAqL1xuICByZWFkb25seSBzZWN1cml0eUdyb3VwSWRzOiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogV2hldGhlciB0aGUgaW1wb3J0ZWQgc2VjdXJpdHkgZ3JvdXBzIGNhbiBiZSBtb2RpZmllZCBieSBhdHRhY2hpbmdcbiAgICogaW5ncmVzcy9lZ3Jlc3MgcnVsZXMuIFNldCB0byBmYWxzZSB0byBhdm9pZCBhZGRpdGlvbmFsIEFQSSBjYWxsc1xuICAgKiBkdXJpbmcgc3ludGhlc2lzLlxuICAgKiBAZGVmYXVsdCB0cnVlXG4gICAqL1xuICByZWFkb25seSBtdXRhYmxlPzogYm9vbGVhbjtcbn1cblxuLyoqXG4gKiBDb25maWd1cmF0aW9uIG9wdGlvbnMgZm9yIHNlY3VyaXR5IGdyb3VwIGxvb2t1cCBieSBuYW1lXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU2VjdXJpdHlHcm91cExvb2t1cE9wdGlvbnMge1xuICAvKipcbiAgICogTmFtZSBvZiB0aGUgc2VjdXJpdHkgZ3JvdXAgdG8gbG9vayB1cFxuICAgKiBAZXhhbXBsZSAnbXktY29kZWJ1aWxkLXNnJ1xuICAgKi9cbiAgcmVhZG9ubHkgc2VjdXJpdHlHcm91cE5hbWU6IHN0cmluZztcblxuICAvKipcbiAgICogVlBDIElEIHRoYXQgY29udGFpbnMgdGhlIHNlY3VyaXR5IGdyb3VwLlxuICAgKiBSZXF1aXJlZCBmb3IgbmFtZS1iYXNlZCBsb29rdXAuXG4gICAqIEBleGFtcGxlICd2cGMtMGExYjJjM2Q0ZTVmNmE3YjgnXG4gICAqL1xuICByZWFkb25seSB2cGNJZDogc3RyaW5nO1xufVxuXG4vKipcbiAqIFVuaW9uIHR5cGUgb2YgYWxsIHN1cHBvcnRlZCBzZWN1cml0eSBncm91cCBjb25maWd1cmF0aW9ucy5cbiAqXG4gKiBVc2VkIGF0IHRoZSBwaXBlbGluZSBsZXZlbCAoYENvZGVCdWlsZERlZmF1bHRzLnNlY3VyaXR5R3JvdXBzYCkgdG8gc3BlY2lmeVxuICogc2VjdXJpdHkgZ3JvdXBzIGZvciBDb2RlQnVpbGQgYWN0aW9ucy5cbiAqXG4gKiBFYWNoIHZhcmlhbnQgcmVzb2x2ZXMgdG8gQ0RLIGBJU2VjdXJpdHlHcm91cFtdYDpcbiAqIC0gU2VjdXJpdHlHcm91cElkc0NvbmZpZzogU2VjdXJpdHkgZ3JvdXBzIGxvb2tlZCB1cCBieSBJRHNcbiAqIC0gU2VjdXJpdHlHcm91cExvb2t1cENvbmZpZzogU2VjdXJpdHkgZ3JvdXAgbG9va2VkIHVwIGJ5IG5hbWUgKyBWUENcbiAqL1xuZXhwb3J0IHR5cGUgU2VjdXJpdHlHcm91cENvbmZpZyA9IFNlY3VyaXR5R3JvdXBJZHNDb25maWcgfCBTZWN1cml0eUdyb3VwTG9va3VwQ29uZmlnO1xuIl19
@@ -0,0 +1,14 @@
1
+ import { ISecurityGroup } from 'aws-cdk-lib/aws-ec2';
2
+ import { Construct } from 'constructs';
3
+ import { UniqueId } from './id-generator';
4
+ import type { SecurityGroupConfig } from './security-group-types';
5
+ /**
6
+ * Resolve a SecurityGroupConfig into CDK ISecurityGroup[].
7
+ * Uses discriminated union narrowing to delegate to the appropriate CDK lookup.
8
+ *
9
+ * @param scope - CDK construct scope
10
+ * @param id - UniqueId instance for generating unique construct IDs
11
+ * @param config - Security group configuration to resolve
12
+ * @returns Resolved CDK ISecurityGroup array
13
+ */
14
+ export declare function resolveSecurityGroup(scope: Construct, id: UniqueId, config: SecurityGroupConfig): ISecurityGroup[];
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ // Copyright 2026 Pipeline Builder Contributors
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.resolveSecurityGroup = resolveSecurityGroup;
6
+ const aws_ec2_1 = require("aws-cdk-lib/aws-ec2");
7
+ /**
8
+ * Resolve a SecurityGroupConfig into CDK ISecurityGroup[].
9
+ * Uses discriminated union narrowing to delegate to the appropriate CDK lookup.
10
+ *
11
+ * @param scope - CDK construct scope
12
+ * @param id - UniqueId instance for generating unique construct IDs
13
+ * @param config - Security group configuration to resolve
14
+ * @returns Resolved CDK ISecurityGroup array
15
+ */
16
+ function resolveSecurityGroup(scope, id, config) {
17
+ switch (config.type) {
18
+ case 'securityGroupIds':
19
+ return config.options.securityGroupIds.map((sgId) => aws_ec2_1.SecurityGroup.fromSecurityGroupId(scope, id.generate('sg:id'), sgId, { mutable: config.options.mutable }));
20
+ case 'securityGroupLookup': {
21
+ const vpc = aws_ec2_1.Vpc.fromLookup(scope, id.generate('sg:vpc'), {
22
+ vpcId: config.options.vpcId,
23
+ });
24
+ return [
25
+ aws_ec2_1.SecurityGroup.fromLookupByName(scope, id.generate('sg:lookup'), config.options.securityGroupName, vpc),
26
+ ];
27
+ }
28
+ default: {
29
+ const _exhaustive = config;
30
+ throw new Error(`Unknown security group config type: ${_exhaustive.type}`);
31
+ }
32
+ }
33
+ }
34
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VjdXJpdHktZ3JvdXAuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29yZS9zZWN1cml0eS1ncm91cC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsK0NBQStDO0FBQy9DLHNDQUFzQzs7QUFnQnRDLG9EQWlDQztBQS9DRCxpREFBeUU7QUFLekU7Ozs7Ozs7O0dBUUc7QUFDSCxTQUFnQixvQkFBb0IsQ0FDbEMsS0FBZ0IsRUFDaEIsRUFBWSxFQUNaLE1BQTJCO0lBRTNCLFFBQVEsTUFBTSxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ3BCLEtBQUssa0JBQWtCO1lBQ3JCLE9BQU8sTUFBTSxDQUFDLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLENBQ3hDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyx1QkFBYSxDQUFDLG1CQUFtQixDQUN6QyxLQUFLLEVBQ0wsRUFBRSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsRUFDcEIsSUFBSSxFQUNKLEVBQUUsT0FBTyxFQUFFLE1BQU0sQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLENBQ3BDLENBQ0YsQ0FBQztRQUNKLEtBQUsscUJBQXFCLENBQUMsQ0FBQyxDQUFDO1lBQzNCLE1BQU0sR0FBRyxHQUFHLGFBQUcsQ0FBQyxVQUFVLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLEVBQUU7Z0JBQ3ZELEtBQUssRUFBRSxNQUFNLENBQUMsT0FBTyxDQUFDLEtBQUs7YUFDNUIsQ0FBQyxDQUFDO1lBQ0gsT0FBTztnQkFDTCx1QkFBYSxDQUFDLGdCQUFnQixDQUM1QixLQUFLLEVBQ0wsRUFBRSxDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQUMsRUFDeEIsTUFBTSxDQUFDLE9BQU8sQ0FBQyxpQkFBaUIsRUFDaEMsR0FBRyxDQUNKO2FBQ0YsQ0FBQztRQUNKLENBQUM7UUFDRCxPQUFPLENBQUMsQ0FBQyxDQUFDO1lBQ1IsTUFBTSxXQUFXLEdBQVUsTUFBTSxDQUFDO1lBQ2xDLE1BQU0sSUFBSSxLQUFLLENBQUMsdUNBQXdDLFdBQW1DLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQztRQUN0RyxDQUFDO0lBQ0gsQ0FBQztBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuaW1wb3J0IHsgSVNlY3VyaXR5R3JvdXAsIFNlY3VyaXR5R3JvdXAsIFZwYyB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1lYzInO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgeyBVbmlxdWVJZCB9IGZyb20gJy4vaWQtZ2VuZXJhdG9yJztcbmltcG9ydCB0eXBlIHsgU2VjdXJpdHlHcm91cENvbmZpZyB9IGZyb20gJy4vc2VjdXJpdHktZ3JvdXAtdHlwZXMnO1xuXG4vKipcbiAqIFJlc29sdmUgYSBTZWN1cml0eUdyb3VwQ29uZmlnIGludG8gQ0RLIElTZWN1cml0eUdyb3VwW10uXG4gKiBVc2VzIGRpc2NyaW1pbmF0ZWQgdW5pb24gbmFycm93aW5nIHRvIGRlbGVnYXRlIHRvIHRoZSBhcHByb3ByaWF0ZSBDREsgbG9va3VwLlxuICpcbiAqIEBwYXJhbSBzY29wZSAtIENESyBjb25zdHJ1Y3Qgc2NvcGVcbiAqIEBwYXJhbSBpZCAtIFVuaXF1ZUlkIGluc3RhbmNlIGZvciBnZW5lcmF0aW5nIHVuaXF1ZSBjb25zdHJ1Y3QgSURzXG4gKiBAcGFyYW0gY29uZmlnIC0gU2VjdXJpdHkgZ3JvdXAgY29uZmlndXJhdGlvbiB0byByZXNvbHZlXG4gKiBAcmV0dXJucyBSZXNvbHZlZCBDREsgSVNlY3VyaXR5R3JvdXAgYXJyYXlcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlc29sdmVTZWN1cml0eUdyb3VwKFxuICBzY29wZTogQ29uc3RydWN0LFxuICBpZDogVW5pcXVlSWQsXG4gIGNvbmZpZzogU2VjdXJpdHlHcm91cENvbmZpZyxcbik6IElTZWN1cml0eUdyb3VwW10ge1xuICBzd2l0Y2ggKGNvbmZpZy50eXBlKSB7XG4gICAgY2FzZSAnc2VjdXJpdHlHcm91cElkcyc6XG4gICAgICByZXR1cm4gY29uZmlnLm9wdGlvbnMuc2VjdXJpdHlHcm91cElkcy5tYXAoXG4gICAgICAgIChzZ0lkKSA9PiBTZWN1cml0eUdyb3VwLmZyb21TZWN1cml0eUdyb3VwSWQoXG4gICAgICAgICAgc2NvcGUsXG4gICAgICAgICAgaWQuZ2VuZXJhdGUoJ3NnOmlkJyksXG4gICAgICAgICAgc2dJZCxcbiAgICAgICAgICB7IG11dGFibGU6IGNvbmZpZy5vcHRpb25zLm11dGFibGUgfSxcbiAgICAgICAgKSxcbiAgICAgICk7XG4gICAgY2FzZSAnc2VjdXJpdHlHcm91cExvb2t1cCc6IHtcbiAgICAgIGNvbnN0IHZwYyA9IFZwYy5mcm9tTG9va3VwKHNjb3BlLCBpZC5nZW5lcmF0ZSgnc2c6dnBjJyksIHtcbiAgICAgICAgdnBjSWQ6IGNvbmZpZy5vcHRpb25zLnZwY0lkLFxuICAgICAgfSk7XG4gICAgICByZXR1cm4gW1xuICAgICAgICBTZWN1cml0eUdyb3VwLmZyb21Mb29rdXBCeU5hbWUoXG4gICAgICAgICAgc2NvcGUsXG4gICAgICAgICAgaWQuZ2VuZXJhdGUoJ3NnOmxvb2t1cCcpLFxuICAgICAgICAgIGNvbmZpZy5vcHRpb25zLnNlY3VyaXR5R3JvdXBOYW1lLFxuICAgICAgICAgIHZwYyxcbiAgICAgICAgKSxcbiAgICAgIF07XG4gICAgfVxuICAgIGRlZmF1bHQ6IHtcbiAgICAgIGNvbnN0IF9leGhhdXN0aXZlOiBuZXZlciA9IGNvbmZpZztcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVW5rbm93biBzZWN1cml0eSBncm91cCBjb25maWcgdHlwZTogJHsoX2V4aGF1c3RpdmUgYXMgU2VjdXJpdHlHcm91cENvbmZpZykudHlwZX1gKTtcbiAgICB9XG4gIH1cbn1cbiJdfQ==
@@ -0,0 +1,32 @@
1
+ import { CloudFormationCustomResourceEvent, CloudFormationCustomResourceResponse } from 'aws-lambda';
2
+ /**
3
+ * Lambda handler for CloudFormation Custom Resource that performs plugin lookup.
4
+ *
5
+ * Authenticates using JWT token from AWS Secrets Manager (PLATFORM_SECRET_NAME env var).
6
+ * Create the secret with: `pipeline-manager store-token`
7
+ *
8
+ * Request Types:
9
+ * - Create/Update: fetches and returns plugin configuration from API
10
+ * - Delete: no-op (always succeeds)
11
+ *
12
+ * Response:
13
+ * - Success: Returns base64-encoded plugin JSON in Data.ResultValue
14
+ * - Failure: Returns error message in Reason
15
+ *
16
+ * @param event - CloudFormation custom resource event
17
+ * @returns CloudFormation response
18
+ *
19
+ * @example
20
+ * Custom Resource Properties:
21
+ * ```json
22
+ * {
23
+ * "baseURL": "https://api.example.com",
24
+ * "pluginFilter": {
25
+ * "name": "nodejs-build",
26
+ * "version": "1.0.0",
27
+ * "isActive": true
28
+ * }
29
+ * }
30
+ * ```
31
+ */
32
+ export declare const handler: (event: CloudFormationCustomResourceEvent) => Promise<CloudFormationCustomResourceResponse>;