diff --git a/backend/backend/handlers/indexing/streams.py b/backend/backend/handlers/indexing/streams.py index 8682e8ad..f44e0c45 100644 --- a/backend/backend/handlers/indexing/streams.py +++ b/backend/backend/handlers/indexing/streams.py @@ -129,8 +129,14 @@ def from_env(env=os.environ): service = 'aoss' credentials = boto3.Session().get_credentials() auth = AWSV4SignerAuth(credentials, region, service) + ssm = boto3.client('ssm', region_name=region) + param = ssm.get_parameter( + Name=env.get('AOSS_ENDPOINT_PARAM'), + WithDecryption=False + ) + host = param.get("Parameter", {}).get("Value") aosclient = OpenSearch( - hosts=[{'host': urlparse(env.get('AOSS_ENDPOINT')).hostname, 'port': 443}], + hosts=[{'host': urlparse(host).hostname, 'port': 443}], http_auth=auth, use_ssl=True, verify_certs=True, @@ -223,7 +229,15 @@ def from_env(env=os.environ): service = 'aoss' credentials = boto3.Session().get_credentials() auth = AWSV4SignerAuth(credentials, region, service) - return AOSSIndexAssetMetadata(host=env.get('AOSS_ENDPOINT'), region=region, service=service, auth=auth) + + ssm = boto3.client('ssm', region_name=region) + param = ssm.get_parameter( + Name=env.get('AOSS_ENDPOINT_PARAM'), + WithDecryption=False + ) + host = param.get("Parameter", {}).get("Value") + + return AOSSIndexAssetMetadata(host=host, region=region, service=service, auth=auth) @staticmethod diff --git a/backend/backend/handlers/search/search.py b/backend/backend/handlers/search/search.py index 643f5d31..c6e6f03f 100644 --- a/backend/backend/handlers/search/search.py +++ b/backend/backend/handlers/search/search.py @@ -152,8 +152,16 @@ def from_env(env=os.environ): credentials = boto3.Session().get_credentials() auth = AWSV4SignerAuth(credentials, region, service) print(auth) + + ssm = boto3.client('ssm', region_name=region) + param = ssm.get_parameter( + Name=env.get('AOSS_ENDPOINT_PARAM'), + WithDecryption=False + ) + host = param.get("Parameter", {}).get("Value") + return SearchAOSS( - host=env.get('AOSS_ENDPOINT'), + host=host, region=region, service=service, auth=auth diff --git a/infra/lib/constructs/amplify-config-lambda-construct.ts b/infra/lib/constructs/amplify-config-lambda-construct.ts index a803586b..aa0d2cf0 100644 --- a/infra/lib/constructs/amplify-config-lambda-construct.ts +++ b/infra/lib/constructs/amplify-config-lambda-construct.ts @@ -59,6 +59,8 @@ interface InlineLambdaProps { * Additional configuration needed for federated auth */ federatedConfig?: AmplifyConfigFederatedIdentityProps; + + stackName: string; } export interface AmplifyConfigLambdaConstructProps extends cdk.StackProps { @@ -110,6 +112,7 @@ export class AmplifyConfigLambdaConstruct extends Construct { identityPoolId: props.identityPoolId, api: props.api.url || "us-east-1", federatedConfig: props.federatedConfig, + stackName: props.stackName!, }) ), timeout: cdk.Duration.seconds(15), diff --git a/infra/lib/constructs/location-service-construct.ts b/infra/lib/constructs/location-service-construct.ts index 6ec64e0c..7cf16945 100644 --- a/infra/lib/constructs/location-service-construct.ts +++ b/infra/lib/constructs/location-service-construct.ts @@ -4,7 +4,7 @@ */ import * as iam from "aws-cdk-lib/aws-iam"; -import { CfnOutput, aws_location } from "aws-cdk-lib"; +import { CfnOutput, aws_location, Stack } from "aws-cdk-lib"; import { Construct } from "constructs"; @@ -38,13 +38,13 @@ export class LocationServiceConstruct extends Construct { configuration: { style: "RasterEsriImagery", }, - mapName: "vams-map-raster", + mapName: `vams-map-raster-${Stack.of(scope).region}-${Stack.of(scope).stackName}`, }); const cfnMap_streets = new aws_location.CfnMap(scope, "MyCfnMapStreets", { configuration: { style: "VectorEsriStreets", }, - mapName: "vams-map-streets", + mapName: `vams-map-streets-${Stack.of(scope).region}-${Stack.of(scope).stackName}`, }); role.addToPolicy( @@ -60,23 +60,23 @@ export class LocationServiceConstruct extends Construct { }) ); - const cfnIndex = new aws_location.CfnPlaceIndex(scope, "MyCfnPlaceIndex", { - dataSource: "Esri", - indexName: "vams-index", - }); + // const cfnIndex = new aws_location.CfnPlaceIndex(scope, "MyCfnPlaceIndex", { + // dataSource: "Esri", + // indexName: "vams-index", + // }); - role.addToPolicy( - new iam.PolicyStatement({ - effect: iam.Effect.ALLOW, - actions: [ - "geo:SearchPlaceIndexForPosition", - "geo:SearchPlaceIndexForText", - "geo:SearchPlaceIndexForSuggestions", - "geo:GetPlace", - ], - resources: [cfnIndex.attrArn], - }) - ); + // role.addToPolicy( + // new iam.PolicyStatement({ + // effect: iam.Effect.ALLOW, + // actions: [ + // "geo:SearchPlaceIndexForPosition", + // "geo:SearchPlaceIndexForText", + // "geo:SearchPlaceIndexForSuggestions", + // "geo:GetPlace", + // ], + // resources: [cfnIndex.attrArn], + // }) + // ); // make cfn outputs @@ -95,11 +95,11 @@ export class LocationServiceConstruct extends Construct { // description: "Location Service Index Arn", // exportName: "LocationServiceIndexArn", // }); - new CfnOutput(this, "MapArn", { - value: cfnMap.attrArn, - description: "Map Arn", - exportName: "MapArn", - }); + // new CfnOutput(this, "MapArn", { + // value: cfnMap.attrArn, + // description: "Map Arn", + // exportName: "MapArn", + // }); this.map = cfnMap; // this.location = location; diff --git a/infra/lib/lambdaBuilder/metadataFunctions.ts b/infra/lib/lambdaBuilder/metadataFunctions.ts index 59e32366..052ca8e3 100644 --- a/infra/lib/lambdaBuilder/metadataFunctions.ts +++ b/infra/lib/lambdaBuilder/metadataFunctions.ts @@ -8,6 +8,7 @@ import * as path from "path"; import { Construct } from "constructs"; import { Duration } from "aws-cdk-lib"; import { storageResources } from "../storage-builder"; +import * as cdk from "aws-cdk-lib"; export function buildMetadataFunctions( scope: Construct, @@ -57,9 +58,22 @@ export function buildMetadataIndexingFunction( ASSET_STORAGE_TABLE_NAME: storageResources.dynamo.assetStorageTable.tableName, DATABASE_STORAGE_TABLE_NAME: storageResources.dynamo.databaseStorageTable.tableName, ASSET_BUCKET_NAME: storageResources.s3.assetBucket.bucketName, - AOSS_ENDPOINT: aossEndpoint, + AOSS_ENDPOINT_PARAM: aossEndpoint, }, }); + + // add access to read the parameter store param aossEndpoint + fun.role?.addToPrincipalPolicy( + new cdk.aws_iam.PolicyStatement({ + actions: ["ssm:GetParameter"], + resources: [ + `arn:aws:ssm:${cdk.Stack.of(scope).region}:${ + cdk.Stack.of(scope).account + }:parameter${aossEndpoint}`, + ], + }) + ); + storageResources.dynamo.metadataStorageTable.grantReadWriteData(fun); storageResources.dynamo.assetStorageTable.grantReadData(fun); storageResources.dynamo.databaseStorageTable.grantReadData(fun); diff --git a/infra/lib/lambdaBuilder/searchFunctions.ts b/infra/lib/lambdaBuilder/searchFunctions.ts index e849ded9..fbe43141 100644 --- a/infra/lib/lambdaBuilder/searchFunctions.ts +++ b/infra/lib/lambdaBuilder/searchFunctions.ts @@ -9,6 +9,8 @@ import { Construct } from "constructs"; import { Duration } from "aws-cdk-lib"; import { OpensearchServerlessConstruct } from "../constructs/opensearch-serverless"; import { storageResources } from "../storage-builder"; +import { iam } from "cdk-nag/lib/rules"; +import * as cdk from "aws-cdk-lib"; export function buildSearchFunction( scope: Construct, @@ -23,12 +25,24 @@ export function buildSearchFunction( timeout: Duration.minutes(15), memorySize: 3008, environment: { - AOSS_ENDPOINT: aossEndpoint, + AOSS_ENDPOINT_PARAM: aossEndpoint, AUTH_ENTITIES_TABLE: storageResources.dynamo.authEntitiesStorageTable.tableName, DATABASE_STORAGE_TABLE_NAME: storageResources.dynamo.databaseStorageTable.tableName, }, }); + // add access to read the parameter store param aossEndpoint + fun.role?.addToPrincipalPolicy( + new cdk.aws_iam.PolicyStatement({ + actions: ["ssm:GetParameter"], + resources: [ + `arn:aws:ssm:${cdk.Stack.of(scope).region}:${ + cdk.Stack.of(scope).account + }:parameter${aossEndpoint}`, + ], + }) + ); + storageResources.dynamo.authEntitiesStorageTable.grantReadData(fun); storageResources.dynamo.databaseStorageTable.grantReadData(fun); aossConstruct.grantCollectionAccess(fun); diff --git a/infra/lib/streams-builder.ts b/infra/lib/streams-builder.ts index b88acfc9..c002b9b8 100644 --- a/infra/lib/streams-builder.ts +++ b/infra/lib/streams-builder.ts @@ -27,17 +27,12 @@ export function streamsBuilder( principalArn: [], }); - // the ssm parameter store value for the endpoint - const aossParam = ssm.StringParameter.fromStringParameterName( + const indexingFunction = buildMetadataIndexingFunction( scope, - "aossEndpoint", + storage, aoss.endpointSSMParameterName() ); - aossParam.node.addDependency(aoss); - - const indexingFunction = buildMetadataIndexingFunction(scope, storage, aossParam.stringValue); - indexingFunction.addEventSource( new eventsources.DynamoEventSource(storage.dynamo.metadataStorageTable, { startingPosition: lambda.StartingPosition.TRIM_HORIZON, @@ -46,7 +41,7 @@ export function streamsBuilder( aoss.grantCollectionAccess(indexingFunction); - const searchFun = buildSearchFunction(scope, aossParam.stringValue, aoss, storage); + const searchFun = buildSearchFunction(scope, aoss.endpointSSMParameterName(), aoss, storage); attachFunctionToApi(scope, searchFun, { routePath: "/search", method: apigwv2.HttpMethod.POST, diff --git a/web/src/FedAuth/VAMSAuth.tsx b/web/src/FedAuth/VAMSAuth.tsx index d3898ba6..ccf59606 100644 --- a/web/src/FedAuth/VAMSAuth.tsx +++ b/web/src/FedAuth/VAMSAuth.tsx @@ -61,6 +61,8 @@ interface Config { * bucket */ bucket?: string; + + stackName: string; } function configureAmplify(config: Config, setAmpInit: (x: boolean) => void) { @@ -115,20 +117,20 @@ function configureAmplify(config: Config, setAmpInit: (x: boolean) => void) { AmazonLocationService: { maps: { items: { - "vams-map-raster": { + [`vams-map-raster-${config.region}-${config.stackName}`]: { // REQUIRED - Amazon Location Service Map resource name style: "RasterEsriImagery", // REQUIRED - String representing the style of map resource }, - "vams-map-streets": { + [`vams-map-streets-${config.region}-${config.stackName}`]: { style: "VectorEsriStreets", }, }, - default: "vams-map-raster", // REQUIRED - Amazon Location Service Map resource name to set as default - }, - search_indices: { - items: ["vams-index"], // REQUIRED - Amazon Location Service Place Index name - default: "vams-index", // REQUIRED - Amazon Location Service Place Index name to set as default + default: `vams-map-raster-${config.region}-${config.stackName}`, // REQUIRED - Amazon Location Service Map resource name to set as default }, + // search_indices: { + // items: ["vams-index"], // REQUIRED - Amazon Location Service Place Index name + // default: "vams-index", // REQUIRED - Amazon Location Service Place Index name to set as default + // }, // geofenceCollections: { // items: ["XXXXXXXXX", "XXXXXXXXX"], // REQUIRED - Amazon Location Service Geofence Collection name // default: "XXXXXXXXX", // REQUIRED - Amazon Location Service Geofence Collection name to set as default