sst 2.0.35 → 2.0.37
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/bootstrap.js +1 -1
- package/constructs/Api.d.ts +2 -10
- package/constructs/Api.js +2 -2
- package/constructs/ApiGatewayV1Api.d.ts +2 -10
- package/constructs/ApiGatewayV1Api.js +2 -2
- package/constructs/App.d.ts +0 -2
- package/constructs/App.js +3 -7
- package/constructs/AppSyncApi.d.ts +2 -10
- package/constructs/AppSyncApi.js +2 -2
- package/constructs/Auth.js +10 -7
- package/constructs/Bucket.d.ts +2 -12
- package/constructs/Bucket.js +2 -2
- package/constructs/EventBus.d.ts +2 -12
- package/constructs/EventBus.js +2 -2
- package/constructs/Function.d.ts +3 -12
- package/constructs/Function.js +10 -6
- package/constructs/Job.d.ts +3 -13
- package/constructs/Job.js +9 -7
- package/constructs/KinesisStream.d.ts +2 -12
- package/constructs/KinesisStream.js +2 -2
- package/constructs/NextjsSite.js +19 -30
- package/constructs/Parameter.d.ts +2 -10
- package/constructs/Parameter.js +2 -2
- package/constructs/Queue.d.ts +2 -12
- package/constructs/Queue.js +2 -2
- package/constructs/RDS.d.ts +2 -22
- package/constructs/RDS.js +7 -7
- package/constructs/Secret.js +2 -4
- package/constructs/SsrSite.js +14 -9
- package/constructs/StaticSite.js +14 -9
- package/constructs/Table.d.ts +2 -12
- package/constructs/Table.js +2 -2
- package/constructs/Topic.d.ts +2 -12
- package/constructs/Topic.js +2 -2
- package/constructs/WebSocketApi.d.ts +2 -10
- package/constructs/WebSocketApi.js +2 -2
- package/constructs/deprecated/NextjsSite.js +4 -4
- package/constructs/util/functionBinding.d.ts +14 -3
- package/constructs/util/functionBinding.js +45 -11
- package/node/api/index.js +5 -5
- package/node/auth/auth.js +9 -53
- package/node/bucket/index.js +2 -2
- package/node/config/index.js +4 -56
- package/node/event-bus/index.js +2 -2
- package/node/function/index.js +2 -2
- package/node/job/index.js +2 -2
- package/node/kinesis-stream/index.js +2 -2
- package/node/queue/index.js +2 -2
- package/node/rds/index.js +2 -2
- package/node/site/index.js +6 -52
- package/node/table/index.js +2 -2
- package/node/topic/index.js +2 -2
- package/node/util/index.d.ts +1 -6
- package/node/util/index.js +122 -26
- package/package.json +1 -1
- package/runtime/handlers/node.js +2 -0
- package/runtime/server.js +1 -5
- package/sst.mjs +6 -6
- package/support/bridge/bridge.mjs +23 -23
- /package/support/{ssr-site-function-stub → sls-nextjs-site-function-stub}/index.js +0 -0
package/constructs/RDS.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import * as rds from "aws-cdk-lib/aws-rds";
|
|
|
4
4
|
import * as secretsManager from "aws-cdk-lib/aws-secretsmanager";
|
|
5
5
|
import { SSTConstruct } from "./Construct.js";
|
|
6
6
|
import { Function as Fn } from "./Function.js";
|
|
7
|
+
import { FunctionBindingProps } from "./util/functionBinding.js";
|
|
7
8
|
export interface RDSTypes {
|
|
8
9
|
path: string;
|
|
9
10
|
camelCase?: boolean;
|
|
@@ -203,28 +204,7 @@ export declare class RDS extends Construct implements SSTConstruct {
|
|
|
203
204
|
};
|
|
204
205
|
};
|
|
205
206
|
/** @internal */
|
|
206
|
-
getFunctionBinding():
|
|
207
|
-
clientPackage: string;
|
|
208
|
-
variables: {
|
|
209
|
-
clusterArn: {
|
|
210
|
-
environment: string;
|
|
211
|
-
parameter: string;
|
|
212
|
-
};
|
|
213
|
-
secretArn: {
|
|
214
|
-
environment: string;
|
|
215
|
-
parameter: string;
|
|
216
|
-
};
|
|
217
|
-
defaultDatabaseName: {
|
|
218
|
-
environment: string;
|
|
219
|
-
parameter: string;
|
|
220
|
-
};
|
|
221
|
-
};
|
|
222
|
-
permissions: {
|
|
223
|
-
"rds-data:*": string[];
|
|
224
|
-
"secretsmanager:GetSecretValue": string[];
|
|
225
|
-
"secretsmanager:DescribeSecret": string[];
|
|
226
|
-
};
|
|
227
|
-
};
|
|
207
|
+
getFunctionBinding(): FunctionBindingProps;
|
|
228
208
|
private validateRequiredProps;
|
|
229
209
|
private validateCDKPropWhenIsConstruct;
|
|
230
210
|
private validateCDKPropWhenIsClusterProps;
|
package/constructs/RDS.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import path from "path";
|
|
2
2
|
import glob from "glob";
|
|
3
3
|
import fs from "fs";
|
|
4
|
+
import url from "url";
|
|
4
5
|
import * as crypto from "crypto";
|
|
5
6
|
import { Construct } from "constructs";
|
|
6
7
|
import * as cdk from "aws-cdk-lib";
|
|
@@ -9,7 +10,6 @@ import * as rds from "aws-cdk-lib/aws-rds";
|
|
|
9
10
|
import * as lambda from "aws-cdk-lib/aws-lambda";
|
|
10
11
|
import { getFunctionRef, isCDKConstruct } from "./Construct.js";
|
|
11
12
|
import { Function as Fn } from "./Function.js";
|
|
12
|
-
import url from "url";
|
|
13
13
|
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
|
|
14
14
|
/////////////////////
|
|
15
15
|
// Construct
|
|
@@ -117,16 +117,16 @@ export class RDS extends Construct {
|
|
|
117
117
|
clientPackage: "rds",
|
|
118
118
|
variables: {
|
|
119
119
|
clusterArn: {
|
|
120
|
-
|
|
121
|
-
|
|
120
|
+
type: "plain",
|
|
121
|
+
value: this.clusterArn,
|
|
122
122
|
},
|
|
123
123
|
secretArn: {
|
|
124
|
-
|
|
125
|
-
|
|
124
|
+
type: "plain",
|
|
125
|
+
value: this.secretArn,
|
|
126
126
|
},
|
|
127
127
|
defaultDatabaseName: {
|
|
128
|
-
|
|
129
|
-
|
|
128
|
+
type: "plain",
|
|
129
|
+
value: this.defaultDatabaseName,
|
|
130
130
|
},
|
|
131
131
|
},
|
|
132
132
|
permissions: {
|
package/constructs/Secret.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Construct } from "constructs";
|
|
2
2
|
import { Stack } from "./Stack.js";
|
|
3
|
-
import {
|
|
3
|
+
import { getParameterPath, getParameterFallbackPath, } from "./util/functionBinding.js";
|
|
4
4
|
/**
|
|
5
5
|
* The `Secret` construct is a higher level CDK construct that makes it easy to manage app secrets.
|
|
6
6
|
*
|
|
@@ -38,9 +38,7 @@ export class Secret extends Construct {
|
|
|
38
38
|
clientPackage: "config",
|
|
39
39
|
variables: {
|
|
40
40
|
value: {
|
|
41
|
-
|
|
42
|
-
// SSM parameters will be created manually via CLI
|
|
43
|
-
parameter: undefined,
|
|
41
|
+
type: "secret",
|
|
44
42
|
},
|
|
45
43
|
},
|
|
46
44
|
permissions: {
|
package/constructs/SsrSite.js
CHANGED
|
@@ -23,7 +23,7 @@ import { getBuildCmdEnvironment, } from "./BaseSite.js";
|
|
|
23
23
|
import { HttpsRedirect } from "./cdk/website-redirect.js";
|
|
24
24
|
import { DnsValidatedCertificate } from "./cdk/dns-validated-certificate.js";
|
|
25
25
|
import { attachPermissionsToRole } from "./util/permission.js";
|
|
26
|
-
import {
|
|
26
|
+
import { getParameterPath, } from "./util/functionBinding.js";
|
|
27
27
|
import { SiteEnv } from "../site-env.js";
|
|
28
28
|
import { useProject } from "../project.js";
|
|
29
29
|
import { VisibleError } from "../error.js";
|
|
@@ -183,14 +183,19 @@ export class SsrSite extends Construct {
|
|
|
183
183
|
return {
|
|
184
184
|
clientPackage: "site",
|
|
185
185
|
variables: {
|
|
186
|
-
url:
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
186
|
+
url: this.doNotDeploy
|
|
187
|
+
? {
|
|
188
|
+
type: "plain",
|
|
189
|
+
value: "localhost",
|
|
190
|
+
}
|
|
191
|
+
: {
|
|
192
|
+
// Do not set real value b/c we don't want to make the Lambda function
|
|
193
|
+
// depend on the Site. B/c often the site depends on the Api, causing
|
|
194
|
+
// a CloudFormation circular dependency if the Api and the Site belong
|
|
195
|
+
// to different stacks.
|
|
196
|
+
type: "site_url",
|
|
197
|
+
value: this.customDomainUrl || this.url,
|
|
198
|
+
},
|
|
194
199
|
},
|
|
195
200
|
permissions: {
|
|
196
201
|
"ssm:GetParameters": [
|
package/constructs/StaticSite.js
CHANGED
|
@@ -19,7 +19,7 @@ import { getBuildCmdEnvironment, buildErrorResponsesFor404ErrorPage, buildErrorR
|
|
|
19
19
|
import { HttpsRedirect } from "./cdk/website-redirect.js";
|
|
20
20
|
import { DnsValidatedCertificate } from "./cdk/dns-validated-certificate.js";
|
|
21
21
|
import { isCDKConstruct } from "./Construct.js";
|
|
22
|
-
import {
|
|
22
|
+
import { getParameterPath, } from "./util/functionBinding.js";
|
|
23
23
|
import { gray } from "colorette";
|
|
24
24
|
import { useProject } from "../project.js";
|
|
25
25
|
import { SiteEnv } from "../site-env.js";
|
|
@@ -151,14 +151,19 @@ export class StaticSite extends Construct {
|
|
|
151
151
|
return {
|
|
152
152
|
clientPackage: "site",
|
|
153
153
|
variables: {
|
|
154
|
-
url:
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
154
|
+
url: this.doNotDeploy
|
|
155
|
+
? {
|
|
156
|
+
type: "plain",
|
|
157
|
+
value: "localhost",
|
|
158
|
+
}
|
|
159
|
+
: {
|
|
160
|
+
// Do not set real value b/c we don't want to make the Lambda function
|
|
161
|
+
// depend on the Site. B/c often the site depends on the Api, causing
|
|
162
|
+
// a CloudFormation circular dependency if the Api and the Site belong
|
|
163
|
+
// to different stacks.
|
|
164
|
+
type: "site_url",
|
|
165
|
+
value: this.customDomainUrl || this.url,
|
|
166
|
+
},
|
|
162
167
|
},
|
|
163
168
|
permissions: {
|
|
164
169
|
"ssm:GetParameters": [
|
package/constructs/Table.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import * as lambdaEventSources from "aws-cdk-lib/aws-lambda-event-sources";
|
|
|
4
4
|
import { SSTConstruct } from "./Construct.js";
|
|
5
5
|
import { Function as Fn, FunctionProps, FunctionInlineDefinition, FunctionDefinition } from "./Function.js";
|
|
6
6
|
import { KinesisStream } from "./KinesisStream.js";
|
|
7
|
+
import { FunctionBindingProps } from "./util/functionBinding.js";
|
|
7
8
|
import { Permissions } from "./util/permission.js";
|
|
8
9
|
export interface TableConsumerProps {
|
|
9
10
|
/**
|
|
@@ -398,18 +399,7 @@ export declare class Table extends Construct implements SSTConstruct {
|
|
|
398
399
|
};
|
|
399
400
|
};
|
|
400
401
|
/** @internal */
|
|
401
|
-
getFunctionBinding():
|
|
402
|
-
clientPackage: string;
|
|
403
|
-
variables: {
|
|
404
|
-
tableName: {
|
|
405
|
-
environment: string;
|
|
406
|
-
parameter: string;
|
|
407
|
-
};
|
|
408
|
-
};
|
|
409
|
-
permissions: {
|
|
410
|
-
"dynamodb:*": string[];
|
|
411
|
-
};
|
|
412
|
-
};
|
|
402
|
+
getFunctionBinding(): FunctionBindingProps;
|
|
413
403
|
private createTable;
|
|
414
404
|
private addConsumer;
|
|
415
405
|
private buildAttribute;
|
package/constructs/Table.js
CHANGED
package/constructs/Topic.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import * as snsSubscriptions from "aws-cdk-lib/aws-sns-subscriptions";
|
|
|
4
4
|
import { SSTConstruct } from "./Construct.js";
|
|
5
5
|
import { Function as Fn, FunctionProps, FunctionInlineDefinition, FunctionDefinition } from "./Function.js";
|
|
6
6
|
import { Queue } from "./Queue.js";
|
|
7
|
+
import { FunctionBindingProps } from "./util/functionBinding.js";
|
|
7
8
|
import { Permissions } from "./util/permission.js";
|
|
8
9
|
/**
|
|
9
10
|
* Used to define a queue subscriber for a topic
|
|
@@ -248,18 +249,7 @@ export declare class Topic extends Construct implements SSTConstruct {
|
|
|
248
249
|
};
|
|
249
250
|
};
|
|
250
251
|
/** @internal */
|
|
251
|
-
getFunctionBinding():
|
|
252
|
-
clientPackage: string;
|
|
253
|
-
variables: {
|
|
254
|
-
topicArn: {
|
|
255
|
-
environment: string;
|
|
256
|
-
parameter: string;
|
|
257
|
-
};
|
|
258
|
-
};
|
|
259
|
-
permissions: {
|
|
260
|
-
"sns:*": string[];
|
|
261
|
-
};
|
|
262
|
-
};
|
|
252
|
+
getFunctionBinding(): FunctionBindingProps;
|
|
263
253
|
private createTopic;
|
|
264
254
|
private addSubscriber;
|
|
265
255
|
private addQueueSubscriber;
|
package/constructs/Topic.js
CHANGED
|
@@ -5,6 +5,7 @@ import * as apig from "@aws-cdk/aws-apigatewayv2-alpha";
|
|
|
5
5
|
import * as apigAuthorizers from "@aws-cdk/aws-apigatewayv2-authorizers-alpha";
|
|
6
6
|
import { SSTConstruct } from "./Construct.js";
|
|
7
7
|
import { Function as Fn, FunctionProps, FunctionInlineDefinition, FunctionDefinition } from "./Function.js";
|
|
8
|
+
import { FunctionBindingProps } from "./util/functionBinding.js";
|
|
8
9
|
import { Permissions } from "./util/permission.js";
|
|
9
10
|
import * as apigV2Domain from "./util/apiGatewayV2Domain.js";
|
|
10
11
|
import * as apigV2AccessLog from "./util/apiGatewayV2AccessLog.js";
|
|
@@ -342,16 +343,7 @@ export declare class WebSocketApi extends Construct implements SSTConstruct {
|
|
|
342
343
|
};
|
|
343
344
|
};
|
|
344
345
|
/** @internal */
|
|
345
|
-
getFunctionBinding():
|
|
346
|
-
clientPackage: string;
|
|
347
|
-
variables: {
|
|
348
|
-
url: {
|
|
349
|
-
environment: string;
|
|
350
|
-
parameter: string;
|
|
351
|
-
};
|
|
352
|
-
};
|
|
353
|
-
permissions: {};
|
|
354
|
-
};
|
|
346
|
+
getFunctionBinding(): FunctionBindingProps;
|
|
355
347
|
private createWebSocketApi;
|
|
356
348
|
private createWebSocketStage;
|
|
357
349
|
private createCloudWatchRole;
|
|
@@ -197,8 +197,8 @@ export class WebSocketApi extends Construct {
|
|
|
197
197
|
clientPackage: "api",
|
|
198
198
|
variables: {
|
|
199
199
|
url: {
|
|
200
|
-
|
|
201
|
-
|
|
200
|
+
type: "plain",
|
|
201
|
+
value: this.customDomainUrl || this.url,
|
|
202
202
|
},
|
|
203
203
|
},
|
|
204
204
|
permissions: {},
|
|
@@ -24,7 +24,7 @@ import { isCDKConstruct } from "../Construct.js";
|
|
|
24
24
|
import { getBuildCmdEnvironment, buildErrorResponsesForRedirectToIndex, } from "../BaseSite.js";
|
|
25
25
|
import { attachPermissionsToRole } from "../util/permission.js";
|
|
26
26
|
import { getHandlerHash } from "../util/builder.js";
|
|
27
|
-
import {
|
|
27
|
+
import { getParameterPath, } from "../util/functionBinding.js";
|
|
28
28
|
import * as crossRegionHelper from "./cross-region-helper.js";
|
|
29
29
|
import { gray, red } from "colorette";
|
|
30
30
|
import { SiteEnv } from "../../site-env.js";
|
|
@@ -247,8 +247,8 @@ export class NextjsSite extends Construct {
|
|
|
247
247
|
// depend on the Site. B/c often the site depends on the Api, causing
|
|
248
248
|
// a CloudFormation circular dependency if the Api and the Site belong
|
|
249
249
|
// to different stacks.
|
|
250
|
-
|
|
251
|
-
|
|
250
|
+
type: "site_url",
|
|
251
|
+
value: this.customDomainUrl || this.url,
|
|
252
252
|
},
|
|
253
253
|
},
|
|
254
254
|
permissions: {
|
|
@@ -308,7 +308,7 @@ export class NextjsSite extends Construct {
|
|
|
308
308
|
// Create function asset
|
|
309
309
|
const assetPath = hasRealCode && this.buildOutDir
|
|
310
310
|
? path.join(this.buildOutDir, handlerPath)
|
|
311
|
-
: path.join(__dirname, "../../support/
|
|
311
|
+
: path.join(__dirname, "../../support/sls-nextjs-site-function-stub");
|
|
312
312
|
const asset = new s3Assets.Asset(this, `${name}FunctionAsset`, {
|
|
313
313
|
path: assetPath,
|
|
314
314
|
});
|
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
import { SSTConstruct } from "../Construct.js";
|
|
2
|
-
|
|
2
|
+
import { Secret } from "../Secret.js";
|
|
3
3
|
export interface FunctionBindingProps {
|
|
4
4
|
clientPackage: string;
|
|
5
5
|
permissions: Record<string, string[]>;
|
|
6
6
|
variables: Record<string, {
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
type: "plain";
|
|
8
|
+
value: string;
|
|
9
|
+
} | {
|
|
10
|
+
type: "secret";
|
|
11
|
+
} | {
|
|
12
|
+
type: "secret_reference";
|
|
13
|
+
secret: Secret;
|
|
14
|
+
} | {
|
|
15
|
+
type: "site_url";
|
|
16
|
+
value: string;
|
|
9
17
|
}>;
|
|
10
18
|
}
|
|
11
19
|
export declare function bindEnvironment(c: SSTConstruct): Record<string, string>;
|
|
@@ -15,6 +23,9 @@ export declare function bindType(c: SSTConstruct): {
|
|
|
15
23
|
clientPackage: string;
|
|
16
24
|
variables: string[];
|
|
17
25
|
} | undefined;
|
|
26
|
+
export declare function getReferencedSecrets(c: SSTConstruct): Secret[];
|
|
18
27
|
export declare function getEnvironmentKey(c: SSTConstruct, prop: string): string;
|
|
19
28
|
export declare function getParameterPath(c: SSTConstruct, prop: string): string;
|
|
20
29
|
export declare function getParameterFallbackPath(c: SSTConstruct, prop: string): string;
|
|
30
|
+
export declare function placeholderSecretValue(): string;
|
|
31
|
+
export declare function placeholderSecretReferenceValue(secret: Secret): string;
|
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
import * as ssm from "aws-cdk-lib/aws-ssm";
|
|
2
2
|
import { Config } from "../../config.js";
|
|
3
|
-
export const ENVIRONMENT_PLACEHOLDER = "__FETCH_FROM_SSM__";
|
|
4
3
|
export function bindEnvironment(c) {
|
|
5
4
|
const binding = c.getFunctionBinding();
|
|
6
|
-
|
|
5
|
+
let environment = {};
|
|
7
6
|
if (binding) {
|
|
8
7
|
Object.entries(binding.variables).forEach(([prop, variable]) => {
|
|
9
8
|
const envName = getEnvironmentKey(c, prop);
|
|
10
|
-
|
|
9
|
+
if (variable.type === "plain") {
|
|
10
|
+
environment[envName] = variable.value;
|
|
11
|
+
}
|
|
12
|
+
else if (variable.type === "secret" || variable.type === "site_url") {
|
|
13
|
+
environment[envName] = placeholderSecretValue();
|
|
14
|
+
}
|
|
15
|
+
else if (variable.type === "secret_reference") {
|
|
16
|
+
environment[envName] = placeholderSecretReferenceValue(variable.secret);
|
|
17
|
+
}
|
|
11
18
|
});
|
|
12
19
|
}
|
|
13
20
|
return environment;
|
|
@@ -18,20 +25,29 @@ export function bindParameters(c) {
|
|
|
18
25
|
return;
|
|
19
26
|
}
|
|
20
27
|
const app = c.node.root;
|
|
21
|
-
Object.entries(binding.variables)
|
|
22
|
-
.filter(([, variable]) => variable.parameter !== undefined)
|
|
23
|
-
.forEach(([prop, variable]) => {
|
|
28
|
+
Object.entries(binding.variables).forEach(([prop, variable]) => {
|
|
24
29
|
const resId = `Parameter_${prop}`;
|
|
25
30
|
if (!c.node.tryFindChild(resId)) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
+
if (variable.type === "plain" || variable.type === "site_url") {
|
|
32
|
+
new ssm.StringParameter(c, resId, {
|
|
33
|
+
parameterName: getParameterPath(c, prop),
|
|
34
|
+
stringValue: variable.value,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
else if (variable.type === "secret_reference") {
|
|
38
|
+
new ssm.StringParameter(c, resId, {
|
|
39
|
+
parameterName: getParameterPath(c, prop),
|
|
40
|
+
stringValue: placeholderSecretReferenceValue(variable.secret),
|
|
41
|
+
});
|
|
42
|
+
}
|
|
31
43
|
}
|
|
32
44
|
});
|
|
33
45
|
}
|
|
34
46
|
export function bindPermissions(c) {
|
|
47
|
+
const binding = c.getFunctionBinding();
|
|
48
|
+
if (!binding) {
|
|
49
|
+
return {};
|
|
50
|
+
}
|
|
35
51
|
return c.getFunctionBinding()?.permissions || {};
|
|
36
52
|
}
|
|
37
53
|
export function bindType(c) {
|
|
@@ -44,6 +60,18 @@ export function bindType(c) {
|
|
|
44
60
|
variables: Object.keys(binding.variables),
|
|
45
61
|
};
|
|
46
62
|
}
|
|
63
|
+
export function getReferencedSecrets(c) {
|
|
64
|
+
const binding = c.getFunctionBinding();
|
|
65
|
+
const secrets = [];
|
|
66
|
+
if (binding) {
|
|
67
|
+
Object.values(binding.variables).forEach((variable) => {
|
|
68
|
+
if (variable.type === "secret_reference") {
|
|
69
|
+
secrets.push(variable.secret);
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
return secrets;
|
|
74
|
+
}
|
|
47
75
|
export function getEnvironmentKey(c, prop) {
|
|
48
76
|
return Config.envFor({
|
|
49
77
|
type: c.constructor.name,
|
|
@@ -68,3 +96,9 @@ export function getParameterFallbackPath(c, prop) {
|
|
|
68
96
|
fallback: true,
|
|
69
97
|
});
|
|
70
98
|
}
|
|
99
|
+
export function placeholderSecretValue() {
|
|
100
|
+
return "__FETCH_FROM_SSM__";
|
|
101
|
+
}
|
|
102
|
+
export function placeholderSecretReferenceValue(secret) {
|
|
103
|
+
return "__FETCH_FROM_SECRET__:" + secret.name;
|
|
104
|
+
}
|
package/node/api/index.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { createProxy,
|
|
1
|
+
import { createProxy, getVariables } from "../util/index.js";
|
|
2
2
|
import { Context } from "../../context/context.js";
|
|
3
3
|
import { useEvent, Handler } from "../../context/handler.js";
|
|
4
4
|
export const Api = createProxy("Api");
|
|
5
5
|
export const AppSyncApi = createProxy("AppSyncApi");
|
|
6
6
|
export const ApiGatewayV1Api = createProxy("ApiGatewayV1Api");
|
|
7
7
|
export const WebSocketApi = createProxy("WebSocketApi");
|
|
8
|
-
Object.assign(Api,
|
|
9
|
-
Object.assign(AppSyncApi,
|
|
10
|
-
Object.assign(ApiGatewayV1Api,
|
|
11
|
-
Object.assign(WebSocketApi,
|
|
8
|
+
Object.assign(Api, getVariables("Api"));
|
|
9
|
+
Object.assign(AppSyncApi, getVariables("AppSyncApi"));
|
|
10
|
+
Object.assign(ApiGatewayV1Api, getVariables("ApiGatewayV1Api"));
|
|
11
|
+
Object.assign(WebSocketApi, getVariables("WebSocketApi"));
|
|
12
12
|
/**
|
|
13
13
|
* Create a new api handler that can be used to create an authenticated session.
|
|
14
14
|
*
|
package/node/auth/auth.js
CHANGED
|
@@ -1,62 +1,18 @@
|
|
|
1
|
-
import {
|
|
2
|
-
const ssm = new SSMClient({});
|
|
3
|
-
import { parseEnvironment, buildSsmPath, ssmNameToPropName, } from "../util/index.js";
|
|
1
|
+
import { getVariables } from "../util/index.js";
|
|
4
2
|
import { Handler } from "../../context/handler.js";
|
|
5
3
|
import { useDomainName, usePath } from "../api/index.js";
|
|
6
4
|
const className = "Auth";
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
]);
|
|
5
|
+
// Each function can only be attached to one Auth construct, so we can
|
|
6
|
+
// assume there is only one entry in authData.
|
|
7
|
+
const authData = getVariables(className);
|
|
8
|
+
const authValues = Object.values(authData);
|
|
12
9
|
let prefix;
|
|
13
10
|
let publicKey;
|
|
14
11
|
let privateKey;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
const authName = authNames[0];
|
|
20
|
-
await replaceWithSsmValues(authName);
|
|
21
|
-
// @ts-ignore
|
|
22
|
-
prefix = authData[authName].prefix;
|
|
23
|
-
// @ts-ignore
|
|
24
|
-
publicKey = authData[authName].publicKey;
|
|
25
|
-
// @ts-ignore
|
|
26
|
-
privateKey = authData[authName].privateKey;
|
|
27
|
-
}
|
|
28
|
-
async function replaceWithSsmValues(name) {
|
|
29
|
-
// Fetch all secrets
|
|
30
|
-
const props = ["privateKey", "publicKey"].filter((prop) => authData[name][prop] === "__FETCH_FROM_SSM__");
|
|
31
|
-
if (props.length === 0) {
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
const results = await loadSsm(name, props);
|
|
35
|
-
if (results.invalidParams.length > 0) {
|
|
36
|
-
const missingProps = results.invalidParams.map(ssmNameToPropName);
|
|
37
|
-
throw new Error(`The following Auth parameters were not found: ${missingProps.join(", ")}`);
|
|
38
|
-
}
|
|
39
|
-
// Store all secrets in a map
|
|
40
|
-
for (const item of results.validParams) {
|
|
41
|
-
const prop = ssmNameToPropName(item.Name);
|
|
42
|
-
// @ts-ignore
|
|
43
|
-
authData[name][prop] = item.Value;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
async function loadSsm(name, props) {
|
|
47
|
-
const SSM_PREFIX = `/sst/${process.env.SST_APP}/${process.env.SST_STAGE}/${className}/${name}`;
|
|
48
|
-
// Fetch secrets
|
|
49
|
-
const validParams = [];
|
|
50
|
-
const invalidParams = [];
|
|
51
|
-
const command = new GetParametersCommand({
|
|
52
|
-
Names: props.map((prop) => buildSsmPath(className, name, prop)),
|
|
53
|
-
WithDecryption: true,
|
|
54
|
-
});
|
|
55
|
-
const result = await ssm.send(command);
|
|
56
|
-
return {
|
|
57
|
-
validParams: result.Parameters || [],
|
|
58
|
-
invalidParams: result.InvalidParameters || [],
|
|
59
|
-
};
|
|
12
|
+
if (authValues.length !== 0) {
|
|
13
|
+
prefix = authValues[0].prefix;
|
|
14
|
+
publicKey = authValues[0].publicKey;
|
|
15
|
+
privateKey = authValues[0].privateKey;
|
|
60
16
|
}
|
|
61
17
|
export function getPublicKey() {
|
|
62
18
|
if (!publicKey) {
|
package/node/bucket/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { createProxy,
|
|
1
|
+
import { createProxy, getVariables } from "../util/index.js";
|
|
2
2
|
export const Bucket = createProxy("Bucket");
|
|
3
|
-
Object.assign(Bucket,
|
|
3
|
+
Object.assign(Bucket, getVariables("Bucket"));
|
package/node/config/index.js
CHANGED
|
@@ -1,13 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
const ssm = new SSMClient({});
|
|
3
|
-
import { createProxy, parseEnvironment, buildSsmPath, buildSsmFallbackPath, ssmNameToConstructId, ssmFallbackNameToConstructId, } from "../util/index.js";
|
|
1
|
+
import { createProxy, getVariables } from "../util/index.js";
|
|
4
2
|
export const Config = createProxy("Config");
|
|
5
3
|
const metadata = parseMetadataEnvironment();
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
const parameters = flattenConfigValues(parametersRaw);
|
|
9
|
-
const secrets = flattenConfigValues(secretsRaw);
|
|
10
|
-
await replaceSecretsWithRealValues();
|
|
4
|
+
const parameters = flattenValues(getVariables("Parameter"));
|
|
5
|
+
const secrets = flattenValues(getVariables("Secret"));
|
|
11
6
|
Object.assign(Config, metadata, parameters, secrets);
|
|
12
7
|
///////////////
|
|
13
8
|
// Functions
|
|
@@ -27,57 +22,10 @@ function parseMetadataEnvironment() {
|
|
|
27
22
|
STAGE: process.env.SST_STAGE,
|
|
28
23
|
};
|
|
29
24
|
}
|
|
30
|
-
function
|
|
25
|
+
function flattenValues(configValues) {
|
|
31
26
|
const acc = {};
|
|
32
27
|
Object.keys(configValues).forEach((name) => {
|
|
33
28
|
acc[name] = configValues[name].value;
|
|
34
29
|
});
|
|
35
30
|
return acc;
|
|
36
31
|
}
|
|
37
|
-
async function replaceSecretsWithRealValues() {
|
|
38
|
-
// Find all the secrets and params that match the prefix
|
|
39
|
-
const names = Object.keys(secrets).filter((name) => secrets[name] === "__FETCH_FROM_SSM__");
|
|
40
|
-
if (names.length === 0) {
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
// Fetch all secrets
|
|
44
|
-
const paths = names.map((name) => buildSsmPath("Secret", name, "value"));
|
|
45
|
-
const results = await loadSecrets(paths);
|
|
46
|
-
results.validParams.forEach((item) => {
|
|
47
|
-
const name = ssmNameToConstructId(item.Name);
|
|
48
|
-
secrets[name] = item.Value;
|
|
49
|
-
});
|
|
50
|
-
// Fetch fallback secrets
|
|
51
|
-
if (results.invalidParams.length > 0) {
|
|
52
|
-
const missingNames = results.invalidParams.map(ssmNameToConstructId);
|
|
53
|
-
const missingPaths = missingNames.map((name) => buildSsmFallbackPath("Secret", name, "value"));
|
|
54
|
-
const missingResults = await loadSecrets(missingPaths);
|
|
55
|
-
missingResults.validParams.forEach((item) => {
|
|
56
|
-
const name = ssmFallbackNameToConstructId(item.Name);
|
|
57
|
-
secrets[name] = item.Value;
|
|
58
|
-
});
|
|
59
|
-
if (missingResults.invalidParams.length > 0) {
|
|
60
|
-
throw new Error(`The following secrets were not found: ${missingNames.join(", ")}`);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
async function loadSecrets(paths) {
|
|
65
|
-
// Split paths into chunks of 10
|
|
66
|
-
const chunks = [];
|
|
67
|
-
for (let i = 0; i < paths.length; i += 10) {
|
|
68
|
-
chunks.push(paths.slice(i, i + 10));
|
|
69
|
-
}
|
|
70
|
-
// Fetch secrets
|
|
71
|
-
const validParams = [];
|
|
72
|
-
const invalidParams = [];
|
|
73
|
-
await Promise.all(chunks.map(async (chunk) => {
|
|
74
|
-
const command = new GetParametersCommand({
|
|
75
|
-
Names: chunk,
|
|
76
|
-
WithDecryption: true,
|
|
77
|
-
});
|
|
78
|
-
const result = await ssm.send(command);
|
|
79
|
-
validParams.push(...(result.Parameters || []));
|
|
80
|
-
invalidParams.push(...(result.InvalidParameters || []));
|
|
81
|
-
}));
|
|
82
|
-
return { validParams, invalidParams };
|
|
83
|
-
}
|
package/node/event-bus/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { createProxy,
|
|
1
|
+
import { createProxy, getVariables } from "../util/index.js";
|
|
2
2
|
export const EventBus = createProxy("EventBus");
|
|
3
|
-
Object.assign(EventBus,
|
|
3
|
+
Object.assign(EventBus, getVariables("EventBus"));
|
package/node/function/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { createProxy,
|
|
1
|
+
import { createProxy, getVariables } from "../util/index.js";
|
|
2
2
|
export const Function = createProxy("Function");
|
|
3
|
-
Object.assign(Function,
|
|
3
|
+
Object.assign(Function, getVariables("Function"));
|
package/node/job/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { createProxy,
|
|
1
|
+
import { createProxy, getVariables } from "../util/index.js";
|
|
2
2
|
import { InvokeCommand, LambdaClient } from "@aws-sdk/client-lambda";
|
|
3
3
|
const lambda = new LambdaClient({});
|
|
4
4
|
export const Job = createProxy("Job");
|
|
5
|
-
const jobData =
|
|
5
|
+
const jobData = getVariables("Job");
|
|
6
6
|
Object.keys(jobData).forEach((name) => {
|
|
7
7
|
// @ts-ignore
|
|
8
8
|
Job[name] = JobControl(name);
|