sst 2.24.19 → 2.24.21
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/cli/sst.js +1 -0
- package/config.js +4 -1
- package/constructs/EventBus.d.ts +4 -2
- package/constructs/EventBus.js +33 -8
- package/constructs/Service.js +18 -4
- package/node/future/auth/handler.d.ts +5 -1
- package/node/future/auth/handler.js +9 -2
- package/package.json +1 -1
- package/support/event-bus-retrier/index.mjs +20 -20
package/cli/sst.js
CHANGED
package/config.js
CHANGED
|
@@ -5,7 +5,6 @@ import { useProject } from "./project.js";
|
|
|
5
5
|
import { useAWSClient } from "./credentials.js";
|
|
6
6
|
import { useIOT } from "./iot.js";
|
|
7
7
|
import { Stacks } from "./stacks/index.js";
|
|
8
|
-
const ssm = useAWSClient(SSMClient);
|
|
9
8
|
const FALLBACK_STAGE = ".fallback";
|
|
10
9
|
const SECRET_UPDATED_AT_ENV = "SST_ADMIN_SECRET_UPDATED_AT";
|
|
11
10
|
const PREFIX = {
|
|
@@ -171,6 +170,7 @@ export var Config;
|
|
|
171
170
|
Config.restart = restart;
|
|
172
171
|
})(Config || (Config = {}));
|
|
173
172
|
async function* scanParameters(prefix) {
|
|
173
|
+
const ssm = useAWSClient(SSMClient);
|
|
174
174
|
let token;
|
|
175
175
|
while (true) {
|
|
176
176
|
const results = await ssm.send(new GetParametersByPathCommand({
|
|
@@ -186,12 +186,14 @@ async function* scanParameters(prefix) {
|
|
|
186
186
|
}
|
|
187
187
|
}
|
|
188
188
|
function getParameter(name) {
|
|
189
|
+
const ssm = useAWSClient(SSMClient);
|
|
189
190
|
return ssm.send(new GetParameterCommand({
|
|
190
191
|
Name: name,
|
|
191
192
|
WithDecryption: true,
|
|
192
193
|
}));
|
|
193
194
|
}
|
|
194
195
|
function putParameter(name, value) {
|
|
196
|
+
const ssm = useAWSClient(SSMClient);
|
|
195
197
|
return ssm.send(new PutParameterCommand({
|
|
196
198
|
Name: name,
|
|
197
199
|
Value: value,
|
|
@@ -201,6 +203,7 @@ function putParameter(name, value) {
|
|
|
201
203
|
}));
|
|
202
204
|
}
|
|
203
205
|
function deleteParameter(name) {
|
|
206
|
+
const ssm = useAWSClient(SSMClient);
|
|
204
207
|
return ssm.send(new DeleteParameterCommand({
|
|
205
208
|
Name: name,
|
|
206
209
|
}));
|
package/constructs/EventBus.d.ts
CHANGED
|
@@ -426,7 +426,6 @@ export declare class EventBus extends Construct implements SSTConstruct {
|
|
|
426
426
|
getFunctionBinding(): FunctionBindingProps;
|
|
427
427
|
private retrierQueue;
|
|
428
428
|
private retrierFn;
|
|
429
|
-
private retrierMap;
|
|
430
429
|
private getRetrier;
|
|
431
430
|
private createEventBus;
|
|
432
431
|
private addRule;
|
|
@@ -437,6 +436,9 @@ export declare class EventBus extends Construct implements SSTConstruct {
|
|
|
437
436
|
private subs;
|
|
438
437
|
subscribe(type: string | string[], target: FunctionDefinition, props?: {
|
|
439
438
|
retries?: number;
|
|
440
|
-
}):
|
|
439
|
+
}): EventBus;
|
|
440
|
+
subscribe(scope: Construct, type: string | string[], target: FunctionDefinition, props?: {
|
|
441
|
+
retries?: number;
|
|
442
|
+
}): EventBus;
|
|
441
443
|
private addFunctionTarget;
|
|
442
444
|
}
|
package/constructs/EventBus.js
CHANGED
|
@@ -10,6 +10,9 @@ import { SqsEventSource } from "aws-cdk-lib/aws-lambda-event-sources";
|
|
|
10
10
|
import { SqsDestination } from "aws-cdk-lib/aws-lambda-destinations";
|
|
11
11
|
import url from "url";
|
|
12
12
|
import path from "path";
|
|
13
|
+
import { Effect, PolicyStatement } from "aws-cdk-lib/aws-iam";
|
|
14
|
+
import { Duration } from "aws-cdk-lib/core";
|
|
15
|
+
import { Stack } from "./Stack.js";
|
|
13
16
|
const __dirname = path.dirname(url.fileURLToPath(import.meta.url));
|
|
14
17
|
/////////////////////
|
|
15
18
|
// Construct
|
|
@@ -233,7 +236,6 @@ export class EventBus extends Construct {
|
|
|
233
236
|
}
|
|
234
237
|
retrierQueue;
|
|
235
238
|
retrierFn;
|
|
236
|
-
retrierMap = {};
|
|
237
239
|
getRetrier() {
|
|
238
240
|
const app = this.node.root;
|
|
239
241
|
if (this.retrierFn && this.retrierQueue) {
|
|
@@ -245,12 +247,26 @@ export class EventBus extends Construct {
|
|
|
245
247
|
this.retrierFn = new lambda.Function(this, `RetrierFunction`, {
|
|
246
248
|
functionName: app.logicalPrefixedName(this.node.id + "Retrier"),
|
|
247
249
|
runtime: lambda.Runtime.NODEJS_14_X,
|
|
250
|
+
timeout: Duration.seconds(30),
|
|
248
251
|
handler: "index.handler",
|
|
249
252
|
code: lambda.Code.fromAsset(path.join(__dirname, "../support/event-bus-retrier")),
|
|
250
253
|
environment: {
|
|
251
254
|
RETRIER_QUEUE_URL: this.retrierQueue.queueUrl,
|
|
252
255
|
},
|
|
253
256
|
});
|
|
257
|
+
this.retrierFn.addToRolePolicy(new PolicyStatement({
|
|
258
|
+
effect: Effect.ALLOW,
|
|
259
|
+
actions: ["lambda:InvokeFunction", "lambda:GetFunction"],
|
|
260
|
+
resources: [
|
|
261
|
+
`arn:${Stack.of(this).partition}:lambda:${app.region}:${app.account}:function:*`,
|
|
262
|
+
],
|
|
263
|
+
conditions: {
|
|
264
|
+
StringEquals: {
|
|
265
|
+
"aws:ResourceTag/sst:app": app.name,
|
|
266
|
+
"aws:ResourceTag/sst:stage": app.stage,
|
|
267
|
+
},
|
|
268
|
+
},
|
|
269
|
+
}));
|
|
254
270
|
this.retrierFn.addEventSource(new SqsEventSource(this.retrierQueue));
|
|
255
271
|
this.retrierQueue.grantSendMessages(this.retrierFn);
|
|
256
272
|
return { fn: this.retrierFn, queue: this.retrierQueue };
|
|
@@ -353,7 +369,18 @@ export class EventBus extends Construct {
|
|
|
353
369
|
eventsRule.addTarget(new LambdaFunctionTarget(fn, targetProps));
|
|
354
370
|
}
|
|
355
371
|
subs = new Map();
|
|
356
|
-
subscribe(
|
|
372
|
+
subscribe(scope_or_type, type_or_target, target_or_props, maybe_props) {
|
|
373
|
+
let [scope, type, target, props] = (() => {
|
|
374
|
+
if (scope_or_type instanceof Construct) {
|
|
375
|
+
return [
|
|
376
|
+
scope_or_type,
|
|
377
|
+
type_or_target,
|
|
378
|
+
target_or_props,
|
|
379
|
+
maybe_props,
|
|
380
|
+
];
|
|
381
|
+
}
|
|
382
|
+
return [this, scope_or_type, type_or_target, maybe_props];
|
|
383
|
+
})();
|
|
357
384
|
type = Array.isArray(type) ? type : [type];
|
|
358
385
|
const joined = type.length > 1 ? "multi" : type.join("_");
|
|
359
386
|
const count = (this.subs.get(joined) || 0) + 1;
|
|
@@ -363,17 +390,15 @@ export class EventBus extends Construct {
|
|
|
363
390
|
const fn = (() => {
|
|
364
391
|
if (retries) {
|
|
365
392
|
const retrier = this.getRetrier();
|
|
366
|
-
const fn = Fn.fromDefinition(
|
|
393
|
+
const fn = Fn.fromDefinition(scope, name, target, {
|
|
367
394
|
onFailure: new SqsDestination(retrier.queue),
|
|
368
395
|
});
|
|
369
|
-
|
|
370
|
-
retrier.fn.addEnvironment(`RETRIES`, JSON.stringify(this.retrierMap));
|
|
371
|
-
fn.grantInvoke(retrier.fn);
|
|
396
|
+
fn.addEnvironment("SST_RETRIES", retries.toString());
|
|
372
397
|
return fn;
|
|
373
398
|
}
|
|
374
|
-
return Fn.fromDefinition(
|
|
399
|
+
return Fn.fromDefinition(scope, name, target);
|
|
375
400
|
})();
|
|
376
|
-
this.addRule(
|
|
401
|
+
this.addRule(scope, name + "_rule", {
|
|
377
402
|
pattern: {
|
|
378
403
|
detailType: type,
|
|
379
404
|
},
|
package/constructs/Service.js
CHANGED
|
@@ -342,24 +342,38 @@ export class Service extends Construct {
|
|
|
342
342
|
/////////////////////
|
|
343
343
|
validateServiceExists() {
|
|
344
344
|
const { path: servicePath, file } = this.props;
|
|
345
|
+
// Validate path exists
|
|
345
346
|
if (!fs.existsSync(servicePath)) {
|
|
346
|
-
throw new
|
|
347
|
+
throw new VisibleError(`In the "${this.node.id}" Service, path is not found at "${path.resolve(servicePath)}"`);
|
|
347
348
|
}
|
|
349
|
+
// Validate path is a directory
|
|
350
|
+
if (fs.statSync(servicePath).isFile()) {
|
|
351
|
+
throw new VisibleError([
|
|
352
|
+
`In the "${this.node.id}" Service, the path "${path.resolve(servicePath)}" should be a directory.`,
|
|
353
|
+
`Did you mean:`,
|
|
354
|
+
``,
|
|
355
|
+
` {`,
|
|
356
|
+
` path: "${path.dirname(servicePath)}",`,
|
|
357
|
+
` file: "${path.basename(servicePath)}",`,
|
|
358
|
+
` }`,
|
|
359
|
+
].join("\n"));
|
|
360
|
+
}
|
|
361
|
+
// Validate path exists
|
|
348
362
|
if (file) {
|
|
349
363
|
const dockerfilePath = path.join(servicePath, file);
|
|
350
364
|
if (!fs.existsSync(dockerfilePath)) {
|
|
351
|
-
throw new
|
|
365
|
+
throw new VisibleError(`In the "${this.node.id}" Service, no Dockerfile is found at "${dockerfilePath}". Make sure to set the "file" property to the path of the Dockerfile relative to "${servicePath}".`);
|
|
352
366
|
}
|
|
353
367
|
}
|
|
354
368
|
}
|
|
355
369
|
validateMemoryAndCpu() {
|
|
356
370
|
const { memory, cpu } = this.props;
|
|
357
371
|
if (!supportedCpus[cpu]) {
|
|
358
|
-
throw new
|
|
372
|
+
throw new VisibleError(`In the "${this.node.id}" Service, only the following "cpu" settings are supported: ${Object.keys(supportedCpus).join(", ")}`);
|
|
359
373
|
}
|
|
360
374
|
// @ts-ignore
|
|
361
375
|
if (!supportedMemories[cpu][memory]) {
|
|
362
|
-
throw new
|
|
376
|
+
throw new VisibleError(`In the "${this.node.id}" Service, only the following "memory" settings are supported with "${cpu}": ${Object.keys(supportedMemories[cpu]).join(", ")}`);
|
|
363
377
|
}
|
|
364
378
|
}
|
|
365
379
|
createVpc() {
|
|
@@ -12,6 +12,10 @@ interface OnSuccessResponder<T> {
|
|
|
12
12
|
properties: typeof input;
|
|
13
13
|
};
|
|
14
14
|
}
|
|
15
|
+
export declare class UnknownProviderError {
|
|
16
|
+
provider?: string | undefined;
|
|
17
|
+
constructor(provider?: string | undefined);
|
|
18
|
+
}
|
|
15
19
|
export declare function AuthHandler<Providers extends Record<string, Adapter<any>>, Sessions extends SessionBuilder, Result = {
|
|
16
20
|
[key in keyof Providers]: {
|
|
17
21
|
provider: key;
|
|
@@ -25,6 +29,6 @@ export declare function AuthHandler<Providers extends Record<string, Adapter<any
|
|
|
25
29
|
onAuthorize?: (event: APIGatewayProxyEventV2) => Promise<void | keyof Providers>;
|
|
26
30
|
onSuccess: (input: Result, response: OnSuccessResponder<SessionValue | Sessions["$type"]>) => Promise<ReturnType<OnSuccessResponder<SessionValue | Sessions["$type"]>[keyof OnSuccessResponder<any>]>>;
|
|
27
31
|
onIndex?: (event: APIGatewayProxyEventV2) => Promise<APIGatewayProxyStructuredResultV2>;
|
|
28
|
-
onError?: () => Promise<APIGatewayProxyStructuredResultV2>;
|
|
32
|
+
onError?: (error: UnknownProviderError) => Promise<APIGatewayProxyStructuredResultV2 | undefined>;
|
|
29
33
|
}): (event: APIGatewayProxyEventV2, context: import("aws-lambda").Context) => Promise<APIGatewayProxyStructuredResultV2>;
|
|
30
34
|
export {};
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { createSigner, createVerifier } from "fast-jwt";
|
|
2
2
|
import { ApiHandler, useCookie, useCookies, useFormValue, usePathParam, useQueryParam, useQueryParams, useResponse, } from "../../api/index.js";
|
|
3
3
|
import { Config } from "../../config/index.js";
|
|
4
|
+
export class UnknownProviderError {
|
|
5
|
+
provider;
|
|
6
|
+
constructor(provider) {
|
|
7
|
+
this.provider = provider;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
4
10
|
export function AuthHandler(input) {
|
|
5
11
|
return ApiHandler(async (evt) => {
|
|
6
12
|
const step = usePathParam("step");
|
|
@@ -139,6 +145,9 @@ export function AuthHandler(input) {
|
|
|
139
145
|
});
|
|
140
146
|
}
|
|
141
147
|
if (!provider || !input.providers[provider]) {
|
|
148
|
+
const response = input.onError?.(new UnknownProviderError(provider));
|
|
149
|
+
if (response)
|
|
150
|
+
return response;
|
|
142
151
|
return {
|
|
143
152
|
statusCode: 400,
|
|
144
153
|
body: `Was not able to find provider "${String(provider)}"`,
|
|
@@ -246,8 +255,6 @@ export function AuthHandler(input) {
|
|
|
246
255
|
}
|
|
247
256
|
}
|
|
248
257
|
if (result.type === "error") {
|
|
249
|
-
if (input.onError)
|
|
250
|
-
return input.onError();
|
|
251
258
|
return {
|
|
252
259
|
statusCode: 400,
|
|
253
260
|
body: "an error has occured",
|