-
-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
1,688 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
--- | ||
description: 'C4 Api' | ||
tags: | ||
- C4 | ||
published_at: 2024-07-25 | ||
--- | ||
|
||
# Nitric 'API' Architecture | ||
|
||
## 1. System Context (Level 1) | ||
|
||
- A **Developer** uses Nitric to create and manage APIs within their application. | ||
- App code interacts with the **API resource** through defined endpoints. | ||
- Developers define API specifications and implement backend logic to handle requests. | ||
- **Operations** use default or overridden Terraform modules to provision the necessary AWS API Gateway resources. | ||
- **AWS API Gateway v2** serves as the HTTP API management service. | ||
- **AWS Lambda** functions are deployed to handle API requests. | ||
- **AWS IAM** (implicitly assumed) provides roles and policies for secure interaction between API Gateway and Lambda functions. | ||
- **AWS ACM** manages SSL/TLS certificates for custom domain names. | ||
|
||
```mermaid | ||
flowchart TD | ||
Developer["Developer"] | ||
Operations["Operations"] | ||
App["nitric up"] | ||
APIGateway["AWS API Gateway v2<br>(HTTP API)"] | ||
Lambda["AWS Lambda Functions"] | ||
IAM["AWS IAM"] | ||
ACM["AWS ACM<br>(Certificates)"] | ||
Developer -->|Define API| App | ||
Operations -->|Terraform| App | ||
App -->|Create API Gateway| APIGateway | ||
App -->|Deploy Lambda Functions| Lambda | ||
App -->|Configure Permissions| IAM | ||
APIGateway -->|Invoke| Lambda | ||
ACM -->|Provide Certificates| APIGateway | ||
IAM -->|Manage Access| APIGateway | ||
App -->ACM | ||
classDef default line-height:1; | ||
classDef edgeLabel line-height:2; | ||
``` | ||
|
||
## 2. Container (Level 2) | ||
|
||
Each **API** is managed through AWS API Gateway v2 and interacts with backend Lambda functions to process HTTP requests. | ||
|
||
```mermaid | ||
flowchart TD | ||
Nitric["Nitric Application"] | ||
Nitric -->B(API 1) | ||
Nitric -->C(API 2) | ||
Nitric -->D(...) | ||
B(API 1) -->E(HTTP GET) | ||
B(API 1) -->F(HTTP POST) | ||
B(API 1) -->G(...) | ||
classDef default line-height:1; | ||
classDef edgeLabel line-height:2; | ||
``` | ||
|
||
## 3. Component (Level 3) | ||
|
||
### API Module | ||
|
||
- **aws_apigatewayv2_api.api_gateway** | ||
- Creates an AWS API Gateway v2 HTTP API. | ||
- Configures the API name, protocol type, API specification (`body`), and tags for identification and management. | ||
- **aws_apigatewayv2_stage.stage** | ||
- Creates a stage for the API Gateway. | ||
- Sets the stage name to `$default` and enables automatic deployment of changes. | ||
- **aws_lambda_permission.apigw_lambda** | ||
- Grants API Gateway permission to invoke the specified Lambda functions. | ||
- Iterates over `var.target_lambda_functions` to set permissions for each target function. | ||
- **data.aws_acm_certificate.cert** | ||
- Looks up existing ACM certificates for the specified domains. | ||
- Iterates over `var.domains` to retrieve certificate details for each domain. | ||
- **aws_apigatewayv2_domain_name.domain** | ||
|
||
- Creates custom domain names for the API Gateway using the retrieved ACM certificates. | ||
- Configures domain name settings, including the certificate ARN, endpoint type, and security policy. | ||
|
||
## 4. Code (Level 4) | ||
|
||
**Developers** write application code that imports the 'api' resource from the SDK, configures the api, and implements HTTP routes, implement middleware, etc. | ||
|
||
```typescript | ||
import { api } from '@nitric/sdk' | ||
|
||
const publicApi = api('public') | ||
|
||
api('public').get('/customers', (ctx) => { | ||
// construct response for the GET: /customers request... | ||
const responseBody = {} | ||
ctx.res.json(responseBody) | ||
}) | ||
|
||
const authMiddleware = async (ctx, next) => { | ||
// Perform auth validation. | ||
return await next(ctx) | ||
} | ||
|
||
const privateApi = api('private', { middleware: authMiddleware }) | ||
``` | ||
|
||
**Operations** will use the provided Terraform module to create and manage the AWS API Gateway as defined. | ||
|
||
```hcl | ||
resource "aws_apigatewayv2_api" "api_gateway" { | ||
name = var.name | ||
protocol_type = "HTTP" | ||
body = var.spec | ||
tags = { | ||
"x-nitric-${var.stack_id}-name" = var.name, | ||
"x-nitric-${var.stack_id}-type" = "api", | ||
} | ||
} | ||
resource "aws_apigatewayv2_stage" "stage" { | ||
api_id = aws_apigatewayv2_api.api_gateway.id | ||
name = "$default" | ||
auto_deploy = true | ||
} | ||
# deploy lambda permissions for execution | ||
resource "aws_lambda_permission" "apigw_lambda" { | ||
for_each = var.target_lambda_functions | ||
action = "lambda:InvokeFunction" | ||
function_name = each.value | ||
principal = "apigateway.amazonaws.com" | ||
source_arn = "${aws_apigatewayv2_api.api_gateway.execution_arn}/*/*/*" | ||
} | ||
# look up existing certificate for domains | ||
data "aws_acm_certificate" "cert" { | ||
for_each = var.domains | ||
domain = each.value | ||
} | ||
# deploy custom domain names | ||
resource "aws_apigatewayv2_domain_name" "domain" { | ||
for_each = var.domains | ||
domain_name = each.value | ||
domain_name_configuration { | ||
certificate_arn = data.aws_acm_certificate.cert[each.key].arn | ||
endpoint_type = "REGIONAL" | ||
security_policy = "TLS_1_2" | ||
} | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
--- | ||
description: 'C4 Nitric High-Level Architecture' | ||
tags: | ||
- C4 | ||
published_at: 2024-07-25 | ||
--- | ||
|
||
# Nitric High-Level Architecture | ||
|
||
Nitric allows your team to work together to build an application: | ||
|
||
- **Developer**: Writes application code with built-in support for APIs, file storage (bucket), secrets, key‑value store, and RDS, leveraging the Nitric SDK. | ||
- **Operations**: Customize, extend or use Nitric's generated IaC (Terraform or Pulumi) to provision and manage the resources that the developer needs for their application. | ||
- **SRE**: Configure environment/region/policy specific details, they also are heavily involved in overseeing that the Terraform modules themselves adhere to governance standards. | ||
|
||
The roles above may overlap depending on your organization structure, for example, it is not abnormal Developers to assume all roles, or for Operations and SRE responsibilities to be handled by the same team. | ||
|
||
```mermaid | ||
flowchart TD | ||
Developer[Developer] | ||
Operations[Operations] | ||
SRE[Site Reliablility Engineer] | ||
App[Nitric App - 'nitric up'] | ||
Repo[Code Repository] | ||
API[API Gateway] | ||
Bucket[Bucket - AWS S3] | ||
Secrets[Secrets - AWS Secrets Manager\n] | ||
KVStore[Key-Value Store - AWS DynamoDB] | ||
RDS[Relational Database - AWS RDS/Aurora] | ||
Other[Other resources] | ||
SRE -->|Deployment Config| Repo | ||
Developer -->|Code| Repo | ||
Operations -->|Extend/Customize Terraform| Repo | ||
Repo-->App | ||
App -->|Exposes REST/HTTP Routes| API | ||
App -->|Stores/Retrieves Files| Bucket | ||
App -->|Manages Sensitive Data| Secrets | ||
App -->|Reads/Writes Data| KVStore | ||
App -->|Executes SQL Queries| RDS | ||
App -->|1..n|Other | ||
classDef default line-height:1; | ||
classDef edgeLabel line-height:2; | ||
``` | ||
|
||
Nitric applications can have any number of APIs, Secrets, Buckets etc. Providers can also be extended to further support new resources, many which will work across all cloud providers and some that are cloud specific. | ||
|
||
## Example: Handling HTTP requests. | ||
|
||
Interaction with services that have been exposed as HTTP routes within an API gateway, Scheduled tasks, Event subscriptions, WebSocket handlers and more. | ||
|
||
```mermaid | ||
flowchart TD | ||
%% Actors | ||
Browser[Client Browser] | ||
%% Nitric Application Containers | ||
API[HTTP API - API Gateway] | ||
Service[GET Route] | ||
Service2[POST Route] | ||
Service3[...] | ||
%% Backend Services / Resources | ||
Bucket[AWS S3 Bucket] | ||
Secrets[AWS Secrets Manager] | ||
KVStore[AWS DynamoDB - Key-Value Store] | ||
RDS[AWS RDS/Aurora] | ||
%% Interactions | ||
Browser -->|Sends HTTP Request| API | ||
API -->|Triggers Service| Service | ||
API -->|Triggers Service| Service2 | ||
API -->|Triggers Service| Service3 | ||
Service -->|Manage/Uploads/Downloads files| Bucket | ||
Service -->|Retrieves credentials/config data| Secrets | ||
Service -->|Reads/Writes key data| KVStore | ||
Service -->|Queries/Updates relational data| RDS | ||
classDef default line-height:1; | ||
classDef edgeLabel line-height:2; | ||
``` | ||
|
||
- The **Client Browser** sends an HTTP request to the **API Gateway**. | ||
- The **API Gateway** acts as a proxy, forwarding the request to the appropriate **Services**. | ||
- The **Services** process the request by coordinating with different backend services, this is done through : | ||
- They interact with one or more **AWS S3 Bucket** to manage files. | ||
- They retrieve credentials or configuration from **AWS Secrets Manager**. | ||
- They use **AWS DynamoDB** for fast key-value operations. | ||
- They query or update structured data in **AWS RDS/Aurora**. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
--- | ||
description: 'C4 Buckets' | ||
tags: | ||
- C4 | ||
published_at: 2024-07-25 | ||
--- | ||
|
||
# Nitric 'Bucket' Architecture | ||
|
||
## 1. System Context (Level 1) | ||
|
||
- A **Developer** uses Nitric to manage S3 buckets within their application. | ||
- App code imports the **Bucket resource** from the Nitric SDK. | ||
- Developers configure buckets and implement application logic to securely access and manipulate bucket data. | ||
- Developers can also implement hanlders for on events like on read, write or delete. | ||
- **Operations** use default or overridden Terraform modules to provision the necessary AWS S3 resources. | ||
- **AWS S3** serves as the storage backend. | ||
- **AWS Lambda** functions are used to process events triggered by S3. | ||
- **AWS IAM** provides roles and policies for secure access to S3 buckets and Lambda functions. | ||
- **Random ID** resource is used to generate unique bucket names. | ||
|
||
```mermaid | ||
flowchart TD | ||
Developer["Developer"] | ||
Operations["Operations"] | ||
App["nitric up"] | ||
S3Bucket["AWS S3 Bucket"] | ||
Lambda["AWS Lambda Functions"] | ||
IAM["AWS IAM"] | ||
Developer -->|Code| App | ||
Operations -->|Terraform| App | ||
App -->|Create S3 Bucket| S3Bucket | ||
App -->|Configure Notifications| S3Bucket | ||
App -->|Allow Lambda Invocation| Lambda | ||
S3Bucket -->|Store/Retrieve Data| App | ||
Lambda -->|Process Events| App | ||
App -->|Provide Access| IAM | ||
IAM -->S3Bucket | ||
classDef default line-height:1; | ||
classDef edgeLabel line-height:2; | ||
``` | ||
|
||
## 2. Container (Level 2) | ||
|
||
Each **Bucket** is managed through AWS S3 and accessed by the application through securely configured mechanisms provided by Nitric. | ||
|
||
```mermaid | ||
flowchart TD | ||
Nitric["Nitric Application"] | ||
Nitric -->B(Bucket 1) | ||
Nitric -->C(Bucket 2) | ||
Nitric -->D(...) | ||
B(BUCKET 1) -->E(ON Read) | ||
B(BUCKET 1) -->F(ON Write) | ||
B(BUCKET 1) -->G(ON Delete) | ||
``` | ||
|
||
## 3. Component (Level 3) | ||
|
||
### Bucket Module | ||
|
||
- **random_id.bucket_id** | ||
- Generates a random ID for the S3 bucket to ensure unique naming. | ||
- **aws_s3_bucket.bucket** | ||
- Creates an AWS S3 bucket with a unique name by appending the generated random ID. | ||
- Configures tags for identification and management. | ||
- **aws_lambda_permission.allow_bucket** | ||
- Grants AWS S3 permission to invoke the specified Lambda functions. | ||
- Iterates over `var.notification_targets` to set permissions for each target. | ||
- **aws_s3_bucket_notification.bucket_notification** | ||
- Configures S3 bucket notifications to trigger Lambda functions based on specified events. | ||
- Uses dynamic blocks to handle multiple Lambda function notifications. | ||
|
||
## 4. Code (Level 4) | ||
|
||
**Developers** write application code that imports the 'bucket' resource from the SDK, configures the bucket, and implements the application logic to read, write and delete files. | ||
|
||
```typescript | ||
import { bucket } from '@nitric/sdk' | ||
|
||
const profiles = bucket('profiles').allow('read') | ||
|
||
const image = await profiles.file('users/bruce-wayne/profile.png').read() | ||
``` | ||
|
||
**Operations** will use the provided Terraform module to create and manage the AWS S3 Buckets as defined. | ||
|
||
```hcl | ||
# Generate a random id for the bucket | ||
resource "random_id" "bucket_id" { | ||
byte_length = 8 | ||
keepers = { | ||
# Generate a new id each time we switch to a new AMI id | ||
bucket_name = var.bucket_name | ||
} | ||
} | ||
# AWS S3 bucket | ||
resource "aws_s3_bucket" "bucket" { | ||
bucket = "${var.bucket_name}-${random_id.bucket_id.hex}" | ||
tags = { | ||
"x-nitric-${var.stack_id}-name" = var.bucket_name | ||
"x-nitric-${var.stack_id}-type" = "bucket" | ||
} | ||
} | ||
# Deploy bucket lambda invocation permissions | ||
resource "aws_lambda_permission" "allow_bucket" { | ||
for_each = var.notification_targets | ||
action = "lambda:InvokeFunction" | ||
function_name = each.value.arn | ||
principal = "s3.amazonaws.com" | ||
source_arn = aws_s3_bucket.bucket.arn | ||
} | ||
# Deploy lambda notifications | ||
resource "aws_s3_bucket_notification" "bucket_notification" { | ||
bucket = aws_s3_bucket.bucket.id | ||
// make dynamic blocks for lambda function | ||
dynamic "lambda_function" { | ||
for_each = var.notification_targets | ||
content { | ||
lambda_function_arn = lambda_function.value.arn | ||
events = lambda_function.value.events | ||
filter_prefix = lambda_function.value.prefix | ||
} | ||
} | ||
} | ||
``` |
Oops, something went wrong.