From 7d3ca2e3442bc4f83fe36edefb29489263f9de85 Mon Sep 17 00:00:00 2001 From: Alex Tarasov Date: Wed, 4 Sep 2024 20:22:38 +0100 Subject: [PATCH] fix:requested review changes --- .../lib/opensearch/opensearch-api-props.ts | 31 ++++++++++-- .../lib/opensearch/opensearch-api.ts | 49 +++++++++++++++++++ .../consumption/lib/opensearch/opensearch.ts | 25 +++++++++- 3 files changed, 100 insertions(+), 5 deletions(-) diff --git a/framework/src/consumption/lib/opensearch/opensearch-api-props.ts b/framework/src/consumption/lib/opensearch/opensearch-api-props.ts index 8fa28ca81..02db52a23 100644 --- a/framework/src/consumption/lib/opensearch/opensearch-api-props.ts +++ b/framework/src/consumption/lib/opensearch/opensearch-api-props.ts @@ -1,8 +1,8 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -import { RemovalPolicy } from 'aws-cdk-lib'; -import { IVpc, SubnetSelection } from 'aws-cdk-lib/aws-ec2'; +import { Duration, RemovalPolicy } from 'aws-cdk-lib'; +import { ISecurityGroup, IVpc, SubnetSelection } from 'aws-cdk-lib/aws-ec2'; import { IRole } from 'aws-cdk-lib/aws-iam'; /** @@ -21,9 +21,9 @@ export interface OpenSearchApiProps { /** * The IAM role to pass to IAM authentication lambda handler * This role must be able to be assumed with `lambda.amazonaws.com` service principal - * @default - new IAMRole is created. + * and have the necessary permissions to call OpenSearch API. */ - readonly iamHandlerRole?: IRole; + readonly iamHandlerRole: IRole; /** * Defines the virtual networking environment for this construct. @@ -40,6 +40,15 @@ export interface OpenSearchApiProps { */ readonly subnets?: SubnetSelection; + /** + * The list of security groups to attach to the lambda functions. + * The security groups MUST be exclusively used by the custom resource. + * @default - If `vpc` is not supplied, no security groups are attached. Otherwise, a dedicated security + * group is created for each function. + */ + + readonly securityGroups?: ISecurityGroup []; + /** * The OpenSearch Cluster or Serverless collection endpoint to connect to. * if you provisoned your cluster using CDK @@ -58,6 +67,20 @@ export interface OpenSearchApiProps { * @default - same region as stack. */ readonly openSearchEndpointRegion? : string; + + /** + * Total timeout for the entire custom resource operation. + * The maximum timeout is 1 hour. @see dsf.utils.DsfProviderProps + * @default Duration.minutes(30) + */ + readonly queryTimeout?: Duration; + + /** + * Time between calls to the `isComplete` handler which determines if the + * resource has been stabilized. @see dsf.utils.DsfProviderProps + * @default Duration.seconds(5) + */ + readonly queryInterval?: Duration; } diff --git a/framework/src/consumption/lib/opensearch/opensearch-api.ts b/framework/src/consumption/lib/opensearch/opensearch-api.ts index 4f3f76e44..4ebccfd8e 100644 --- a/framework/src/consumption/lib/opensearch/opensearch-api.ts +++ b/framework/src/consumption/lib/opensearch/opensearch-api.ts @@ -3,6 +3,10 @@ import * as path from 'path'; import { CustomResource, Stack } from 'aws-cdk-lib'; +import { ISecurityGroup } from 'aws-cdk-lib/aws-ec2'; +import { IRole } from 'aws-cdk-lib/aws-iam'; +import { IFunction } from 'aws-cdk-lib/aws-lambda'; +import { ILogGroup } from 'aws-cdk-lib/aws-logs'; import { Construct } from 'constructs'; import { OpenSearchApiProps } from './opensearch-api-props'; import { Context, TrackedConstruct, TrackedConstructProps } from '../../../utils'; @@ -10,9 +14,45 @@ import { DsfProvider } from '../../../utils/lib/dsf-provider'; /** * A construct to create an OpenSearch API client + * + * @example + * const apiRole = cdk.iam.Role.fromRoleName(this, 'ApiRole', ''); + * const osApi = new dsf.consumption.OpensearchApi(this, 'MyOpenSearchApi',{ + * iamHandlerRole:apiRole, + * openSearchEndpoint:'https://search-XXXXXX.XXXXXX.es.amazonaws.com', + * openSearchClusterType:dsf.consumption.OpenSearchClusterType.PROVISIONED, + * removalPolicy:cdk.RemovalPolicy.DESTROY + * }); + * + * const roleMap = osApi.addRoleMapping('DashBoardUser', 'dashboards_user',''); + * const add1Cr = osApi.callOpenSearchApi('AddData1', 'movies-01/_doc/1111',{"title": "Rush", "year": 2013}, 'PUT'); + * add1Cr.node.addDependency(roleMap); + * const add2Cr = osApi.callOpenSearchApi('AddData3', 'movies-01/_doc/2222',{"title": "Toy Story", "year": 2014}, 'PUT'); + * add2Cr.node.addDependency(roleMap); */ + export class OpenSearchApi extends TrackedConstruct { + /** + * The CloudWatch Log Group for the onEventHandler Lambda Function + */ + public apiLogGroup: ILogGroup; + + /** + * The list of EC2 Security Groups used by the Lambda Functions + */ + public apiSecurityGroups?: ISecurityGroup[]; + + /** + * The Lambda Function used for the onEventHandler + */ + public apiFunction: IFunction; + + /** + * The IAM Role for the onEventHandler Lambba Function + */ + public apiRole: IRole; + /** * Custom resource provider for the OpenSearch API client */ @@ -51,6 +91,8 @@ export class OpenSearchApi extends TrackedConstruct { this.apiProvider = new DsfProvider(this, 'Provider', { providerName: 'opensearchApiProvider', + queryInterval: props.queryInterval ?? undefined, + queryTimeout: props.queryTimeout ?? undefined, onEventHandlerDefinition: { iamRole: props.iamHandlerRole, handler: 'handler', @@ -73,8 +115,15 @@ export class OpenSearchApi extends TrackedConstruct { }, vpc: props.vpc, subnets: props.subnets, + securityGroups: props.securityGroups, removalPolicy: this.removalPolicy, }); + + this.apiLogGroup = this.apiProvider.onEventHandlerLogGroup; + this.apiSecurityGroups = this.apiProvider.securityGroups; + this.apiFunction = this.apiProvider.onEventHandlerFunction; + this.apiRole = this.apiProvider.onEventHandlerRole; + } diff --git a/framework/src/consumption/lib/opensearch/opensearch.ts b/framework/src/consumption/lib/opensearch/opensearch.ts index d36273670..c15ec3394 100644 --- a/framework/src/consumption/lib/opensearch/opensearch.ts +++ b/framework/src/consumption/lib/opensearch/opensearch.ts @@ -2,9 +2,10 @@ // SPDX-License-Identifier: MIT-0 import { RemovalPolicy, Stack, Duration, Aws, CustomResource } from 'aws-cdk-lib'; -import { EbsDeviceVolumeType, IVpc, Peer, Port, SecurityGroup, SubnetType } from 'aws-cdk-lib/aws-ec2'; +import { EbsDeviceVolumeType, ISecurityGroup, IVpc, Peer, Port, SecurityGroup, SubnetType } from 'aws-cdk-lib/aws-ec2'; import { AnyPrincipal, Effect, IRole, ManagedPolicy, PolicyStatement, Role, ServicePrincipal } from 'aws-cdk-lib/aws-iam'; import { IKey, Key } from 'aws-cdk-lib/aws-kms'; +import { IFunction } from 'aws-cdk-lib/aws-lambda'; import { ILogGroup, LogGroup } from 'aws-cdk-lib/aws-logs'; import { Domain, DomainProps, IDomain, SAMLOptionsProperty } from 'aws-cdk-lib/aws-opensearchservice'; import { AwsCustomResource, PhysicalResourceId } from 'aws-cdk-lib/custom-resources'; @@ -65,6 +66,24 @@ export class OpenSearchCluster extends TrackedConstruct { */ public readonly masterRole: IRole; + + /** + * CloudWatch Logs Log Group to store OpenSearch API logs + */ + public readonly openSearchApiLogGroup: ILogGroup; + + /** + * Security Group for OpenSearch API Lambda Function + * @see OpenSearchApi + */ + public readonly apiSecurityGroups?: ISecurityGroup[]; + + /** + * Lambda Function used for OpenSearch API + * @see OpenSearchApi + */ + public readonly openSearchApiFunction: IFunction; + /** * Opesearch API client * @see OpenSearchApi @@ -286,6 +305,10 @@ export class OpenSearchCluster extends TrackedConstruct { removalPolicy: this.removalPolicy, }); + this.openSearchApiLogGroup = this.openSearchApi.apiLogGroup; + this.apiSecurityGroups = this.openSearchApi.apiSecurityGroups; + this.openSearchApiFunction = this.openSearchApi.apiFunction; + const allAccessRoleLambdaCr=this.openSearchApi.addRoleMapping('AllAccessRoleLambda', 'all_access', this.masterRole.roleArn, true); const allAccessRoleSamlCr=this.openSearchApi.addRoleMapping('AllAccessRoleSAML', 'all_access', samlAdminGroupId, true); allAccessRoleSamlCr.node.addDependency(allAccessRoleLambdaCr);