@quiltdata/benchling-webhook 0.5.4-20251102T020826Z → 0.5.4-20251103T180145Z
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/README.md +26 -17
- package/dist/bin/benchling-webhook.d.ts +1 -1
- package/dist/bin/benchling-webhook.d.ts.map +1 -1
- package/dist/bin/benchling-webhook.js +8 -23
- package/dist/bin/benchling-webhook.js.map +1 -1
- package/dist/bin/cdk-dev.js +51 -0
- package/dist/bin/cli.js +8 -22
- package/dist/bin/cli.js.map +1 -1
- package/dist/bin/commands/deploy.d.ts +4 -2
- package/dist/bin/commands/deploy.d.ts.map +1 -1
- package/dist/bin/commands/deploy.js +88 -300
- package/dist/bin/commands/deploy.js.map +1 -1
- package/dist/bin/config-profiles.d.ts +59 -0
- package/dist/bin/config-profiles.d.ts.map +1 -0
- package/dist/bin/config-profiles.js +272 -0
- package/dist/bin/config-profiles.js.map +1 -0
- package/dist/bin/create-secret.d.ts +3 -0
- package/dist/bin/create-secret.d.ts.map +1 -1
- package/dist/bin/create-secret.js +51 -48
- package/dist/bin/create-secret.js.map +1 -1
- package/dist/lib/benchling-auth-validator.d.ts +65 -0
- package/dist/lib/benchling-auth-validator.d.ts.map +1 -0
- package/dist/lib/benchling-auth-validator.js +213 -0
- package/dist/lib/benchling-auth-validator.js.map +1 -0
- package/dist/lib/benchling-webhook-stack.d.ts +5 -23
- package/dist/lib/benchling-webhook-stack.d.ts.map +1 -1
- package/dist/lib/benchling-webhook-stack.js +25 -145
- package/dist/lib/benchling-webhook-stack.js.map +1 -1
- package/dist/lib/config-logger.d.ts +191 -0
- package/dist/lib/config-logger.d.ts.map +1 -0
- package/dist/lib/config-logger.js +372 -0
- package/dist/lib/config-logger.js.map +1 -0
- package/dist/lib/configuration-saver.d.ts +75 -0
- package/dist/lib/configuration-saver.d.ts.map +1 -0
- package/dist/lib/configuration-saver.js +145 -0
- package/dist/lib/configuration-saver.js.map +1 -0
- package/dist/lib/configuration-validator.d.ts +63 -0
- package/dist/lib/configuration-validator.d.ts.map +1 -0
- package/dist/lib/configuration-validator.js +136 -0
- package/dist/lib/configuration-validator.js.map +1 -0
- package/dist/lib/configuration-wizard.d.ts +52 -0
- package/dist/lib/configuration-wizard.d.ts.map +1 -0
- package/dist/lib/configuration-wizard.js +193 -0
- package/dist/lib/configuration-wizard.js.map +1 -0
- package/dist/lib/quilt-config-resolver.d.ts +53 -0
- package/dist/lib/quilt-config-resolver.d.ts.map +1 -0
- package/dist/lib/quilt-config-resolver.js +100 -0
- package/dist/lib/quilt-config-resolver.js.map +1 -0
- package/dist/lib/s3-bucket-validator.d.ts +76 -0
- package/dist/lib/s3-bucket-validator.d.ts.map +1 -0
- package/dist/lib/s3-bucket-validator.js +237 -0
- package/dist/lib/s3-bucket-validator.js.map +1 -0
- package/dist/lib/types/config.d.ts +398 -0
- package/dist/lib/types/config.d.ts.map +1 -0
- package/dist/lib/types/config.js +11 -0
- package/dist/lib/types/config.js.map +1 -0
- package/dist/lib/utils/config-loader.js.map +1 -1
- package/dist/lib/utils/config-resolver.d.ts +26 -26
- package/dist/lib/utils/config-resolver.d.ts.map +1 -1
- package/dist/lib/utils/config-resolver.js +29 -29
- package/dist/lib/utils/config-resolver.js.map +1 -1
- package/dist/lib/utils/config.d.ts +2 -0
- package/dist/lib/utils/config.d.ts.map +1 -1
- package/dist/lib/utils/config.js.map +1 -1
- package/dist/lib/xdg-cli-wrapper.d.ts +113 -0
- package/dist/lib/xdg-cli-wrapper.d.ts.map +1 -0
- package/dist/lib/xdg-cli-wrapper.js +288 -0
- package/dist/lib/xdg-cli-wrapper.js.map +1 -0
- package/dist/lib/xdg-config.d.ts +187 -0
- package/dist/lib/xdg-config.d.ts.map +1 -0
- package/dist/lib/xdg-config.js +562 -0
- package/dist/lib/xdg-config.js.map +1 -0
- package/dist/package.json +38 -26
- package/dist/scripts/config-health-check.d.ts +78 -0
- package/dist/scripts/config-health-check.d.ts.map +1 -0
- package/dist/scripts/config-health-check.js +559 -0
- package/dist/scripts/config-health-check.js.map +1 -0
- package/dist/scripts/infer-quilt-config.d.ts +50 -0
- package/dist/scripts/infer-quilt-config.d.ts.map +1 -0
- package/dist/scripts/infer-quilt-config.js +353 -0
- package/dist/scripts/infer-quilt-config.js.map +1 -0
- package/dist/scripts/install-wizard.d.ts +34 -0
- package/dist/scripts/install-wizard.d.ts.map +1 -0
- package/dist/scripts/install-wizard.js +719 -0
- package/dist/scripts/install-wizard.js.map +1 -0
- package/dist/scripts/sync-secrets.d.ts +63 -0
- package/dist/scripts/sync-secrets.d.ts.map +1 -0
- package/dist/scripts/sync-secrets.js +424 -0
- package/dist/scripts/sync-secrets.js.map +1 -0
- package/env.template +60 -47
- package/package.json +38 -26
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.BenchlingAuthValidator = void 0;
|
|
37
|
+
const https = __importStar(require("https"));
|
|
38
|
+
/**
|
|
39
|
+
* Benchling authentication validator
|
|
40
|
+
*
|
|
41
|
+
* Validates Benchling credentials by attempting OAuth authentication
|
|
42
|
+
* and checking required permissions.
|
|
43
|
+
*/
|
|
44
|
+
class BenchlingAuthValidator {
|
|
45
|
+
/**
|
|
46
|
+
* Validate Benchling credentials
|
|
47
|
+
*
|
|
48
|
+
* @param credentials - Benchling credentials to validate
|
|
49
|
+
* @returns Validation result with errors and warnings
|
|
50
|
+
*/
|
|
51
|
+
static async validate(credentials) {
|
|
52
|
+
const errors = [];
|
|
53
|
+
const warnings = [];
|
|
54
|
+
// Basic credential validation
|
|
55
|
+
if (!BenchlingAuthValidator.validateCredentials(credentials)) {
|
|
56
|
+
errors.push("Invalid credentials: missing required fields");
|
|
57
|
+
return {
|
|
58
|
+
isValid: false,
|
|
59
|
+
errors,
|
|
60
|
+
warnings,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
// Validate tenant format
|
|
64
|
+
if (!(await BenchlingAuthValidator.validateTenant(credentials.tenant))) {
|
|
65
|
+
errors.push("Invalid tenant format");
|
|
66
|
+
return {
|
|
67
|
+
isValid: false,
|
|
68
|
+
errors,
|
|
69
|
+
warnings,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
// Attempt OAuth authentication
|
|
73
|
+
try {
|
|
74
|
+
const tokenResponse = await BenchlingAuthValidator.authenticate(credentials);
|
|
75
|
+
if (!tokenResponse.access_token) {
|
|
76
|
+
if (tokenResponse.error === "invalid_client") {
|
|
77
|
+
errors.push("Invalid client credentials");
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
errors.push("Authentication failed");
|
|
81
|
+
}
|
|
82
|
+
return {
|
|
83
|
+
isValid: false,
|
|
84
|
+
errors,
|
|
85
|
+
warnings,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
// Check OAuth scopes
|
|
89
|
+
const hasPermissions = BenchlingAuthValidator.checkPermissions(tokenResponse.scope || "");
|
|
90
|
+
if (!hasPermissions) {
|
|
91
|
+
warnings.push("Missing required permissions");
|
|
92
|
+
}
|
|
93
|
+
return {
|
|
94
|
+
isValid: true,
|
|
95
|
+
hasRequiredPermissions: hasPermissions,
|
|
96
|
+
errors: [],
|
|
97
|
+
warnings: warnings.length > 0 ? warnings : undefined,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
if (error instanceof Error) {
|
|
102
|
+
if (error.message.includes("404") || error.message.includes("tenant_not_found")) {
|
|
103
|
+
errors.push("Tenant not found");
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
errors.push("Network error during validation");
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return {
|
|
110
|
+
isValid: false,
|
|
111
|
+
errors,
|
|
112
|
+
warnings,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Validate tenant format
|
|
118
|
+
*
|
|
119
|
+
* @param tenant - Benchling tenant name
|
|
120
|
+
* @returns True if tenant format is valid
|
|
121
|
+
*/
|
|
122
|
+
static async validateTenant(tenant) {
|
|
123
|
+
if (!tenant || tenant.trim() === "") {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
// Check for invalid characters (spaces, special chars)
|
|
127
|
+
if (/\s/.test(tenant)) {
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
return true;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Validate credentials completeness
|
|
134
|
+
*
|
|
135
|
+
* @param credentials - Credentials to validate
|
|
136
|
+
* @returns True if all required fields are present
|
|
137
|
+
*/
|
|
138
|
+
static validateCredentials(credentials) {
|
|
139
|
+
return !!(credentials.tenant &&
|
|
140
|
+
credentials.clientId &&
|
|
141
|
+
credentials.clientSecret &&
|
|
142
|
+
credentials.tenant.trim() !== "" &&
|
|
143
|
+
credentials.clientId.trim() !== "" &&
|
|
144
|
+
credentials.clientSecret.trim() !== "");
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Authenticate with Benchling OAuth API
|
|
148
|
+
*
|
|
149
|
+
* @param credentials - Benchling credentials
|
|
150
|
+
* @returns Token response from Benchling
|
|
151
|
+
*/
|
|
152
|
+
static async authenticate(credentials) {
|
|
153
|
+
const { tenant, clientId, clientSecret } = credentials;
|
|
154
|
+
return new Promise((resolve, reject) => {
|
|
155
|
+
const authString = Buffer.from(`${clientId}:${clientSecret}`).toString("base64");
|
|
156
|
+
const postData = "grant_type=client_credentials";
|
|
157
|
+
const options = {
|
|
158
|
+
hostname: `${tenant}.benchling.com`,
|
|
159
|
+
port: 443,
|
|
160
|
+
path: "/api/v2/token",
|
|
161
|
+
method: "POST",
|
|
162
|
+
headers: {
|
|
163
|
+
"Authorization": `Basic ${authString}`,
|
|
164
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
165
|
+
"Content-Length": Buffer.byteLength(postData),
|
|
166
|
+
},
|
|
167
|
+
};
|
|
168
|
+
const req = https.request(options, (res) => {
|
|
169
|
+
let data = "";
|
|
170
|
+
res.on("data", (chunk) => {
|
|
171
|
+
data += chunk.toString();
|
|
172
|
+
});
|
|
173
|
+
res.on("end", () => {
|
|
174
|
+
if (res.statusCode === 404) {
|
|
175
|
+
reject(new Error("404: Tenant not found"));
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
try {
|
|
179
|
+
const response = JSON.parse(data);
|
|
180
|
+
if (res.statusCode === 401) {
|
|
181
|
+
response.error = "invalid_client";
|
|
182
|
+
}
|
|
183
|
+
resolve(response);
|
|
184
|
+
}
|
|
185
|
+
catch (error) {
|
|
186
|
+
reject(error);
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
req.on("error", (error) => {
|
|
191
|
+
reject(error);
|
|
192
|
+
});
|
|
193
|
+
req.write(postData);
|
|
194
|
+
req.end();
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Check if OAuth scopes include required permissions
|
|
199
|
+
*
|
|
200
|
+
* @param scope - OAuth scope string
|
|
201
|
+
* @returns True if all required scopes are present
|
|
202
|
+
*/
|
|
203
|
+
static checkPermissions(scope) {
|
|
204
|
+
const scopes = scope.toLowerCase().split(" ");
|
|
205
|
+
return BenchlingAuthValidator.REQUIRED_SCOPES.every((requiredScope) => scopes.includes(requiredScope));
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
exports.BenchlingAuthValidator = BenchlingAuthValidator;
|
|
209
|
+
/**
|
|
210
|
+
* Required OAuth scopes for the webhook integration
|
|
211
|
+
*/
|
|
212
|
+
BenchlingAuthValidator.REQUIRED_SCOPES = ["read", "write"];
|
|
213
|
+
//# sourceMappingURL=benchling-auth-validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"benchling-auth-validator.js","sourceRoot":"","sources":["../../lib/benchling-auth-validator.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,35 +3,17 @@ import { Construct } from "constructs";
|
|
|
3
3
|
export interface BenchlingWebhookStackProps extends cdk.StackProps {
|
|
4
4
|
/**
|
|
5
5
|
* ARN of the Quilt CloudFormation stack.
|
|
6
|
-
*
|
|
7
|
-
* is resolved from AWS (CloudFormation outputs + Secrets Manager).
|
|
6
|
+
* All configuration is resolved from AWS (CloudFormation outputs + Secrets Manager).
|
|
8
7
|
* Format: arn:aws:cloudformation:{region}:{account}:stack/{name}/{id}
|
|
8
|
+
* REQUIRED.
|
|
9
9
|
*/
|
|
10
|
-
readonly quiltStackArn
|
|
10
|
+
readonly quiltStackArn: string;
|
|
11
11
|
/**
|
|
12
12
|
* Name or ARN of the AWS Secrets Manager secret containing Benchling credentials.
|
|
13
|
-
* When provided with quiltStackArn, enables secrets-only mode.
|
|
14
13
|
* Secret must contain: client_id, client_secret, tenant, app_definition_id (optional)
|
|
14
|
+
* REQUIRED.
|
|
15
15
|
*/
|
|
16
|
-
readonly benchlingSecret
|
|
17
|
-
readonly bucketName?: string;
|
|
18
|
-
readonly environment?: string;
|
|
19
|
-
readonly prefix?: string;
|
|
20
|
-
readonly queueArn?: string;
|
|
21
|
-
readonly benchlingClientId?: string;
|
|
22
|
-
readonly benchlingClientSecret?: string;
|
|
23
|
-
readonly benchlingTenant?: string;
|
|
24
|
-
readonly benchlingAppDefinitionId?: string;
|
|
25
|
-
/**
|
|
26
|
-
* Consolidated Benchling secrets as JSON string.
|
|
27
|
-
* When provided, this takes precedence over individual secret parameters.
|
|
28
|
-
* Expected format: {"client_id": "...", "client_secret": "...", "tenant": "...", "app_definition_id": "..."}
|
|
29
|
-
* If not provided or empty, individual parameters (benchlingClientId, benchlingClientSecret, benchlingTenant) are used.
|
|
30
|
-
*/
|
|
31
|
-
readonly benchlingSecrets?: string;
|
|
32
|
-
readonly quiltCatalog?: string;
|
|
33
|
-
readonly quiltDatabase?: string;
|
|
34
|
-
readonly webhookAllowList?: string;
|
|
16
|
+
readonly benchlingSecret: string;
|
|
35
17
|
readonly createEcrRepository?: boolean;
|
|
36
18
|
readonly ecrRepositoryName?: string;
|
|
37
19
|
readonly logLevel?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"benchling-webhook-stack.d.ts","sourceRoot":"","sources":["../../lib/benchling-webhook-stack.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,aAAa,CAAC;AAInC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAMvC,MAAM,WAAW,0BAA2B,SAAQ,GAAG,CAAC,UAAU;IAE9D;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,
|
|
1
|
+
{"version":3,"file":"benchling-webhook-stack.d.ts","sourceRoot":"","sources":["../../lib/benchling-webhook-stack.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,aAAa,CAAC;AAInC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAMvC,MAAM,WAAW,0BAA2B,SAAQ,GAAG,CAAC,UAAU;IAE9D;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B;;;;OAIG;IACH,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IAGjC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,OAAO,CAAC;IACvC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,qBAAa,qBAAsB,SAAQ,GAAG,CAAC,KAAK;IAChD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAa;IACpC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAiB;IAChD,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAgB;IACpC,SAAgB,eAAe,EAAE,MAAM,CAAC;gBAGpC,KAAK,EAAE,SAAS,EAChB,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,0BAA0B;CA0IxC"}
|
|
@@ -48,80 +48,26 @@ const package_json_1 = __importDefault(require("../package.json"));
|
|
|
48
48
|
class BenchlingWebhookStack extends cdk.Stack {
|
|
49
49
|
constructor(scope, id, props) {
|
|
50
50
|
super(scope, id, props);
|
|
51
|
-
//
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}
|
|
58
|
-
else {
|
|
59
|
-
// Legacy mode: validate required legacy props
|
|
60
|
-
if (!props.bucketName || !props.prefix || !props.queueArn || !props.quiltDatabase) {
|
|
61
|
-
throw new Error("Legacy mode requires: bucketName, prefix, queueArn, quiltDatabase.\n" +
|
|
62
|
-
"Or use secrets-only mode with: quiltStackArn, benchlingSecret");
|
|
63
|
-
}
|
|
64
|
-
if (props.prefix.includes("/")) {
|
|
65
|
-
throw new Error("Prefix should not contain a '/' character.");
|
|
66
|
-
}
|
|
67
|
-
console.log("⚠️ Using legacy mode (DEPRECATED - consider migrating to secrets-only mode)");
|
|
51
|
+
// Validate required secrets-only mode parameters
|
|
52
|
+
if (!props.quiltStackArn || !props.benchlingSecret) {
|
|
53
|
+
throw new Error("Secrets-only mode (v0.6.0+) requires both:\n" +
|
|
54
|
+
" - quiltStackArn: CloudFormation stack ARN\n" +
|
|
55
|
+
" - benchlingSecret: Secrets Manager secret name\n\n" +
|
|
56
|
+
"See: https://github.com/quiltdata/benchling-webhook/issues/156");
|
|
68
57
|
}
|
|
58
|
+
console.log("✓ Using secrets-only mode (v0.6.0+)");
|
|
69
59
|
// Create CloudFormation parameters for runtime-configurable values
|
|
70
|
-
//
|
|
71
|
-
//
|
|
72
|
-
// ===== Secrets-Only Mode Parameters (NEW) =====
|
|
60
|
+
// Parameters can be updated via CloudFormation stack updates
|
|
61
|
+
// ===== Secrets-Only Mode Parameters (v0.6.0+) =====
|
|
73
62
|
const quiltStackArnParam = new cdk.CfnParameter(this, "QuiltStackARN", {
|
|
74
63
|
type: "String",
|
|
75
|
-
description: "
|
|
76
|
-
default: props.quiltStackArn
|
|
64
|
+
description: "ARN of Quilt CloudFormation stack for configuration resolution",
|
|
65
|
+
default: props.quiltStackArn,
|
|
77
66
|
});
|
|
78
67
|
const benchlingSecretParam = new cdk.CfnParameter(this, "BenchlingSecret", {
|
|
79
68
|
type: "String",
|
|
80
|
-
description: "
|
|
81
|
-
default: props.benchlingSecret
|
|
82
|
-
});
|
|
83
|
-
// ===== Legacy Mode Parameters (DEPRECATED) =====
|
|
84
|
-
const webhookAllowListParam = new cdk.CfnParameter(this, "WebhookAllowList", {
|
|
85
|
-
type: "String",
|
|
86
|
-
description: "Comma-separated list of IP addresses allowed to send webhooks (leave empty to allow all IPs)",
|
|
87
|
-
default: props.webhookAllowList || "",
|
|
88
|
-
});
|
|
89
|
-
const quiltCatalogParam = new cdk.CfnParameter(this, "QuiltCatalog", {
|
|
90
|
-
type: "String",
|
|
91
|
-
description: "Quilt catalog URL for package links",
|
|
92
|
-
default: props.quiltCatalog || "open.quiltdata.com",
|
|
93
|
-
});
|
|
94
|
-
// Infrastructure parameters - these can be updated without redeploying
|
|
95
|
-
const bucketNameParam = new cdk.CfnParameter(this, "BucketName", {
|
|
96
|
-
type: "String",
|
|
97
|
-
description: "[LEGACY] S3 bucket name for storing packages (not used in secrets-only mode)",
|
|
98
|
-
default: props.bucketName || "",
|
|
99
|
-
});
|
|
100
|
-
const prefixParam = new cdk.CfnParameter(this, "PackagePrefix", {
|
|
101
|
-
type: "String",
|
|
102
|
-
description: "[LEGACY] Prefix for package names (not used in secrets-only mode)",
|
|
103
|
-
default: props.prefix || "benchling",
|
|
104
|
-
});
|
|
105
|
-
const pkgKeyParam = new cdk.CfnParameter(this, "PackageKey", {
|
|
106
|
-
type: "String",
|
|
107
|
-
description: "Metadata key used to link Benchling entries to Quilt packages",
|
|
108
|
-
default: "experiment_id",
|
|
109
|
-
});
|
|
110
|
-
const queueArnParam = new cdk.CfnParameter(this, "QueueArn", {
|
|
111
|
-
type: "String",
|
|
112
|
-
description: "[LEGACY] SQS queue ARN for package notifications (not used in secrets-only mode)",
|
|
113
|
-
default: props.queueArn || "",
|
|
114
|
-
});
|
|
115
|
-
const quiltDatabaseParam = new cdk.CfnParameter(this, "QuiltDatabase", {
|
|
116
|
-
type: "String",
|
|
117
|
-
description: "[LEGACY] Quilt database name (not used in secrets-only mode)",
|
|
118
|
-
default: props.quiltDatabase || "",
|
|
119
|
-
});
|
|
120
|
-
// DEPRECATED: Benchling tenant parameter (kept for backward compatibility)
|
|
121
|
-
const benchlingTenantParam = new cdk.CfnParameter(this, "BenchlingTenant", {
|
|
122
|
-
type: "String",
|
|
123
|
-
description: "[DEPRECATED] Use BenchlingSecrets parameter instead. Benchling tenant name (e.g., 'company' for company.benchling.com)",
|
|
124
|
-
default: props.benchlingTenant,
|
|
69
|
+
description: "Name/ARN of Secrets Manager secret with Benchling credentials",
|
|
70
|
+
default: props.benchlingSecret,
|
|
125
71
|
});
|
|
126
72
|
const logLevelParam = new cdk.CfnParameter(this, "LogLevel", {
|
|
127
73
|
type: "String",
|
|
@@ -129,66 +75,20 @@ class BenchlingWebhookStack extends cdk.Stack {
|
|
|
129
75
|
default: props.logLevel || "INFO",
|
|
130
76
|
allowedValues: ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"],
|
|
131
77
|
});
|
|
132
|
-
const enableWebhookVerificationParam = new cdk.CfnParameter(this, "EnableWebhookVerification", {
|
|
133
|
-
type: "String",
|
|
134
|
-
description: "Enable webhook signature verification (true/false)",
|
|
135
|
-
default: "true",
|
|
136
|
-
allowedValues: ["true", "false"],
|
|
137
|
-
});
|
|
138
78
|
const imageTagParam = new cdk.CfnParameter(this, "ImageTag", {
|
|
139
79
|
type: "String",
|
|
140
80
|
description: "Docker image tag to deploy (e.g., latest, 0.5.3, 0.5.3-20251030T123456Z)",
|
|
141
81
|
default: props.imageTag || "latest",
|
|
142
82
|
});
|
|
143
|
-
// Benchling Secrets - consolidated secret parameter (Phase 3)
|
|
144
|
-
const benchlingSecretsParam = new cdk.CfnParameter(this, "BenchlingSecrets", {
|
|
145
|
-
type: "String",
|
|
146
|
-
description: "JSON string containing Benchling secrets (client_id, client_secret, tenant, app_definition_id)",
|
|
147
|
-
default: "",
|
|
148
|
-
noEcho: true,
|
|
149
|
-
});
|
|
150
|
-
// DEPRECATED: Individual secret parameters (kept for backward compatibility)
|
|
151
|
-
const benchlingClientIdParam = new cdk.CfnParameter(this, "BenchlingClientId", {
|
|
152
|
-
type: "String",
|
|
153
|
-
description: "[DEPRECATED] Use BenchlingSecrets parameter instead. Benchling OAuth client ID.",
|
|
154
|
-
default: "",
|
|
155
|
-
noEcho: true,
|
|
156
|
-
});
|
|
157
|
-
const benchlingClientSecretParam = new cdk.CfnParameter(this, "BenchlingClientSecret", {
|
|
158
|
-
type: "String",
|
|
159
|
-
description: "[DEPRECATED] Use BenchlingSecrets parameter instead. Benchling OAuth client secret.",
|
|
160
|
-
default: "",
|
|
161
|
-
noEcho: true,
|
|
162
|
-
});
|
|
163
83
|
// Use parameter values (which have props as defaults)
|
|
164
84
|
// This allows runtime updates via CloudFormation
|
|
165
|
-
const webhookAllowListValue = webhookAllowListParam.valueAsString;
|
|
166
|
-
const quiltCatalogValue = quiltCatalogParam.valueAsString;
|
|
167
|
-
const bucketNameValue = bucketNameParam.valueAsString;
|
|
168
|
-
const prefixValue = prefixParam.valueAsString;
|
|
169
|
-
const pkgKeyValue = pkgKeyParam.valueAsString;
|
|
170
|
-
const queueArnValue = queueArnParam.valueAsString;
|
|
171
|
-
const quiltDatabaseValue = quiltDatabaseParam.valueAsString;
|
|
172
|
-
const benchlingTenantValue = benchlingTenantParam.valueAsString;
|
|
173
|
-
const logLevelValue = logLevelParam.valueAsString;
|
|
174
|
-
const enableWebhookVerificationValue = enableWebhookVerificationParam.valueAsString;
|
|
175
|
-
const imageTagValue = imageTagParam.valueAsString;
|
|
176
|
-
// Phase 3: New secret parameters (not used directly - mode determined by props)
|
|
177
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
178
|
-
const benchlingSecretsValue = benchlingSecretsParam.valueAsString;
|
|
179
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
180
|
-
const benchlingClientIdValue = benchlingClientIdParam.valueAsString;
|
|
181
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
182
|
-
const benchlingClientSecretValue = benchlingClientSecretParam.valueAsString;
|
|
183
|
-
// New secrets-only mode parameter values
|
|
184
85
|
const quiltStackArnValue = quiltStackArnParam.valueAsString;
|
|
185
86
|
const benchlingSecretValue = benchlingSecretParam.valueAsString;
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
//
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
: s3.Bucket.fromBucketName(this, "BWBucket", bucketNameValue);
|
|
87
|
+
const logLevelValue = logLevelParam.valueAsString;
|
|
88
|
+
const imageTagValue = imageTagParam.valueAsString;
|
|
89
|
+
// Bucket name will be resolved at runtime from CloudFormation outputs
|
|
90
|
+
// For CDK purposes, we use a placeholder for IAM permissions
|
|
91
|
+
this.bucket = s3.Bucket.fromBucketName(this, "BWBucket", "placeholder-bucket-resolved-at-runtime");
|
|
192
92
|
// Get the default VPC or create a new one
|
|
193
93
|
const vpc = ec2.Vpc.fromLookup(this, "DefaultVPC", {
|
|
194
94
|
isDefault: true,
|
|
@@ -215,8 +115,8 @@ class BenchlingWebhookStack extends cdk.Stack {
|
|
|
215
115
|
// (e.g., "0.5.3-20251031T000139Z"), otherwise use package.json version
|
|
216
116
|
const isDevVersion = imageTagValue.match(/^\d+\.\d+\.\d+-\d{8}T\d{6}Z$/);
|
|
217
117
|
const stackVersion = isDevVersion ? imageTagValue : package_json_1.default.version;
|
|
218
|
-
// Build Fargate Service props
|
|
219
|
-
|
|
118
|
+
// Build Fargate Service props - secrets-only mode
|
|
119
|
+
this.fargateService = new fargate_service_1.FargateService(this, "FargateService", {
|
|
220
120
|
vpc,
|
|
221
121
|
bucket: this.bucket,
|
|
222
122
|
region: this.region,
|
|
@@ -225,34 +125,14 @@ class BenchlingWebhookStack extends cdk.Stack {
|
|
|
225
125
|
imageTag: imageTagValue,
|
|
226
126
|
stackVersion: stackVersion,
|
|
227
127
|
logLevel: logLevelValue,
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
fargateProps.quiltStackArn = quiltStackArnValue;
|
|
233
|
-
fargateProps.benchlingSecret = benchlingSecretValue;
|
|
234
|
-
}
|
|
235
|
-
else {
|
|
236
|
-
// Legacy mode: Pass all individual parameters
|
|
237
|
-
fargateProps.queueArn = queueArnValue;
|
|
238
|
-
fargateProps.prefix = prefixValue;
|
|
239
|
-
fargateProps.pkgKey = pkgKeyValue;
|
|
240
|
-
fargateProps.benchlingClientId = props.benchlingClientId;
|
|
241
|
-
fargateProps.benchlingClientSecret = props.benchlingClientSecret;
|
|
242
|
-
fargateProps.benchlingTenant = benchlingTenantValue;
|
|
243
|
-
fargateProps.benchlingAppDefinitionId = props.benchlingAppDefinitionId;
|
|
244
|
-
// Use props.benchlingSecrets (original value) to determine mode
|
|
245
|
-
// The CloudFormation parameter value (benchlingSecretsValue) is a token that can't be evaluated at synth time
|
|
246
|
-
fargateProps.benchlingSecrets = props.benchlingSecrets;
|
|
247
|
-
fargateProps.quiltCatalog = quiltCatalogValue;
|
|
248
|
-
fargateProps.quiltDatabase = quiltDatabaseValue;
|
|
249
|
-
fargateProps.webhookAllowList = webhookAllowListValue;
|
|
250
|
-
}
|
|
251
|
-
this.fargateService = new fargate_service_1.FargateService(this, "FargateService", fargateProps);
|
|
128
|
+
// Secrets-only mode: Only 2 required parameters
|
|
129
|
+
quiltStackArn: quiltStackArnValue,
|
|
130
|
+
benchlingSecret: benchlingSecretValue,
|
|
131
|
+
});
|
|
252
132
|
// Create API Gateway that routes to the ALB
|
|
253
133
|
this.api = new alb_api_gateway_1.AlbApiGateway(this, "ApiGateway", {
|
|
254
134
|
loadBalancer: this.fargateService.loadBalancer,
|
|
255
|
-
webhookAllowList:
|
|
135
|
+
webhookAllowList: "", // Empty allow list = allow all IPs
|
|
256
136
|
});
|
|
257
137
|
// Store webhook endpoint for easy access
|
|
258
138
|
this.webhookEndpoint = this.api.api.url;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"benchling-webhook-stack.js","sourceRoot":"","sources":["../../lib/benchling-webhook-stack.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,iDAAmC;AACnC,uDAAyC;AACzC,yDAA2C;AAC3C,yDAA2C;AAE3C,uDAAmD;AACnD,uDAAkD;AAClD,qDAAiD;AACjD,mEAA0C;
|
|
1
|
+
{"version":3,"file":"benchling-webhook-stack.js","sourceRoot":"","sources":["../../lib/benchling-webhook-stack.ts"],"names":[],"mappings":"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"}
|