mirror of
https://github.com/Sea-Haven-Industries/proposal-system.git
synced 2026-10-07 04:42:00 +00:00
fix: LAM-C1/INF-H1 require IAM auth on Function URL, INF-H3 restrict OpenSearch to VPC
LAM-C1/INF-H1: Change Function URL authType from NONE to AWS_IAM and grant invokeUrl permission to all four caller Lambdas (suggestions, pdf-extract, pdf-generate, library-ingest). Lambda HTTP clients will need SigV4 signing as a follow-up. INF-H3: Create OpenSearch Serverless VPC endpoint in private subnets and update network policy from AllowFromPublic to SourceVPCEs, removing public internet access to the vector search collection.
This commit is contained in:
parent
67b4732395
commit
a74ac4945f
1 changed files with 25 additions and 3 deletions
|
|
@ -58,6 +58,15 @@ export class ComputeStack extends cdk.Stack {
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Fix: INF-H3 — restrict OpenSearch Serverless to VPC (was AllowFromPublic: true).
|
||||||
|
// Create a VPC endpoint so Lambdas in private subnets can reach the collection.
|
||||||
|
const ossVpcEndpoint = new opensearchserverless.CfnVpcEndpoint(this, 'OssVpcEndpoint', {
|
||||||
|
name: 'proposal-system-kb-vpce',
|
||||||
|
vpcId: props.vpc.vpcId,
|
||||||
|
subnetIds: props.vpc.selectSubnets({ subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS }).subnetIds,
|
||||||
|
securityGroupIds: [props.lambdaSecurityGroup.securityGroupId],
|
||||||
|
});
|
||||||
|
|
||||||
const ossNetworkPolicy = new opensearchserverless.CfnSecurityPolicy(this, 'OssNetworkPolicy', {
|
const ossNetworkPolicy = new opensearchserverless.CfnSecurityPolicy(this, 'OssNetworkPolicy', {
|
||||||
name: 'proposal-system-kb-net',
|
name: 'proposal-system-kb-net',
|
||||||
type: 'network',
|
type: 'network',
|
||||||
|
|
@ -65,9 +74,11 @@ export class ComputeStack extends cdk.Stack {
|
||||||
Rules: [
|
Rules: [
|
||||||
{ ResourceType: 'collection', Resource: ['collection/proposal-system-kb'] },
|
{ ResourceType: 'collection', Resource: ['collection/proposal-system-kb'] },
|
||||||
],
|
],
|
||||||
AllowFromPublic: true,
|
AllowFromPublic: false,
|
||||||
|
SourceVPCEs: [ossVpcEndpoint.attrId],
|
||||||
}]),
|
}]),
|
||||||
});
|
});
|
||||||
|
ossNetworkPolicy.addDependency(ossVpcEndpoint);
|
||||||
|
|
||||||
const ossCollection = new opensearchserverless.CfnCollection(this, 'OssCollection', {
|
const ossCollection = new opensearchserverless.CfnCollection(this, 'OssCollection', {
|
||||||
name: 'proposal-system-kb',
|
name: 'proposal-system-kb',
|
||||||
|
|
@ -237,9 +248,12 @@ export class ComputeStack extends cdk.Stack {
|
||||||
resources: [props.userPool.userPoolArn],
|
resources: [props.userPool.userPoolArn],
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Function URL for internal Lambda-to-API calls (bypasses API Gateway JWT authorizer)
|
// Fix: LAM-C1/INF-H1 — require IAM auth on Function URL (was authType NONE).
|
||||||
|
// NOTE: Lambda HTTP clients (suggestions, pdf-extract, pdf-generate, library-ingest)
|
||||||
|
// must use SigV4 signing when calling this URL. The API key header alone is no longer
|
||||||
|
// sufficient for authentication at the transport layer.
|
||||||
const apiFunctionUrl = apiFunction.addFunctionUrl({
|
const apiFunctionUrl = apiFunction.addFunctionUrl({
|
||||||
authType: lambda.FunctionUrlAuthType.NONE,
|
authType: lambda.FunctionUrlAuthType.AWS_IAM,
|
||||||
});
|
});
|
||||||
|
|
||||||
// API Gateway HTTP API
|
// API Gateway HTTP API
|
||||||
|
|
@ -338,6 +352,8 @@ export class ComputeStack extends cdk.Stack {
|
||||||
});
|
});
|
||||||
|
|
||||||
internalApiKeySecret.grantRead(suggestionsFunction);
|
internalApiKeySecret.grantRead(suggestionsFunction);
|
||||||
|
// Fix: LAM-C1/INF-H1 — grant Function URL invoke permission for IAM auth
|
||||||
|
apiFunctionUrl.grantInvokeUrl(suggestionsFunction);
|
||||||
suggestionsFunction.addToRolePolicy(new iam.PolicyStatement({
|
suggestionsFunction.addToRolePolicy(new iam.PolicyStatement({
|
||||||
actions: ['bedrock:InvokeModel'],
|
actions: ['bedrock:InvokeModel'],
|
||||||
resources: [`arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-*`],
|
resources: [`arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-*`],
|
||||||
|
|
@ -369,6 +385,8 @@ export class ComputeStack extends cdk.Stack {
|
||||||
});
|
});
|
||||||
|
|
||||||
internalApiKeySecret.grantRead(pdfExtractFunction);
|
internalApiKeySecret.grantRead(pdfExtractFunction);
|
||||||
|
// Fix: LAM-C1/INF-H1 — grant Function URL invoke permission for IAM auth
|
||||||
|
apiFunctionUrl.grantInvokeUrl(pdfExtractFunction);
|
||||||
props.uploadsBucket.grantRead(pdfExtractFunction);
|
props.uploadsBucket.grantRead(pdfExtractFunction);
|
||||||
pdfExtractFunction.addToRolePolicy(new iam.PolicyStatement({
|
pdfExtractFunction.addToRolePolicy(new iam.PolicyStatement({
|
||||||
actions: ['bedrock:InvokeModel'],
|
actions: ['bedrock:InvokeModel'],
|
||||||
|
|
@ -396,6 +414,8 @@ export class ComputeStack extends cdk.Stack {
|
||||||
});
|
});
|
||||||
|
|
||||||
internalApiKeySecret.grantRead(pdfGenerateFunction);
|
internalApiKeySecret.grantRead(pdfGenerateFunction);
|
||||||
|
// Fix: LAM-C1/INF-H1 — grant Function URL invoke permission for IAM auth
|
||||||
|
apiFunctionUrl.grantInvokeUrl(pdfGenerateFunction);
|
||||||
props.generatedBucket.grantWrite(pdfGenerateFunction);
|
props.generatedBucket.grantWrite(pdfGenerateFunction);
|
||||||
|
|
||||||
// Python Lambda: Library Ingest
|
// Python Lambda: Library Ingest
|
||||||
|
|
@ -421,6 +441,8 @@ export class ComputeStack extends cdk.Stack {
|
||||||
});
|
});
|
||||||
|
|
||||||
internalApiKeySecret.grantRead(libraryIngestFunction);
|
internalApiKeySecret.grantRead(libraryIngestFunction);
|
||||||
|
// Fix: LAM-C1/INF-H1 — grant Function URL invoke permission for IAM auth
|
||||||
|
apiFunctionUrl.grantInvokeUrl(libraryIngestFunction);
|
||||||
props.libraryBucket.grantWrite(libraryIngestFunction);
|
props.libraryBucket.grantWrite(libraryIngestFunction);
|
||||||
libraryIngestFunction.addToRolePolicy(new iam.PolicyStatement({
|
libraryIngestFunction.addToRolePolicy(new iam.PolicyStatement({
|
||||||
actions: ['bedrock:StartIngestionJob'],
|
actions: ['bedrock:StartIngestionJob'],
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue