in packages/constructs/L3/ai/gaia-l3-construct/lib/rag-engines/aurora-pgvector/create-aurora-workspace.ts [31:246]
constructor(scope: Construct, id: string, props: CreateAuroraWorkspaceProps) {
super(scope, id, props);
const createFunctionRole = new MdaaLambdaRole(this, 'CreateAuroraWorkspaceFunctionRole', {
naming: props.naming,
createParams: false,
createOutputs: false,
roleName: 'create-aurora-workspace-function-role',
logGroupNames: [props.naming.resourceName('create-aurora-workspace')],
});
createFunctionRole.addToPolicy(
new iam.PolicyStatement({
effect: Effect.ALLOW,
actions: ['ec2:CreateNetworkInterface', 'ec2:DescribeNetworkInterfaces', 'ec2:DeleteNetworkInterface'],
resources: ['*'],
}),
);
createFunctionRole.addManagedPolicy(ManagedPolicy.fromAwsManagedPolicyName('AWSLambdaExecute'));
const createAuroraWorkspaceCodePath =
props.config?.codeOverwrites?.createAuroraWorkspaceCodePath !== undefined
? props.config.codeOverwrites.createAuroraWorkspaceCodePath
: path.join(__dirname, './functions/create-workflow/create');
const createFunction = new MdaaLambdaFunction(this, 'CreateAuroraWorkspaceFunction', {
functionName: 'create-aurora-workspace',
naming: props.naming,
createParams: false,
createOutputs: false,
role: createFunctionRole,
vpc: props.shared.vpc,
vpcSubnets: { subnets: props.shared.appSubnets },
securityGroups: [props.shared.appSecurityGroup],
code: lambda.Code.fromAsset(createAuroraWorkspaceCodePath),
runtime: props.shared.pythonRuntime,
architecture: props.shared.lambdaArchitecture,
handler: 'index.lambda_handler',
layers: [props.shared.powerToolsLayer, props.shared.commonLayer, props.shared.pythonSDKLayer],
timeout: cdk.Duration.minutes(5),
environment: {
...props.shared.defaultEnvironmentVariables,
AURORA_DB_SECRET_ID: props.dbCluster.secret?.secretArn as string,
WORKSPACES_TABLE_NAME: props.ragDynamoDBTables.workspacesTable.tableName,
WORKSPACES_BY_OBJECT_TYPE_INDEX_NAME: props.ragDynamoDBTables.workspacesByObjectTypeIndexName,
},
});
MdaaNagSuppressions.addCodeResourceSuppressions(
createFunction,
[
{
id: 'NIST.800.53.R5-LambdaConcurrency',
reason: 'Only run during deployment, concurrency does not fit the scenario.',
},
{
id: 'HIPAA.Security-LambdaConcurrency',
reason: 'Only run during deployment, concurrency does not fit the scenario.',
},
{
id: 'PCI.DSS.321-LambdaConcurrency',
reason: 'Only run during deployment, concurrency does not fit the scenario.',
},
{
id: 'NIST.800.53.R5-LambdaDLQ',
reason: 'Used in a custom resource, error handling is managed by Cloudformation.',
},
{
id: 'HIPAA.Security-LambdaDLQ',
reason: 'Used in a custom resource, error handling is managed by Cloudformation.',
},
{
id: 'PCI.DSS.321-LambdaDLQ',
reason: 'Used in a custom resource, error handling is managed by Cloudformation.',
},
{ id: 'NIST.800.53.R5-LambdaInsideVPC', reason: 'Used in a custom resource only during deployment.' },
{ id: 'HIPAA.Security-LambdaInsideVPC', reason: 'Used in a custom resource only during deployment.' },
{ id: 'PCI.DSS.321-LambdaInsideVPC', reason: 'Used in a custom resource only during deployment.' },
{
id: 'AwsSolutions-IAM5',
reason: 'Event handler lambda resources unknown at deployment, used for deployment only',
},
],
true,
);
props.dbCluster.secret?.grantRead(createFunctionRole);
props.dbCluster.grantConnect(createFunction, 'postgres');
props.encryptionKey.grantEncryptDecrypt(createFunctionRole);
props.dbCluster.connections.allowDefaultPortFrom(createFunction);
props.ragDynamoDBTables.workspacesTable.grantReadWriteData(createFunctionRole);
MdaaNagSuppressions.addCodeResourceSuppressions(
createFunctionRole,
[
{ id: 'AwsSolutions-IAM4', reason: 'Standard Lambda Execution Managed Policy' },
{
id: 'AwsSolutions-IAM5',
reason: 'DDB index names not known at deployment time. KMS Permissions are appropriately scoped.',
},
{
id: 'NIST.800.53.R5-IAMNoInlinePolicy',
reason: 'Permissions are role specific. Inline policy use appropriate.',
},
{
id: 'HIPAA.Security-IAMNoInlinePolicy',
reason: 'Permissions are role specific. Inline policy use appropriate.',
},
{
id: 'PCI.DSS.321-IAMNoInlinePolicy',
reason: 'Permissions are role specific. Inline policy use appropriate.',
},
],
true,
);
const handleError = new tasks.DynamoUpdateItem(this, 'HandleError', {
table: props.ragDynamoDBTables.workspacesTable,
key: {
workspace_id: tasks.DynamoAttributeValue.fromString(sfn.JsonPath.stringAt('$.workspace_id')),
object_type: tasks.DynamoAttributeValue.fromString('workspace'),
},
updateExpression: 'set #status = :error',
expressionAttributeNames: {
'#status': 'status',
},
expressionAttributeValues: {
':error': tasks.DynamoAttributeValue.fromString('error'),
},
}).next(
new sfn.Fail(this, 'Fail', {
cause: 'Workspace creation failed',
}),
);
const setCreating = new tasks.DynamoUpdateItem(this, 'SetCreating', {
table: props.ragDynamoDBTables.workspacesTable,
key: {
workspace_id: tasks.DynamoAttributeValue.fromString(sfn.JsonPath.stringAt('$.workspace_id')),
object_type: tasks.DynamoAttributeValue.fromString('workspace'),
},
updateExpression: 'set #status=:statusValue',
expressionAttributeNames: {
'#status': 'status',
},
expressionAttributeValues: {
':statusValue': tasks.DynamoAttributeValue.fromString('creating'),
},
resultPath: sfn.JsonPath.DISCARD,
});
const setReady = new tasks.DynamoUpdateItem(this, 'SetReady', {
table: props.ragDynamoDBTables.workspacesTable,
key: {
workspace_id: tasks.DynamoAttributeValue.fromString(sfn.JsonPath.stringAt('$.workspace_id')),
object_type: tasks.DynamoAttributeValue.fromString('workspace'),
},
updateExpression: 'set #status=:statusValue',
expressionAttributeNames: {
'#status': 'status',
},
expressionAttributeValues: {
':statusValue': tasks.DynamoAttributeValue.fromString('ready'),
},
resultPath: sfn.JsonPath.DISCARD,
});
const createTask = new tasks.LambdaInvoke(this, 'Create', {
lambdaFunction: createFunction,
resultPath: '$.createResult',
}).addCatch(handleError, {
errors: ['States.ALL'],
resultPath: '$.createResult',
});
const workflow = setCreating.next(createTask).next(setReady).next(new sfn.Succeed(this, 'Success'));
const logGroup: LogGroup = new MdaaLogGroup(this, `CreateAuroraWorkspace-loggroup`, {
naming: props.naming,
createParams: false,
createOutputs: false,
logGroupName: 'create-aurora-workspace',
logGroupNamePathPrefix: `/aws/stepfunction/`,
encryptionKey: props.encryptionKey,
retention: RetentionDays.INFINITE,
});
props.encryptionKey.grantEncryptDecrypt(new ServicePrincipal('logs.amazonaws.com'));
const stateMachine = new sfn.StateMachine(this, 'CreateAuroraWorkspaceStateMachine', {
definitionBody: sfn.DefinitionBody.fromChainable(workflow),
timeout: cdk.Duration.minutes(5),
comment: 'Create Aurora Workspace Workflow',
tracingEnabled: true,
logs: {
destination: logGroup,
level: sfn.LogLevel.ALL,
},
});
props.encryptionKey.grantEncryptDecrypt(stateMachine.role);
MdaaNagSuppressions.addCodeResourceSuppressions(
stateMachine,
[
{
id: 'AwsSolutions-IAM5',
reason:
'Invoke function restricted to delete workspace lambda. The lambda arn is not known at deployment time.',
},
{ id: 'NIST.800.53.R5-IAMNoInlinePolicy', reason: 'Inline policy managed by MDAA framework.' },
{ id: 'HIPAA.Security-IAMNoInlinePolicy', reason: 'Inline policy managed by MDAA framework.' },
{ id: 'PCI.DSS.321-IAMNoInlinePolicy', reason: 'Inline policy managed by MDAA framework.' },
],
true,
);
this.stateMachine = stateMachine;
}