From 75b1e07f34a95a43652ab0687fc356d49d67329c Mon Sep 17 00:00:00 2001 From: Marko Malenic Date: Fri, 6 Dec 2024 10:10:52 +1100 Subject: [PATCH 1/6] build: use pnpm, add github workflows, remove compiled .js and .d.ts files, publish dist output directory on compile and export in index.ts --- .github/workflows/build.yaml | 20 ++ .github/workflows/release.yaml | 22 ++ .gitignore | 4 +- .pre-commit-config.yaml | 19 + .prettierignore | 1 + .secrets.baseline | 133 +++++++ DEPLOY.md | 6 +- LICENSE | 23 ++ README.md | 2 +- bin/htsget-lambda.js | 43 --- bin/htsget-lambda.ts | 44 +-- bin/settings.js | 26 -- cdk.json | 31 +- examples/minio/compose.yml | 2 +- index.js | 17 - index.ts | 1 + lib/htsget-lambda-construct.d.ts | 59 ---- lib/htsget-lambda-construct.js | 306 ---------------- lib/htsget-lambda-construct.ts | 12 +- package.json | 40 +-- pnpm-lock.yaml | 585 +++++++++++++++++++++++++++++++ tsconfig.json | 36 +- 22 files changed, 900 insertions(+), 532 deletions(-) create mode 100644 .github/workflows/build.yaml create mode 100644 .github/workflows/release.yaml create mode 100644 .pre-commit-config.yaml create mode 100644 .prettierignore create mode 100644 .secrets.baseline create mode 100644 LICENSE delete mode 100644 bin/htsget-lambda.js delete mode 100644 bin/settings.js delete mode 100644 index.js create mode 100644 index.ts delete mode 100644 lib/htsget-lambda-construct.d.ts delete mode 100644 lib/htsget-lambda-construct.js create mode 100644 pnpm-lock.yaml diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml new file mode 100644 index 0000000..af53800 --- /dev/null +++ b/.github/workflows/build.yaml @@ -0,0 +1,20 @@ +name: build + +on: + push: + branches: + - main + pull_request: + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: pnpm/action-setup@v4 + - uses: actions/setup-node@v4 + with: + node-version: 22 + cache: "pnpm" + - run: pnpm install + - run: pnpm run build diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..647cf5c --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,22 @@ +name: release + +on: + release: + types: [released] + +jobs: + release: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: pnpm/action-setup@v4 + - uses: actions/setup-node@v4 + with: + node-version: 22 + cache: "pnpm" + - run: pnpm install + - run: pnpm version ${{ github.ref_name }} + - run: pnpm run build + - run: pnpm publish --access public + env: + NPM_TOKEN: ${{ secrets.HTSGET_RS_DEPLOY_PUBLISH_TOKEN }} diff --git a/.gitignore b/.gitignore index 03ad55f..9bd9cbe 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,9 @@ node_modules .DS_Store volume -package-lock.json .build cdk.context.json cdk.out +*.js +*.d.ts +dist diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..b9caf74 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,19 @@ +repos: + + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v5.0.0 + hooks: + - id: check-added-large-files + - id: detect-private-key + - id: no-commit-to-branch + args: [--branch, main] + - id: check-yaml + - id: end-of-file-fixer + - id: trailing-whitespace + - id: pretty-format-json + args: ['--autofix'] + - repo: https://github.com/Yelp/detect-secrets + rev: v1.5.0 + hooks: + - id: detect-secrets + args: ['--baseline', '.secrets.baseline'] diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..de05607 --- /dev/null +++ b/.prettierignore @@ -0,0 +1 @@ +**/*.md diff --git a/.secrets.baseline b/.secrets.baseline new file mode 100644 index 0000000..6eb228b --- /dev/null +++ b/.secrets.baseline @@ -0,0 +1,133 @@ +{ + "version": "1.5.0", + "plugins_used": [ + { + "name": "ArtifactoryDetector" + }, + { + "name": "AWSKeyDetector" + }, + { + "name": "AzureStorageKeyDetector" + }, + { + "name": "Base64HighEntropyString", + "limit": 4.5 + }, + { + "name": "BasicAuthDetector" + }, + { + "name": "CloudantDetector" + }, + { + "name": "DiscordBotTokenDetector" + }, + { + "name": "GitHubTokenDetector" + }, + { + "name": "GitLabTokenDetector" + }, + { + "name": "HexHighEntropyString", + "limit": 3.0 + }, + { + "name": "IbmCloudIamDetector" + }, + { + "name": "IbmCosHmacDetector" + }, + { + "name": "IPPublicDetector" + }, + { + "name": "JwtTokenDetector" + }, + { + "name": "KeywordDetector", + "keyword_exclude": "" + }, + { + "name": "MailchimpDetector" + }, + { + "name": "NpmDetector" + }, + { + "name": "OpenAIDetector" + }, + { + "name": "PrivateKeyDetector" + }, + { + "name": "PypiTokenDetector" + }, + { + "name": "SendGridDetector" + }, + { + "name": "SlackDetector" + }, + { + "name": "SoftlayerDetector" + }, + { + "name": "SquareOAuthDetector" + }, + { + "name": "StripeDetector" + }, + { + "name": "TelegramBotTokenDetector" + }, + { + "name": "TwilioKeyDetector" + } + ], + "filters_used": [ + { + "path": "detect_secrets.filters.allowlist.is_line_allowlisted" + }, + { + "path": "detect_secrets.filters.common.is_ignored_due_to_verification_policies", + "min_level": 2 + }, + { + "path": "detect_secrets.filters.heuristic.is_indirect_reference" + }, + { + "path": "detect_secrets.filters.heuristic.is_likely_id_string" + }, + { + "path": "detect_secrets.filters.heuristic.is_lock_file" + }, + { + "path": "detect_secrets.filters.heuristic.is_not_alphanumeric_string" + }, + { + "path": "detect_secrets.filters.heuristic.is_potential_uuid" + }, + { + "path": "detect_secrets.filters.heuristic.is_prefixed_with_dollar_sign" + }, + { + "path": "detect_secrets.filters.heuristic.is_sequential_string" + }, + { + "path": "detect_secrets.filters.heuristic.is_swagger_file" + }, + { + "path": "detect_secrets.filters.heuristic.is_templated_secret" + }, + { + "path": "detect_secrets.filters.regex.should_exclude_file", + "pattern": [ + "pnpm-lock.yaml" + ] + } + ], + "results": {}, + "generated_at": "2024-12-05T23:39:24Z" +} diff --git a/DEPLOY.md b/DEPLOY.md index 87fb1c4..dfc9b70 100644 --- a/DEPLOY.md +++ b/DEPLOY.md @@ -75,7 +75,7 @@ npm install ### Deploy to AWS -> [!IMPORTANT] +> [!IMPORTANT] > The default deployment is designed to work out of the box. A bucket with a CDK-generated name is created with test > data from the [`data`][data] directory. All deployment settings can be tweaked using the [`settings.ts`][htsget-settings]. > The only option that must be specified in the `domain`, which determines the domain name to serve htsget-rs at. @@ -92,7 +92,7 @@ Then to deploy the stack, run: npx cdk deploy ``` -> [!WARNING] +> [!WARNING] > By default this deployment will create a public instance of htsget-rs. Anyone will be able to query the server > without authorizing unless you modify the `HtsgetJwtAuthSettings` settings. @@ -190,4 +190,4 @@ and a [MinIO][minio] deployment. [rust]: https://www.rust-lang.org/tools/install [zig]: https://ziglang.org/ [zig-getting-started]: https://ziglang.org/learn/getting-started/ -[data]: ../data \ No newline at end of file +[data]: ../data diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..31aa793 --- /dev/null +++ b/LICENSE @@ -0,0 +1,23 @@ +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index 24a48d6..b50ebea 100644 --- a/README.md +++ b/README.md @@ -40,4 +40,4 @@ Should return a response similar to the following one (some fields elided for br } ``` -Please note that the example above assumes a publicly accessible endpoint. If you have an authz'd deployment, please use `-H "Authorization: $JWT_TOKEN"` flags added to your `curl` command. \ No newline at end of file +Please note that the example above assumes a publicly accessible endpoint. If you have an authz'd deployment, please use `-H "Authorization: $JWT_TOKEN"` flags added to your `curl` command. diff --git a/bin/htsget-lambda.js b/bin/htsget-lambda.js deleted file mode 100644 index 24d3134..0000000 --- a/bin/htsget-lambda.js +++ /dev/null @@ -1,43 +0,0 @@ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - return function (d, b) { - if (typeof b !== "function" && b !== null) - throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -exports.__esModule = true; -exports.HtsgetTestStack = void 0; -var cdk = require("aws-cdk-lib"); -var htsget_lambda_construct_1 = require("../../deploy/lib/htsget-lambda-construct"); -var settings_1 = require("../../deploy/bin/settings"); -var HtsgetTestStack = /** @class */ (function (_super) { - __extends(HtsgetTestStack, _super); - function HtsgetTestStack(scope, id, settings, props) { - var _this = _super.call(this, scope, id, props) || this; - new htsget_lambda_construct_1.HtsgetLambdaConstruct(_this, 'Htsget-rs', settings_1.SETTINGS); - return _this; - } - return HtsgetTestStack; -}(cdk.Stack)); -exports.HtsgetTestStack = HtsgetTestStack; -var app = new cdk.App(); -new HtsgetTestStack(app, "HtsgetTestStack", settings_1.SETTINGS, { - stackName: "HtsgetTestStack", - description: "HtsgetTestStack", - tags: { - Stack: "HtsgetTestStack" - }, - env: { - account: process.env.CDK_DEFAULT_ACCOUNT, - region: process.env.CDK_DEFAULT_REGION - } -}); diff --git a/bin/htsget-lambda.ts b/bin/htsget-lambda.ts index bd0475e..0cfc6aa 100644 --- a/bin/htsget-lambda.ts +++ b/bin/htsget-lambda.ts @@ -1,32 +1,32 @@ -import * as cdk from 'aws-cdk-lib'; -import { Construct } from 'constructs'; +import * as cdk from "aws-cdk-lib"; +import { Construct } from "constructs"; import { HtsgetLambdaConstruct } from "../lib/htsget-lambda-construct"; -import { SETTINGS } from "../bin/settings" -import { HtsgetStatefulSettings } from "../lib/htsget-lambda-construct" -import { HtsgetStatelessSettings } from "../lib/htsget-lambda-construct" +import { SETTINGS } from "../bin/settings"; +import { HtsgetStatefulSettings } from "../lib/htsget-lambda-construct"; +import { HtsgetStatelessSettings } from "../lib/htsget-lambda-construct"; export class HtsgetTestStack extends cdk.Stack { - constructor(scope: Construct, id: string, settings: HtsgetStatefulSettings & HtsgetStatelessSettings, props?: cdk.StackProps) { + constructor( + scope: Construct, + id: string, + settings: HtsgetStatefulSettings & HtsgetStatelessSettings, + props?: cdk.StackProps, + ) { super(scope, id, props); - new HtsgetLambdaConstruct(this, 'Htsget-rs', SETTINGS); + new HtsgetLambdaConstruct(this, "Htsget-rs", SETTINGS); } } const app = new cdk.App(); -new HtsgetTestStack( - app, - "HtsgetTestStack", - SETTINGS, - { - stackName: "HtsgetTestStack", - description: "HtsgetTestStack", - tags: { - Stack: "HtsgetTestStack", - }, - env: { - account: process.env.CDK_DEFAULT_ACCOUNT, - region: process.env.CDK_DEFAULT_REGION, - }, +new HtsgetTestStack(app, "HtsgetTestStack", SETTINGS, { + stackName: "HtsgetTestStack", + description: "HtsgetTestStack", + tags: { + Stack: "HtsgetTestStack", }, -); + env: { + account: process.env.CDK_DEFAULT_ACCOUNT, + region: process.env.CDK_DEFAULT_REGION, + }, +}); diff --git a/bin/settings.js b/bin/settings.js deleted file mode 100644 index 37a5289..0000000 --- a/bin/settings.js +++ /dev/null @@ -1,26 +0,0 @@ -"use strict"; -exports.__esModule = true; -exports.SETTINGS = void 0; -/** - * Settings to use for the htsget deployment. - */ -exports.SETTINGS = { - config: "config/example_deploy.toml", - domain: "dev.umccr.org", - subDomain: "htsget-c4gh", - s3BucketResources: [], - lookupHostedZone: true, - createS3Bucket: true, - copyTestData: true, - copyExampleKeys: true, - // Override the bucket name. - // bucketName: "bucket", - jwtAuthorizer: { - // Set this to false if you want a private instance. - public: false, - cogUserPoolId: "", - jwtAudience: [""] - }, - // Enable additional features for compiling htsget-rs. `s3-storage` is always enabled. - features: ["experimental"] -}; diff --git a/cdk.json b/cdk.json index 509b75b..4ae1044 100644 --- a/cdk.json +++ b/cdk.json @@ -1,7 +1,21 @@ { "app": "npx ts-node --prefer-ts-exts bin/htsget-lambda.ts", + "context": { + "@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true, + "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": true, + "@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": true, + "@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true, + "@aws-cdk/aws-iam:minimizePolicies": true, + "@aws-cdk/aws-lambda:recognizeVersionProps": true, + "@aws-cdk/aws-rds:lowercaseDbIdentifier": true, + "@aws-cdk/core:checkSecretUsage": true, + "@aws-cdk/core:stackRelativeExports": true, + "@aws-cdk/core:target-partitions": [ + "aws", + "aws-cn" + ] + }, "watch": { - "include": ["**"], "exclude": [ "README.md", "cdk*.json", @@ -12,18 +26,9 @@ "yarn.lock", "node_modules", "test" + ], + "include": [ + "**" ] - }, - "context": { - "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": true, - "@aws-cdk/core:stackRelativeExports": true, - "@aws-cdk/aws-rds:lowercaseDbIdentifier": true, - "@aws-cdk/aws-lambda:recognizeVersionProps": true, - "@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": true, - "@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true, - "@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true, - "@aws-cdk/core:checkSecretUsage": true, - "@aws-cdk/aws-iam:minimizePolicies": true, - "@aws-cdk/core:target-partitions": ["aws", "aws-cn"] } } diff --git a/examples/minio/compose.yml b/examples/minio/compose.yml index e7a37e7..d19a777 100644 --- a/examples/minio/compose.yml +++ b/examples/minio/compose.yml @@ -28,7 +28,7 @@ services: /opt/bitnami/scripts/minio/run.sh & until $(curl -s -f http://localhost:9000/minio/health/live); do sleep 1 - done && + done && mc alias set minio http://minio:9000 user password; mc mirror /tmp/data minio/data; tail -f /dev/null diff --git a/index.js b/index.js deleted file mode 100644 index efa0aa4..0000000 --- a/index.js +++ /dev/null @@ -1,17 +0,0 @@ -"use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __exportStar = (this && this.__exportStar) || function(m, exports) { - for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); -}; -Object.defineProperty(exports, "__esModule", { value: true }); -__exportStar(require("./htsget-lambda"), exports); \ No newline at end of file diff --git a/index.ts b/index.ts new file mode 100644 index 0000000..e01e1c9 --- /dev/null +++ b/index.ts @@ -0,0 +1 @@ +export * from "./lib/htsget-lambda-construct"; diff --git a/lib/htsget-lambda-construct.d.ts b/lib/htsget-lambda-construct.d.ts deleted file mode 100644 index cbaaabe..0000000 --- a/lib/htsget-lambda-construct.d.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { Duration, Stack, StackProps } from "aws-cdk-lib"; -import { Construct } from "constructs"; -import * as apigwv2 from "@aws-cdk/aws-apigatewayv2-alpha"; -/** - * Configuration for HtsgetLambdaStack. - */ -export type Config = { - environment: string; - htsgetConfig: { - [key: string]: any; - }; - allowCredentials?: boolean; - allowHeaders?: string[]; - allowMethods?: apigwv2.CorsHttpMethod[]; - allowOrigins?: string[]; - exposeHeaders?: string[]; - maxAge?: Duration; - parameterStoreConfig: ParameterStoreConfig; -}; -/** - * Configuration values obtained from AWS System Manager Parameter Store. - */ -export type ParameterStoreConfig = { - arnCert: string; - hostedZoneId: string; - hostedZoneName: string; - htsgetDomain: string; - cogUserPoolId: string; - jwtAud: string[]; -}; -/** - * Stack used to deploy htsget-lambda. - */ -export declare class HtsgetLambdaStack extends Stack { - constructor(scope: Construct, id: string, props?: StackProps); - /** - * Get config values from the Parameter Store. - */ - getParameterStoreConfig(config: any): ParameterStoreConfig; - /** - * Convert JSON config to htsget-rs env representation. - */ - static configToEnv(config: any): { - [key: string]: string; - }; - /** - * Convert htsget-rs CORS option to CORS options for API Gateway. - */ - static convertCors(configToml: any, corsValue: string): string[] | undefined; - /** - * Convert a string CORS allowMethod option to CorsHttpMethod. - */ - static corsAllowMethodToHttpMethod(corsAllowMethod?: string[]): apigwv2.CorsHttpMethod[] | undefined; - /** - * Get the environment configuration from cdk.json. Pass `--context "env=dev"` or `--context "env=prod"` to - * control the environment. - */ - getConfig(): Config; -} diff --git a/lib/htsget-lambda-construct.js b/lib/htsget-lambda-construct.js deleted file mode 100644 index ed24c59..0000000 --- a/lib/htsget-lambda-construct.js +++ /dev/null @@ -1,306 +0,0 @@ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - return function (d, b) { - if (typeof b !== "function" && b !== null) - throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -var __assign = (this && this.__assign) || function () { - __assign = Object.assign || function(t) { - for (var s, i = 1, n = arguments.length; i < n; i++) { - s = arguments[i]; - for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) - t[p] = s[p]; - } - return t; - }; - return __assign.apply(this, arguments); -}; -exports.__esModule = true; -exports.HtsgetLambdaConstruct = void 0; -var TOML = require("@iarna/toml"); -var fs_1 = require("fs"); -var aws_cdk_lib_1 = require("aws-cdk-lib"); -var constructs_1 = require("constructs"); -var aws_cognito_1 = require("aws-cdk-lib/aws-cognito"); -var aws_iam_1 = require("aws-cdk-lib/aws-iam"); -var aws_lambda_1 = require("aws-cdk-lib/aws-lambda"); -var aws_certificatemanager_1 = require("aws-cdk-lib/aws-certificatemanager"); -var aws_route53_1 = require("aws-cdk-lib/aws-route53"); -var aws_route53_targets_1 = require("aws-cdk-lib/aws-route53-targets"); -var cargo_lambda_cdk_1 = require("cargo-lambda-cdk"); -var path_1 = require("path"); -var aws_apigatewayv2_integrations_1 = require("aws-cdk-lib/aws-apigatewayv2-integrations"); -var aws_apigatewayv2_1 = require("aws-cdk-lib/aws-apigatewayv2"); -var aws_apigatewayv2_authorizers_1 = require("aws-cdk-lib/aws-apigatewayv2-authorizers"); -var aws_s3_1 = require("aws-cdk-lib/aws-s3"); -var aws_s3_deployment_1 = require("aws-cdk-lib/aws-s3-deployment"); -var aws_secretsmanager_1 = require("aws-cdk-lib/aws-secretsmanager"); -// export class HtsgetStatelessConstruct extends Construct { -// constructor( -// scope: Construct, -// id: string, -// settings: HtsgetStatelessSettings -// ) { -// super(scope, id); -// const config = this.getConfig(settings.config); -// const lambdaRole = new Role(this, id + "Role", { -// assumedBy: new ServicePrincipal("lambda.amazonaws.com"), -// description: "Lambda execution role for " + id, -// }); -// const s3BucketPolicy = new PolicyStatement({ -// actions: ["s3:List*", "s3:Get*"], -// resources: settings.s3BucketResources ?? [], -// }); -// const secretPolicy = new PolicyStatement({ -// actions: ["secretsmanager:GetSecretValue"], -// resources: settings.secretArns ?? [], -// }); -// } -// /** -// * Get the environment from config.toml -// */ -// getConfig(config: string): Config { -// const configToml = TOML.parse(readFileSync(config).toString()); -// return { -// htsgetConfig: HtsgetLambdaConstruct.configToEnv(configToml), -// allowCredentials: -// configToml.ticket_server_cors_allow_credentials as boolean, -// allowHeaders: HtsgetLambdaConstruct.convertCors( -// configToml, -// "ticket_server_cors_allow_headers", -// ), -// allowMethods: HtsgetLambdaConstruct.corsAllowMethodToHttpMethod( -// HtsgetLambdaConstruct.convertCors( -// configToml, -// "ticket_server_cors_allow_methods", -// ), -// ), -// allowOrigins: HtsgetLambdaConstruct.convertCors( -// configToml, -// "ticket_server_cors_allow_origins", -// ), -// exposeHeaders: HtsgetLambdaConstruct.convertCors( -// configToml, -// "ticket_server_cors_expose_headers", -// ), -// maxAge: -// configToml.ticket_server_cors_max_age !== undefined -// ? Duration.seconds(configToml.ticket_server_cors_max_age as number) -// : undefined, -// }; -// } -// } -/** - * Construct used to deploy htsget-lambda. - */ -var HtsgetLambdaConstruct = /** @class */ (function (_super) { - __extends(HtsgetLambdaConstruct, _super); - function HtsgetLambdaConstruct(scope, id, settings) { - var _this = this; - var _a, _b, _c, _d, _e, _f, _g; - _this = _super.call(this, scope, id) || this; - var config = _this.getConfig(settings.config); - var lambdaRole = new aws_iam_1.Role(_this, id + "Role", { - assumedBy: new aws_iam_1.ServicePrincipal("lambda.amazonaws.com"), - description: "Lambda execution role for " + id - }); - var s3BucketPolicy = new aws_iam_1.PolicyStatement({ - actions: ["s3:List*", "s3:Get*"], - resources: (_a = settings.s3BucketResources) !== null && _a !== void 0 ? _a : [] - }); - if (settings.createS3Bucket) { - var bucket = new aws_s3_1.Bucket(_this, "Bucket", { - blockPublicAccess: aws_s3_1.BlockPublicAccess.BLOCK_ALL, - encryption: aws_s3_1.BucketEncryption.S3_MANAGED, - enforceSSL: true, - removalPolicy: aws_cdk_lib_1.RemovalPolicy.RETAIN, - bucketName: settings.bucketName - }); - if (settings.copyTestData) { - var dataDir = path_1["default"].join(__dirname, "..", "..", "data"); - new aws_s3_deployment_1.BucketDeployment(_this, "DeployFiles", { - sources: [aws_s3_deployment_1.Source.asset(dataDir)], - destinationBucket: bucket - }); - } - s3BucketPolicy.addResources("arn:aws:s3:::".concat(bucket.bucketName, "/*")); - new aws_cdk_lib_1.CfnOutput(_this, "HtsgetBucketName", { value: bucket.bucketName }); - } - var secretPolicy = new aws_iam_1.PolicyStatement({ - actions: ["secretsmanager:GetSecretValue"], - resources: (_b = settings.secretArns) !== null && _b !== void 0 ? _b : [] - }); - if (settings.copyExampleKeys) { - var dataDir = path_1["default"].join(__dirname, "..", "..", "data", "c4gh", "keys"); - var private_key = new aws_secretsmanager_1.Secret(_this, "SecretPrivateKey-C4GH", { - secretName: "htsget-rs/c4gh-private-key-c4gh", - secretStringValue: aws_cdk_lib_1.SecretValue.unsafePlainText((0, fs_1.readFileSync)(path_1["default"].join(dataDir, "bob.sec")).toString()), - removalPolicy: aws_cdk_lib_1.RemovalPolicy.RETAIN - }); - var public_key = new aws_secretsmanager_1.Secret(_this, "SecretPublicKey-C4GH", { - secretName: "htsget-rs/c4gh-recipient-public-key-c4gh", - secretStringValue: aws_cdk_lib_1.SecretValue.unsafePlainText((0, fs_1.readFileSync)(path_1["default"].join(dataDir, "alice.pub")).toString()), - removalPolicy: aws_cdk_lib_1.RemovalPolicy.RETAIN - }); - secretPolicy.addResources(private_key.secretArn, public_key.secretArn); - } - lambdaRole.addManagedPolicy(aws_iam_1.ManagedPolicy.fromAwsManagedPolicyName("service-role/AWSLambdaBasicExecutionRole")); - if (s3BucketPolicy.resources.length !== 0) { - lambdaRole.addToPolicy(s3BucketPolicy); - } - if (secretPolicy.resources.length !== 0) { - lambdaRole.addToPolicy(secretPolicy); - } - var features = (_c = settings.features) !== null && _c !== void 0 ? _c : []; - features = features - .filter(function (f) { return f !== "s3-storage"; }) - .concat(["s3-storage"]); - var htsgetLambda = new cargo_lambda_cdk_1.RustFunction(_this, id + "Function", { - manifestPath: path_1["default"].join(__dirname, "..", ".."), - binaryName: "htsget-lambda", - bundling: { - environment: { - RUSTFLAGS: "-C target-cpu=neoverse-n1", - CARGO_PROFILE_RELEASE_LTO: "true", - CARGO_PROFILE_RELEASE_CODEGEN_UNITS: "1" - }, - cargoLambdaFlags: ["--features", features.join(",")] - }, - memorySize: 128, - timeout: aws_cdk_lib_1.Duration.seconds(28), - environment: __assign(__assign({}, config.htsgetConfig), { RUST_LOG: "info,htsget_http_lambda=trace,htsget_config=trace,htsget_http_core=trace,htsget_search=trace" }), - architecture: aws_lambda_1.Architecture.ARM_64, - role: lambdaRole - }); - var httpIntegration = new aws_apigatewayv2_integrations_1.HttpLambdaIntegration(id + "HtsgetIntegration", htsgetLambda); - // Add an authorizer if auth is required. - var authorizer = undefined; - if (!settings.jwtAuthorizer.public) { - // If the cog user pool id is not specified, create a new one. - if (settings.jwtAuthorizer.cogUserPoolId === undefined) { - var pool = new aws_cognito_1.UserPool(_this, "userPool", { - userPoolName: "HtsgetRsUserPool" - }); - settings.jwtAuthorizer.cogUserPoolId = pool.userPoolId; - } - authorizer = new aws_apigatewayv2_authorizers_1.HttpJwtAuthorizer(id + "HtsgetAuthorizer", "https://cognito-idp.".concat(aws_cdk_lib_1.Stack.of(_this).region, ".amazonaws.com/").concat(settings.jwtAuthorizer.cogUserPoolId), { - identitySource: ["$request.header.Authorization"], - jwtAudience: (_d = settings.jwtAuthorizer.jwtAudience) !== null && _d !== void 0 ? _d : [] - }); - } - else { - console.warn("This will create an instance of htsget-rs that is public! Anyone will be able to query the server without authorization."); - } - var hostedZone; - if ((_e = settings.lookupHostedZone) !== null && _e !== void 0 ? _e : true) { - hostedZone = aws_route53_1.HostedZone.fromLookup(_this, "HostedZone", { - domainName: settings.domain - }); - } - else { - hostedZone = new aws_route53_1.HostedZone(_this, id + "HtsgetHostedZone", { - zoneName: settings.domain - }); - } - var url = "".concat((_f = settings.subDomain) !== null && _f !== void 0 ? _f : "htsget", ".").concat(settings.domain); - var certificate = new aws_certificatemanager_1.Certificate(_this, id + "HtsgetCertificate", { - domainName: url, - validation: aws_certificatemanager_1.CertificateValidation.fromDns(hostedZone), - certificateName: url - }); - var domainName = new aws_apigatewayv2_1.DomainName(_this, id + "HtsgetDomainName", { - certificate: certificate, - domainName: url - }); - new aws_route53_1.ARecord(_this, id + "HtsgetARecord", { - zone: hostedZone, - recordName: (_g = settings.subDomain) !== null && _g !== void 0 ? _g : "htsget", - target: aws_route53_1.RecordTarget.fromAlias(new aws_route53_targets_1.ApiGatewayv2DomainProperties(domainName.regionalDomainName, domainName.regionalHostedZoneId)) - }); - var httpApi = new aws_apigatewayv2_1.HttpApi(_this, id + "ApiGw", { - defaultAuthorizer: authorizer, - defaultDomainMapping: { - domainName: domainName - }, - corsPreflight: { - allowCredentials: config.allowCredentials, - allowHeaders: config.allowHeaders, - allowMethods: config.allowMethods, - allowOrigins: config.allowOrigins, - exposeHeaders: config.exposeHeaders, - maxAge: config.maxAge - } - }); - httpApi.addRoutes({ - path: "/{proxy+}", - methods: [aws_apigatewayv2_1.HttpMethod.GET, aws_apigatewayv2_1.HttpMethod.POST], - integration: httpIntegration - }); - return _this; - } - /** - * Convert JSON config to htsget-rs env representation. - */ - HtsgetLambdaConstruct.configToEnv = function (config) { - var out = {}; - for (var key in config) { - out["HTSGET_".concat(key.toUpperCase())] = TOML.stringify.value(config[key]); - } - return out; - }; - /** - * Convert htsget-rs CORS option to CORS options for API Gateway. - */ - HtsgetLambdaConstruct.convertCors = function (configToml, corsValue) { - var value = configToml[corsValue]; - if (value !== undefined && - (value.toString().toLowerCase() === "all" || - value.toString().toLowerCase() === "mirror")) { - return ["*"]; - } - else if (Array.isArray(value)) { - return value; - } - return undefined; - }; - /** - * Convert a string CORS allowMethod option to CorsHttpMethod. - */ - HtsgetLambdaConstruct.corsAllowMethodToHttpMethod = function (corsAllowMethod) { - if ((corsAllowMethod === null || corsAllowMethod === void 0 ? void 0 : corsAllowMethod.length) === 1 && corsAllowMethod.includes("*")) { - return [aws_apigatewayv2_1.CorsHttpMethod.ANY]; - } - else { - return corsAllowMethod === null || corsAllowMethod === void 0 ? void 0 : corsAllowMethod.map(function (element) { return aws_apigatewayv2_1.CorsHttpMethod[element]; }); - } - }; - /** - * Get the environment from config.toml - */ - HtsgetLambdaConstruct.prototype.getConfig = function (config) { - var configToml = TOML.parse((0, fs_1.readFileSync)(config).toString()); - return { - htsgetConfig: HtsgetLambdaConstruct.configToEnv(configToml), - allowCredentials: configToml.ticket_server_cors_allow_credentials, - allowHeaders: HtsgetLambdaConstruct.convertCors(configToml, "ticket_server_cors_allow_headers"), - allowMethods: HtsgetLambdaConstruct.corsAllowMethodToHttpMethod(HtsgetLambdaConstruct.convertCors(configToml, "ticket_server_cors_allow_methods")), - allowOrigins: HtsgetLambdaConstruct.convertCors(configToml, "ticket_server_cors_allow_origins"), - exposeHeaders: HtsgetLambdaConstruct.convertCors(configToml, "ticket_server_cors_expose_headers"), - maxAge: configToml.ticket_server_cors_max_age !== undefined - ? aws_cdk_lib_1.Duration.seconds(configToml.ticket_server_cors_max_age) - : undefined - }; - }; - return HtsgetLambdaConstruct; -}(constructs_1.Construct)); -exports.HtsgetLambdaConstruct = HtsgetLambdaConstruct; diff --git a/lib/htsget-lambda-construct.ts b/lib/htsget-lambda-construct.ts index b785d8e..331449d 100644 --- a/lib/htsget-lambda-construct.ts +++ b/lib/htsget-lambda-construct.ts @@ -66,7 +66,7 @@ export type HtsgetStatefulSettings = { */ lookupHostedZone?: boolean; - /** + /** * Whether to create a test bucket. Defaults to true. Buckets are created with * [`RemovalPolicy.RETAIN`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.RemovalPolicy.html). * The correct access permissions are automatically added. @@ -79,7 +79,7 @@ export type HtsgetStatefulSettings = { */ bucketName?: string; - /** + /** * Whether to copy test data into the bucket. Defaults to true. This copies the example data under the `data` * directory to those buckets. This option only has an affect is `createS3Buckets` is true. */ @@ -472,8 +472,8 @@ export class HtsgetLambdaConstruct extends Construct { } /** - * Spawn sync with error handling - */ + * Spawn sync with error handling + */ exec(cmd: string, args: string[]) { const proc = spawnSync(cmd, args); @@ -483,7 +483,9 @@ export class HtsgetLambdaConstruct extends Construct { if (proc.status !== 0) { if (proc.stdout || proc.stderr) { - throw new Error(`[Status ${proc.status}] stdout: ${proc.stdout?.toString().trim()}\n\n\nstderr: ${proc.stderr?.toString().trim()}`); + throw new Error( + `[Status ${proc.status}] stdout: ${proc.stdout?.toString().trim()}\n\n\nstderr: ${proc.stderr?.toString().trim()}`, + ); } throw new Error(`${cmd} exited with status ${proc.status}`); } diff --git a/package.json b/package.json index da5cc9b..6e4ae04 100644 --- a/package.json +++ b/package.json @@ -1,27 +1,7 @@ { - "name": "htsget-lambda-construct", - "version": "0.5.1", "bin": { "htsget_app": "bin/htsget-lambda.js" }, - "files": [ - "bin/htsget-lambda.ts", - "bin/settings.ts", - "lib/htsget-lambda-construct.ts", - "config/example_deploy.toml" - ], - "scripts": { - "run": "cdk deploy", - "build": "tsc", - "watch": "tsc -w", - "cdk": "cdk" - }, - "devDependencies": { - "@types/node": "22.8.4", - "aws-cdk": "2.164.1", - "prettier": "^3.3.3", - "typescript": "5.6.3" - }, "dependencies": { "@iarna/toml": "^3.0.0", "aws-cdk-lib": "2.162.1", @@ -29,5 +9,23 @@ "constructs": "10.4.2", "glob": "^11.0.0", "source-map-support": "^0.5.21" - } + }, + "devDependencies": { + "@types/node": "22.8.4", + "aws-cdk": "2.164.1", + "prettier": "^3.3.3", + "typescript": "5.6.3" + }, + "files": [ + "dist" + ], + "name": "htsget-lambda", + "scripts": { + "build": "tsc", + "cdk": "cdk", + "prettier": "prettier", + "run": "cdk deploy", + "watch": "tsc -w" + }, + "version": "0.6.0" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..de8523f --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,585 @@ +lockfileVersion: "9.0" + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + .: + dependencies: + "@iarna/toml": + specifier: ^3.0.0 + version: 3.0.0 + aws-cdk-lib: + specifier: 2.162.1 + version: 2.162.1(constructs@10.4.2) + cargo-lambda-cdk: + specifier: ^0.0.31 + version: 0.0.31(aws-cdk-lib@2.162.1(constructs@10.4.2))(constructs@10.4.2) + constructs: + specifier: 10.4.2 + version: 10.4.2 + glob: + specifier: ^11.0.0 + version: 11.0.0 + source-map-support: + specifier: ^0.5.21 + version: 0.5.21 + devDependencies: + "@types/node": + specifier: 22.8.4 + version: 22.8.4 + aws-cdk: + specifier: 2.164.1 + version: 2.164.1 + prettier: + specifier: ^3.3.3 + version: 3.4.2 + typescript: + specifier: 5.6.3 + version: 5.6.3 + +packages: + "@aws-cdk/asset-awscli-v1@2.2.213": + resolution: + { + integrity: sha512-crm1yDJmORJF2Y9gDvNUX4Q3iQXVhWrL7oaZfpx3QDqrvVz5UEgWGpJdysqDuWFZTmIgtrI5Svq3UfdwCNNpsg==, + } + + "@aws-cdk/asset-kubectl-v20@2.1.3": + resolution: + { + integrity: sha512-cDG1w3ieM6eOT9mTefRuTypk95+oyD7P5X/wRltwmYxU7nZc3+076YEVS6vrjDKr3ADYbfn0lDKpfB1FBtO9CQ==, + } + + "@aws-cdk/asset-node-proxy-agent-v6@2.1.0": + resolution: + { + integrity: sha512-7bY3J8GCVxLupn/kNmpPc5VJz8grx+4RKfnnJiO1LG+uxkZfANZG3RMHhE+qQxxwkyQ9/MfPtTpf748UhR425A==, + } + + "@aws-cdk/cloud-assembly-schema@38.0.1": + resolution: + { + integrity: sha512-KvPe+NMWAulfNVwY7jenFhzhuLhLqJ/OPy5jx7wUstbjnYnjRVLpUHPU3yCjXFE0J8cuJVdx95BJ4rOs66Pi9w==, + } + bundledDependencies: + - jsonschema + - semver + + "@iarna/toml@3.0.0": + resolution: + { + integrity: sha512-td6ZUkz2oS3VeleBcN+m//Q6HlCFCPrnI0FZhrt/h4XqLEdOyYp2u21nd8MdsR+WJy5r9PTDaHTDDfhf4H4l6Q==, + } + + "@isaacs/cliui@8.0.2": + resolution: + { + integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==, + } + engines: { node: ">=12" } + + "@types/node@22.8.4": + resolution: + { + integrity: sha512-SpNNxkftTJOPk0oN+y2bIqurEXHTA2AOZ3EJDDKeJ5VzkvvORSvmQXGQarcOzWV1ac7DCaPBEdMDxBsM+d8jWw==, + } + + ansi-regex@5.0.1: + resolution: + { + integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==, + } + engines: { node: ">=8" } + + ansi-regex@6.1.0: + resolution: + { + integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==, + } + engines: { node: ">=12" } + + ansi-styles@4.3.0: + resolution: + { + integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==, + } + engines: { node: ">=8" } + + ansi-styles@6.2.1: + resolution: + { + integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==, + } + engines: { node: ">=12" } + + aws-cdk-lib@2.162.1: + resolution: + { + integrity: sha512-XiZLVE5ISNajNNmLye8l5w4EGqm6/d8C8shw63QwxaRVYdHl5e+EAaUEmZJpWc4sYtY/sS+GHOfhoKFLjha2rg==, + } + engines: { node: ">= 14.15.0" } + peerDependencies: + constructs: ^10.0.0 + bundledDependencies: + - "@balena/dockerignore" + - case + - fs-extra + - ignore + - jsonschema + - minimatch + - punycode + - semver + - table + - yaml + - mime-types + + aws-cdk@2.164.1: + resolution: + { + integrity: sha512-dWRViQgHLe7GHkPIQGA+8EQSm8TBcxemyCC3HHW3wbLMWUDbspio9Dktmw5EmWxlFjjWh86Dk1JWf1zKQo8C5g==, + } + engines: { node: ">= 14.15.0" } + hasBin: true + + balanced-match@1.0.2: + resolution: + { + integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==, + } + + brace-expansion@2.0.1: + resolution: + { + integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==, + } + + buffer-from@1.1.2: + resolution: + { + integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==, + } + + cargo-lambda-cdk@0.0.31: + resolution: + { + integrity: sha512-DUHRl9VVLlMagHsgDLjJWXOWzEWTGQQ3FzVLHuJRDXAL5wOAtaEDvemwcAuCi4swmkA6FoyN3Z8P5lPs4a5EVw==, + } + peerDependencies: + aws-cdk-lib: ^2.63.0 + constructs: ^10.0.5 + bundledDependencies: + - js-toml + + color-convert@2.0.1: + resolution: + { + integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==, + } + engines: { node: ">=7.0.0" } + + color-name@1.1.4: + resolution: + { + integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==, + } + + constructs@10.4.2: + resolution: + { + integrity: sha512-wsNxBlAott2qg8Zv87q3eYZYgheb9lchtBfjHzzLHtXbttwSrHPs1NNQbBrmbb1YZvYg2+Vh0Dor76w4mFxJkA==, + } + + cross-spawn@7.0.6: + resolution: + { + integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==, + } + engines: { node: ">= 8" } + + eastasianwidth@0.2.0: + resolution: + { + integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==, + } + + emoji-regex@8.0.0: + resolution: + { + integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==, + } + + emoji-regex@9.2.2: + resolution: + { + integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==, + } + + foreground-child@3.3.0: + resolution: + { + integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==, + } + engines: { node: ">=14" } + + fsevents@2.3.2: + resolution: + { + integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==, + } + engines: { node: ^8.16.0 || ^10.6.0 || >=11.0.0 } + os: [darwin] + + glob@11.0.0: + resolution: + { + integrity: sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==, + } + engines: { node: 20 || >=22 } + hasBin: true + + is-fullwidth-code-point@3.0.0: + resolution: + { + integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==, + } + engines: { node: ">=8" } + + isexe@2.0.0: + resolution: + { + integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==, + } + + jackspeak@4.0.2: + resolution: + { + integrity: sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==, + } + engines: { node: 20 || >=22 } + + lru-cache@11.0.2: + resolution: + { + integrity: sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA==, + } + engines: { node: 20 || >=22 } + + minimatch@10.0.1: + resolution: + { + integrity: sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==, + } + engines: { node: 20 || >=22 } + + minipass@7.1.2: + resolution: + { + integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==, + } + engines: { node: ">=16 || 14 >=14.17" } + + package-json-from-dist@1.0.1: + resolution: + { + integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==, + } + + path-key@3.1.1: + resolution: + { + integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==, + } + engines: { node: ">=8" } + + path-scurry@2.0.0: + resolution: + { + integrity: sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==, + } + engines: { node: 20 || >=22 } + + prettier@3.4.2: + resolution: + { + integrity: sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==, + } + engines: { node: ">=14" } + hasBin: true + + shebang-command@2.0.0: + resolution: + { + integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==, + } + engines: { node: ">=8" } + + shebang-regex@3.0.0: + resolution: + { + integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==, + } + engines: { node: ">=8" } + + signal-exit@4.1.0: + resolution: + { + integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==, + } + engines: { node: ">=14" } + + source-map-support@0.5.21: + resolution: + { + integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==, + } + + source-map@0.6.1: + resolution: + { + integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==, + } + engines: { node: ">=0.10.0" } + + string-width@4.2.3: + resolution: + { + integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==, + } + engines: { node: ">=8" } + + string-width@5.1.2: + resolution: + { + integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==, + } + engines: { node: ">=12" } + + strip-ansi@6.0.1: + resolution: + { + integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==, + } + engines: { node: ">=8" } + + strip-ansi@7.1.0: + resolution: + { + integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==, + } + engines: { node: ">=12" } + + typescript@5.6.3: + resolution: + { + integrity: sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==, + } + engines: { node: ">=14.17" } + hasBin: true + + undici-types@6.19.8: + resolution: + { + integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==, + } + + which@2.0.2: + resolution: + { + integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==, + } + engines: { node: ">= 8" } + hasBin: true + + wrap-ansi@7.0.0: + resolution: + { + integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==, + } + engines: { node: ">=10" } + + wrap-ansi@8.1.0: + resolution: + { + integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==, + } + engines: { node: ">=12" } + +snapshots: + "@aws-cdk/asset-awscli-v1@2.2.213": {} + + "@aws-cdk/asset-kubectl-v20@2.1.3": {} + + "@aws-cdk/asset-node-proxy-agent-v6@2.1.0": {} + + "@aws-cdk/cloud-assembly-schema@38.0.1": {} + + "@iarna/toml@3.0.0": {} + + "@isaacs/cliui@8.0.2": + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.1.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + + "@types/node@22.8.4": + dependencies: + undici-types: 6.19.8 + + ansi-regex@5.0.1: {} + + ansi-regex@6.1.0: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@6.2.1: {} + + aws-cdk-lib@2.162.1(constructs@10.4.2): + dependencies: + "@aws-cdk/asset-awscli-v1": 2.2.213 + "@aws-cdk/asset-kubectl-v20": 2.1.3 + "@aws-cdk/asset-node-proxy-agent-v6": 2.1.0 + "@aws-cdk/cloud-assembly-schema": 38.0.1 + constructs: 10.4.2 + + aws-cdk@2.164.1: + optionalDependencies: + fsevents: 2.3.2 + + balanced-match@1.0.2: {} + + brace-expansion@2.0.1: + dependencies: + balanced-match: 1.0.2 + + buffer-from@1.1.2: {} + + cargo-lambda-cdk@0.0.31(aws-cdk-lib@2.162.1(constructs@10.4.2))(constructs@10.4.2): + dependencies: + aws-cdk-lib: 2.162.1(constructs@10.4.2) + constructs: 10.4.2 + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + constructs@10.4.2: {} + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + eastasianwidth@0.2.0: {} + + emoji-regex@8.0.0: {} + + emoji-regex@9.2.2: {} + + foreground-child@3.3.0: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + + fsevents@2.3.2: + optional: true + + glob@11.0.0: + dependencies: + foreground-child: 3.3.0 + jackspeak: 4.0.2 + minimatch: 10.0.1 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 2.0.0 + + is-fullwidth-code-point@3.0.0: {} + + isexe@2.0.0: {} + + jackspeak@4.0.2: + dependencies: + "@isaacs/cliui": 8.0.2 + + lru-cache@11.0.2: {} + + minimatch@10.0.1: + dependencies: + brace-expansion: 2.0.1 + + minipass@7.1.2: {} + + package-json-from-dist@1.0.1: {} + + path-key@3.1.1: {} + + path-scurry@2.0.0: + dependencies: + lru-cache: 11.0.2 + minipass: 7.1.2 + + prettier@3.4.2: {} + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + signal-exit@4.1.0: {} + + source-map-support@0.5.21: + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + + source-map@0.6.1: {} + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.1.0: + dependencies: + ansi-regex: 6.1.0 + + typescript@5.6.3: {} + + undici-types@6.19.8: {} + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 diff --git a/tsconfig.json b/tsconfig.json index c4a2e10..9813f30 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,24 +1,32 @@ { "compilerOptions": { - "target": "ES2021", - "module": "commonjs", - "lib": ["ES2021"], + "alwaysStrict": true, "declaration": true, - "strict": true, + "esModuleInterop": true, + "experimentalDecorators": true, + "inlineSourceMap": true, + "inlineSources": true, + "lib": [ + "ES2021" + ], + "module": "commonjs", + "noFallthroughCasesInSwitch": false, "noImplicitAny": true, - "strictNullChecks": true, + "noImplicitReturns": true, "noImplicitThis": true, - "alwaysStrict": true, "noUnusedLocals": false, "noUnusedParameters": false, - "noImplicitReturns": true, - "noFallthroughCasesInSwitch": false, - "inlineSourceMap": true, - "inlineSources": true, - "experimentalDecorators": true, + "outDir": "dist", + "strict": true, + "strictNullChecks": true, "strictPropertyInitialization": false, - "typeRoots": ["./node_modules/@types"], - "esModuleInterop": true + "target": "ES2021", + "typeRoots": [ + "./node_modules/@types" + ] }, - "exclude": ["node_modules", "cdk.out"] + "exclude": [ + "node_modules", + "cdk.out" + ] } From 345c8ee0a67c8c929886d9e5fdf919cd6be558b5 Mon Sep 17 00:00:00 2001 From: Marko Malenic Date: Fri, 6 Dec 2024 11:55:12 +1100 Subject: [PATCH 2/6] feat: add props for roles, existing httpApis and VPCs --- .pre-commit-config.yaml | 5 +- lib/htsget-lambda-construct.ts | 314 +++++++++++++++++++++------------ 2 files changed, 201 insertions(+), 118 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b9caf74..770ea0a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,5 +1,4 @@ repos: - - repo: https://github.com/pre-commit/pre-commit-hooks rev: v5.0.0 hooks: @@ -11,9 +10,9 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - id: pretty-format-json - args: ['--autofix'] + args: ["--autofix"] - repo: https://github.com/Yelp/detect-secrets rev: v1.5.0 hooks: - id: detect-secrets - args: ['--baseline', '.secrets.baseline'] + args: ["--baseline", ".secrets.baseline"] diff --git a/lib/htsget-lambda-construct.ts b/lib/htsget-lambda-construct.ts index 331449d..54a5a92 100644 --- a/lib/htsget-lambda-construct.ts +++ b/lib/htsget-lambda-construct.ts @@ -12,6 +12,7 @@ import { Construct } from "constructs"; import { UserPool } from "aws-cdk-lib/aws-cognito"; import { + IRole, ManagedPolicy, PolicyStatement, Role, @@ -22,7 +23,12 @@ import { Certificate, CertificateValidation, } from "aws-cdk-lib/aws-certificatemanager"; -import { ARecord, HostedZone, RecordTarget } from "aws-cdk-lib/aws-route53"; +import { + ARecord, + CfnHostedZone, + HostedZone, + RecordTarget, +} from "aws-cdk-lib/aws-route53"; import { ApiGatewayv2DomainProperties } from "aws-cdk-lib/aws-route53-targets"; import { RustFunction } from "cargo-lambda-cdk"; import path from "path"; @@ -43,6 +49,8 @@ import { BucketDeployment, Source } from "aws-cdk-lib/aws-s3-deployment"; import { Secret } from "aws-cdk-lib/aws-secretsmanager"; import { tmpdir } from "os"; import { spawnSync } from "child_process"; +import VPCProperty = CfnHostedZone.VPCProperty; +import { IVpc } from "aws-cdk-lib/aws-ec2"; /** * These options are related to creating stateful resources. Some of these might conflict with existing resources @@ -52,7 +60,7 @@ export type HtsgetStatefulSettings = { /** * The domain name for the htsget server. */ - domain: string; + domain?: string; /** * The domain name prefix to use for the htsget-rs server. Defaults to `"htsget"`. @@ -93,6 +101,23 @@ export type HtsgetStatefulSettings = { * with [`RemovalPolicy.RETAIN`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.RemovalPolicy.html). */ copyExampleKeys?: boolean; + + /** + * Use a VPC for the Lambda function. + */ + vpc?: IVpc; + + /** + * Manually specify an `HttpApi`. This will not create a `HostedZone`, any Route53 records, certificates, + * or authorizers, and will instead rely on the existing `HttpApi`. + */ + httpApi?: HttpApi; + + /** + * Use the provided role instead of creating one. This will ignore any configuration related to permissions for + * buckets and secrets, and rely on the existing role. + */ + role?: Role; }; /** @@ -111,12 +136,12 @@ export type HtsgetStatelessSettings = { * option. This option must be specified to allow `htsget-rs` to access data in buckets that are not created in * this construct. */ - s3BucketResources: string[]; + s3BucketResources?: string[]; /** * Whether this deployment is gated behind a JWT authorizer, or if its public. */ - jwtAuthorizer: HtsgetJwtAuthSettings; + jwtAuthorizer?: HtsgetJwtAuthSettings; /** * The Secrets Manager secrets which htsget-rs needs access to. This affects the permissions that get added to the @@ -205,75 +230,50 @@ export class HtsgetLambdaConstruct extends Construct { const config = this.getConfig(settings.config); - const lambdaRole = new Role(this, id + "Role", { - assumedBy: new ServicePrincipal("lambda.amazonaws.com"), - description: "Lambda execution role for " + id, - }); - - const s3BucketPolicy = new PolicyStatement({ - actions: ["s3:List*", "s3:Get*"], - resources: settings.s3BucketResources ?? [], - }); - + let bucket = undefined; if (settings.createS3Bucket) { - const bucket = new Bucket(this, "Bucket", { - blockPublicAccess: BlockPublicAccess.BLOCK_ALL, - encryption: BucketEncryption.S3_MANAGED, - enforceSSL: true, - removalPolicy: RemovalPolicy.RETAIN, - bucketName: settings.bucketName, - }); - - if (settings.copyTestData) { - // Copy data from upstream htsget-data repo - const localDataPath = path.join(tmpdir(), "htsget-rs"); - - new BucketDeployment(this, "DeployFiles", { - sources: [Source.asset(localDataPath)], - destinationBucket: bucket, - }); - } - - s3BucketPolicy.addResources(`arn:aws:s3:::${bucket.bucketName}/*`); - - new CfnOutput(this, "HtsgetBucketName", { value: bucket.bucketName }); + bucket = this.createBucket(settings.copyTestData, settings.bucketName); } - const secretPolicy = new PolicyStatement({ - actions: ["secretsmanager:GetSecretValue"], - resources: settings.secretArns ?? [], - }); - + let keys = undefined; if (settings.copyTestData && settings.copyExampleKeys) { - const dataDir = path.join(tmpdir(), "htsget-rs", "data", "c4gh", "keys"); - const private_key = new Secret(this, "SecretPrivateKey-C4GH", { - secretName: "htsget-rs/privkey-crypt4gh", // pragma: allowlist secret - secretStringValue: SecretValue.unsafePlainText( - readFileSync(path.join(dataDir, "bob.sec")).toString(), - ), - removalPolicy: RemovalPolicy.RETAIN, - }); - const public_key = new Secret(this, "SecretPublicKey-C4GH", { - secretName: "htsget-rs/pubkey-crypt4gh", // pragma: allowlist secret - secretStringValue: SecretValue.unsafePlainText( - readFileSync(path.join(dataDir, "alice.pub")).toString(), - ), - removalPolicy: RemovalPolicy.RETAIN, - }); - - secretPolicy.addResources(private_key.secretArn, public_key.secretArn); + keys = this.createKeys(); } - lambdaRole.addManagedPolicy( - ManagedPolicy.fromAwsManagedPolicyName( - "service-role/AWSLambdaBasicExecutionRole", - ), - ); - if (s3BucketPolicy.resources.length !== 0) { - lambdaRole.addToPolicy(s3BucketPolicy); + let lambdaRole: Role; + if (settings.role !== undefined) { + lambdaRole = settings.role; + } else { + lambdaRole = this.createRole( + id, + bucket, + settings.s3BucketResources, + settings.secretArns, + keys?.private_key, + keys?.public_key, + ); } - if (secretPolicy.resources.length !== 0) { - lambdaRole.addToPolicy(secretPolicy); + + let httpApi; + if (settings.httpApi !== undefined) { + httpApi = settings.httpApi; + } else { + if ( + settings.domain === undefined || + settings.jwtAuthorizer === undefined + ) { + throw Error( + "domain and jwtAuthorizer must be defined if httpApi is not specified", + ); + } + + httpApi = this.createHttpApi( + settings.domain, + settings.jwtAuthorizer, + config, + settings.subDomain, + settings.lookupHostedZone, + ); } let features = settings.features ?? []; @@ -281,7 +281,7 @@ export class HtsgetLambdaConstruct extends Construct { .filter((f) => f !== "s3-storage") .concat(["s3-storage"]); - let htsgetLambda = new RustFunction(this, id + "Function", { + let htsgetLambda = new RustFunction(this, "Function", { gitRemote: "https://github.com/umccr/htsget-rs", gitForceClone: true, binaryName: "htsget-lambda", @@ -302,30 +302,145 @@ export class HtsgetLambdaConstruct extends Construct { }, architecture: Architecture.ARM_64, role: lambdaRole, + vpc: settings.vpc, }); const httpIntegration = new HttpLambdaIntegration( - id + "HtsgetIntegration", + "HtsgetIntegration", htsgetLambda, ); + httpApi.addRoutes({ + path: "/{proxy+}", + methods: [HttpMethod.GET, HttpMethod.POST], + integration: httpIntegration, + }); + } + + /** + * Create a bucket and copy test data if configured. + */ + private createBucket(copyTestData?: boolean, bucketName?: string): Bucket { + const bucket = new Bucket(this, "Bucket", { + blockPublicAccess: BlockPublicAccess.BLOCK_ALL, + encryption: BucketEncryption.S3_MANAGED, + enforceSSL: true, + removalPolicy: RemovalPolicy.RETAIN, + bucketName, + }); + + if (copyTestData) { + // Copy data from upstream htsget-data repo + const localDataPath = path.join(tmpdir(), "htsget-rs"); + + new BucketDeployment(this, "DeployFiles", { + sources: [Source.asset(localDataPath)], + destinationBucket: bucket, + }); + } + + new CfnOutput(this, "HtsgetBucketName", { value: bucket.bucketName }); + + return bucket; + } + + /** + * Create C4GH keys inside AWS SecretsManager + */ + private createKeys(): { private_key: Secret; public_key: Secret } { + const dataDir = path.join(tmpdir(), "htsget-rs", "data", "c4gh", "keys"); + const private_key = new Secret(this, "SecretPrivateKey-C4GH", { + secretName: "htsget-rs/privkey-crypt4gh", // pragma: allowlist secret + secretStringValue: SecretValue.unsafePlainText( + readFileSync(path.join(dataDir, "bob.sec")).toString(), + ), + removalPolicy: RemovalPolicy.RETAIN, + }); + const public_key = new Secret(this, "SecretPublicKey-C4GH", { + secretName: "htsget-rs/pubkey-crypt4gh", // pragma: allowlist secret + secretStringValue: SecretValue.unsafePlainText( + readFileSync(path.join(dataDir, "alice.pub")).toString(), + ), + removalPolicy: RemovalPolicy.RETAIN, + }); + + return { private_key, public_key }; + } + + /** + * Creates a lambda role with the configured permissions. + */ + private createRole( + id: string, + bucket: any, + s3BucketResources?: string[], + secretArns?: string[], + private_key?: Secret, + public_key?: Secret, + ): Role { + const lambdaRole = new Role(this, "Role", { + assumedBy: new ServicePrincipal("lambda.amazonaws.com"), + description: "Lambda execution role for " + id, + }); + lambdaRole.addManagedPolicy( + ManagedPolicy.fromAwsManagedPolicyName( + "service-role/AWSLambdaBasicExecutionRole", + ), + ); + + if (bucket !== undefined) { + const s3BucketPolicy = new PolicyStatement({ + actions: ["s3:List*", "s3:Get*"], + resources: s3BucketResources ?? [], + }); + s3BucketPolicy.addResources(`arn:aws:s3:::${bucket.bucketName}/*`); + + if (s3BucketPolicy.resources.length !== 0) { + lambdaRole.addToPolicy(s3BucketPolicy); + } + } + + if (private_key !== undefined && public_key !== undefined) { + const secretPolicy = new PolicyStatement({ + actions: ["secretsmanager:GetSecretValue"], + resources: secretArns ?? [], + }); + secretPolicy.addResources(private_key.secretArn, public_key.secretArn); + + if (secretPolicy.resources.length !== 0) { + lambdaRole.addToPolicy(secretPolicy); + } + } + return lambdaRole; + } + + /** + * Create stateful config related to the httpApi and the API itself. + */ + private createHttpApi( + domain: string, + jwtAuthorizer: HtsgetJwtAuthSettings, + config: Config, + subDomain?: string, + lookupHostedZone?: boolean, + ): HttpApi { // Add an authorizer if auth is required. let authorizer = undefined; - if (!settings.jwtAuthorizer.public) { + if (!jwtAuthorizer.public) { // If the cog user pool id is not specified, create a new one. - if (settings.jwtAuthorizer.cogUserPoolId === undefined) { + if (jwtAuthorizer.cogUserPoolId === undefined) { const pool = new UserPool(this, "userPool", { userPoolName: "HtsgetRsUserPool", }); - settings.jwtAuthorizer.cogUserPoolId = pool.userPoolId; + jwtAuthorizer.cogUserPoolId = pool.userPoolId; } authorizer = new HttpJwtAuthorizer( - id + "HtsgetAuthorizer", - `https://cognito-idp.${Stack.of(this).region}.amazonaws.com/${settings.jwtAuthorizer.cogUserPoolId}`, + "HtsgetAuthorizer", + `https://cognito-idp.${Stack.of(this).region}.amazonaws.com/${jwtAuthorizer.cogUserPoolId}`, { identitySource: ["$request.header.Authorization"], - jwtAudience: settings.jwtAuthorizer.jwtAudience ?? [], + jwtAudience: jwtAuthorizer.jwtAudience ?? [], }, ); } else { @@ -335,32 +450,32 @@ export class HtsgetLambdaConstruct extends Construct { } let hostedZone; - if (settings.lookupHostedZone ?? true) { + if (lookupHostedZone ?? true) { hostedZone = HostedZone.fromLookup(this, "HostedZone", { - domainName: settings.domain, + domainName: domain, }); } else { - hostedZone = new HostedZone(this, id + "HtsgetHostedZone", { - zoneName: settings.domain, + hostedZone = new HostedZone(this, "HtsgetHostedZone", { + zoneName: domain, }); } - let url = `${settings.subDomain ?? "htsget"}.${settings.domain}`; + let url = `${subDomain ?? "htsget"}.${domain}`; - let certificate = new Certificate(this, id + "HtsgetCertificate", { + let certificate = new Certificate(this, "HtsgetCertificate", { domainName: url, validation: CertificateValidation.fromDns(hostedZone), certificateName: url, }); - const domainName = new DomainName(this, id + "HtsgetDomainName", { + const domainName = new DomainName(this, "HtsgetDomainName", { certificate: certificate, domainName: url, }); - new ARecord(this, id + "HtsgetARecord", { + new ARecord(this, "HtsgetARecord", { zone: hostedZone, - recordName: settings.subDomain ?? "htsget", + recordName: subDomain ?? "htsget", target: RecordTarget.fromAlias( new ApiGatewayv2DomainProperties( domainName.regionalDomainName, @@ -369,7 +484,7 @@ export class HtsgetLambdaConstruct extends Construct { ), }); - const httpApi = new HttpApi(this, id + "ApiGw", { + return new HttpApi(this, "ApiGw", { defaultAuthorizer: authorizer, defaultDomainMapping: { domainName: domainName, @@ -383,12 +498,6 @@ export class HtsgetLambdaConstruct extends Construct { maxAge: config.maxAge, }, }); - - httpApi.addRoutes({ - path: "/{proxy+}", - methods: [HttpMethod.GET, HttpMethod.POST], - integration: httpIntegration, - }); } /** @@ -470,29 +579,4 @@ export class HtsgetLambdaConstruct extends Construct { : undefined, }; } - - /** - * Spawn sync with error handling - */ - exec(cmd: string, args: string[]) { - const proc = spawnSync(cmd, args); - - if (proc.error) { - throw proc.error; - } - - if (proc.status !== 0) { - if (proc.stdout || proc.stderr) { - throw new Error( - `[Status ${proc.status}] stdout: ${proc.stdout?.toString().trim()}\n\n\nstderr: ${proc.stderr?.toString().trim()}`, - ); - } - throw new Error(`${cmd} exited with status ${proc.status}`); - } - - return proc; - } - // fetchExampleDataAndKeys() { - // - // } } From 1b69d3dae6578cde17acdd76ccab262757cd5509 Mon Sep 17 00:00:00 2001 From: Marko Malenic Date: Fri, 6 Dec 2024 12:08:02 +1100 Subject: [PATCH 3/6] build: fix publish working directory --- .github/workflows/release.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 647cf5c..4c116ec 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -18,5 +18,6 @@ jobs: - run: pnpm version ${{ github.ref_name }} - run: pnpm run build - run: pnpm publish --access public + working-directory: dist env: NPM_TOKEN: ${{ secrets.HTSGET_RS_DEPLOY_PUBLISH_TOKEN }} From 28d2196b3455fdac52b71e506ee5a56a2b4951ad Mon Sep 17 00:00:00 2001 From: Marko Malenic Date: Fri, 6 Dec 2024 12:13:27 +1100 Subject: [PATCH 4/6] build: add packageManager field --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 6e4ae04..5b2c065 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "dist" ], "name": "htsget-lambda", + "packageManager": "pnpm@9.14.0", "scripts": { "build": "tsc", "cdk": "cdk", From 24f010311693ac4b4857838ce2638bd447008435 Mon Sep 17 00:00:00 2001 From: Marko Malenic Date: Fri, 6 Dec 2024 12:14:40 +1100 Subject: [PATCH 5/6] build: remove version set inside github action --- .github/workflows/release.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 4c116ec..061c5b5 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -15,7 +15,6 @@ jobs: node-version: 22 cache: "pnpm" - run: pnpm install - - run: pnpm version ${{ github.ref_name }} - run: pnpm run build - run: pnpm publish --access public working-directory: dist From 3b456e29b509b33426c9cae2dba722d857080ff2 Mon Sep 17 00:00:00 2001 From: Marko Malenic Date: Fri, 6 Dec 2024 13:36:15 +1100 Subject: [PATCH 6/6] fix: update example deploy config --- .github/workflows/release.yaml | 4 +- config/example_deploy.toml | 23 -- package.json | 8 +- pnpm-lock.yaml | 394 ++++++++++----------------------- tsconfig.json | 1 - 5 files changed, 129 insertions(+), 301 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 061c5b5..e694559 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -14,9 +14,9 @@ jobs: with: node-version: 22 cache: "pnpm" + registry-url: "https://registry.npmjs.org" - run: pnpm install - run: pnpm run build - run: pnpm publish --access public - working-directory: dist env: - NPM_TOKEN: ${{ secrets.HTSGET_RS_DEPLOY_PUBLISH_TOKEN }} + NODE_AUTH_TOKEN: ${{ secrets.HTSGET_RS_DEPLOY_PUBLISH_TOKEN }} diff --git a/config/example_deploy.toml b/config/example_deploy.toml index 1320795..6aa8bc2 100644 --- a/config/example_deploy.toml +++ b/config/example_deploy.toml @@ -14,29 +14,6 @@ contact_url = "https://umccr.org/" documentation_url = "https://github.com/umccr/htsget-rs" environment = "dev" -# C4GH prefix indicates Crypt4GH files. -[[resolvers]] -regex = '^(?P.*?)/(?Pc4gh/.*)$' -substitution_string = '$key' -storage.backend = 'S3' - -[resolvers.storage.keys] -location = "SecretsManager" -private_key = "htsget-rs/private-key-c4gh" # pragma: allowlist secret -recipient_public_key = "htsget-rs/recipient-public-key-c4gh" - -# Everything else is a regular file. -[[resolvers]] -regex = '^(?P.*?)/(?Pc4gh/.*)$' -substitution_string = '$key' -storage.backend = 'S3' - -[resolvers.storage.keys] -location = "SecretsManager" -private_key = "htsget-rs/private-key-c4gh" # pragma: allowlist secret -recipient_public_key = "htsget-rs/recipient-public-key-c4gh" - -# Everything else is a regular file. [[resolvers]] regex = '^(?P.*?)/(?Pc4gh/.*)$' substitution_string = '$key' diff --git a/package.json b/package.json index 5b2c065..6a2b628 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ }, "dependencies": { "@iarna/toml": "^3.0.0", - "aws-cdk-lib": "2.162.1", + "aws-cdk-lib": "2.164.1", "cargo-lambda-cdk": "^0.0.31", "constructs": "10.4.2", "glob": "^11.0.0", @@ -17,8 +17,10 @@ "typescript": "5.6.3" }, "files": [ - "dist" + "./**/*.d.ts", + "./**/*.js" ], + "license": "MIT", "name": "htsget-lambda", "packageManager": "pnpm@9.14.0", "scripts": { @@ -28,5 +30,5 @@ "run": "cdk deploy", "watch": "tsc -w" }, - "version": "0.6.0" + "version": "0.6.2" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index de8523f..bee3997 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,21 +1,22 @@ -lockfileVersion: "9.0" +lockfileVersion: '9.0' settings: autoInstallPeers: true excludeLinksFromLockfile: false importers: + .: dependencies: - "@iarna/toml": + '@iarna/toml': specifier: ^3.0.0 version: 3.0.0 aws-cdk-lib: - specifier: 2.162.1 - version: 2.162.1(constructs@10.4.2) + specifier: 2.164.1 + version: 2.164.1(constructs@10.4.2) cargo-lambda-cdk: specifier: ^0.0.31 - version: 0.0.31(aws-cdk-lib@2.162.1(constructs@10.4.2))(constructs@10.4.2) + version: 0.0.31(aws-cdk-lib@2.164.1(constructs@10.4.2))(constructs@10.4.2) constructs: specifier: 10.4.2 version: 10.4.2 @@ -26,7 +27,7 @@ importers: specifier: ^0.5.21 version: 0.5.21 devDependencies: - "@types/node": + '@types/node': specifier: 22.8.4 version: 22.8.4 aws-cdk: @@ -40,90 +41,55 @@ importers: version: 5.6.3 packages: - "@aws-cdk/asset-awscli-v1@2.2.213": - resolution: - { - integrity: sha512-crm1yDJmORJF2Y9gDvNUX4Q3iQXVhWrL7oaZfpx3QDqrvVz5UEgWGpJdysqDuWFZTmIgtrI5Svq3UfdwCNNpsg==, - } - - "@aws-cdk/asset-kubectl-v20@2.1.3": - resolution: - { - integrity: sha512-cDG1w3ieM6eOT9mTefRuTypk95+oyD7P5X/wRltwmYxU7nZc3+076YEVS6vrjDKr3ADYbfn0lDKpfB1FBtO9CQ==, - } - - "@aws-cdk/asset-node-proxy-agent-v6@2.1.0": - resolution: - { - integrity: sha512-7bY3J8GCVxLupn/kNmpPc5VJz8grx+4RKfnnJiO1LG+uxkZfANZG3RMHhE+qQxxwkyQ9/MfPtTpf748UhR425A==, - } - - "@aws-cdk/cloud-assembly-schema@38.0.1": - resolution: - { - integrity: sha512-KvPe+NMWAulfNVwY7jenFhzhuLhLqJ/OPy5jx7wUstbjnYnjRVLpUHPU3yCjXFE0J8cuJVdx95BJ4rOs66Pi9w==, - } + + '@aws-cdk/asset-awscli-v1@2.2.213': + resolution: {integrity: sha512-crm1yDJmORJF2Y9gDvNUX4Q3iQXVhWrL7oaZfpx3QDqrvVz5UEgWGpJdysqDuWFZTmIgtrI5Svq3UfdwCNNpsg==} + + '@aws-cdk/asset-kubectl-v20@2.1.3': + resolution: {integrity: sha512-cDG1w3ieM6eOT9mTefRuTypk95+oyD7P5X/wRltwmYxU7nZc3+076YEVS6vrjDKr3ADYbfn0lDKpfB1FBtO9CQ==} + + '@aws-cdk/asset-node-proxy-agent-v6@2.1.0': + resolution: {integrity: sha512-7bY3J8GCVxLupn/kNmpPc5VJz8grx+4RKfnnJiO1LG+uxkZfANZG3RMHhE+qQxxwkyQ9/MfPtTpf748UhR425A==} + + '@aws-cdk/cloud-assembly-schema@38.0.1': + resolution: {integrity: sha512-KvPe+NMWAulfNVwY7jenFhzhuLhLqJ/OPy5jx7wUstbjnYnjRVLpUHPU3yCjXFE0J8cuJVdx95BJ4rOs66Pi9w==} bundledDependencies: - jsonschema - semver - "@iarna/toml@3.0.0": - resolution: - { - integrity: sha512-td6ZUkz2oS3VeleBcN+m//Q6HlCFCPrnI0FZhrt/h4XqLEdOyYp2u21nd8MdsR+WJy5r9PTDaHTDDfhf4H4l6Q==, - } - - "@isaacs/cliui@8.0.2": - resolution: - { - integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==, - } - engines: { node: ">=12" } - - "@types/node@22.8.4": - resolution: - { - integrity: sha512-SpNNxkftTJOPk0oN+y2bIqurEXHTA2AOZ3EJDDKeJ5VzkvvORSvmQXGQarcOzWV1ac7DCaPBEdMDxBsM+d8jWw==, - } + '@iarna/toml@3.0.0': + resolution: {integrity: sha512-td6ZUkz2oS3VeleBcN+m//Q6HlCFCPrnI0FZhrt/h4XqLEdOyYp2u21nd8MdsR+WJy5r9PTDaHTDDfhf4H4l6Q==} + + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + + '@types/node@22.8.4': + resolution: {integrity: sha512-SpNNxkftTJOPk0oN+y2bIqurEXHTA2AOZ3EJDDKeJ5VzkvvORSvmQXGQarcOzWV1ac7DCaPBEdMDxBsM+d8jWw==} ansi-regex@5.0.1: - resolution: - { - integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} ansi-regex@6.1.0: - resolution: - { - integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==, - } - engines: { node: ">=12" } + resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} + engines: {node: '>=12'} ansi-styles@4.3.0: - resolution: - { - integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} ansi-styles@6.2.1: - resolution: - { - integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==, - } - engines: { node: ">=12" } - - aws-cdk-lib@2.162.1: - resolution: - { - integrity: sha512-XiZLVE5ISNajNNmLye8l5w4EGqm6/d8C8shw63QwxaRVYdHl5e+EAaUEmZJpWc4sYtY/sS+GHOfhoKFLjha2rg==, - } - engines: { node: ">= 14.15.0" } + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + + aws-cdk-lib@2.164.1: + resolution: {integrity: sha512-jNvVmfZJbZoAYU94b5dzTlF2z6JXJ204NgcYY5haOa6mq3m2bzdYPXnPtB5kpAX3oBi++yoRdmLhqgckdEhUZA==} + engines: {node: '>= 14.15.0'} peerDependencies: constructs: ^10.0.0 bundledDependencies: - - "@balena/dockerignore" + - '@balena/dockerignore' - case - fs-extra - ignore @@ -136,36 +102,21 @@ packages: - mime-types aws-cdk@2.164.1: - resolution: - { - integrity: sha512-dWRViQgHLe7GHkPIQGA+8EQSm8TBcxemyCC3HHW3wbLMWUDbspio9Dktmw5EmWxlFjjWh86Dk1JWf1zKQo8C5g==, - } - engines: { node: ">= 14.15.0" } + resolution: {integrity: sha512-dWRViQgHLe7GHkPIQGA+8EQSm8TBcxemyCC3HHW3wbLMWUDbspio9Dktmw5EmWxlFjjWh86Dk1JWf1zKQo8C5g==} + engines: {node: '>= 14.15.0'} hasBin: true balanced-match@1.0.2: - resolution: - { - integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==, - } + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} brace-expansion@2.0.1: - resolution: - { - integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==, - } + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} buffer-from@1.1.2: - resolution: - { - integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==, - } + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} cargo-lambda-cdk@0.0.31: - resolution: - { - integrity: sha512-DUHRl9VVLlMagHsgDLjJWXOWzEWTGQQ3FzVLHuJRDXAL5wOAtaEDvemwcAuCi4swmkA6FoyN3Z8P5lPs4a5EVw==, - } + resolution: {integrity: sha512-DUHRl9VVLlMagHsgDLjJWXOWzEWTGQQ3FzVLHuJRDXAL5wOAtaEDvemwcAuCi4swmkA6FoyN3Z8P5lPs4a5EVw==} peerDependencies: aws-cdk-lib: ^2.63.0 constructs: ^10.0.5 @@ -173,251 +124,150 @@ packages: - js-toml color-convert@2.0.1: - resolution: - { - integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==, - } - engines: { node: ">=7.0.0" } + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} color-name@1.1.4: - resolution: - { - integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==, - } + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} constructs@10.4.2: - resolution: - { - integrity: sha512-wsNxBlAott2qg8Zv87q3eYZYgheb9lchtBfjHzzLHtXbttwSrHPs1NNQbBrmbb1YZvYg2+Vh0Dor76w4mFxJkA==, - } + resolution: {integrity: sha512-wsNxBlAott2qg8Zv87q3eYZYgheb9lchtBfjHzzLHtXbttwSrHPs1NNQbBrmbb1YZvYg2+Vh0Dor76w4mFxJkA==} cross-spawn@7.0.6: - resolution: - { - integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==, - } - engines: { node: ">= 8" } + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} eastasianwidth@0.2.0: - resolution: - { - integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==, - } + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} emoji-regex@8.0.0: - resolution: - { - integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==, - } + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} emoji-regex@9.2.2: - resolution: - { - integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==, - } + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} foreground-child@3.3.0: - resolution: - { - integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==, - } - engines: { node: ">=14" } + resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==} + engines: {node: '>=14'} fsevents@2.3.2: - resolution: - { - integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==, - } - engines: { node: ^8.16.0 || ^10.6.0 || >=11.0.0 } + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] glob@11.0.0: - resolution: - { - integrity: sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==, - } - engines: { node: 20 || >=22 } + resolution: {integrity: sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==} + engines: {node: 20 || >=22} hasBin: true is-fullwidth-code-point@3.0.0: - resolution: - { - integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} isexe@2.0.0: - resolution: - { - integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==, - } + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} jackspeak@4.0.2: - resolution: - { - integrity: sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==, - } - engines: { node: 20 || >=22 } + resolution: {integrity: sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==} + engines: {node: 20 || >=22} lru-cache@11.0.2: - resolution: - { - integrity: sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA==, - } - engines: { node: 20 || >=22 } + resolution: {integrity: sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA==} + engines: {node: 20 || >=22} minimatch@10.0.1: - resolution: - { - integrity: sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==, - } - engines: { node: 20 || >=22 } + resolution: {integrity: sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==} + engines: {node: 20 || >=22} minipass@7.1.2: - resolution: - { - integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==, - } - engines: { node: ">=16 || 14 >=14.17" } + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + engines: {node: '>=16 || 14 >=14.17'} package-json-from-dist@1.0.1: - resolution: - { - integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==, - } + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} path-key@3.1.1: - resolution: - { - integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} path-scurry@2.0.0: - resolution: - { - integrity: sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==, - } - engines: { node: 20 || >=22 } + resolution: {integrity: sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==} + engines: {node: 20 || >=22} prettier@3.4.2: - resolution: - { - integrity: sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==, - } - engines: { node: ">=14" } + resolution: {integrity: sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==} + engines: {node: '>=14'} hasBin: true shebang-command@2.0.0: - resolution: - { - integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} shebang-regex@3.0.0: - resolution: - { - integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} signal-exit@4.1.0: - resolution: - { - integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==, - } - engines: { node: ">=14" } + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} source-map-support@0.5.21: - resolution: - { - integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==, - } + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} source-map@0.6.1: - resolution: - { - integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} string-width@4.2.3: - resolution: - { - integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} string-width@5.1.2: - resolution: - { - integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==, - } - engines: { node: ">=12" } + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} strip-ansi@6.0.1: - resolution: - { - integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} strip-ansi@7.1.0: - resolution: - { - integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==, - } - engines: { node: ">=12" } + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} typescript@5.6.3: - resolution: - { - integrity: sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==, - } - engines: { node: ">=14.17" } + resolution: {integrity: sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==} + engines: {node: '>=14.17'} hasBin: true undici-types@6.19.8: - resolution: - { - integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==, - } + resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} which@2.0.2: - resolution: - { - integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==, - } - engines: { node: ">= 8" } + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} hasBin: true wrap-ansi@7.0.0: - resolution: - { - integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} wrap-ansi@8.1.0: - resolution: - { - integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==, - } - engines: { node: ">=12" } + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} snapshots: - "@aws-cdk/asset-awscli-v1@2.2.213": {} - "@aws-cdk/asset-kubectl-v20@2.1.3": {} + '@aws-cdk/asset-awscli-v1@2.2.213': {} + + '@aws-cdk/asset-kubectl-v20@2.1.3': {} - "@aws-cdk/asset-node-proxy-agent-v6@2.1.0": {} + '@aws-cdk/asset-node-proxy-agent-v6@2.1.0': {} - "@aws-cdk/cloud-assembly-schema@38.0.1": {} + '@aws-cdk/cloud-assembly-schema@38.0.1': {} - "@iarna/toml@3.0.0": {} + '@iarna/toml@3.0.0': {} - "@isaacs/cliui@8.0.2": + '@isaacs/cliui@8.0.2': dependencies: string-width: 5.1.2 string-width-cjs: string-width@4.2.3 @@ -426,7 +276,7 @@ snapshots: wrap-ansi: 8.1.0 wrap-ansi-cjs: wrap-ansi@7.0.0 - "@types/node@22.8.4": + '@types/node@22.8.4': dependencies: undici-types: 6.19.8 @@ -440,12 +290,12 @@ snapshots: ansi-styles@6.2.1: {} - aws-cdk-lib@2.162.1(constructs@10.4.2): + aws-cdk-lib@2.164.1(constructs@10.4.2): dependencies: - "@aws-cdk/asset-awscli-v1": 2.2.213 - "@aws-cdk/asset-kubectl-v20": 2.1.3 - "@aws-cdk/asset-node-proxy-agent-v6": 2.1.0 - "@aws-cdk/cloud-assembly-schema": 38.0.1 + '@aws-cdk/asset-awscli-v1': 2.2.213 + '@aws-cdk/asset-kubectl-v20': 2.1.3 + '@aws-cdk/asset-node-proxy-agent-v6': 2.1.0 + '@aws-cdk/cloud-assembly-schema': 38.0.1 constructs: 10.4.2 aws-cdk@2.164.1: @@ -460,9 +310,9 @@ snapshots: buffer-from@1.1.2: {} - cargo-lambda-cdk@0.0.31(aws-cdk-lib@2.162.1(constructs@10.4.2))(constructs@10.4.2): + cargo-lambda-cdk@0.0.31(aws-cdk-lib@2.164.1(constructs@10.4.2))(constructs@10.4.2): dependencies: - aws-cdk-lib: 2.162.1(constructs@10.4.2) + aws-cdk-lib: 2.164.1(constructs@10.4.2) constructs: 10.4.2 color-convert@2.0.1: @@ -508,7 +358,7 @@ snapshots: jackspeak@4.0.2: dependencies: - "@isaacs/cliui": 8.0.2 + '@isaacs/cliui': 8.0.2 lru-cache@11.0.2: {} diff --git a/tsconfig.json b/tsconfig.json index 9813f30..4c6665f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -16,7 +16,6 @@ "noImplicitThis": true, "noUnusedLocals": false, "noUnusedParameters": false, - "outDir": "dist", "strict": true, "strictNullChecks": true, "strictPropertyInitialization": false,