diff --git a/.gitignore b/.gitignore index 83e9d32a6..2e7a8d686 100644 --- a/.gitignore +++ b/.gitignore @@ -55,7 +55,11 @@ data/ Brewfile.lock.json *.xml -target/ - .coverage htmlcov/ + +# Filemanager-specific +.sqlx +target/ +lib/workload/stateful/filemanager/volume +skel/rust-api/Cargo.lock diff --git a/.vscode/settings.json b/.vscode/settings.json index c116f2d07..40105014c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,6 @@ { "rust-analyzer.linkedProjects": [ - "lib/workload/stateful/filemanager/Cargo.toml", + "lib/workload/stateless/stacks/filemanager/Cargo.toml", "skel/rust-api/Cargo.toml" ] } diff --git a/config/stacks/fileManager.ts b/config/stacks/fileManager.ts index 5a6d96e47..f85431ebf 100644 --- a/config/stacks/fileManager.ts +++ b/config/stacks/fileManager.ts @@ -1,4 +1,4 @@ -import { FilemanagerConfig } from '../../lib/workload/stateless/stacks/filemanager/deploy/lib/filemanager'; +import { FilemanagerConfig } from '../../lib/workload/stateless/stacks/filemanager/deploy/stack'; import { AccountName, computeSecurityGroupName, @@ -9,6 +9,9 @@ import { prodBucket, stgBucket, vpcProps, + cognitoPortalAppClientIdParameterName, + cognitoStatusPageAppClientIdParameterName, + cognitoUserPoolIdParameterName, } from '../constants'; export const getFileManagerStackProps = (n: AccountName): FilemanagerConfig => { @@ -19,6 +22,9 @@ export const getFileManagerStackProps = (n: AccountName): FilemanagerConfig => { databaseClusterEndpointHostParameter: dbClusterEndpointHostParameterName, port: databasePort, migrateDatabase: true, + cognitoPortalAppClientIdParameterName: cognitoPortalAppClientIdParameterName, + cognitoStatusPageAppClientIdParameterName: cognitoStatusPageAppClientIdParameterName, + cognitoUserPoolIdParameterName: cognitoUserPoolIdParameterName, }; switch (n) { diff --git a/config/stacks/postgresManager.ts b/config/stacks/postgresManager.ts index ea163e9b4..095a021c6 100644 --- a/config/stacks/postgresManager.ts +++ b/config/stacks/postgresManager.ts @@ -1,5 +1,5 @@ import { Duration } from 'aws-cdk-lib'; -import { FILEMANAGER_SERVICE_NAME } from '../../lib/workload/stateless/stacks/filemanager/deploy/lib/filemanager'; +import { FILEMANAGER_SERVICE_NAME } from '../../lib/workload/stateless/stacks/filemanager/deploy/stack'; import { PostgresManagerStackProps } from '../../lib/workload/stateless/stacks/postgres-manager/deploy/stack'; import { DbAuthType } from '../../lib/workload/stateless/stacks/postgres-manager/function/type'; import { diff --git a/lib/workload/stateless/stacks/sequence-run-manager/deploy/constructs/api-gw/index.ts b/lib/workload/components/api-gateway/index.ts similarity index 54% rename from lib/workload/stateless/stacks/sequence-run-manager/deploy/constructs/api-gw/index.ts rename to lib/workload/components/api-gateway/index.ts index 15a0d55d7..20180cf91 100644 --- a/lib/workload/stateless/stacks/sequence-run-manager/deploy/constructs/api-gw/index.ts +++ b/lib/workload/components/api-gateway/index.ts @@ -1,24 +1,27 @@ import { Construct } from 'constructs'; import { aws_ssm, Duration } from 'aws-cdk-lib'; import { HttpJwtAuthorizer } from 'aws-cdk-lib/aws-apigatewayv2-authorizers'; -import { CorsHttpMethod, HttpApi } from 'aws-cdk-lib/aws-apigatewayv2'; +import { CorsHttpMethod, HttpApi, CfnStage } from 'aws-cdk-lib/aws-apigatewayv2'; import { IStringParameter } from 'aws-cdk-lib/aws-ssm'; +import { LogGroup } from 'aws-cdk-lib/aws-logs'; +import { Role, ServicePrincipal } from 'aws-cdk-lib/aws-iam'; -export interface SRMApiGatewayConstructProps { +export interface ApiGatewayConstructProps { region: string; + apiName: string | undefined; cognitoUserPoolIdParameterName: string; cognitoPortalAppClientIdParameterName: string; cognitoStatusPageAppClientIdParameterName: string; } -export class SRMApiGatewayConstruct extends Construct { +export class ApiGatewayConstruct extends Construct { private readonly _httpApi: HttpApi; - constructor(scope: Construct, id: string, props: SRMApiGatewayConstructProps) { + constructor(scope: Construct, id: string, props: ApiGatewayConstructProps) { super(scope, id); this._httpApi = new HttpApi(this, 'HttpApi', { - apiName: 'OrcaBusAPI-SequenceRunManager', + apiName: 'OrcaBusAPI-' + props.apiName, corsPreflight: { allowHeaders: ['Authorization'], allowMethods: [ @@ -34,12 +37,48 @@ export class SRMApiGatewayConstruct extends Construct { // defaultDomainMapping: ... TODO }); - // TODO Configure access logging. See https://github.com/aws/aws-cdk/issues/11100 + // LogGroups + this.setupAccessLogs(); - // TODO setup cloud map service discovery perhaps + // CloudMap + // this.setupCloudServiceDiscovery() } - private getAuthorizer(props: SRMApiGatewayConstructProps): HttpJwtAuthorizer { + // TODO: https://github.com/aws-samples/aws-cdk-service-discovery-example/tree/main + // private setupCloudServiceDiscovery() { + // } + + // TODO: Taken from https://github.com/aws/aws-cdk/issues/11100#issuecomment-904627081 + // Monitor for higher level CDK construct instead of leveraging CfnStage + private setupAccessLogs() { + const accessLogs = new LogGroup(this, 'OrcaBus-ApiGw-AccessLogs'); + const stage = this.httpApi.defaultStage?.node.defaultChild as CfnStage; + stage.accessLogSettings = { + destinationArn: accessLogs.logGroupArn, + format: JSON.stringify({ + requestId: '$context.requestId', + userAgent: '$context.identity.userAgent', + sourceIp: '$context.identity.sourceIp', + requestTime: '$context.requestTime', + requestTimeEpoch: '$context.requestTimeEpoch', + httpMethod: '$context.httpMethod', + path: '$context.path', + status: '$context.status', + protocol: '$context.protocol', + responseLength: '$context.responseLength', + domainName: '$context.domainName', + }), + }; + + // Allow writing access logs, managed + const role = new Role(this, 'AmazonAPIGatewayPushToCloudWatchLogs', { + assumedBy: new ServicePrincipal('apigateway.amazonaws.com'), + }); + + accessLogs.grantWrite(role); + } + + private getAuthorizer(props: ApiGatewayConstructProps): HttpJwtAuthorizer { /** * FIXME One fine day in future when we have proper Cognito AAI setup. * For the moment, we leverage Portal and established Cognito infrastructure. diff --git a/lib/workload/stateless/stacks/filemanager/Cargo.lock b/lib/workload/stateless/stacks/filemanager/Cargo.lock index b16ac8605..20c4a8639 100644 --- a/lib/workload/stateless/stacks/filemanager/Cargo.lock +++ b/lib/workload/stateless/stacks/filemanager/Cargo.lock @@ -41,9 +41,9 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.16" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" [[package]] name = "android-tzdata" @@ -85,18 +85,18 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] name = "async-trait" -version = "0.1.79" +version = "0.1.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507401cad91ec6a857ed5513a2073c82a9b9048762b885bb98655b306964681" +checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -122,9 +122,9 @@ checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" [[package]] name = "aws-config" -version = "1.1.9" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "297b64446175a73987cedc3c438d79b2a654d0fff96f65ff530fbe039347644c" +checksum = "e2a89e0000cde82447155d64eeb71720b933b4396a6fbbebad3f8b4f88ca7b54" dependencies = [ "aws-credential-types", "aws-runtime", @@ -153,9 +153,9 @@ dependencies = [ [[package]] name = "aws-credential-types" -version = "1.1.8" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa8587ae17c8e967e4b05a62d495be2fb7701bec52a97f7acfe8a29f938384c8" +checksum = "e16838e6c9e12125face1c1eff1343c75e3ff540de98ff7ebd61874a89bcfeb9" dependencies = [ "aws-smithy-async", "aws-smithy-runtime-api", @@ -165,9 +165,9 @@ dependencies = [ [[package]] name = "aws-runtime" -version = "1.1.8" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b13dc54b4b49f8288532334bba8f87386a40571c47c37b1304979b556dc613c8" +checksum = "f4963ac9ff2d33a4231b3806c1c69f578f221a9cabb89ad2bde62ce2b442c8a7" dependencies = [ "aws-credential-types", "aws-sigv4", @@ -189,9 +189,9 @@ dependencies = [ [[package]] name = "aws-sdk-s3" -version = "1.21.0" +version = "1.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc075ffee2a40cb1590bed35d7ec953589a564e768fa91947c565425cd569269" +checksum = "4576ae7eb91e4d0ca76a3b443c3be979322fc01836cad7908534ae507fa41d99" dependencies = [ "ahash", "aws-credential-types", @@ -224,9 +224,9 @@ dependencies = [ [[package]] name = "aws-sdk-sqs" -version = "1.18.0" +version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaacad4846908c0ff49edf57136ab10b58b177739897a502fe007db7a2025af2" +checksum = "58db01650d3be6d83a5cfb921b61e8cf20c3953d501caa71dd68884877d440ce" dependencies = [ "aws-credential-types", "aws-runtime", @@ -246,9 +246,9 @@ dependencies = [ [[package]] name = "aws-sdk-sso" -version = "1.18.0" +version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "019a07902c43b03167ea5df0182f0cb63fae89f9a9682c44d18cf2e4a042cb34" +checksum = "32fcc572fd5c58489ec205ec3e4e5f7d63018898a485cbf922a462af496bc300" dependencies = [ "aws-credential-types", "aws-runtime", @@ -268,9 +268,9 @@ dependencies = [ [[package]] name = "aws-sdk-ssooidc" -version = "1.18.0" +version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04c46ee08a48a7f4eaa4ad201dcc1dd537b49c50859d14d4510e00ad9d3f9af2" +checksum = "5b6275fa8684a1192754221173b1f7a7c1260d6b0571cc2b8af09468eb0cffe5" dependencies = [ "aws-credential-types", "aws-runtime", @@ -290,9 +290,9 @@ dependencies = [ [[package]] name = "aws-sdk-sts" -version = "1.18.0" +version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f752ac730125ca6017f72f9db5ec1772c9ecc664f87aa7507a7d81b023c23713" +checksum = "30acd58272fd567e4853c5075d838be1626b59057e0249c9be5a1a7eb13bf70f" dependencies = [ "aws-credential-types", "aws-runtime", @@ -425,9 +425,9 @@ dependencies = [ [[package]] name = "aws-smithy-runtime" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c53572b4cd934ee5e8461ad53caa36e9d246aaef42166e3ac539e206a925d330" +checksum = "de34bcfa1fb3c82a80e252a753db34a6658e07f23d3a5b3fc96919518fa7a3f5" dependencies = [ "aws-smithy-async", "aws-smithy-http", @@ -451,9 +451,9 @@ dependencies = [ [[package]] name = "aws-smithy-runtime-api" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccb2b3a7030dc9a3c9a08ce0b25decea5130e9db19619d4dffbbff34f75fe850" +checksum = "4cc56a5c96ec741de6c5e6bf1ce6948be969d6506dfa9c39cffc284e31e4979b" dependencies = [ "aws-smithy-async", "aws-smithy-types", @@ -503,9 +503,9 @@ dependencies = [ [[package]] name = "aws-types" -version = "1.1.8" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dbf2f3da841a8930f159163175cf6a3d16ddde517c1b0fba7aa776822800f40" +checksum = "5a43b56df2c529fe44cb4d92bd64d0479883fb9608ff62daede4df5405381814" dependencies = [ "aws-credential-types", "aws-smithy-async", @@ -605,9 +605,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.15.4" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "byteorder" @@ -636,9 +636,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.91" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd97381a8cc6493395a5afc4c691c1084b3768db713b73aa215217aa245d153" +checksum = "17f6e324229dc011159fcc089755d1e2e216a90d43a7dea6853ca740b84f35e7" [[package]] name = "cfg-if" @@ -648,9 +648,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.37" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a0d04d43504c61aa6c7531f1871dd0d418d91130162063b789da00fd7057a5e" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", @@ -658,7 +658,7 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-targets 0.52.4", + "windows-targets 0.52.5", ] [[package]] @@ -694,9 +694,9 @@ dependencies = [ [[package]] name = "crc" -version = "3.2.0" +version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2b432c56615136f8dba245fed7ec3d5518c500a31108661067e61e72fe7e6bc" +checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" dependencies = [ "crc-catalog", ] @@ -793,7 +793,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -804,7 +804,7 @@ checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" dependencies = [ "darling_core", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -876,9 +876,9 @@ dependencies = [ [[package]] name = "either" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" +checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" dependencies = [ "serde", ] @@ -905,9 +905,9 @@ dependencies = [ [[package]] name = "encoding_rs" -version = "0.8.33" +version = "0.8.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" dependencies = [ "cfg-if", ] @@ -992,6 +992,10 @@ dependencies = [ "uuid", ] +[[package]] +name = "filemanager-api" +version = "0.1.0" + [[package]] name = "filemanager-http-lambda" version = "0.1.0" @@ -1142,7 +1146,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -1363,9 +1367,9 @@ dependencies = [ [[package]] name = "http-serde" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fb7239a6d49eda628c2dfdd7e982c59b0c3f0fb99ce45c4237f02a520030688" +checksum = "1133cafcce27ea69d35e56b3a8772e265633e04de73c5f4e1afdffc1d19b5419" dependencies = [ "http 1.1.0", "serde", @@ -1409,9 +1413,9 @@ dependencies = [ [[package]] name = "hyper" -version = "1.2.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "186548d73ac615b32a73aafe38fb4f56c0d340e110e5a200bcadbaf2e199263a" +checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" dependencies = [ "bytes", "futures-channel", @@ -1453,7 +1457,7 @@ dependencies = [ "futures-util", "http 1.1.0", "http-body 1.0.0", - "hyper 1.2.0", + "hyper 1.3.1", "pin-project-lite", "socket2", "tokio", @@ -1562,7 +1566,7 @@ dependencies = [ "http 1.1.0", "http-body 1.0.0", "http-body-util", - "hyper 1.2.0", + "hyper 1.3.1", "lambda_runtime", "mime", "percent-encoding", @@ -1588,7 +1592,7 @@ dependencies = [ "http-body 1.0.0", "http-body-util", "http-serde", - "hyper 1.2.0", + "hyper 1.3.1", "hyper-util", "lambda_runtime_api_client", "pin-project", @@ -1614,7 +1618,7 @@ dependencies = [ "http 1.1.0", "http-body 1.0.0", "http-body-util", - "hyper 1.2.0", + "hyper 1.3.1", "hyper-util", "tokio", "tower", @@ -1767,7 +1771,7 @@ dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -1779,7 +1783,7 @@ dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -1954,7 +1958,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -2046,9 +2050,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.79" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" +checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" dependencies = [ "unicode-ident", ] @@ -2066,9 +2070,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.35" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -2355,22 +2359,22 @@ checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" [[package]] name = "serde" -version = "1.0.197" +version = "1.0.198" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +checksum = "9846a40c979031340571da2545a4e5b7c4163bdae79b301d5f86d03979451fcc" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.197" +version = "1.0.198" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -2385,9 +2389,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.115" +version = "1.0.116" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" +checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" dependencies = [ "itoa", "ryu", @@ -2443,7 +2447,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -2818,9 +2822,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.58" +version = "2.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687" +checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" dependencies = [ "proc-macro2", "quote", @@ -2862,7 +2866,7 @@ checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -2877,9 +2881,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.34" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", "itoa", @@ -2898,9 +2902,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" dependencies = [ "num-conv", "time-core", @@ -2947,7 +2951,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -3033,7 +3037,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -3218,7 +3222,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", "wasm-bindgen-shared", ] @@ -3240,7 +3244,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3273,7 +3277,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.4", + "windows-targets 0.52.5", ] [[package]] @@ -3291,7 +3295,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.4", + "windows-targets 0.52.5", ] [[package]] @@ -3311,17 +3315,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" dependencies = [ - "windows_aarch64_gnullvm 0.52.4", - "windows_aarch64_msvc 0.52.4", - "windows_i686_gnu 0.52.4", - "windows_i686_msvc 0.52.4", - "windows_x86_64_gnu 0.52.4", - "windows_x86_64_gnullvm 0.52.4", - "windows_x86_64_msvc 0.52.4", + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", ] [[package]] @@ -3332,9 +3337,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" [[package]] name = "windows_aarch64_msvc" @@ -3344,9 +3349,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" [[package]] name = "windows_i686_gnu" @@ -3356,9 +3361,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.4" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" [[package]] name = "windows_i686_msvc" @@ -3368,9 +3379,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" [[package]] name = "windows_x86_64_gnu" @@ -3380,9 +3391,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" [[package]] name = "windows_x86_64_gnullvm" @@ -3392,9 +3403,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" [[package]] name = "windows_x86_64_msvc" @@ -3404,9 +3415,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" [[package]] name = "xmlparser" @@ -3431,7 +3442,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] diff --git a/lib/workload/stateless/stacks/filemanager/Cargo.toml b/lib/workload/stateless/stacks/filemanager/Cargo.toml index fe3f40e58..ba6ce0c50 100644 --- a/lib/workload/stateless/stacks/filemanager/Cargo.toml +++ b/lib/workload/stateless/stacks/filemanager/Cargo.toml @@ -3,6 +3,7 @@ resolver = "2" members = [ "filemanager", + "filemanager-api", "filemanager-http-lambda", "filemanager-ingest-lambda", "filemanager-migrate-lambda" diff --git a/lib/workload/stateless/stacks/filemanager/README.md b/lib/workload/stateless/stacks/filemanager/README.md index 6a2566da0..7114cbfce 100644 --- a/lib/workload/stateless/stacks/filemanager/README.md +++ b/lib/workload/stateless/stacks/filemanager/README.md @@ -32,12 +32,6 @@ from an `.env` file. E.g. see [`.env.example`][env-example]. For development of the rust workspace, it's recommended to install a build cache (sccache) to improve compilation speeds: -```sh -brew install sccache && export RUSTC_WRAPPER=`which sccache` -``` - -or - ```sh cargo install sccache && export RUSTC_WRAPPER=`which sccache` ``` diff --git a/lib/workload/stateless/stacks/filemanager/compose.yml b/lib/workload/stateless/stacks/filemanager/compose.yml index 34177cfc6..9841a8a1b 100644 --- a/lib/workload/stateless/stacks/filemanager/compose.yml +++ b/lib/workload/stateless/stacks/filemanager/compose.yml @@ -1,5 +1,3 @@ -version: '3.1' - services: postgres: build: database diff --git a/lib/workload/stateless/stacks/filemanager/database/queries/api/select_object_ids.sql b/lib/workload/stateless/stacks/filemanager/database/queries/api/select_object_ids.sql new file mode 100644 index 000000000..819bb0c0b --- /dev/null +++ b/lib/workload/stateless/stacks/filemanager/database/queries/api/select_object_ids.sql @@ -0,0 +1,3 @@ +-- Select all objects that meet regexp criteria +-- FIXME: Should not trust user input, should be a bit more robust than like/similar to +select from s3_object where key like $1; \ No newline at end of file diff --git a/lib/workload/stateless/stacks/filemanager/deploy/constructs/functions/function.ts b/lib/workload/stateless/stacks/filemanager/deploy/constructs/functions/function.ts index bf8ce0f37..cc1f5c470 100644 --- a/lib/workload/stateless/stacks/filemanager/deploy/constructs/functions/function.ts +++ b/lib/workload/stateless/stacks/filemanager/deploy/constructs/functions/function.ts @@ -9,7 +9,7 @@ import { exec } from 'cargo-lambda-cdk/lib/util'; import { randomUUID } from 'node:crypto'; import { print } from 'aws-cdk/lib/logging'; import { PostgresManagerStack } from '../../../../postgres-manager/deploy/stack'; -import { FILEMANAGER_SERVICE_NAME } from '../../lib/filemanager'; +import { FILEMANAGER_SERVICE_NAME } from '../../stack'; /** * Properties for the database. @@ -129,7 +129,7 @@ export class Function extends Construct { functionName: props.functionName, }); - // Todo this should probably connect to an RDS proxy rather than directly to the database. + // TODO: this should probably connect to an RDS proxy rather than directly to the database. } /** diff --git a/lib/workload/stateless/stacks/filemanager/deploy/constructs/functions/query.ts b/lib/workload/stateless/stacks/filemanager/deploy/constructs/functions/query.ts new file mode 100644 index 000000000..9d3ae056c --- /dev/null +++ b/lib/workload/stateless/stacks/filemanager/deploy/constructs/functions/query.ts @@ -0,0 +1,17 @@ +import { Construct } from 'constructs'; +import * as fn from './function'; +import { DatabaseProps } from './function'; + +/** + * Props for the (objects) query function. + */ +export type ObjectsQueryFunctionProps = fn.FunctionPropsNoPackage & DatabaseProps; + +/** + * A construct for the Lambda query function. + */ +export class QueryFunction extends fn.Function { + constructor(scope: Construct, id: string, props: ObjectsQueryFunctionProps) { + super(scope, id, { package: 'filemanager-api', ...props }); + } +} diff --git a/lib/workload/stateless/stacks/filemanager/deploy/lib/filemanager.ts b/lib/workload/stateless/stacks/filemanager/deploy/lib/filemanager.ts deleted file mode 100644 index a8ebb6903..000000000 --- a/lib/workload/stateless/stacks/filemanager/deploy/lib/filemanager.ts +++ /dev/null @@ -1,104 +0,0 @@ -import { Construct } from 'constructs'; -import { IngestFunction } from '../constructs/functions/ingest'; -import { MigrateFunction } from '../constructs/functions/migrate'; -import { DatabaseProps } from '../constructs/functions/function'; -import { Vpc, SecurityGroup, VpcLookupOptions } from 'aws-cdk-lib/aws-ec2'; -import { Arn, Stack, StackProps } from 'aws-cdk-lib'; -import { StringParameter } from 'aws-cdk-lib/aws-ssm'; -import { ProviderFunction } from '../../../../../components/provider-function'; -import { Queue } from 'aws-cdk-lib/aws-sqs'; - -export const FILEMANAGER_SERVICE_NAME = 'filemanager'; - -/** - * Stateful config for filemanager. - */ -export type FilemanagerConfig = Omit & { - /** - * Queue name used by the EventSource construct. - */ - eventSourceQueueName: string; - /** - * Buckets defined by the EventSource construct. - */ - eventSourceBuckets: string[]; - /** - * The parameter name that contains the database cluster endpoint. - */ - databaseClusterEndpointHostParameter: string; - /** - * The parameter name that contains the database cluster endpoint. - */ - vpcProps: VpcLookupOptions; - /** - * Whether to initialize a database migration. - */ - migrateDatabase?: boolean; - /** - * The security group name to be attached to lambdas. - */ - securityGroupName: string; -} - -/** - * Props for the filemanager stack. - */ -export type FilemanagerProps = StackProps & FilemanagerConfig; - -/** - * Construct used to configure the filemanager. - */ -export class Filemanager extends Stack { - constructor(scope: Construct, id: string, props: FilemanagerProps) { - super(scope, id, props); - - const vpc = Vpc.fromLookup(this, 'MainVpc', props.vpcProps); - - const lambdaSecurityGroup = SecurityGroup.fromLookupByName( - this, - 'OrcaBusLambdaSecurityGroup', - props.securityGroupName, - vpc - ); - - const host = StringParameter.valueForStringParameter( - this, - props.databaseClusterEndpointHostParameter - ); - - if (props?.migrateDatabase) { - const migrateFunction = new MigrateFunction(this, 'MigrateFunction', { - vpc: vpc, - host: host, - port: props.port, - securityGroup: lambdaSecurityGroup, - }); - - new ProviderFunction(this, 'MigrateProviderFunction', { - vpc: vpc, - function: migrateFunction.function, - }); - } - - const queue = Queue.fromQueueArn( - this, - 'FilemanagerQueue', - Arn.format( - { - resource: props.eventSourceQueueName, - service: 'sqs', - }, - this - ) - ); - - new IngestFunction(this, 'IngestLambda', { - vpc: vpc, - host: host, - port: props.port, - securityGroup: lambdaSecurityGroup, - eventSources: [queue], - buckets: props.eventSourceBuckets, - }); - } -} diff --git a/lib/workload/stateless/stacks/filemanager/deploy/stack.ts b/lib/workload/stateless/stacks/filemanager/deploy/stack.ts new file mode 100644 index 000000000..6b679d3e0 --- /dev/null +++ b/lib/workload/stateless/stacks/filemanager/deploy/stack.ts @@ -0,0 +1,130 @@ +import { Construct } from 'constructs'; +import { IngestFunction } from './constructs/functions/ingest'; +import { MigrateFunction } from './constructs/functions/migrate'; +import { QueryFunction } from './constructs/functions/query'; +import { DatabaseProps } from './constructs/functions/function'; +import { Vpc, SecurityGroup, VpcLookupOptions, IVpc, ISecurityGroup } from 'aws-cdk-lib/aws-ec2'; +import { Arn, Stack, StackProps } from 'aws-cdk-lib'; +import { StringParameter } from 'aws-cdk-lib/aws-ssm'; +import { ProviderFunction } from '../../../../components/provider-function'; +import { ApiGatewayConstruct } from '../../../../components/api-gateway'; +import { IQueue, Queue } from 'aws-cdk-lib/aws-sqs'; +import { HttpMethod, HttpRoute, HttpRouteKey } from 'aws-cdk-lib/aws-apigatewayv2'; +import { HttpLambdaIntegration } from 'aws-cdk-lib/aws-apigatewayv2-integrations'; + +export const FILEMANAGER_SERVICE_NAME = 'filemanager'; + +/** + * Stateful config for filemanager. + */ +export type FilemanagerConfig = Omit & { + eventSourceQueueName: string; + eventSourceBuckets: string[]; + databaseClusterEndpointHostParameter: string; + vpcProps: VpcLookupOptions; + migrateDatabase?: boolean; + securityGroupName: string; + cognitoUserPoolIdParameterName: string; + cognitoPortalAppClientIdParameterName: string; + cognitoStatusPageAppClientIdParameterName: string; +} + +/** + * Props for the filemanager stack. + */ +export type FilemanagerProps = StackProps & FilemanagerConfig; + +/** + * Construct used to configure the filemanager. + */ +export class Filemanager extends Stack { + private readonly vpc: IVpc; + private readonly host: string; + private readonly securityGroup: ISecurityGroup; + private readonly queue: IQueue; + + constructor(scope: Construct, id: string, props: FilemanagerProps) { + super(scope, id, props); + + this.vpc = Vpc.fromLookup(this, 'MainVpc', props.vpcProps); + + this.securityGroup = SecurityGroup.fromLookupByName( + this, + 'OrcaBusLambdaSecurityGroup', + props.securityGroupName, + this.vpc + ); + + this.host = StringParameter.valueForStringParameter( + this, + props.databaseClusterEndpointHostParameter + ); + + if (props?.migrateDatabase) { + const migrateFunction = new MigrateFunction(this, 'MigrateFunction', { + vpc: this.vpc, + host: this.host, + port: props.port, + securityGroup: this.securityGroup, + }); + + new ProviderFunction(this, 'MigrateProviderFunction', { + vpc: this.vpc, + function: migrateFunction.function, + }); + } + + this.queue = Queue.fromQueueArn( + this, + 'FilemanagerQueue', + Arn.format( + { + resource: props.eventSourceQueueName, + service: 'sqs', + }, + this + ) + ); + + this.createIngestFunction(props); + this.createQueryFunction(props); + } + + /// Lambda function definitions and surrounding infra + // Ingest function + private createIngestFunction(props: FilemanagerProps) { + return new IngestFunction(this, 'IngestFunction', { + vpc: this.vpc, + host: this.host, + securityGroup: this.securityGroup, + eventSources: [this.queue], + buckets: props.eventSourceBuckets, + ...props + }); + } + + // Query function and API Gateway fronting the function + private createQueryFunction(props: FilemanagerProps) { + let objectsQueryLambda = new QueryFunction(this, 'ObjectsQueryFunction', { + vpc: this.vpc, + host: this.host, + securityGroup: this.securityGroup, + ...props + }); + + const ApiGateway = new ApiGatewayConstruct(this, 'ApiGateway', { + region: this.region, + apiName: props.stackName, + ...props, + }); + const httpApi = ApiGateway.httpApi; + + const apiIntegration = new HttpLambdaIntegration('ApiIntegration', objectsQueryLambda.function); + + new HttpRoute(this, 'HttpRoute', { // FIXME: Should not be just proxy but objects/{:id} + httpApi: httpApi, + integration: apiIntegration, + routeKey: HttpRouteKey.with('/{proxy+}', HttpMethod.ANY), + }); + } +} diff --git a/lib/workload/stateless/stacks/filemanager/filemanager-api/Cargo.toml b/lib/workload/stateless/stacks/filemanager/filemanager-api/Cargo.toml new file mode 100644 index 000000000..6ed1c978d --- /dev/null +++ b/lib/workload/stateless/stacks/filemanager/filemanager-api/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "filemanager-api" +version = "0.1.0" +license.workspace = true +edition.workspace = true +authors.workspace = true + +[dependencies] diff --git a/lib/workload/stateless/stacks/filemanager/filemanager-api/src/main.rs b/lib/workload/stateless/stacks/filemanager/filemanager-api/src/main.rs new file mode 100644 index 000000000..e7a11a969 --- /dev/null +++ b/lib/workload/stateless/stacks/filemanager/filemanager-api/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +} diff --git a/lib/workload/stateless/stacks/filemanager/filemanager/src/database/aws/mod.rs b/lib/workload/stateless/stacks/filemanager/filemanager/src/database/aws/mod.rs index 04e760ee0..23e08a600 100644 --- a/lib/workload/stateless/stacks/filemanager/filemanager/src/database/aws/mod.rs +++ b/lib/workload/stateless/stacks/filemanager/filemanager/src/database/aws/mod.rs @@ -1,6 +1,7 @@ //! Database logic for AWS events. //! +pub mod query; pub mod ingester; pub mod credentials; diff --git a/lib/workload/stateless/stacks/filemanager/filemanager/src/database/aws/query.rs b/lib/workload/stateless/stacks/filemanager/filemanager/src/database/aws/query.rs new file mode 100644 index 000000000..238225ddf --- /dev/null +++ b/lib/workload/stateless/stacks/filemanager/filemanager/src/database/aws/query.rs @@ -0,0 +1,46 @@ +use sqlx::{ Row, query_file }; + +use crate::database::Client; +use crate::error::Result; + +/// Query the filemanager via REST interface. +#[derive(Debug)] +pub struct Query<'a> { + client: Client<'a>, +} + +pub struct QueryResults { + _results: Vec, // FIXME: Adjust return type +} + +impl<'a> Query<'a> { + /// Creates a new filemanager query client. + pub fn new(client: Client<'a>) -> Self { + Self { client } + } + + /// Creates a new filemanager query client with default connection settings. + /// -- FIXME: Should not trust user input, should be a bit more robust than like/similar to + pub async fn query_objects(&self, query: String) -> Result { + + let mut tx = self.client.pool().begin().await?; + + let query_results: Vec = query_file!("../database/queries/api/select_object_ids.sql", &query) + .fetch_all(&mut *tx) + .await? + .into_iter() + .map(|row| row.get(0)) + .collect(); + + tx.commit().await?; + + let query_results = QueryResults::new(query_results); // Convert PgQueryResult to QueryResults + Ok(query_results) + } +} + +impl QueryResults { + pub fn new(_results: Vec) -> Self { + Self { _results } + } +} \ No newline at end of file diff --git a/lib/workload/stateless/stacks/metadata-manager/deploy/construct/api-gw/index.ts b/lib/workload/stateless/stacks/metadata-manager/deploy/construct/api-gw/index.ts deleted file mode 100644 index aded5178b..000000000 --- a/lib/workload/stateless/stacks/metadata-manager/deploy/construct/api-gw/index.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { Construct } from 'constructs'; -import { aws_ssm, Duration } from 'aws-cdk-lib'; -import { HttpJwtAuthorizer } from 'aws-cdk-lib/aws-apigatewayv2-authorizers'; -import { CorsHttpMethod, HttpApi } from 'aws-cdk-lib/aws-apigatewayv2'; -import { IStringParameter } from 'aws-cdk-lib/aws-ssm'; - -export class ApiGatewayConstruct extends Construct { - private readonly _httpApi: HttpApi; - - constructor(scope: Construct, id: string) { - super(scope, id); - - this._httpApi = new HttpApi(this, 'HttpApi', { - apiName: 'OrcaBusAPI-MetadataManager', - corsPreflight: { - allowHeaders: ['Authorization'], - allowMethods: [ - CorsHttpMethod.GET, - CorsHttpMethod.HEAD, - CorsHttpMethod.OPTIONS, - CorsHttpMethod.POST, - ], - allowOrigins: ['*'], // FIXME allowed origins from config constant - maxAge: Duration.days(10), - }, - defaultAuthorizer: this.getAuthorizer(id, 'ap-southeast-2'), - // defaultDomainMapping: ... TODO - }); - - // TODO Configure access logging. See https://github.com/aws/aws-cdk/issues/11100 - - // TODO setup cloud map service discovery perhaps - } - - private getAuthorizer(id: string, region: string): HttpJwtAuthorizer { - /** - * FIXME One fine day in future when we have proper Cognito AAI setup. - * For the moment, we leverage Portal and established Cognito infrastructure. - * See https://github.com/umccr/orcabus/issues/102 - */ - - // i.e. JWT from UI client https://status.[dev|stg|prod].umccr.org - const SSM_USER_POOL_ID: string = '/data_portal/client/cog_user_pool_id'; - const SSM_PORTAL_CLIENT_ID: string = '/data_portal/client/data2/cog_app_client_id_stage'; - const SSM_STATUS_PAGE_CLIENT_ID: string = '/data_portal/status_page/cog_app_client_id_stage'; - - const userPoolIdParam: IStringParameter = aws_ssm.StringParameter.fromStringParameterName( - this, - 'CognitoUserPoolIdParameter', - SSM_USER_POOL_ID - ); - const portalClientIdParam: IStringParameter = aws_ssm.StringParameter.fromStringParameterName( - this, - 'CognitoPortalClientIdParameter', - SSM_PORTAL_CLIENT_ID - ); - const statusPageClientIdParam: IStringParameter = - aws_ssm.StringParameter.fromStringParameterName( - this, - 'CognitoStatusPageClientIdParameter', - SSM_STATUS_PAGE_CLIENT_ID - ); - - const issuer = - 'https://cognito-idp.' + region + '.amazonaws.com/' + userPoolIdParam.stringValue; - - return new HttpJwtAuthorizer('PortalAuthorizer', issuer, { - jwtAudience: [portalClientIdParam.stringValue, statusPageClientIdParam.stringValue], - }); - } - - get httpApi(): HttpApi { - return this._httpApi; - } -} diff --git a/lib/workload/stateless/stacks/metadata-manager/deploy/stack.ts b/lib/workload/stateless/stacks/metadata-manager/deploy/stack.ts index 8004c4dfe..1022f2641 100644 --- a/lib/workload/stateless/stacks/metadata-manager/deploy/stack.ts +++ b/lib/workload/stateless/stacks/metadata-manager/deploy/stack.ts @@ -10,7 +10,7 @@ import { Code, Runtime, Architecture, LayerVersion } from 'aws-cdk-lib/aws-lambd import { LambdaSyncGsheetConstruct } from './construct/lambda-sync-gsheet'; import { LambdaMigrationConstruct } from './construct/lambda-migration'; import { LambdaAPIConstruct } from './construct/lambda-api'; -import { ApiGatewayConstruct } from './construct/api-gw'; +import { ApiGatewayConstruct } from '../../../../components/api-gateway'; import { PostgresManagerStack } from '../../postgres-manager/deploy/stack'; export type MetadataManagerStackProps = { @@ -80,11 +80,18 @@ export class MetadataManagerStack extends Stack { // 3. To sync db with external sources (e.g. metadata in gsheet) // (1) - const apiGW = new ApiGatewayConstruct(this, 'APIGW').httpApi; + const apiGW = new ApiGatewayConstruct(this, 'OrcabusAPI-MetadataManager', { + region: this.region, + apiName: 'MetadataManager', + cognitoUserPoolIdParameterName: 'YOUR_USER_POOL_ID_PARAMETER_NAME', + cognitoPortalAppClientIdParameterName: 'YOUR_PORTAL_APP_CLIENT_ID_PARAMETER_NAME', + cognitoStatusPageAppClientIdParameterName: 'YOUR_STATUS_PAGE_APP_CLIENT_ID_PARAMETER_NAME', + ...props, + }); new LambdaAPIConstruct(this, 'APILambda', { basicLambdaConfig: basicLambdaConfig, dbConnectionSecret: dbSecret, - apiGW: apiGW, + apiGW: apiGW.httpApi, }); // (2) diff --git a/lib/workload/stateless/stacks/sequence-run-manager/deploy/README.md b/lib/workload/stateless/stacks/sequence-run-manager/deploy/README.md index 17f5907d7..8d5577fdb 100644 --- a/lib/workload/stateless/stacks/sequence-run-manager/deploy/README.md +++ b/lib/workload/stateless/stacks/sequence-run-manager/deploy/README.md @@ -2,7 +2,7 @@ This directory contains CDK code that will be called and assembled by higher level class such as `lib/workload/stateless/statelessStackCollectionClass.ts`. -Collectively, all CDK constructs created under this `deploy` directory forms as **one deployable stack**. Hence, just single `stack.ts` file might be sufficed if your app deployment is simple. +Collectively, all CDK constructs created under this `deploy` directory forms as **one deployable stack**. Hence, just a single `stack.ts` file should suffice if your app deployment is simple. ## TL;DR diff --git a/lib/workload/stateless/stacks/sequence-run-manager/deploy/stack.ts b/lib/workload/stateless/stacks/sequence-run-manager/deploy/stack.ts index 0a4ec4ee0..3f97ff6aa 100644 --- a/lib/workload/stateless/stacks/sequence-run-manager/deploy/stack.ts +++ b/lib/workload/stateless/stacks/sequence-run-manager/deploy/stack.ts @@ -8,7 +8,7 @@ import { PythonFunction, PythonLayerVersion } from '@aws-cdk/aws-lambda-python-a import { HttpLambdaIntegration } from 'aws-cdk-lib/aws-apigatewayv2-integrations'; import { HttpMethod, HttpRoute, HttpRouteKey } from 'aws-cdk-lib/aws-apigatewayv2'; import { ManagedPolicy, Role, ServicePrincipal } from 'aws-cdk-lib/aws-iam'; -import { SRMApiGatewayConstruct } from './constructs/api-gw'; +import { ApiGatewayConstruct } from '../../../../components/api-gateway'; import { Architecture } from 'aws-cdk-lib/aws-lambda'; import { PostgresManagerStack } from '../../postgres-manager/deploy/stack'; @@ -111,8 +111,9 @@ export class SequenceRunManagerStack extends Stack { timeout: Duration.seconds(28), }); - const srmApi = new SRMApiGatewayConstruct(this, 'SRMApiGatewayConstruct', { + const srmApi = new ApiGatewayConstruct(this, 'ApiGateway', { region: this.region, + apiName: 'SequenceRunManager', ...props, }); const httpApi = srmApi.httpApi; diff --git a/lib/workload/stateless/statelessStackCollectionClass.ts b/lib/workload/stateless/statelessStackCollectionClass.ts index 8f3f8f36d..6c129d98a 100644 --- a/lib/workload/stateless/statelessStackCollectionClass.ts +++ b/lib/workload/stateless/statelessStackCollectionClass.ts @@ -1,7 +1,7 @@ import { Construct } from 'constructs'; import { Stack, Environment, StackProps } from 'aws-cdk-lib'; -import { FilemanagerProps, Filemanager } from './stacks/filemanager/deploy/lib/filemanager'; +import { FilemanagerProps, Filemanager } from './stacks/filemanager/deploy/stack'; import { PostgresManagerStack, PostgresManagerStackProps, diff --git a/openapi/orcabus/filemanager.json b/openapi/orcabus/filemanager.json index a19a2fbf6..31f479503 100644 --- a/openapi/orcabus/filemanager.json +++ b/openapi/orcabus/filemanager.json @@ -1 +1,151 @@ -{"openapi":"3.0.3","info":{"title":"rust-api","description":"","license":{"name":""},"version":"0.1.0"},"paths":{"/file/":{"get":{"tags":["file"],"summary":"Search query","description":"Search query\nSearch files","operationId":"search","parameters":[{"name":"id","in":"query","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"name","in":"query","required":true,"schema":{"type":"string"}},{"name":"size","in":"query","required":true,"schema":{"type":"integer","format":"int64","minimum":0.0}},{"name":"hash","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"List matching objects","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/File"}}}}}}}}},"components":{"schemas":{"File":{"type":"object","description":"Item to do.","required":["id","name","size","hash"],"properties":{"hash":{"type":"string"},"id":{"type":"integer","format":"int32"},"name":{"type":"string","example":"foo.bam"},"size":{"type":"integer","format":"int64","minimum":0.0}}},"FileError":{"oneOf":[{"type":"object","required":["NotFound"],"properties":{"NotFound":{"type":"string","description":"File not found by id."}},"example":"id = 1"},{"type":"object","required":["Unauthorized"],"properties":{"Unauthorized":{"type":"string","description":"File operation unauthorized"}},"example":"missing api key"}],"description":"File operation errors"}},"securitySchemes":{"api_key":{"type":"apiKey","in":"header","name":"File_apikey"}}},"tags":[{"name":"File","description":"File manager API"}]} \ No newline at end of file +{ + "openapi": "3.0.3", + "info": { + "title": "rust-api", + "description": "", + "license": { + "name": "" + }, + "version": "0.1.0" + }, + "paths": { + "/file/": { + "get": { + "tags": [ + "file" + ], + "summary": "Search query", + "description": "Search query\nSearch files", + "operationId": "search", + "parameters": [ + { + "name": "id", + "in": "query", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "name", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "size", + "in": "query", + "required": true, + "schema": { + "type": "integer", + "format": "int64", + "minimum": 0.0 + } + }, + { + "name": "hash", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "List matching objects", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/File" + } + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "File": { + "type": "object", + "description": "Item to do.", + "required": [ + "id", + "name", + "size", + "hash" + ], + "properties": { + "hash": { + "type": "string" + }, + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string", + "example": "foo.bam" + }, + "size": { + "type": "integer", + "format": "int64", + "minimum": 0.0 + } + } + }, + "FileError": { + "oneOf": [ + { + "type": "object", + "required": [ + "NotFound" + ], + "properties": { + "NotFound": { + "type": "string", + "description": "File not found by id." + } + }, + "example": "id = 1" + }, + { + "type": "object", + "required": [ + "Unauthorized" + ], + "properties": { + "Unauthorized": { + "type": "string", + "description": "File operation unauthorized" + } + }, + "example": "missing api key" + } + ], + "description": "File operation errors" + } + }, + "securitySchemes": { + "api_key": { + "type": "apiKey", + "in": "header", + "name": "File_apikey" + } + } + }, + "tags": [ + { + "name": "File", + "description": "File manager API" + } + ] +} \ No newline at end of file