@aws/nx-plugin-mcp 1.0.0-rc.4 → 1.0.0-rc.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/aws-nx-mcp.js +2240 -1030
- package/docs/get_started/building-with-ai.mdx +116 -0
- package/docs/get_started/concepts.mdx +52 -0
- package/docs/get_started/existing-project.mdx +176 -0
- package/docs/get_started/quick-start.mdx +266 -0
- package/docs/get_started/tutorials/contribute-generator.mdx +405 -0
- package/docs/get_started/tutorials/dungeon-game/1.mdx +1205 -0
- package/docs/get_started/tutorials/dungeon-game/2.mdx +237 -0
- package/docs/get_started/tutorials/dungeon-game/3.mdx +76 -0
- package/docs/get_started/tutorials/dungeon-game/4.mdx +162 -0
- package/docs/get_started/tutorials/dungeon-game/overview.mdx +144 -0
- package/docs/get_started/tutorials/dungeon-game/wrap-up.mdx +41 -0
- package/docs/get_started/tutorials/existing-project.mdx +4 -0
- package/docs/guides/agentcore-gateway.mdx +376 -0
- package/docs/guides/connection/agentcore-gateway-gateway.mdx +154 -0
- package/docs/guides/connection/agentcore-gateway-mcp.mdx +134 -0
- package/docs/guides/connection/py-agent-a2a.mdx +47 -15
- package/docs/guides/connection/py-agent-dynamodb.mdx +116 -0
- package/docs/guides/connection/py-agent-gateway.mdx +176 -0
- package/docs/guides/connection/py-agent-mcp.mdx +42 -13
- package/docs/guides/connection/py-agent-rdb.mdx +178 -0
- package/docs/guides/connection/py-fast-api-dynamodb.mdx +56 -0
- package/docs/guides/connection/py-fast-api-rdb.mdx +184 -0
- package/docs/guides/connection/py-mcp-server-dynamodb.mdx +116 -0
- package/docs/guides/connection/py-mcp-server-rdb.mdx +187 -0
- package/docs/guides/connection/react-agui.mdx +4 -4
- package/docs/guides/connection/react-fastapi.mdx +38 -2
- package/docs/guides/connection/react-py-agent.mdx +7 -13
- package/docs/guides/connection/react-smithy.mdx +3 -3
- package/docs/guides/connection/react-trpc.mdx +1 -1
- package/docs/guides/connection/react-ts-agent.mdx +8 -8
- package/docs/guides/connection/smithy-dynamodb.mdx +4 -4
- package/docs/guides/connection/smithy-rdb.mdx +5 -5
- package/docs/guides/connection/trpc-dynamodb.mdx +4 -4
- package/docs/guides/connection/trpc-rdb.mdx +5 -5
- package/docs/guides/connection/ts-agent-a2a.mdx +12 -9
- package/docs/guides/connection/ts-agent-dynamodb.mdx +3 -3
- package/docs/guides/connection/ts-agent-gateway.mdx +141 -0
- package/docs/guides/connection/ts-agent-mcp.mdx +11 -8
- package/docs/guides/connection/ts-agent-rdb.mdx +66 -21
- package/docs/guides/connection/ts-mcp-server-dynamodb.mdx +3 -3
- package/docs/guides/connection/ts-mcp-server-rdb.mdx +66 -16
- package/docs/guides/connection.mdx +104 -5
- package/docs/guides/docker-bundling.mdx +68 -8
- package/docs/guides/fastapi.mdx +244 -4
- package/docs/guides/license.mdx +264 -109
- package/docs/guides/local-development.mdx +87 -0
- package/docs/guides/nx-generator.mdx +7 -2
- package/docs/guides/py-agent.mdx +257 -49
- package/docs/guides/py-dynamodb.mdx +476 -0
- package/docs/guides/py-mcp-server.mdx +61 -2
- package/docs/guides/py-rdb.mdx +254 -0
- package/docs/guides/react-website-auth.mdx +58 -1
- package/docs/guides/react-website.mdx +130 -19
- package/docs/guides/security.mdx +75 -0
- package/docs/guides/terraform-project.mdx +1 -1
- package/docs/guides/trpc.mdx +45 -9
- package/docs/guides/ts-agent.mdx +149 -9
- package/docs/guides/ts-dynamodb.mdx +62 -239
- package/docs/guides/ts-mcp-server.mdx +66 -3
- package/docs/guides/ts-nx-plugin.mdx +1 -1
- package/docs/guides/ts-rdb.mdx +117 -470
- package/docs/guides/ts-smithy-api.mdx +183 -4
- package/docs/guides/typescript-infrastructure.mdx +9 -1
- package/docs/guides/typescript-project.mdx +5 -10
- package/docs/guides/workspace.mdx +2 -2
- package/docs/snippets/agent/architecture.mdx +1 -1
- package/docs/snippets/agent/bedrock-deployment.mdx +4 -0
- package/docs/snippets/agent/runtime-arn.mdx +21 -0
- package/docs/snippets/agent/securing-your-agent.mdx +39 -0
- package/docs/snippets/api/access-logging.mdx +33 -0
- package/docs/snippets/api/type-safe-api-integrations.mdx +31 -0
- package/docs/snippets/api/waf-configuration.mdx +1 -1
- package/docs/snippets/connection/dynamodb-local-development.mdx +2 -2
- package/docs/snippets/connection/py-dynamodb-local-development.mdx +7 -0
- package/docs/snippets/connection/py-lambda-rdb-ssl-requirements.mdx +7 -0
- package/docs/snippets/connection/rdb-api-infrastructure.mdx +50 -18
- package/docs/snippets/dynamodb/deploying-table.mdx +166 -0
- package/docs/snippets/dynamodb/gsi-config.mdx +38 -0
- package/docs/snippets/dynamodb/infrastructure.mdx +33 -0
- package/docs/snippets/dynamodb/local-dev-start.mdx +13 -0
- package/docs/snippets/dynamodb/local-dev-windows.mdx +15 -0
- package/docs/snippets/mcp/architecture.mdx +1 -1
- package/docs/snippets/mcp/bedrock-deployment.mdx +4 -0
- package/docs/snippets/mcp/config.mdx +3 -2
- package/docs/snippets/rdb/architecture.mdx +38 -0
- package/docs/snippets/rdb/cluster-instances.mdx +31 -0
- package/docs/snippets/rdb/deletion-protection.mdx +34 -0
- package/docs/snippets/rdb/deploying.mdx +187 -0
- package/docs/snippets/rdb/encryption-key-rotation.mdx +30 -0
- package/docs/snippets/rdb/engine-version.mdx +63 -0
- package/docs/snippets/rdb/infrastructure.mdx +35 -0
- package/docs/snippets/rdb/logging.mdx +32 -0
- package/docs/snippets/rdb/rds-proxy.mdx +50 -0
- package/docs/snippets/rdb/removal-policy.mdx +57 -0
- package/docs/snippets/rdb/serverless-capacity.mdx +32 -0
- package/docs/snippets/required-prerequisites.mdx +1 -1
- package/docs/snippets/trivy-image-scan.mdx +27 -0
- package/generators.json +101 -2
- package/package.json +1 -1
- package/src/agentcore-gateway/gateway-connection/schema.json +31 -0
- package/src/agentcore-gateway/mcp-connection/schema.json +31 -0
- package/src/agentcore-gateway/schema.json +70 -0
- package/src/connection/schema.json +5 -0
- package/src/infra/app/schema.json +5 -0
- package/src/init/schema.json +35 -0
- package/src/license/schema.json +11 -0
- package/src/preset/schema.json +11 -5
- package/src/py/agent/a2a-connection/schema.json +5 -0
- package/src/py/agent/gateway-connection/schema.json +31 -0
- package/src/py/agent/mcp-connection/schema.json +5 -0
- package/src/py/agent/react-connection/schema.json +5 -0
- package/src/py/agent/schema.json +6 -1
- package/src/py/api/schema.json +5 -0
- package/src/py/dynamodb/agent-connection/schema.json +27 -0
- package/src/py/dynamodb/fast-api-connection/schema.json +23 -0
- package/src/py/dynamodb/mcp-server-connection/schema.json +27 -0
- package/src/py/dynamodb/schema.json +75 -0
- package/src/py/fast-api/react/schema.json +5 -0
- package/src/py/fast-api/schema.json +5 -0
- package/src/py/lambda-function/schema.json +5 -0
- package/src/py/mcp-server/schema.json +5 -0
- package/src/py/project/schema.json +5 -0
- package/src/py/rdb/agent-connection/schema.json +27 -0
- package/src/py/rdb/fast-api-connection/schema.json +23 -0
- package/src/py/rdb/mcp-server-connection/schema.json +27 -0
- package/src/py/rdb/schema.json +77 -0
- package/src/smithy/project/schema.json +5 -0
- package/src/smithy/react-connection/schema.json +5 -0
- package/src/smithy/ts/api/schema.json +5 -0
- package/src/terraform/project/schema.json +5 -0
- package/src/trpc/backend/schema.json +5 -0
- package/src/trpc/react/schema.json +5 -0
- package/src/ts/agent/a2a-connection/schema.json +5 -0
- package/src/ts/agent/gateway-connection/schema.json +31 -0
- package/src/ts/agent/mcp-connection/schema.json +5 -0
- package/src/ts/agent/react-connection/schema.json +5 -0
- package/src/ts/agent/schema.json +5 -0
- package/src/ts/api/schema.json +5 -0
- package/src/ts/astro-docs/schema.json +3 -3
- package/src/ts/docs/schema.json +3 -3
- package/src/ts/dynamodb/agent-connection/schema.json +5 -0
- package/src/ts/dynamodb/mcp-server-connection/schema.json +5 -0
- package/src/ts/dynamodb/schema.json +25 -2
- package/src/ts/dynamodb/smithy-connection/schema.json +5 -0
- package/src/ts/dynamodb/trpc-connection/schema.json +5 -0
- package/src/ts/lambda-function/schema.json +5 -0
- package/src/ts/lib/schema.json +5 -0
- package/src/ts/mcp-server/schema.json +5 -0
- package/src/ts/nx-generator/schema.json +5 -0
- package/src/ts/nx-plugin/schema.json +5 -0
- package/src/ts/rdb/agent-connection/schema.json +5 -0
- package/src/ts/rdb/mcp-server-connection/schema.json +5 -0
- package/src/ts/rdb/schema.json +6 -1
- package/src/ts/rdb/smithy-connection/schema.json +5 -0
- package/src/ts/rdb/trpc-connection/schema.json +5 -0
- package/src/ts/react-website/app/schema.json +11 -6
- package/src/ts/react-website/cognito-auth/schema.json +5 -0
- package/src/ts/react-website/runtime-config/schema.json +5 -0
- package/src/ts/website/app/schema.json +11 -6
- package/src/ts/website/auth/schema.json +5 -0
- /package/docs/snippets/connection/{lambda-rdb-ssl-requirements.mdx → ts-lambda-rdb-ssl-requirements.mdx} +0 -0
- /package/docs/snippets/connection/{mcp-server-rdb-ssl-requirements.mdx → ts-mcp-server-rdb-ssl-requirements.mdx} +0 -0
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Smithy TypeScript API
|
|
3
3
|
description: Reference documentation for Smithy TypeScript API
|
|
4
|
-
generator: ts#
|
|
4
|
+
generator: ts#api
|
|
5
5
|
when:
|
|
6
6
|
framework: [smithy]
|
|
7
7
|
infra: [rest-lambda]
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
-
import { FileTree } from '@astrojs/starlight/components';
|
|
10
|
+
import { FileTree, CardGrid } from '@astrojs/starlight/components';
|
|
11
|
+
import Astro from '@astrojs/react';
|
|
12
|
+
import ConnectionCard from '@components/connection-card.astro';
|
|
11
13
|
import Link from '@components/link.astro';
|
|
12
14
|
import RunGenerator from '@components/run-generator.astro';
|
|
13
15
|
import GeneratorParameters from '@components/generator-parameters.astro';
|
|
@@ -27,11 +29,11 @@ The Smithy TypeScript API generator creates a new API using Smithy for service d
|
|
|
27
29
|
|
|
28
30
|
You can generate a new Smithy TypeScript API in two ways:
|
|
29
31
|
|
|
30
|
-
<RunGenerator generator="ts#
|
|
32
|
+
<RunGenerator generator="ts#api" requiredParameters={{ framework: 'smithy' }} />
|
|
31
33
|
|
|
32
34
|
### Options
|
|
33
35
|
|
|
34
|
-
<GeneratorParameters generator="ts#
|
|
36
|
+
<GeneratorParameters generator="ts#api" />
|
|
35
37
|
|
|
36
38
|
:::tip[Integration Pattern]
|
|
37
39
|
The `integrationPattern` option defaults to `isolated`, which creates one Lambda per Smithy operation. Select `shared` if you would prefer a single shared Lambda handler for the whole API, with optional per-operation overrides.
|
|
@@ -401,6 +403,151 @@ export const MyOperation: MyOperationHandler<ServiceContext> = async (input) =>
|
|
|
401
403
|
};
|
|
402
404
|
```
|
|
403
405
|
|
|
406
|
+
### Accessing the Calling User
|
|
407
|
+
|
|
408
|
+
When your API is protected by authentication, your operations often need to know who is calling. The recommended approach is to resolve the caller's identity once in the handler and pass it through the [service context](#service-context) for consumption by specific operations.
|
|
409
|
+
|
|
410
|
+
We'll model the unauthorized case as a Smithy error so it serializes to a proper `403` response. Add it to your model, for example in `model/src/operations/errors.smithy`, and reference it on any operation that requires identity:
|
|
411
|
+
|
|
412
|
+
```smithy
|
|
413
|
+
$version: "2.0"
|
|
414
|
+
|
|
415
|
+
namespace your.namespace
|
|
416
|
+
|
|
417
|
+
/// Thrown when the calling user cannot be determined
|
|
418
|
+
@error("client")
|
|
419
|
+
@httpError(403)
|
|
420
|
+
structure UnauthorizedError {
|
|
421
|
+
@required
|
|
422
|
+
message: String
|
|
423
|
+
}
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
First, expose the resolved identity on the service context in `src/context.ts`. We provide it as a function so that the `UnauthorizedError` is thrown from within an operation (where the Server SDK serializes it to a `403`), rather than from the handler:
|
|
427
|
+
|
|
428
|
+
```ts {4-7,15} ins={4-7,15}
|
|
429
|
+
import { Logger } from '@aws-lambda-powertools/logger';
|
|
430
|
+
import { Metrics } from '@aws-lambda-powertools/metrics';
|
|
431
|
+
import { Tracer } from '@aws-lambda-powertools/tracer';
|
|
432
|
+
|
|
433
|
+
export interface Identity {
|
|
434
|
+
sub: string;
|
|
435
|
+
username: string;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
/**
|
|
439
|
+
* Context provided to all operations.
|
|
440
|
+
*/
|
|
441
|
+
export interface ServiceContext {
|
|
442
|
+
tracer: Tracer;
|
|
443
|
+
logger: Logger;
|
|
444
|
+
metrics: Metrics;
|
|
445
|
+
getIdentity: () => Promise<Identity>;
|
|
446
|
+
}
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
Next, write the resolver in `src/identity.ts`. It throws `UnauthorizedError` when the caller cannot be determined. The implementation depends on your selected `auth` method:
|
|
450
|
+
|
|
451
|
+
<OptionFilter when={{ auth: 'iam' }} description="Identity resolution for IAM-authenticated APIs">
|
|
452
|
+
For `IAM` authentication, we look up the caller in Cognito using the sub extracted from the API Gateway event:
|
|
453
|
+
|
|
454
|
+
```ts
|
|
455
|
+
import { CognitoIdentityProvider } from '@aws-sdk/client-cognito-identity-provider';
|
|
456
|
+
import type { APIGatewayProxyEvent } from 'aws-lambda';
|
|
457
|
+
import { Identity } from './context.js';
|
|
458
|
+
import { UnauthorizedError } from './generated/ssdk/index.js';
|
|
459
|
+
|
|
460
|
+
const cognito = new CognitoIdentityProvider();
|
|
461
|
+
|
|
462
|
+
export const getIdentity = async (
|
|
463
|
+
event: APIGatewayProxyEvent,
|
|
464
|
+
): Promise<Identity> => {
|
|
465
|
+
const cognitoAuthenticationProvider =
|
|
466
|
+
event.requestContext?.identity?.cognitoAuthenticationProvider;
|
|
467
|
+
|
|
468
|
+
let sub: string | undefined = undefined;
|
|
469
|
+
if (cognitoAuthenticationProvider) {
|
|
470
|
+
const providerParts = cognitoAuthenticationProvider.split(':');
|
|
471
|
+
sub = providerParts[providerParts.length - 1];
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
if (!sub) {
|
|
475
|
+
throw new UnauthorizedError({ message: 'Unable to determine calling user' });
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
const { Users } = await cognito.listUsers({
|
|
479
|
+
// Assumes user pool id is configured in lambda environment
|
|
480
|
+
UserPoolId: process.env.USER_POOL_ID!,
|
|
481
|
+
Limit: 1,
|
|
482
|
+
Filter: `sub="${sub}"`,
|
|
483
|
+
});
|
|
484
|
+
|
|
485
|
+
if (!Users || Users.length !== 1) {
|
|
486
|
+
throw new UnauthorizedError({ message: `No user found with subjectId ${sub}` });
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
return { sub, username: Users[0].Username! };
|
|
490
|
+
};
|
|
491
|
+
```
|
|
492
|
+
</OptionFilter>
|
|
493
|
+
|
|
494
|
+
<OptionFilter when={{ auth: 'cognito' }} description="Identity resolution for Cognito-authenticated APIs">
|
|
495
|
+
With `auth: 'cognito'`, the API Gateway Cognito User Pools authorizer verifies the JWT that the caller supplies in the `Authorization` header and places the verified claims on the event at `event.requestContext.authorizer.claims`:
|
|
496
|
+
|
|
497
|
+
```ts
|
|
498
|
+
import type { APIGatewayProxyEvent } from 'aws-lambda';
|
|
499
|
+
import { Identity } from './context.js';
|
|
500
|
+
import { UnauthorizedError } from './generated/ssdk/index.js';
|
|
501
|
+
|
|
502
|
+
export const getIdentity = async (
|
|
503
|
+
event: APIGatewayProxyEvent,
|
|
504
|
+
): Promise<Identity> => {
|
|
505
|
+
const claims = event.requestContext?.authorizer?.claims as
|
|
506
|
+
| Record<string, string>
|
|
507
|
+
| undefined;
|
|
508
|
+
|
|
509
|
+
const sub = claims?.sub;
|
|
510
|
+
const username = claims?.username;
|
|
511
|
+
|
|
512
|
+
if (!sub || !username) {
|
|
513
|
+
throw new UnauthorizedError({ message: 'Unable to determine calling user' });
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
return { sub, username };
|
|
517
|
+
};
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
:::tip[No token verification required]
|
|
521
|
+
You don't need `aws-jwt-verify` or any other JWT-verification library here — the API Gateway Cognito User Pools authorizer has already verified the signature, issuer, scopes, and expiry by the time your Lambda runs. If any of those checks fail, API Gateway returns `401 Unauthorized` and your handler is never invoked.
|
|
522
|
+
:::
|
|
523
|
+
</OptionFilter>
|
|
524
|
+
|
|
525
|
+
Then wire the resolver into the context in `src/handler.ts`:
|
|
526
|
+
|
|
527
|
+
```ts {2,8} ins={2,8}
|
|
528
|
+
import { Service } from './service.js';
|
|
529
|
+
import { getIdentity } from './identity.js';
|
|
530
|
+
// ...
|
|
531
|
+
const httpResponse = await serviceHandler.handle(httpRequest, {
|
|
532
|
+
tracer,
|
|
533
|
+
logger,
|
|
534
|
+
metrics,
|
|
535
|
+
getIdentity: () => getIdentity(event),
|
|
536
|
+
});
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
We can now use the resolved identity in an operation, for example in `src/operations/echo.ts`:
|
|
540
|
+
|
|
541
|
+
```ts
|
|
542
|
+
import { ServiceContext } from '../context.js';
|
|
543
|
+
import { Echo as EchoOperation } from '../generated/ssdk/index.js';
|
|
544
|
+
|
|
545
|
+
export const Echo: EchoOperation<ServiceContext> = async (input, ctx) => {
|
|
546
|
+
const identity = await ctx.getIdentity();
|
|
547
|
+
return { message: `${identity.username} says ${input.message}` };
|
|
548
|
+
};
|
|
549
|
+
```
|
|
550
|
+
|
|
404
551
|
## Building and Code Generation
|
|
405
552
|
|
|
406
553
|
The Smithy model project uses [Docker](https://www.docker.com/) to build the Smithy artifacts and generate the TypeScript Server SDK:
|
|
@@ -583,6 +730,10 @@ output "lambda_function_name" {
|
|
|
583
730
|
|
|
584
731
|
<Snippet name="api/waf-configuration" parentHeading="WAF" />
|
|
585
732
|
|
|
733
|
+
### Access logging
|
|
734
|
+
|
|
735
|
+
<Snippet name="api/access-logging" parentHeading="Access logging" />
|
|
736
|
+
|
|
586
737
|
### Integrations
|
|
587
738
|
|
|
588
739
|
<Snippet name="api/type-safe-api-integrations" parentHeading="Integrations" />
|
|
@@ -662,3 +813,31 @@ resource "aws_iam_role_policy_attachment" "api_invoke_access" {
|
|
|
662
813
|
## Invoking your Smithy API
|
|
663
814
|
|
|
664
815
|
To invoke your API from a React website, you can use the <Link path="guides/connection/react-smithy">`connection`</Link> generator, which provides type-safe client generation from your Smithy model.
|
|
816
|
+
|
|
817
|
+
## Connections
|
|
818
|
+
|
|
819
|
+
Use the <Link path="guides/connection">`connection`</Link> generator to integrate this project with others in your workspace. The following connections involve this project:
|
|
820
|
+
|
|
821
|
+
<CardGrid>
|
|
822
|
+
<ConnectionCard
|
|
823
|
+
title="React to Smithy API"
|
|
824
|
+
description="Call a Smithy API from a React website"
|
|
825
|
+
href={`/nx-plugin-for-aws/${Astro.currentLocale || 'en'}/guides/connection/react-smithy`}
|
|
826
|
+
source="react"
|
|
827
|
+
target="smithy"
|
|
828
|
+
/>
|
|
829
|
+
<ConnectionCard
|
|
830
|
+
title="Smithy API to Relational Database"
|
|
831
|
+
description="Connect a Smithy API to an Aurora relational database"
|
|
832
|
+
href={`/nx-plugin-for-aws/${Astro.currentLocale || 'en'}/guides/connection/smithy-rdb`}
|
|
833
|
+
source="smithy"
|
|
834
|
+
target="aurora"
|
|
835
|
+
/>
|
|
836
|
+
<ConnectionCard
|
|
837
|
+
title="Smithy API to TypeScript DynamoDB"
|
|
838
|
+
description="Connect a Smithy API to a DynamoDB table"
|
|
839
|
+
href={`/nx-plugin-for-aws/${Astro.currentLocale || 'en'}/guides/connection/smithy-dynamodb`}
|
|
840
|
+
source="smithy"
|
|
841
|
+
target="dynamodb"
|
|
842
|
+
/>
|
|
843
|
+
</CardGrid>
|
|
@@ -286,7 +286,7 @@ export class ApplicationStack extends Stack {
|
|
|
286
286
|
|
|
287
287
|
### Website Infrastructure
|
|
288
288
|
|
|
289
|
-
If you have used the <Link path="guides/react-website">
|
|
289
|
+
If you have used the <Link path="guides/react-website">React Website</Link> generator, you will notice you already have a construct in `packages/common/constructs` to deploy it. For example:
|
|
290
290
|
|
|
291
291
|
```ts title="src/stacks/application-stack.ts" {3, 9-10}
|
|
292
292
|
import { Stack, StackProps } from 'aws-cdk-lib';
|
|
@@ -381,6 +381,14 @@ Then run the deploy target:
|
|
|
381
381
|
|
|
382
382
|
<NxCommands commands={['deploy <my-infra> <my-infra>-sandbox/*']} />
|
|
383
383
|
|
|
384
|
+
:::tip[Express Mode for Faster Deployments]
|
|
385
|
+
The `deploy` target waits for full resource stabilization by default, favouring consistency over speed. To speed up iteration during development, opt into [CloudFormation express mode](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cloudformation-express-mode.html) by passing CDK's `--express` flag:
|
|
386
|
+
|
|
387
|
+
<NxCommands commands={['deploy <my-infra> <my-infra>-sandbox/* --express']} />
|
|
388
|
+
|
|
389
|
+
Express mode finishes once resource configuration is confirmed applied rather than waiting for full stabilization, with propagation continuing in the background, for significantly faster iteration cycles. It is intended for development and iteration.
|
|
390
|
+
:::
|
|
391
|
+
|
|
384
392
|
:::tip[Selective Stack Deployment]
|
|
385
393
|
The above command deploys _all_ stacks for the `<my-infra>-sandbox` stage. You can specify other stages so long as they are defined in `main.ts`.
|
|
386
394
|
|
|
@@ -11,7 +11,7 @@ import NxCommands from '@components/nx-commands.astro';
|
|
|
11
11
|
import PackageManagerShortCommand from '@components/package-manager-short-command.astro';
|
|
12
12
|
import Link from '@components/link.astro';
|
|
13
13
|
|
|
14
|
-
The TypeScript project generator can be used to create a modern [TypeScript](https://www.typescriptlang.org/) library or application configured with best practices such as [ECMAScript Modules (ESM)](https://www.typescriptlang.org/docs/handbook/modules/reference.html), TypeScript [project references](https://www.typescriptlang.org/docs/handbook/project-references.html), [Vitest](https://vitest.dev/) for running tests and [
|
|
14
|
+
The TypeScript project generator can be used to create a modern [TypeScript](https://www.typescriptlang.org/) library or application configured with best practices such as [ECMAScript Modules (ESM)](https://www.typescriptlang.org/docs/handbook/modules/reference.html), TypeScript [project references](https://www.typescriptlang.org/docs/handbook/project-references.html), [Vitest](https://vitest.dev/) for running tests and [Biome](https://biomejs.dev/) for linting and formatting.
|
|
15
15
|
|
|
16
16
|
## Usage
|
|
17
17
|
|
|
@@ -38,7 +38,6 @@ The generator will create the following project structure in the `<directory>/<n
|
|
|
38
38
|
- tsconfig.lib.json TypeScript configuration for your library (your runtime or packaged source)
|
|
39
39
|
- tsconfig.spec.json TypeScript configuration for your tests
|
|
40
40
|
- vitest.config.mts Configuration for Vitest
|
|
41
|
-
- eslint.config.mjs Configuration for ESLint
|
|
42
41
|
|
|
43
42
|
</FileTree>
|
|
44
43
|
|
|
@@ -198,7 +197,7 @@ If you're building an AWS Lambda function, check out the <Link path="/guides/ts-
|
|
|
198
197
|
|
|
199
198
|
If you are publishing your TypeScript project to NPM, you must create a `package.json` file for it.
|
|
200
199
|
|
|
201
|
-
This must declare the dependencies that your project references. Since at build time your project will resolve dependencies installed via the workspace root `package.json`,
|
|
200
|
+
This must declare the dependencies that your project references. Since at build time your project will resolve dependencies installed via the workspace root `package.json`, Biome's `noUndeclaredDependencies` rule will warn you if your project imports a package that isn't listed in its `package.json`.
|
|
202
201
|
|
|
203
202
|
### Building
|
|
204
203
|
|
|
@@ -269,11 +268,7 @@ If you are a VSCode user, we recommend installing the [Vitest Runner for VSCode
|
|
|
269
268
|
|
|
270
269
|
## Linting
|
|
271
270
|
|
|
272
|
-
TypeScript projects use [
|
|
273
|
-
|
|
274
|
-
We recommend configuring ESLint in the workspace root `eslint.config.mjs` file, as changes to this will apply to all TypeScript projects in your workspace and ensure consistency.
|
|
275
|
-
|
|
276
|
-
Likewise, you can configure Prettier in the root `.prettierrc` file.
|
|
271
|
+
TypeScript projects use [Biome](https://biomejs.dev/) for linting and formatting. Biome is configured in the workspace root `biome.json` file — changes to this apply to all TypeScript projects in your workspace and ensure consistency.
|
|
277
272
|
|
|
278
273
|
### Running the Linter
|
|
279
274
|
|
|
@@ -283,7 +278,7 @@ To invoke the linter to check your project, you can run the `lint` target.
|
|
|
283
278
|
|
|
284
279
|
### Fixing Lint Issues
|
|
285
280
|
|
|
286
|
-
The majority of linting or formatting issues can be fixed automatically
|
|
281
|
+
The majority of linting or formatting issues can be fixed automatically by running with the `--configuration=fix` argument.
|
|
287
282
|
|
|
288
283
|
<NxCommands commands={["lint <project-name> --configuration=fix"]} />
|
|
289
284
|
|
|
@@ -303,7 +298,7 @@ To avoid linting issues slowing you down during development (particularly if you
|
|
|
303
298
|
|
|
304
299
|
<NxCommands commands={["run-many --target build --configuration=skip-lint"]} />
|
|
305
300
|
|
|
306
|
-
This
|
|
301
|
+
This skips the lint target entirely during build.
|
|
307
302
|
|
|
308
303
|
:::tip[Shorthand Command]
|
|
309
304
|
This has a shorthand command from the root of your workspace:
|
|
@@ -134,7 +134,7 @@ This will run the chosen target as well as the targets it depends on.
|
|
|
134
134
|
|
|
135
135
|
### Linting
|
|
136
136
|
|
|
137
|
-
New workspaces are configured with [
|
|
137
|
+
New workspaces are configured with [Biome](https://biomejs.dev/) for static analysis and code formatting. Running `lint` checks all projects for issues, and `lint --configuration=fix` auto-fixes them.
|
|
138
138
|
|
|
139
139
|
### Git Secrets
|
|
140
140
|
|
|
@@ -181,7 +181,7 @@ export default {
|
|
|
181
181
|
} satisfies AwsNxPluginConfig;
|
|
182
182
|
```
|
|
183
183
|
|
|
184
|
-
- **`iac.provider`** — the default infrastructure-as-code provider (`cdk` or `terraform`) used by generators that emit infrastructure (e.g. `ts#infra`, `ts#
|
|
184
|
+
- **`iac.provider`** — the default infrastructure-as-code provider (`cdk` or `terraform`) used by generators that emit infrastructure (e.g. `ts#infra`, `ts#api`, `py#api`). Generators that accept an `--iac` flag default to `inherit`, which reads this value.
|
|
185
185
|
- **`containers.engine`** — the container CLI (`docker` or `finch`) baked into generated build/push/login commands. CDK image-asset builds also pick this up via the `CDK_DOCKER` environment variable. See the <Link path="guides/docker-bundling">Docker bundling guide</Link> for details.
|
|
186
186
|
|
|
187
187
|
You can edit either setting at any time — subsequent generator runs will pick up the new value.
|
|
@@ -169,4 +169,8 @@ module "my_project_agent" {
|
|
|
169
169
|
|
|
170
170
|
:::note[Custom OIDC Providers]
|
|
171
171
|
If you require custom JWT authentication with a non-Cognito OIDC provider, you can modify the generated CDK construct or Terraform module for your agent directly. Note that the connection generator will only support `IAM` or `Cognito` authentication.
|
|
172
|
+
:::
|
|
173
|
+
|
|
174
|
+
:::caution[Security Best Practices]
|
|
175
|
+
When implementing your agent's business logic, review the [Bedrock AgentCore Runtime security best practices](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/runtime-security-best-practices.html).
|
|
172
176
|
:::
|
|
@@ -61,4 +61,25 @@ The Bedrock AgentCore Runtime dataplane URL for invoking the agent is as follows
|
|
|
61
61
|
https://bedrock-agentcore.<region>.amazonaws.com/runtimes/<url-encoded-arn>/invocations
|
|
62
62
|
```
|
|
63
63
|
|
|
64
|
+
:::tip[Invocation URL]
|
|
65
|
+
Your infrastructure can also output the full invocation URL directly, with the ARN encoding handled for you:
|
|
66
|
+
|
|
67
|
+
<Infrastructure>
|
|
68
|
+
<Fragment slot="cdk">
|
|
69
|
+
```ts
|
|
70
|
+
new CfnOutput(this, 'AgentUrl', {
|
|
71
|
+
value: agent.invocationUrl,
|
|
72
|
+
});
|
|
73
|
+
```
|
|
74
|
+
</Fragment>
|
|
75
|
+
<Fragment slot="terraform">
|
|
76
|
+
```terraform
|
|
77
|
+
output "agent_url" {
|
|
78
|
+
value = module.my_project_agent.invocation_url
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
</Fragment>
|
|
82
|
+
</Infrastructure>
|
|
83
|
+
:::
|
|
84
|
+
|
|
64
85
|
The exact way to invoke this URL depends upon the authentication method used.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Securing your Agent
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Agents act on untrusted input and can drive real actions through their tools, so it's worth considering security from the start. The following practices apply to the generated agent.
|
|
6
|
+
|
|
7
|
+
### Treat model input and output as untrusted
|
|
8
|
+
|
|
9
|
+
Prompts can contain adversarial instructions (prompt injection), and model output is non-deterministic — neither should be trusted in security-sensitive logic:
|
|
10
|
+
|
|
11
|
+
- Define strict input schemas for your tools, as in the generated example tool. Constrain values to what the tool actually needs (enums, length limits, numeric ranges) rather than accepting free-form strings.
|
|
12
|
+
- Never pass model output directly into shell commands, SQL queries, code evaluation, or rendered HTML without validation or encoding.
|
|
13
|
+
- Apply authorization checks in your tools and downstream services — don't rely on the system prompt to prevent the model from misusing a tool it has access to.
|
|
14
|
+
|
|
15
|
+
Strands' [Prompt Engineering](https://strandsagents.com/docs/user-guide/safety-security/prompt-engineering/) and [Responsible AI](https://strandsagents.com/docs/user-guide/safety-security/responsible-ai/) guides cover writing robust, safety-conscious system prompts.
|
|
16
|
+
|
|
17
|
+
### Scope tool permissions tightly
|
|
18
|
+
|
|
19
|
+
Grant the agent's IAM role only the permissions its tools need. The vended CDK constructs and Terraform modules expose `grant*` methods and scoped policies for this purpose — for example granting an agent access to invoke a specific API rather than attaching broad managed policies. Where a tool acts on behalf of a user, prefer authorizing the action using the calling user's identity (passed through via the request context) over the agent's own ambient permissions.
|
|
20
|
+
|
|
21
|
+
### Provide a kill switch
|
|
22
|
+
|
|
23
|
+
Because model behaviour can change in unexpected ways, plan for quickly disabling or swapping the model without a code change:
|
|
24
|
+
|
|
25
|
+
- Read the model ID from configuration (for example a `MODEL_ID` environment variable) so operators can switch or roll back to a different model by updating configuration.
|
|
26
|
+
- Gate the agent behind a feature flag so its AI functionality can be disabled entirely. When disabled, return a generic message rather than an error, and ensure the rest of your application degrades gracefully.
|
|
27
|
+
|
|
28
|
+
Document how to flip these controls in your operational runbook.
|
|
29
|
+
|
|
30
|
+
### Protect sensitive data
|
|
31
|
+
|
|
32
|
+
- Avoid logging prompts and completions, which may contain user data. The generated agent's model error logging hook logs error metadata only, not conversation content — keep this property when adding your own logging.
|
|
33
|
+
- Return generic error messages to users; log detailed errors server-side.
|
|
34
|
+
- Isolate conversation state between users and sessions, and authorize access to any persisted session data.
|
|
35
|
+
- Redact personally identifiable information (PII) from prompts and outputs — either with a Bedrock Guardrail sensitive information filter (below) or, for Strands agents, the approaches in the [PII Redaction](https://strandsagents.com/docs/user-guide/safety-security/pii-redaction/) guide.
|
|
36
|
+
|
|
37
|
+
### Amazon Bedrock Guardrails
|
|
38
|
+
|
|
39
|
+
[Amazon Bedrock Guardrails](https://docs.aws.amazon.com/bedrock/latest/userguide/guardrails.html) provide configurable content filters, denied topics, and sensitive information (PII) filters which are evaluated on model input and output. You can attach a guardrail to the model used by the generated agent:
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Access logging
|
|
3
|
+
---
|
|
4
|
+
import Infrastructure from '@components/infrastructure.astro';
|
|
5
|
+
|
|
6
|
+
For REST APIs, the generated infrastructure enables [access logging](https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-logging.html) by default, writing one structured JSON line per request to a dedicated CloudWatch Logs group. The log group is encrypted with a customer-managed KMS key and retained for one year.
|
|
7
|
+
|
|
8
|
+
API Gateway writes access logs using an account-level CloudWatch Logs role. This role is configured on the `AWS::ApiGateway::Account` setting, which is a **singleton per region per account** — there is only one role for every REST API in the region. To manage this safely across multiple independently-deployed stacks, the generated infrastructure:
|
|
9
|
+
|
|
10
|
+
- Creates a shared CloudWatch Logs role and configures it on the account only when no working role is already set, so deployments never overwrite a role another stack owns.
|
|
11
|
+
- Leaves the account setting untouched on teardown, so destroying one stack never disables logging for other REST APIs in the region.
|
|
12
|
+
|
|
13
|
+
<Infrastructure>
|
|
14
|
+
<Fragment slot="cdk">
|
|
15
|
+
The account role is managed by the `ApiGatewayAccount` construct, a stack-scoped singleton resolved via `ApiGatewayAccount.ensure(scope)`. Each REST API's stage depends on it, and the role is configured by a Lambda-backed custom resource.
|
|
16
|
+
|
|
17
|
+
You can customise the access log format by passing `deployOptions` when constructing your API:
|
|
18
|
+
|
|
19
|
+
```ts {3-5}
|
|
20
|
+
const api = new MyApi(this, 'MyApi', {
|
|
21
|
+
integrations: MyApi.defaultIntegrations(this).build(),
|
|
22
|
+
deployOptions: {
|
|
23
|
+
accessLogFormat: AccessLogFormat.clf(),
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
```
|
|
27
|
+
</Fragment>
|
|
28
|
+
<Fragment slot="terraform">
|
|
29
|
+
The account role is managed by the `core/api/api-gateway-account` module, which is instantiated by the generated API module. It configures the account idempotently and is never reset on `terraform destroy`.
|
|
30
|
+
|
|
31
|
+
You can customise the access log format by editing the `access_log_settings` block on the `aws_api_gateway_stage` resource in the generated API module.
|
|
32
|
+
</Fragment>
|
|
33
|
+
</Infrastructure>
|
|
@@ -172,6 +172,37 @@ module "my_api" {
|
|
|
172
172
|
</Fragment>
|
|
173
173
|
</Infrastructure>
|
|
174
174
|
|
|
175
|
+
#### Customising Options Per-Operation
|
|
176
|
+
|
|
177
|
+
<Infrastructure>
|
|
178
|
+
<Fragment slot="cdk">
|
|
179
|
+
To customise the options used to create the default integration for _specific_ operations (without affecting the others), you can use the `withOperationOptions` method. For example, if you would like to increase the Lambda function timeout for just one operation:
|
|
180
|
+
|
|
181
|
+
```ts {4-6}
|
|
182
|
+
const api = new MyApi(this, 'MyApi', {
|
|
183
|
+
integrations: MyApi.defaultIntegrations(this)
|
|
184
|
+
.withOperationOptions({
|
|
185
|
+
sayHello: {
|
|
186
|
+
timeout: Duration.seconds(60),
|
|
187
|
+
},
|
|
188
|
+
})
|
|
189
|
+
.build(),
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
// The selected operations remain default integrations, so they're still typed accordingly:
|
|
193
|
+
api.integrations.sayHello.handler.addToRolePolicy(new PolicyStatement({ ... }));
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
The options you specify are merged with the default integration options (and any options set via `withDefaultOptions`). Note that you cannot specify options for operations which you have replaced via `withOverrides`, since these no longer use the default integration.
|
|
197
|
+
|
|
198
|
+
You will encounter a type error if the same operation is targeted by both `withOperationOptions` and `withOverrides`, regardless of the order in which you call them.
|
|
199
|
+
|
|
200
|
+
</Fragment>
|
|
201
|
+
<Fragment slot="terraform">
|
|
202
|
+
To customise options for specific operations with Terraform, you need to edit the generated Terraform module to configure individual Lambda functions per operation (see the [Explicit Integrations](#explicit-integrations) section below).
|
|
203
|
+
</Fragment>
|
|
204
|
+
</Infrastructure>
|
|
205
|
+
|
|
175
206
|
#### Overriding Integrations
|
|
176
207
|
|
|
177
208
|
<Infrastructure>
|
|
@@ -6,7 +6,7 @@ import Infrastructure from '@components/infrastructure.astro';
|
|
|
6
6
|
For REST APIs, the generated construct associates an [AWS WAFv2](https://docs.aws.amazon.com/waf/latest/developerguide/waf-chapter.html) Web ACL with the API Gateway stage by default. The Web ACL uses the AWS managed default ruleset ([`AWSManagedRulesCommonRuleSet`](https://docs.aws.amazon.com/waf/latest/developerguide/aws-managed-rule-groups-baseline.html#aws-managed-rule-groups-baseline-crs) and [`AWSManagedRulesKnownBadInputsRuleSet`](https://docs.aws.amazon.com/waf/latest/developerguide/aws-managed-rule-groups-baseline.html#aws-managed-rule-groups-baseline-known-bad-inputs)), providing protection against common web exploits including the OWASP Top 10. WAF request logs are written to a CloudWatch Logs group.
|
|
7
7
|
|
|
8
8
|
:::caution[SizeRestrictions_BODY deviation from defaults]
|
|
9
|
-
The `SizeRestrictions_BODY` rule from `AWSManagedRulesCommonRuleSet` is overridden to `Count` rather than `Block`, since the rule's 8 KB limit is too restrictive for most APIs. Oversized requests will still be recorded as metrics so you can monitor them. See the [AWS WAF body size limits](https://docs.aws.amazon.com/waf/latest/developerguide/waf-rule-statement-oversize-handling.html) guide for more details.
|
|
9
|
+
The `SizeRestrictions_BODY` rule from `AWSManagedRulesCommonRuleSet` is overridden to `Count` rather than `Block`, since the rule's 8 KB limit is too restrictive for most APIs. Oversized requests will still be recorded as metrics so you can monitor them. See the [AWS WAF body size limits](https://docs.aws.amazon.com/waf/latest/developerguide/waf-rule-statement-oversize-handling.html) guide for more details. API Gateway natively enforces its [maximum payload size of 10 MB](https://docs.aws.amazon.com/apigateway/latest/developerguide/limits.html), returning a `413` for larger requests.
|
|
10
10
|
:::
|
|
11
11
|
|
|
12
12
|
You can edit the generated rest-api construct to add, remove, or adjust rules (for example, to add [rate-based rules](https://docs.aws.amazon.com/waf/latest/developerguide/waf-rule-statement-type-rate-based.html) or additional managed rule groups).
|
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
title: DynamoDB Local Development
|
|
3
3
|
---
|
|
4
4
|
|
|
5
|
-
The `connection` generator configures your project's `
|
|
5
|
+
The `connection` generator configures your project's `dev` target to depend on the DynamoDB project's `dev` target. DynamoDB Local will start automatically alongside your project when running `dev`.
|
|
6
6
|
|
|
7
|
-
The `
|
|
7
|
+
The `LOCAL_DEV=true` environment variable is set automatically, so `getDynamoDBClient()` and `resolveTableName()` connect to the local DynamoDB Local instance instead of AWS.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Python DynamoDB Local Development
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
The `connection` generator configures your project's `dev` target to depend on the DynamoDB project's `dev` target. DynamoDB Local will start automatically alongside your project when running `dev`.
|
|
6
|
+
|
|
7
|
+
The `LOCAL_DEV=true` environment variable is set automatically, so `is_local()` returns `True` and your PynamoDB entities connect to the local DynamoDB instance instead of AWS.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: SSL Requirements when Connecting without RDS Proxy
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
The Amazon Linux 2023 Lambda execution environment's built-in CA trust store includes the Amazon Root CAs used by RDS, so no additional configuration is needed.
|
|
6
|
+
|
|
7
|
+
When using RDS Proxy, you do not need to configure the RDS CA bundle in your Lambda function.
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
title: RDB API Infrastructure
|
|
3
3
|
---
|
|
4
4
|
import Infrastructure from '@components/infrastructure.astro';
|
|
5
|
+
import Link from '@components/link.astro';
|
|
5
6
|
|
|
6
7
|
To allow your API to connect to the database at runtime, the API Lambda functions must be deployed into the same VPC as the database and granted network and IAM access.
|
|
7
8
|
|
|
@@ -39,34 +40,65 @@ This example grants every handler in your API access, but if only some handlers
|
|
|
39
40
|
</Fragment>
|
|
40
41
|
<Fragment slot="terraform">
|
|
41
42
|
|
|
42
|
-
|
|
43
|
+
Deploy the API into the same VPC as the database, grant it `rds-db:connect` via `additional_iam_policy_statements`, and open the network path with a pair of security group rules. The `aws_vpc.main` and `aws_subnet` resources are defined in the database deployment guide:
|
|
43
44
|
|
|
44
45
|
```hcl title="packages/infra/src/main.tf"
|
|
45
46
|
module "my_database" {
|
|
46
47
|
source = "../../common/terraform/src/app/dbs/my-database"
|
|
47
|
-
vpc_id =
|
|
48
|
-
database_subnet_ids =
|
|
49
|
-
lambda_subnet_ids =
|
|
48
|
+
vpc_id = aws_vpc.main.id
|
|
49
|
+
database_subnet_ids = aws_subnet.database[*].id
|
|
50
|
+
lambda_subnet_ids = aws_subnet.private[*].id
|
|
50
51
|
}
|
|
51
52
|
|
|
52
53
|
module "api" {
|
|
53
|
-
source
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
54
|
+
source = "../../common/terraform/src/app/apis/my-api"
|
|
55
|
+
enable_vpc = true
|
|
56
|
+
vpc_id = aws_vpc.main.id
|
|
57
|
+
subnet_ids = aws_subnet.private[*].id
|
|
58
|
+
|
|
59
|
+
appconfig_application_id = module.runtime_config_appconfig.application_id
|
|
60
|
+
appconfig_application_arn = module.runtime_config_appconfig.application_arn
|
|
61
|
+
|
|
62
|
+
additional_iam_policy_statements = [
|
|
63
|
+
{
|
|
64
|
+
Effect = "Allow"
|
|
65
|
+
Action = ["rds-db:connect"]
|
|
66
|
+
Resource = [
|
|
67
|
+
"arn:aws:rds-db:${data.aws_region.current.region}:${data.aws_caller_identity.current.account_id}:dbuser:${module.my_database.connect_resource_id}/${module.my_database.database_runtime_user}"
|
|
68
|
+
]
|
|
69
|
+
}
|
|
70
|
+
]
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
resource "aws_vpc_security_group_ingress_rule" "api_to_database" {
|
|
74
|
+
description = "Allow the API Lambda functions to connect to the database"
|
|
75
|
+
security_group_id = module.my_database.security_group_id
|
|
76
|
+
referenced_security_group_id = module.api.security_group_id
|
|
77
|
+
from_port = module.my_database.cluster_port
|
|
78
|
+
to_port = module.my_database.cluster_port
|
|
79
|
+
ip_protocol = "tcp"
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
resource "aws_vpc_security_group_egress_rule" "api_to_database" {
|
|
83
|
+
description = "Allow outbound traffic from the API Lambda functions to the database"
|
|
84
|
+
security_group_id = module.api.security_group_id
|
|
85
|
+
referenced_security_group_id = module.my_database.security_group_id
|
|
86
|
+
from_port = module.my_database.cluster_port
|
|
87
|
+
to_port = module.my_database.cluster_port
|
|
88
|
+
ip_protocol = "tcp"
|
|
66
89
|
}
|
|
67
90
|
```
|
|
68
91
|
|
|
69
|
-
Deploy the API Lambda functions into **private subnets with egress**, not private isolated subnets.
|
|
92
|
+
Deploy the API Lambda functions into **private subnets with egress**, not private isolated subnets. `appconfig_application_id`/`appconfig_application_arn` come from the shared <Link path="guides/runtime-config">runtime configuration</Link> AppConfig application declared once in your root module, not from the database module — passing them sets `RUNTIME_CONFIG_APP_ID` on the Lambda functions and grants them read access to the application. Include the `database` namespace when instantiating it so the database module's runtime configuration entry is deployed:
|
|
93
|
+
|
|
94
|
+
```hcl title="packages/infra/src/main.tf"
|
|
95
|
+
module "runtime_config_appconfig" {
|
|
96
|
+
source = "../../common/terraform/src/core/runtime-config/appconfig"
|
|
97
|
+
|
|
98
|
+
application_name = "my-app-runtime-config"
|
|
99
|
+
namespaces = ["connection", "agentcore", "database"]
|
|
100
|
+
}
|
|
101
|
+
```
|
|
70
102
|
|
|
71
103
|
</Fragment>
|
|
72
104
|
</Infrastructure>
|