@quiltdata/benchling-webhook 0.5.4 → 0.6.1-20251104T043302Z
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 +295 -12
- 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 +12 -22
- package/dist/bin/benchling-webhook.js.map +1 -1
- package/dist/bin/cdk-dev.js +59 -3
- package/dist/bin/cli.js +27 -9
- package/dist/bin/cli.js.map +1 -1
- package/dist/bin/commands/deploy.d.ts +6 -2
- package/dist/bin/commands/deploy.d.ts.map +1 -1
- package/dist/bin/commands/deploy.js +151 -90
- package/dist/bin/commands/deploy.js.map +1 -1
- package/dist/bin/commands/setup-wizard.d.ts +22 -0
- package/dist/bin/commands/setup-wizard.d.ts.map +1 -0
- package/dist/bin/commands/setup-wizard.js +47 -0
- package/dist/bin/commands/setup-wizard.js.map +1 -0
- 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 +25 -0
- package/dist/bin/create-secret.d.ts.map +1 -0
- package/dist/bin/create-secret.js +239 -0
- package/dist/bin/create-secret.js.map +1 -0
- 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 +13 -10
- package/dist/lib/benchling-webhook-stack.d.ts.map +1 -1
- package/dist/lib/benchling-webhook-stack.js +25 -69
- 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/fargate-service.d.ts +18 -9
- package/dist/lib/fargate-service.d.ts.map +1 -1
- package/dist/lib/fargate-service.js +177 -61
- package/dist/lib/fargate-service.js.map +1 -1
- 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.d.ts +48 -0
- package/dist/lib/utils/config-loader.d.ts.map +1 -0
- package/dist/lib/utils/config-loader.js +109 -0
- package/dist/lib/utils/config-loader.js.map +1 -0
- package/dist/lib/utils/config-resolver.d.ts +138 -0
- package/dist/lib/utils/config-resolver.d.ts.map +1 -0
- package/dist/lib/utils/config-resolver.js +272 -0
- package/dist/lib/utils/config-resolver.js.map +1 -0
- package/dist/lib/utils/config.d.ts +50 -0
- package/dist/lib/utils/config.d.ts.map +1 -1
- package/dist/lib/utils/config.js +86 -0
- package/dist/lib/utils/config.js.map +1 -1
- package/dist/lib/utils/secrets.d.ts +174 -0
- package/dist/lib/utils/secrets.d.ts.map +1 -0
- package/dist/lib/utils/secrets.js +351 -0
- package/dist/lib/utils/secrets.js.map +1 -0
- 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 +34 -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 +34 -26
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../lib/utils/config.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,MAAM;IAErB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IAGtB,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,qBAAqB,EAAE,MAAM,CAAC;IAC9B,wBAAwB,EAAE,MAAM,CAAC;IAGjC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IAGpB,QAAQ,EAAE,MAAM,CAAC;IAGjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../lib/utils/config.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,MAAM;IAErB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IAIzB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IAGtB,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,qBAAqB,EAAE,MAAM,CAAC;IAC9B,wBAAwB,EAAE,MAAM,CAAC;IAGjC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAG1B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IAGpB,QAAQ,EAAE,MAAM,CAAC;IAGjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,GAAG,SAAS,CAerD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAmBnE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CA6BlE;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAY3C;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,CAsD3E;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAC/B,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,EACvB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACrC,OAAO,CAAC,MAAM,CAAC,CASjB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG,gBAAgB,CAkExE;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,CA0CvE"}
|
package/dist/lib/utils/config.js
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getQuilt3Catalog = getQuilt3Catalog;
|
|
4
4
|
exports.loadDotenv = loadDotenv;
|
|
5
|
+
exports.processBenchlingSecretsInput = processBenchlingSecretsInput;
|
|
6
|
+
exports.maskArn = maskArn;
|
|
5
7
|
exports.loadConfigSync = loadConfigSync;
|
|
6
8
|
exports.mergeInferredConfig = mergeInferredConfig;
|
|
7
9
|
exports.validateConfig = validateConfig;
|
|
@@ -49,6 +51,84 @@ function loadDotenv(filePath) {
|
|
|
49
51
|
}
|
|
50
52
|
return result.parsed || {};
|
|
51
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* Process benchling-secrets parameter, handling @file.json syntax
|
|
56
|
+
*
|
|
57
|
+
* Supports three input formats:
|
|
58
|
+
* - ARN: `arn:aws:secretsmanager:...` - passed through unchanged
|
|
59
|
+
* - JSON: `{"client_id":"...","client_secret":"...","tenant":"..."}` - passed through unchanged
|
|
60
|
+
* - File: `@secrets.json` - reads file content from path after @ symbol
|
|
61
|
+
*
|
|
62
|
+
* @param input - The benchling-secrets value (ARN, JSON, or @filepath)
|
|
63
|
+
* @returns Processed secret string (trimmed)
|
|
64
|
+
* @throws Error if file not found or not readable
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* // Pass through ARN
|
|
68
|
+
* processBenchlingSecretsInput("arn:aws:secretsmanager:...")
|
|
69
|
+
* // Returns: "arn:aws:secretsmanager:..."
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* // Pass through JSON
|
|
73
|
+
* processBenchlingSecretsInput('{"client_id":"...","client_secret":"...","tenant":"..."}')
|
|
74
|
+
* // Returns: '{"client_id":"...","client_secret":"...","tenant":"..."}'
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* // Read from file
|
|
78
|
+
* processBenchlingSecretsInput("@secrets.json")
|
|
79
|
+
* // Returns: contents of secrets.json (trimmed)
|
|
80
|
+
*/
|
|
81
|
+
function processBenchlingSecretsInput(input) {
|
|
82
|
+
const trimmed = input.trim();
|
|
83
|
+
// Check for @file syntax
|
|
84
|
+
if (trimmed.startsWith("@")) {
|
|
85
|
+
const filePath = trimmed.slice(1); // Remove @ prefix
|
|
86
|
+
const resolvedPath = (0, path_1.resolve)(filePath);
|
|
87
|
+
if (!(0, fs_1.existsSync)(resolvedPath)) {
|
|
88
|
+
throw new Error(`Secrets file not found: ${filePath}\n` +
|
|
89
|
+
` Resolved path: ${resolvedPath}\n` +
|
|
90
|
+
" Tip: Use relative or absolute path after @ (e.g., @secrets.json or @/path/to/secrets.json)");
|
|
91
|
+
}
|
|
92
|
+
try {
|
|
93
|
+
const fileContent = (0, fs_1.readFileSync)(resolvedPath, "utf-8");
|
|
94
|
+
return fileContent.trim();
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
throw new Error(`Failed to read secrets file: ${filePath}\n` +
|
|
98
|
+
` Error: ${error.message}`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
// Return as-is for ARN or inline JSON
|
|
102
|
+
return trimmed;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Mask sensitive parts of ARN for display
|
|
106
|
+
*
|
|
107
|
+
* Shows region and partial secret name, masks account ID for security.
|
|
108
|
+
* Account ID is masked as ****XXXX where XXXX are the last 4 digits.
|
|
109
|
+
*
|
|
110
|
+
* @param arn - AWS Secrets Manager ARN to mask
|
|
111
|
+
* @returns Masked ARN string or original input if not valid ARN format
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* maskArn("arn:aws:secretsmanager:us-east-1:123456789012:secret:name")
|
|
115
|
+
* // Returns: "arn:aws:secretsmanager:us-east-1:****9012:secret:name"
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* maskArn("not-an-arn")
|
|
119
|
+
* // Returns: "not-an-arn"
|
|
120
|
+
*/
|
|
121
|
+
function maskArn(arn) {
|
|
122
|
+
// Pattern: arn:aws:secretsmanager:region:account:secret:name
|
|
123
|
+
const match = arn.match(/^(arn:aws:secretsmanager:[^:]+:)(\d{12})(:.+)$/);
|
|
124
|
+
if (match) {
|
|
125
|
+
const [, prefix, account, suffix] = match;
|
|
126
|
+
const maskedAccount = "****" + account.slice(-4);
|
|
127
|
+
return prefix + maskedAccount + suffix;
|
|
128
|
+
}
|
|
129
|
+
// Return as-is if pattern doesn't match
|
|
130
|
+
return arn;
|
|
131
|
+
}
|
|
52
132
|
/**
|
|
53
133
|
* Load configuration from multiple sources with priority:
|
|
54
134
|
* 1. CLI options (highest)
|
|
@@ -76,6 +156,12 @@ function loadConfigSync(options = {}) {
|
|
|
76
156
|
benchlingClientId: options.clientId || envVars.BENCHLING_CLIENT_ID,
|
|
77
157
|
benchlingClientSecret: options.clientSecret || envVars.BENCHLING_CLIENT_SECRET,
|
|
78
158
|
benchlingAppDefinitionId: options.appId || envVars.BENCHLING_APP_DEFINITION_ID,
|
|
159
|
+
// Unified secrets (priority: CLI > env > .env)
|
|
160
|
+
// Process file input syntax (@file.json) if present
|
|
161
|
+
benchlingSecrets: (() => {
|
|
162
|
+
const rawSecrets = options.benchlingSecrets || envVars.BENCHLING_SECRETS;
|
|
163
|
+
return rawSecrets ? processBenchlingSecretsInput(rawSecrets) : undefined;
|
|
164
|
+
})(),
|
|
79
165
|
// AWS
|
|
80
166
|
cdkAccount: envVars.CDK_DEFAULT_ACCOUNT,
|
|
81
167
|
cdkRegion: options.region || envVars.CDK_DEFAULT_REGION || envVars.AWS_REGION,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../lib/utils/config.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../lib/utils/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Benchling Secrets Management
|
|
3
|
+
*
|
|
4
|
+
* This module provides types, validation, and utilities for managing
|
|
5
|
+
* Benchling API credentials in AWS Secrets Manager.
|
|
6
|
+
*
|
|
7
|
+
* ## Supported Formats
|
|
8
|
+
*
|
|
9
|
+
* ### ARN Format
|
|
10
|
+
* Provide the ARN of an existing AWS Secrets Manager secret:
|
|
11
|
+
* ```
|
|
12
|
+
* arn:aws:secretsmanager:us-east-1:123456789012:secret:benchling-webhook/credentials
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* ### JSON Format
|
|
16
|
+
* Provide credentials as a JSON object:
|
|
17
|
+
* ```json
|
|
18
|
+
* {
|
|
19
|
+
* "client_id": "your-client-id",
|
|
20
|
+
* "client_secret": "your-client-secret",
|
|
21
|
+
* "tenant": "your-tenant",
|
|
22
|
+
* "app_definition_id": "optional-app-id",
|
|
23
|
+
* "api_url": "https://optional-api-url.com"
|
|
24
|
+
* }
|
|
25
|
+
* ```
|
|
26
|
+
*
|
|
27
|
+
* ## Usage
|
|
28
|
+
*
|
|
29
|
+
* ```typescript
|
|
30
|
+
* import { parseAndValidateSecrets } from './secrets';
|
|
31
|
+
*
|
|
32
|
+
* // Parse and validate ARN
|
|
33
|
+
* const arnConfig = parseAndValidateSecrets(
|
|
34
|
+
* 'arn:aws:secretsmanager:us-east-1:123456789012:secret:name'
|
|
35
|
+
* );
|
|
36
|
+
* console.log(arnConfig.format); // "arn"
|
|
37
|
+
* console.log(arnConfig.arn); // the validated ARN
|
|
38
|
+
*
|
|
39
|
+
* // Parse and validate JSON
|
|
40
|
+
* const jsonConfig = parseAndValidateSecrets(
|
|
41
|
+
* '{"client_id":"abc","client_secret":"secret","tenant":"company"}'
|
|
42
|
+
* );
|
|
43
|
+
* console.log(jsonConfig.format); // "json"
|
|
44
|
+
* console.log(jsonConfig.data); // the validated secret data
|
|
45
|
+
*
|
|
46
|
+
* // Handle validation errors
|
|
47
|
+
* try {
|
|
48
|
+
* parseAndValidateSecrets('invalid');
|
|
49
|
+
* } catch (error) {
|
|
50
|
+
* if (error instanceof SecretsValidationError) {
|
|
51
|
+
* console.error(error.formatForCLI());
|
|
52
|
+
* }
|
|
53
|
+
* }
|
|
54
|
+
* ```
|
|
55
|
+
*
|
|
56
|
+
* @module secrets
|
|
57
|
+
*/
|
|
58
|
+
/**
|
|
59
|
+
* Benchling secret structure stored in AWS Secrets Manager
|
|
60
|
+
*/
|
|
61
|
+
export interface BenchlingSecretData {
|
|
62
|
+
/** Benchling OAuth client ID */
|
|
63
|
+
client_id: string;
|
|
64
|
+
/** Benchling OAuth client secret */
|
|
65
|
+
client_secret: string;
|
|
66
|
+
/** Benchling tenant name (e.g., "company" for company.benchling.com) */
|
|
67
|
+
tenant: string;
|
|
68
|
+
/** Benchling app definition ID (optional for backward compatibility) */
|
|
69
|
+
app_definition_id?: string;
|
|
70
|
+
/** Custom Benchling API URL (optional, defaults to https://{tenant}.benchling.com) */
|
|
71
|
+
api_url?: string;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Accepted formats for BENCHLING_SECRETS parameter
|
|
75
|
+
* Can be either a Secret ARN or JSON string
|
|
76
|
+
*/
|
|
77
|
+
export type BenchlingSecretsInput = string;
|
|
78
|
+
/**
|
|
79
|
+
* Parsed and validated secret configuration
|
|
80
|
+
*/
|
|
81
|
+
export interface BenchlingSecretsConfig {
|
|
82
|
+
/** The input format detected */
|
|
83
|
+
format: "arn" | "json";
|
|
84
|
+
/** If format is "arn", the validated ARN */
|
|
85
|
+
arn?: string;
|
|
86
|
+
/** If format is "json", the validated secret data */
|
|
87
|
+
data?: BenchlingSecretData;
|
|
88
|
+
/** Original input value (for error messages) */
|
|
89
|
+
original: string;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Validation result with errors and warnings
|
|
93
|
+
*/
|
|
94
|
+
export interface ValidationResult {
|
|
95
|
+
valid: boolean;
|
|
96
|
+
errors: ValidationError[];
|
|
97
|
+
warnings: string[];
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Validation error details
|
|
101
|
+
*/
|
|
102
|
+
export interface ValidationError {
|
|
103
|
+
field: string;
|
|
104
|
+
message: string;
|
|
105
|
+
suggestion?: string;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Detect whether input is an ARN or JSON string
|
|
109
|
+
*
|
|
110
|
+
* @param input - The BENCHLING_SECRETS input value
|
|
111
|
+
* @returns "arn" if input looks like an ARN, "json" otherwise
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* detectSecretsFormat("arn:aws:secretsmanager:...") // returns "arn"
|
|
115
|
+
* detectSecretsFormat('{"client_id":"..."}') // returns "json"
|
|
116
|
+
*/
|
|
117
|
+
export declare function detectSecretsFormat(input: string): "arn" | "json";
|
|
118
|
+
/**
|
|
119
|
+
* Validate AWS Secrets Manager ARN format
|
|
120
|
+
*
|
|
121
|
+
* @param arn - The ARN string to validate
|
|
122
|
+
* @returns Validation result with errors and warnings
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* validateSecretArn("arn:aws:secretsmanager:us-east-1:123456789012:secret:name")
|
|
126
|
+
* // returns { valid: true, errors: [], warnings: [] }
|
|
127
|
+
*/
|
|
128
|
+
export declare function validateSecretArn(arn: string): ValidationResult;
|
|
129
|
+
/**
|
|
130
|
+
* Validate secret data structure and field values
|
|
131
|
+
*
|
|
132
|
+
* @param data - The secret data object to validate
|
|
133
|
+
* @returns Validation result with errors and warnings
|
|
134
|
+
*
|
|
135
|
+
* @example
|
|
136
|
+
* validateSecretData({ client_id: "abc", client_secret: "secret", tenant: "company" })
|
|
137
|
+
* // returns { valid: true, errors: [], warnings: [] }
|
|
138
|
+
*/
|
|
139
|
+
export declare function validateSecretData(data: unknown): ValidationResult;
|
|
140
|
+
/**
|
|
141
|
+
* Custom error class for secrets validation failures
|
|
142
|
+
*/
|
|
143
|
+
export declare class SecretsValidationError extends Error {
|
|
144
|
+
readonly errors: ValidationError[];
|
|
145
|
+
readonly warnings: string[];
|
|
146
|
+
constructor(message: string, errors: ValidationError[], warnings: string[]);
|
|
147
|
+
/**
|
|
148
|
+
* Format errors for CLI display
|
|
149
|
+
*/
|
|
150
|
+
formatForCLI(): string;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Parse and validate BENCHLING_SECRETS input
|
|
154
|
+
*
|
|
155
|
+
* This is the main entry point for secret validation. It detects the format
|
|
156
|
+
* (ARN or JSON), performs appropriate validation, and returns a structured
|
|
157
|
+
* configuration object.
|
|
158
|
+
*
|
|
159
|
+
* @param input - The BENCHLING_SECRETS input string
|
|
160
|
+
* @returns Parsed and validated configuration
|
|
161
|
+
* @throws SecretsValidationError if validation fails
|
|
162
|
+
*
|
|
163
|
+
* @example
|
|
164
|
+
* // Parse ARN
|
|
165
|
+
* const config = parseAndValidateSecrets("arn:aws:secretsmanager:...")
|
|
166
|
+
* console.log(config.format) // "arn"
|
|
167
|
+
*
|
|
168
|
+
* @example
|
|
169
|
+
* // Parse JSON
|
|
170
|
+
* const config = parseAndValidateSecrets('{"client_id":"...","client_secret":"...","tenant":"..."}')
|
|
171
|
+
* console.log(config.format) // "json"
|
|
172
|
+
*/
|
|
173
|
+
export declare function parseAndValidateSecrets(input: string): BenchlingSecretsConfig;
|
|
174
|
+
//# sourceMappingURL=secrets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secrets.d.ts","sourceRoot":"","sources":["../../../lib/utils/secrets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwDG;AAEH;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,gCAAgC;IAChC,SAAS,EAAE,MAAM,CAAC;IAElB,oCAAoC;IACpC,aAAa,EAAE,MAAM,CAAC;IAEtB,wEAAwE;IACxE,MAAM,EAAE,MAAM,CAAC;IAEf,wEAAwE;IACxE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B,sFAAsF;IACtF,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,MAAM,MAAM,qBAAqB,GAAG,MAAM,CAAC;AAE3C;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,gCAAgC;IAChC,MAAM,EAAE,KAAK,GAAG,MAAM,CAAC;IAEvB,4CAA4C;IAC5C,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb,qDAAqD;IACrD,IAAI,CAAC,EAAE,mBAAmB,CAAC;IAE3B,gDAAgD;IAChD,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,GAAG,MAAM,CAgBjE;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,gBAAgB,CAoD/D;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,OAAO,GAAG,gBAAgB,CAoGlE;AAED;;GAEG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;IAC7C,SAAgB,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1C,SAAgB,QAAQ,EAAE,MAAM,EAAE,CAAC;gBAEvB,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE;IAY1E;;OAEG;IACI,YAAY,IAAI,MAAM;CAwBhC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,sBAAsB,CAyD7E"}
|
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Benchling Secrets Management
|
|
4
|
+
*
|
|
5
|
+
* This module provides types, validation, and utilities for managing
|
|
6
|
+
* Benchling API credentials in AWS Secrets Manager.
|
|
7
|
+
*
|
|
8
|
+
* ## Supported Formats
|
|
9
|
+
*
|
|
10
|
+
* ### ARN Format
|
|
11
|
+
* Provide the ARN of an existing AWS Secrets Manager secret:
|
|
12
|
+
* ```
|
|
13
|
+
* arn:aws:secretsmanager:us-east-1:123456789012:secret:benchling-webhook/credentials
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* ### JSON Format
|
|
17
|
+
* Provide credentials as a JSON object:
|
|
18
|
+
* ```json
|
|
19
|
+
* {
|
|
20
|
+
* "client_id": "your-client-id",
|
|
21
|
+
* "client_secret": "your-client-secret",
|
|
22
|
+
* "tenant": "your-tenant",
|
|
23
|
+
* "app_definition_id": "optional-app-id",
|
|
24
|
+
* "api_url": "https://optional-api-url.com"
|
|
25
|
+
* }
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* ## Usage
|
|
29
|
+
*
|
|
30
|
+
* ```typescript
|
|
31
|
+
* import { parseAndValidateSecrets } from './secrets';
|
|
32
|
+
*
|
|
33
|
+
* // Parse and validate ARN
|
|
34
|
+
* const arnConfig = parseAndValidateSecrets(
|
|
35
|
+
* 'arn:aws:secretsmanager:us-east-1:123456789012:secret:name'
|
|
36
|
+
* );
|
|
37
|
+
* console.log(arnConfig.format); // "arn"
|
|
38
|
+
* console.log(arnConfig.arn); // the validated ARN
|
|
39
|
+
*
|
|
40
|
+
* // Parse and validate JSON
|
|
41
|
+
* const jsonConfig = parseAndValidateSecrets(
|
|
42
|
+
* '{"client_id":"abc","client_secret":"secret","tenant":"company"}'
|
|
43
|
+
* );
|
|
44
|
+
* console.log(jsonConfig.format); // "json"
|
|
45
|
+
* console.log(jsonConfig.data); // the validated secret data
|
|
46
|
+
*
|
|
47
|
+
* // Handle validation errors
|
|
48
|
+
* try {
|
|
49
|
+
* parseAndValidateSecrets('invalid');
|
|
50
|
+
* } catch (error) {
|
|
51
|
+
* if (error instanceof SecretsValidationError) {
|
|
52
|
+
* console.error(error.formatForCLI());
|
|
53
|
+
* }
|
|
54
|
+
* }
|
|
55
|
+
* ```
|
|
56
|
+
*
|
|
57
|
+
* @module secrets
|
|
58
|
+
*/
|
|
59
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
60
|
+
exports.SecretsValidationError = void 0;
|
|
61
|
+
exports.detectSecretsFormat = detectSecretsFormat;
|
|
62
|
+
exports.validateSecretArn = validateSecretArn;
|
|
63
|
+
exports.validateSecretData = validateSecretData;
|
|
64
|
+
exports.parseAndValidateSecrets = parseAndValidateSecrets;
|
|
65
|
+
/**
|
|
66
|
+
* Detect whether input is an ARN or JSON string
|
|
67
|
+
*
|
|
68
|
+
* @param input - The BENCHLING_SECRETS input value
|
|
69
|
+
* @returns "arn" if input looks like an ARN, "json" otherwise
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* detectSecretsFormat("arn:aws:secretsmanager:...") // returns "arn"
|
|
73
|
+
* detectSecretsFormat('{"client_id":"..."}') // returns "json"
|
|
74
|
+
*/
|
|
75
|
+
function detectSecretsFormat(input) {
|
|
76
|
+
// Trim whitespace
|
|
77
|
+
const trimmed = input.trim();
|
|
78
|
+
// Check if starts with ARN prefix
|
|
79
|
+
if (trimmed.startsWith("arn:aws:secretsmanager:")) {
|
|
80
|
+
return "arn";
|
|
81
|
+
}
|
|
82
|
+
// Check if starts with { (JSON object)
|
|
83
|
+
if (trimmed.startsWith("{")) {
|
|
84
|
+
return "json";
|
|
85
|
+
}
|
|
86
|
+
// Default to JSON and let validation catch errors
|
|
87
|
+
return "json";
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Validate AWS Secrets Manager ARN format
|
|
91
|
+
*
|
|
92
|
+
* @param arn - The ARN string to validate
|
|
93
|
+
* @returns Validation result with errors and warnings
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* validateSecretArn("arn:aws:secretsmanager:us-east-1:123456789012:secret:name")
|
|
97
|
+
* // returns { valid: true, errors: [], warnings: [] }
|
|
98
|
+
*/
|
|
99
|
+
function validateSecretArn(arn) {
|
|
100
|
+
const errors = [];
|
|
101
|
+
const warnings = [];
|
|
102
|
+
// Check ARN format using regex
|
|
103
|
+
// Pattern: arn:aws:secretsmanager:region:account:secret:name
|
|
104
|
+
const arnPattern = /^arn:aws:secretsmanager:([a-z0-9-]+):(\d{12}):secret:(.+)$/;
|
|
105
|
+
const match = arn.match(arnPattern);
|
|
106
|
+
if (!match) {
|
|
107
|
+
errors.push({
|
|
108
|
+
field: "arn",
|
|
109
|
+
message: "Invalid AWS Secrets Manager ARN format",
|
|
110
|
+
suggestion: "Expected format: arn:aws:secretsmanager:region:account:secret:name",
|
|
111
|
+
});
|
|
112
|
+
return { valid: false, errors, warnings };
|
|
113
|
+
}
|
|
114
|
+
const [, region, accountId, secretName] = match;
|
|
115
|
+
// Validate region (basic check - not empty)
|
|
116
|
+
if (!region || region.length === 0) {
|
|
117
|
+
errors.push({
|
|
118
|
+
field: "region",
|
|
119
|
+
message: "ARN missing AWS region",
|
|
120
|
+
suggestion: "Ensure ARN includes a valid AWS region (e.g., us-east-1)",
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
// Validate account ID (must be exactly 12 digits)
|
|
124
|
+
if (accountId.length !== 12) {
|
|
125
|
+
errors.push({
|
|
126
|
+
field: "account",
|
|
127
|
+
message: "Invalid AWS account ID in ARN",
|
|
128
|
+
suggestion: "Account ID must be exactly 12 digits",
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
// Validate secret name (not empty)
|
|
132
|
+
if (!secretName || secretName.length === 0) {
|
|
133
|
+
errors.push({
|
|
134
|
+
field: "secret",
|
|
135
|
+
message: "ARN missing secret name",
|
|
136
|
+
suggestion: "Ensure ARN includes the secret name",
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
return {
|
|
140
|
+
valid: errors.length === 0,
|
|
141
|
+
errors,
|
|
142
|
+
warnings,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Validate secret data structure and field values
|
|
147
|
+
*
|
|
148
|
+
* @param data - The secret data object to validate
|
|
149
|
+
* @returns Validation result with errors and warnings
|
|
150
|
+
*
|
|
151
|
+
* @example
|
|
152
|
+
* validateSecretData({ client_id: "abc", client_secret: "secret", tenant: "company" })
|
|
153
|
+
* // returns { valid: true, errors: [], warnings: [] }
|
|
154
|
+
*/
|
|
155
|
+
function validateSecretData(data) {
|
|
156
|
+
const errors = [];
|
|
157
|
+
const warnings = [];
|
|
158
|
+
// Check if data is an object
|
|
159
|
+
if (typeof data !== "object" || data === null || Array.isArray(data)) {
|
|
160
|
+
errors.push({
|
|
161
|
+
field: "data",
|
|
162
|
+
message: "Secret data must be a JSON object",
|
|
163
|
+
suggestion: "Expected format: {\"client_id\": \"...\", \"client_secret\": \"...\", \"tenant\": \"...\"}",
|
|
164
|
+
});
|
|
165
|
+
return { valid: false, errors, warnings };
|
|
166
|
+
}
|
|
167
|
+
const secretData = data;
|
|
168
|
+
// Required fields
|
|
169
|
+
const requiredFields = [
|
|
170
|
+
"client_id",
|
|
171
|
+
"client_secret",
|
|
172
|
+
"tenant",
|
|
173
|
+
];
|
|
174
|
+
for (const field of requiredFields) {
|
|
175
|
+
if (!(field in secretData)) {
|
|
176
|
+
errors.push({
|
|
177
|
+
field,
|
|
178
|
+
message: `Missing required field: ${field}`,
|
|
179
|
+
suggestion: `Add "${field}" to your secret configuration`,
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
else if (typeof secretData[field] !== "string") {
|
|
183
|
+
errors.push({
|
|
184
|
+
field,
|
|
185
|
+
message: `Field ${field} must be a string`,
|
|
186
|
+
suggestion: `Change ${field} value to a string`,
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
else if (secretData[field].trim() === "") {
|
|
190
|
+
errors.push({
|
|
191
|
+
field,
|
|
192
|
+
message: `Field ${field} cannot be empty`,
|
|
193
|
+
suggestion: `Provide a non-empty value for ${field}`,
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
// Optional fields type checking
|
|
198
|
+
const optionalFields = [
|
|
199
|
+
"app_definition_id",
|
|
200
|
+
"api_url",
|
|
201
|
+
];
|
|
202
|
+
for (const field of optionalFields) {
|
|
203
|
+
if (field in secretData && typeof secretData[field] !== "string") {
|
|
204
|
+
errors.push({
|
|
205
|
+
field,
|
|
206
|
+
message: `Field ${field} must be a string`,
|
|
207
|
+
suggestion: `Change ${field} value to a string or remove it`,
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
// Validate tenant format (alphanumeric and hyphens)
|
|
212
|
+
if (secretData.tenant && typeof secretData.tenant === "string") {
|
|
213
|
+
const tenantPattern = /^[a-z0-9-]+$/i;
|
|
214
|
+
if (!tenantPattern.test(secretData.tenant)) {
|
|
215
|
+
errors.push({
|
|
216
|
+
field: "tenant",
|
|
217
|
+
message: "Invalid tenant format",
|
|
218
|
+
suggestion: "Tenant must contain only letters, numbers, and hyphens",
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
// Validate api_url if provided
|
|
223
|
+
if (secretData.api_url && typeof secretData.api_url === "string") {
|
|
224
|
+
try {
|
|
225
|
+
new URL(secretData.api_url);
|
|
226
|
+
}
|
|
227
|
+
catch {
|
|
228
|
+
errors.push({
|
|
229
|
+
field: "api_url",
|
|
230
|
+
message: "Invalid URL format for api_url",
|
|
231
|
+
suggestion: "Provide a valid URL (e.g., https://company.benchling.com)",
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
// Check for unknown fields (warning only)
|
|
236
|
+
const knownFields = new Set([...requiredFields, ...optionalFields]);
|
|
237
|
+
for (const field in secretData) {
|
|
238
|
+
if (!knownFields.has(field)) {
|
|
239
|
+
warnings.push(`Unknown field "${field}" will be ignored`);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
return {
|
|
243
|
+
valid: errors.length === 0,
|
|
244
|
+
errors,
|
|
245
|
+
warnings,
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Custom error class for secrets validation failures
|
|
250
|
+
*/
|
|
251
|
+
class SecretsValidationError extends Error {
|
|
252
|
+
constructor(message, errors, warnings) {
|
|
253
|
+
super(message);
|
|
254
|
+
this.name = "SecretsValidationError";
|
|
255
|
+
this.errors = errors;
|
|
256
|
+
this.warnings = warnings;
|
|
257
|
+
// Maintain proper stack trace (only available on V8)
|
|
258
|
+
if (Error.captureStackTrace) {
|
|
259
|
+
Error.captureStackTrace(this, SecretsValidationError);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Format errors for CLI display
|
|
264
|
+
*/
|
|
265
|
+
formatForCLI() {
|
|
266
|
+
const lines = [this.message, ""];
|
|
267
|
+
if (this.errors.length > 0) {
|
|
268
|
+
lines.push("Errors:");
|
|
269
|
+
for (const error of this.errors) {
|
|
270
|
+
lines.push(` × ${error.field}: ${error.message}`);
|
|
271
|
+
if (error.suggestion) {
|
|
272
|
+
lines.push(` → ${error.suggestion}`);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
lines.push("");
|
|
276
|
+
}
|
|
277
|
+
if (this.warnings.length > 0) {
|
|
278
|
+
lines.push("Warnings:");
|
|
279
|
+
for (const warning of this.warnings) {
|
|
280
|
+
lines.push(` ⚠ ${warning}`);
|
|
281
|
+
}
|
|
282
|
+
lines.push("");
|
|
283
|
+
}
|
|
284
|
+
return lines.join("\n");
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
exports.SecretsValidationError = SecretsValidationError;
|
|
288
|
+
/**
|
|
289
|
+
* Parse and validate BENCHLING_SECRETS input
|
|
290
|
+
*
|
|
291
|
+
* This is the main entry point for secret validation. It detects the format
|
|
292
|
+
* (ARN or JSON), performs appropriate validation, and returns a structured
|
|
293
|
+
* configuration object.
|
|
294
|
+
*
|
|
295
|
+
* @param input - The BENCHLING_SECRETS input string
|
|
296
|
+
* @returns Parsed and validated configuration
|
|
297
|
+
* @throws SecretsValidationError if validation fails
|
|
298
|
+
*
|
|
299
|
+
* @example
|
|
300
|
+
* // Parse ARN
|
|
301
|
+
* const config = parseAndValidateSecrets("arn:aws:secretsmanager:...")
|
|
302
|
+
* console.log(config.format) // "arn"
|
|
303
|
+
*
|
|
304
|
+
* @example
|
|
305
|
+
* // Parse JSON
|
|
306
|
+
* const config = parseAndValidateSecrets('{"client_id":"...","client_secret":"...","tenant":"..."}')
|
|
307
|
+
* console.log(config.format) // "json"
|
|
308
|
+
*/
|
|
309
|
+
function parseAndValidateSecrets(input) {
|
|
310
|
+
// Detect format
|
|
311
|
+
const format = detectSecretsFormat(input);
|
|
312
|
+
if (format === "arn") {
|
|
313
|
+
// Validate ARN
|
|
314
|
+
const validation = validateSecretArn(input);
|
|
315
|
+
if (!validation.valid) {
|
|
316
|
+
throw new SecretsValidationError("Invalid secret ARN", validation.errors, validation.warnings);
|
|
317
|
+
}
|
|
318
|
+
return {
|
|
319
|
+
format: "arn",
|
|
320
|
+
arn: input.trim(),
|
|
321
|
+
original: input,
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
else {
|
|
325
|
+
// Parse JSON
|
|
326
|
+
let data;
|
|
327
|
+
try {
|
|
328
|
+
data = JSON.parse(input);
|
|
329
|
+
}
|
|
330
|
+
catch (error) {
|
|
331
|
+
throw new SecretsValidationError("Invalid JSON in secret data", [
|
|
332
|
+
{
|
|
333
|
+
field: "json",
|
|
334
|
+
message: `JSON parse error: ${error.message}`,
|
|
335
|
+
suggestion: "Ensure the secret data is valid JSON",
|
|
336
|
+
},
|
|
337
|
+
], []);
|
|
338
|
+
}
|
|
339
|
+
// Validate structure
|
|
340
|
+
const validation = validateSecretData(data);
|
|
341
|
+
if (!validation.valid) {
|
|
342
|
+
throw new SecretsValidationError("Invalid secret data structure", validation.errors, validation.warnings);
|
|
343
|
+
}
|
|
344
|
+
return {
|
|
345
|
+
format: "json",
|
|
346
|
+
data: data,
|
|
347
|
+
original: input,
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
//# sourceMappingURL=secrets.js.map
|