init: Initial commit
This commit is contained in:
155
.docs/architecture.md
Normal file
155
.docs/architecture.md
Normal file
@@ -0,0 +1,155 @@
|
||||
# Architecture
|
||||
|
||||
## System Overview
|
||||
|
||||
The SecNex API Gateway follows a modular architecture with clear separation of concerns. The system is built using the chi/v5 HTTP router and implements a middleware pipeline pattern.
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Client Request │
|
||||
└─────────────────────────┬───────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Gateway (chi Router) │
|
||||
│ ┌──────────────────────────────────────────────────────┐ │
|
||||
│ │ Middleware Pipeline │ │
|
||||
│ │ ┌────────────┐ ┌────────────┐ ┌──────────────┐ │ │
|
||||
│ │ │ Request ID │→ │ Real IP │→ │ Logger │ │ │
|
||||
│ │ └────────────┘ └────────────┘ └──────────────┘ │ │
|
||||
│ └──────────────────────────────────────────────────────┘ │
|
||||
└─────────────────────────┬───────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Route Handler │
|
||||
│ ┌──────────────────────────────────────────────────────┐ │
|
||||
│ │ Per-Route Middleware Chain │ │
|
||||
│ │ ┌────────────┐ ┌─────────┐ ┌──────────────┐ │ │
|
||||
│ │ │ Strip │→ │ WAF │→ │ Auth │ │ │
|
||||
│ │ │ Prefix │ │ Filter │ │ Middleware │ │ │
|
||||
│ │ └────────────┘ └─────────┘ └──────────────┘ │ │
|
||||
│ └──────────────────────────────────────────────────────┘ │
|
||||
└─────────────────────────┬───────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Reverse Proxy (httputil.ReverseProxy) │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ Backend Service │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Component Architecture
|
||||
|
||||
### Directory Structure
|
||||
|
||||
```
|
||||
app/
|
||||
├── main.go # Application entry point
|
||||
├── config/ # Configuration management
|
||||
│ ├── config.go # Config interface
|
||||
│ ├── file.go # File-based config loader
|
||||
│ └── types.go # Configuration type definitions
|
||||
├── server/ # Core server components
|
||||
│ ├── gateway.go # Main gateway server
|
||||
│ ├── routes.go # Route handler creation
|
||||
│ └── proxy.go # Host-based virtual hosting
|
||||
├── middlewares/ # HTTP middleware
|
||||
│ ├── auth.go # Authentication middleware
|
||||
│ └── waf.go # Web Application Firewall
|
||||
├── handlers/ # Request handlers
|
||||
│ └── route.go # Route handlers (placeholder)
|
||||
└── res/ # HTTP responses
|
||||
└── error.go # Error response utilities
|
||||
```
|
||||
|
||||
### Core Components
|
||||
|
||||
#### Gateway (`server/gateway.go`)
|
||||
|
||||
The Gateway is the main server component that:
|
||||
- Initializes the chi router
|
||||
- Applies global middleware (request_id, real_ip, logger)
|
||||
- Registers route handlers
|
||||
- Starts the HTTP server
|
||||
|
||||
#### Routes (`server/routes.go`)
|
||||
|
||||
The Routes component creates handlers for each configured route:
|
||||
1. Finds the matching API backend target
|
||||
2. Creates a reverse proxy using `httputil.NewSingleHostReverseProxy`
|
||||
3. Optionally strips prefix from the request path
|
||||
4. Applies middleware chain: WAF → Auth
|
||||
|
||||
#### Configuration (`config/`)
|
||||
|
||||
Configuration is loaded from YAML and provides:
|
||||
- Gateway settings (host, port, features)
|
||||
- Route definitions with security policies
|
||||
- API backend targets
|
||||
- Proxy configurations for virtual hosting
|
||||
|
||||
## Middleware Chain
|
||||
|
||||
### Global Middleware
|
||||
|
||||
Applied to all requests via chi middleware:
|
||||
|
||||
| Feature | Description |
|
||||
|---------|-------------|
|
||||
| `request_id` | Adds unique request ID to context |
|
||||
| `real_ip` | Determines the real client IP |
|
||||
| `logger` | Logs HTTP requests |
|
||||
|
||||
### Per-Route Middleware
|
||||
|
||||
Applied in order to each route handler:
|
||||
|
||||
1. **StripPrefix** - Removes specified prefix from request path before proxying
|
||||
2. **WAF** - Filters requests based on HTTP method
|
||||
3. **Auth** - Validates authentication credentials
|
||||
|
||||
## Request Flow
|
||||
|
||||
1. **Client Request** → Gateway receives HTTP request
|
||||
2. **Global Middleware** → Request ID, Real IP, Logging applied
|
||||
3. **Route Matching** → Chi matches route pattern (e.g., `/api/v1/dev/*`)
|
||||
4. **Per-Route Middleware** → StripPrefix → WAF → Auth
|
||||
5. **Reverse Proxy** → Request forwarded to backend API
|
||||
6. **Response** → Backend response returned to client
|
||||
|
||||
## Authentication Flow
|
||||
|
||||
The authentication middleware supports path-based filtering:
|
||||
|
||||
```
|
||||
┌─────────────────────┐
|
||||
│ Include Set? │
|
||||
└──────────┬──────────┘
|
||||
│
|
||||
┌─────┴─────┐
|
||||
│ Yes │ No
|
||||
▼ ▼
|
||||
┌─────────┐ ┌─────────────┐
|
||||
│ Match │ │ Exclude │
|
||||
│ Include?│ │ Set? │
|
||||
└────┬────┘ └──────┬──────┘
|
||||
│ │
|
||||
┌──┴──┐ ┌──┴──┐
|
||||
│Yes │No │Yes │No
|
||||
▼ ▼ ▼ ▼
|
||||
┌────┐┌────┐ ┌────┐┌────┐
|
||||
│Auth││Skip│ │Skip││Auth│
|
||||
└────┘└────┘ └────┘└────┘
|
||||
```
|
||||
|
||||
## Configuration Flow
|
||||
|
||||
1. Load `gateway.yaml` via `config.NewFileConfig()`
|
||||
2. Parse YAML into `Configuration` struct
|
||||
3. Create Gateway with configuration
|
||||
4. Create Routes from route definitions and API targets
|
||||
5. Register handlers with chi router
|
||||
6. Start HTTP server
|
||||
203
.docs/configuration.md
Normal file
203
.docs/configuration.md
Normal file
@@ -0,0 +1,203 @@
|
||||
# Configuration
|
||||
|
||||
The gateway is configured via a single YAML file (`gateway.yaml`). This document describes all available configuration options.
|
||||
|
||||
## Configuration File Structure
|
||||
|
||||
```yaml
|
||||
gateway:
|
||||
host: "0.0.0.0"
|
||||
port: 8080
|
||||
features:
|
||||
- request_id
|
||||
- real_ip
|
||||
- logger
|
||||
|
||||
proxies:
|
||||
- id: "proxy-id"
|
||||
host: "example.com"
|
||||
target: "http://backend:3000"
|
||||
|
||||
apis:
|
||||
- id: "api-id"
|
||||
target: "https://api.example.com"
|
||||
|
||||
routes:
|
||||
- id: "route-id"
|
||||
path: "/api/v1/*"
|
||||
strip_prefix:
|
||||
enabled: true
|
||||
prefix: "/api/v1"
|
||||
security:
|
||||
auth:
|
||||
enabled: true
|
||||
type: "api_key"
|
||||
header: "X-Api-Key"
|
||||
path:
|
||||
include: []
|
||||
exclude: []
|
||||
waf:
|
||||
enabled: true
|
||||
methods: ["GET", "POST"]
|
||||
```
|
||||
|
||||
## Sections
|
||||
|
||||
### Gateway
|
||||
|
||||
Global gateway configuration.
|
||||
|
||||
| Field | Type | Description | Default |
|
||||
|-------|------|-------------|---------|
|
||||
| `host` | string | Host address to bind to | Required |
|
||||
| `port` | integer | Port number | Required |
|
||||
| `features` | array | Global middleware features | Required |
|
||||
|
||||
#### Features
|
||||
|
||||
Available global features:
|
||||
|
||||
| Feature | Description |
|
||||
|---------|-------------|
|
||||
| `request_id` | Adds unique request ID to each request |
|
||||
| `real_ip` | Determines real client IP from headers |
|
||||
| `logger` | Logs all HTTP requests |
|
||||
|
||||
### Proxies
|
||||
|
||||
Virtual hosting configuration for host-based routing.
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `id` | string | Unique proxy identifier |
|
||||
| `host` | string | Domain/host name to match |
|
||||
| `target` | string | Backend URL to proxy to |
|
||||
|
||||
### APIs
|
||||
|
||||
Backend service definitions referenced by routes.
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `id` | string | Unique API identifier (referenced by routes) |
|
||||
| `target` | string | Backend URL |
|
||||
|
||||
### Routes
|
||||
|
||||
Route definitions with security policies.
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `id` | string | Unique route identifier (must match API ID) |
|
||||
| `path` | string | Chi route pattern (e.g., `/api/v1/*`) |
|
||||
| `strip_prefix` | object | Prefix stripping configuration |
|
||||
| `security` | object | Security policies (auth, WAF) |
|
||||
|
||||
#### Strip Prefix
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `enabled` | boolean | Enable prefix stripping |
|
||||
| `prefix` | string | Prefix to remove from path |
|
||||
|
||||
#### Security
|
||||
|
||||
##### Authentication
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `enabled` | boolean | Enable authentication |
|
||||
| `type` | string | Auth type (`api_key`, `session`, etc.) |
|
||||
| `header` | string | Header name to validate |
|
||||
| `path` | object | Path-based filtering |
|
||||
|
||||
##### Auth Path Filtering
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `include` | array | Paths that require auth (empty = all) |
|
||||
| `exclude` | array | Paths that skip auth |
|
||||
|
||||
**Include/Exclude Logic:**
|
||||
- If `include` is set → only matching paths require auth
|
||||
- If `include` is empty → all paths require auth except `exclude`
|
||||
|
||||
Wildcards (`*`) are supported in path patterns.
|
||||
|
||||
##### WAF (Web Application Firewall)
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `enabled` | boolean | Enable WAF |
|
||||
| `methods` | array | Allowed HTTP methods (`["*"]` for all) |
|
||||
|
||||
## Example Configurations
|
||||
|
||||
### Public API (No Auth)
|
||||
|
||||
```yaml
|
||||
routes:
|
||||
- id: "public-api"
|
||||
path: "/public/*"
|
||||
strip_prefix:
|
||||
enabled: true
|
||||
prefix: "/public"
|
||||
security:
|
||||
auth:
|
||||
enabled: false
|
||||
waf:
|
||||
enabled: true
|
||||
methods: ["GET", "POST"]
|
||||
```
|
||||
|
||||
### Protected API with API Key
|
||||
|
||||
```yaml
|
||||
routes:
|
||||
- id: "protected-api"
|
||||
path: "/api/v1/*"
|
||||
strip_prefix:
|
||||
enabled: true
|
||||
prefix: "/api/v1"
|
||||
security:
|
||||
auth:
|
||||
enabled: true
|
||||
type: "api_key"
|
||||
header: "X-Api-Key"
|
||||
waf:
|
||||
enabled: true
|
||||
methods: ["*"]
|
||||
```
|
||||
|
||||
### Mixed Auth (Path-based)
|
||||
|
||||
```yaml
|
||||
routes:
|
||||
- id: "mixed-api"
|
||||
path: "/api/*"
|
||||
security:
|
||||
auth:
|
||||
enabled: true
|
||||
header: "Authorization"
|
||||
path:
|
||||
include: ["/api/admin/*", "/api/users/*/profile"]
|
||||
exclude: ["/api/health", "/api/public/*"]
|
||||
waf:
|
||||
enabled: true
|
||||
methods: ["*"]
|
||||
```
|
||||
|
||||
## Configuration Loading
|
||||
|
||||
The gateway loads configuration from a file path relative to the binary:
|
||||
|
||||
```go
|
||||
cfg, err := config.NewFileConfig("../gateway.yaml")
|
||||
```
|
||||
|
||||
For Docker deployments, mount the config file:
|
||||
|
||||
```yaml
|
||||
volumes:
|
||||
- ./gateway.yaml:/app/gateway.yaml:ro
|
||||
```
|
||||
267
.docs/deployment.md
Normal file
267
.docs/deployment.md
Normal file
@@ -0,0 +1,267 @@
|
||||
# Deployment
|
||||
|
||||
## Docker Deployment
|
||||
|
||||
### Using Docker Compose (Recommended)
|
||||
|
||||
```bash
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
This will:
|
||||
1. Pull the image `git.secnex.io/secnex/api-gateway:latest`
|
||||
2. Build locally if the image cannot be pulled
|
||||
3. Start the gateway on port 8080
|
||||
|
||||
### Manual Docker Build
|
||||
|
||||
```bash
|
||||
# Build the image
|
||||
docker build -t secnex-gateway .
|
||||
|
||||
# Run the container
|
||||
docker run -d \
|
||||
-p 8080:8080 \
|
||||
-v $(pwd)/gateway.yaml:/app/gateway.yaml:ro \
|
||||
--name gateway \
|
||||
secnex-gateway
|
||||
```
|
||||
|
||||
### Docker Image from Registry
|
||||
|
||||
```bash
|
||||
docker pull git.secnex.io/secnex/api-gateway:latest
|
||||
docker run -d \
|
||||
-p 8080:8080 \
|
||||
-v $(pwd)/gateway.yaml:/app/gateway.yaml:ro \
|
||||
--name gateway \
|
||||
git.secnex.io/secnex/api-gateway:latest
|
||||
```
|
||||
|
||||
## Configuration Management
|
||||
|
||||
### Production Configuration
|
||||
|
||||
Create a production-specific `gateway.yaml`:
|
||||
|
||||
```yaml
|
||||
gateway:
|
||||
host: "0.0.0.0"
|
||||
port: 8080
|
||||
features:
|
||||
- request_id
|
||||
- real_ip
|
||||
- logger
|
||||
|
||||
# ... rest of configuration
|
||||
```
|
||||
|
||||
### Environment-Specific Configs
|
||||
|
||||
Use multiple config files:
|
||||
|
||||
```bash
|
||||
# Development
|
||||
docker run -v $(pwd)/gateway.dev.yaml:/app/gateway.yaml ...
|
||||
|
||||
# Production
|
||||
docker run -v $(pwd)/gateway.prod.yaml:/app/gateway.yaml ...
|
||||
```
|
||||
|
||||
## Kubernetes Deployment
|
||||
|
||||
### Deployment Manifest
|
||||
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: api-gateway
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: api-gateway
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: api-gateway
|
||||
spec:
|
||||
containers:
|
||||
- name: gateway
|
||||
image: git.secnex.io/secnex/api-gateway:latest
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
volumeMounts:
|
||||
- name: config
|
||||
mountPath: /app/gateway.yaml
|
||||
subPath: gateway.yaml
|
||||
resources:
|
||||
requests:
|
||||
memory: "128Mi"
|
||||
cpu: "100m"
|
||||
limits:
|
||||
memory: "256Mi"
|
||||
cpu: "500m"
|
||||
volumes:
|
||||
- name: config
|
||||
configMap:
|
||||
name: gateway-config
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: gateway-config
|
||||
data:
|
||||
gateway.yaml: |
|
||||
gateway:
|
||||
host: "0.0.0.0"
|
||||
port: 8080
|
||||
features:
|
||||
- request_id
|
||||
- real_ip
|
||||
- logger
|
||||
# ... rest of configuration
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: api-gateway
|
||||
spec:
|
||||
selector:
|
||||
app: api-gateway
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 8080
|
||||
type: LoadBalancer
|
||||
```
|
||||
|
||||
### Apply to Kubernetes
|
||||
|
||||
```bash
|
||||
kubectl apply -f k8s-deployment.yaml
|
||||
```
|
||||
|
||||
## Health Checks
|
||||
|
||||
The gateway provides a health check endpoint:
|
||||
|
||||
```bash
|
||||
curl http://localhost:8080/_/health
|
||||
```
|
||||
|
||||
### Kubernetes Liveness/Readiness Probes
|
||||
|
||||
```yaml
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /_/health
|
||||
port: 8080
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 10
|
||||
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /_/health
|
||||
port: 8080
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 5
|
||||
```
|
||||
|
||||
## Reverse Proxy Setup
|
||||
|
||||
### Nginx Reverse Proxy
|
||||
|
||||
```nginx
|
||||
upstream gateway {
|
||||
server localhost:8080;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name api.example.com;
|
||||
|
||||
location / {
|
||||
proxy_pass http://gateway;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Monitoring
|
||||
|
||||
### Log Collection
|
||||
|
||||
Logs are output in JSON format. Configure your log collector:
|
||||
|
||||
**Fluentd example:**
|
||||
```xml
|
||||
<source>
|
||||
@type tail
|
||||
path /var/log/containers/gateway*.log
|
||||
pos_file /var/log/gateway.log.pos
|
||||
tag gateway.*
|
||||
<parse>
|
||||
@type json
|
||||
</parse>
|
||||
</source>
|
||||
```
|
||||
|
||||
### Metrics
|
||||
|
||||
Consider adding Prometheus metrics for production deployments:
|
||||
- Request count by route
|
||||
- Response time histograms
|
||||
- Error rates
|
||||
- Backend connection status
|
||||
|
||||
## Security Considerations
|
||||
|
||||
### Production Checklist
|
||||
|
||||
- [ ] Use TLS/HTTPS in production
|
||||
- [ ] Restrict gateway configuration file permissions
|
||||
- [ ] Use secrets management for API keys
|
||||
- [ ] Enable rate limiting
|
||||
- [ ] Configure WAF rules appropriately
|
||||
- [ ] Regular security updates
|
||||
- [ ] Log monitoring and alerting
|
||||
- [ ] Backup configuration files
|
||||
|
||||
### TLS Termination
|
||||
|
||||
Options for TLS:
|
||||
1. **At the gateway** - Configure Go server with TLS
|
||||
2. **At reverse proxy** - Use Nginx/HAProxy with TLS
|
||||
3. **At cloud load balancer** - Use AWS ALB, GCP LB, etc.
|
||||
|
||||
## Scaling
|
||||
|
||||
### Horizontal Scaling
|
||||
|
||||
Run multiple instances behind a load balancer:
|
||||
|
||||
```yaml
|
||||
# docker-compose.yml
|
||||
services:
|
||||
gateway:
|
||||
deploy:
|
||||
replicas: 3
|
||||
```
|
||||
|
||||
### Resource Limits
|
||||
|
||||
Configure appropriate resource limits:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
limits:
|
||||
memory: "512Mi"
|
||||
cpu: "1000m"
|
||||
reservations:
|
||||
memory: "256Mi"
|
||||
cpu: "500m"
|
||||
```
|
||||
185
.docs/development.md
Normal file
185
.docs/development.md
Normal file
@@ -0,0 +1,185 @@
|
||||
# Development
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Go 1.25.5 or later
|
||||
- Git
|
||||
|
||||
## Setup
|
||||
|
||||
1. Clone the repository:
|
||||
```bash
|
||||
git clone git.secnex.io/secnex/gateway.git
|
||||
cd gateway
|
||||
```
|
||||
|
||||
2. Install dependencies:
|
||||
```bash
|
||||
cd app
|
||||
go mod download
|
||||
```
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
gateway/
|
||||
├── app/ # Application source code
|
||||
│ ├── main.go # Entry point
|
||||
│ ├── config/ # Configuration management
|
||||
│ ├── server/ # Core server components
|
||||
│ ├── middlewares/ # HTTP middleware
|
||||
│ ├── handlers/ # Request handlers
|
||||
│ └── res/ # Response utilities
|
||||
├── .docs/ # Documentation
|
||||
├── gateway.yaml # Configuration file
|
||||
├── Dockerfile # Docker image definition
|
||||
├── docker-compose.yml # Docker Compose configuration
|
||||
└── .gitignore # Git ignore rules
|
||||
```
|
||||
|
||||
## Running Locally
|
||||
|
||||
```bash
|
||||
cd app
|
||||
go run main.go
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
```bash
|
||||
# Run all tests
|
||||
go test ./...
|
||||
|
||||
# Run tests with coverage
|
||||
go test -cover ./...
|
||||
|
||||
# Run tests for specific package
|
||||
go test ./config
|
||||
go test ./server
|
||||
go test ./middlewares
|
||||
```
|
||||
|
||||
## Building
|
||||
|
||||
```bash
|
||||
# Build binary
|
||||
cd app
|
||||
go build -o gateway main.go
|
||||
|
||||
# Build for Linux
|
||||
GOOS=linux go build -o gateway-linux main.go
|
||||
|
||||
# Build for macOS (ARM64)
|
||||
GOOS=darwin GOARCH=arm64 go build -o gateway-darwin-arm64 main.go
|
||||
```
|
||||
|
||||
## Code Style
|
||||
|
||||
- Follow standard Go conventions
|
||||
- Use `gofmt` for formatting
|
||||
- Keep functions focused and small
|
||||
- Add comments for exported types and functions
|
||||
- Use meaningful variable names
|
||||
|
||||
## Adding Features
|
||||
|
||||
### Adding a New Middleware
|
||||
|
||||
Create a new file in `app/middlewares/`:
|
||||
|
||||
```go
|
||||
package middlewares
|
||||
|
||||
import "net/http"
|
||||
|
||||
func MyMiddleware(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// Your logic here
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
Then apply it in `server/routes.go`:
|
||||
|
||||
```go
|
||||
if route.Security.CustomMiddleware.Enabled {
|
||||
handlers[route.Path] = middlewares.MyMiddleware(handlers[route.Path])
|
||||
}
|
||||
```
|
||||
|
||||
### Adding a New Configuration Field
|
||||
|
||||
1. Update `config/types.go` to add the field to the struct
|
||||
2. Update `gateway.yaml` with the new configuration
|
||||
3. Update configuration documentation in `.docs/configuration.md`
|
||||
|
||||
### Adding a New Handler
|
||||
|
||||
Add your handler in `app/handlers/route.go`:
|
||||
|
||||
```go
|
||||
package handlers
|
||||
|
||||
import "net/http"
|
||||
|
||||
func MyCustomHandler(w http.ResponseWriter, r *http.Request) {
|
||||
// Your logic here
|
||||
}
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
When making changes to the codebase, update the relevant documentation:
|
||||
|
||||
- **Architecture changes** → `.docs/architecture.md`
|
||||
- **Configuration changes** → `.docs/configuration.md`
|
||||
- **New features or usage changes** → `.docs/usage.md`
|
||||
- **Deployment changes** → `.docs/deployment.md`
|
||||
|
||||
## Debugging
|
||||
|
||||
### Enable Debug Logging
|
||||
|
||||
Debug logging is enabled by default in `main.go`:
|
||||
|
||||
```go
|
||||
masterlog.SetLevel(masterlog.LevelDebug)
|
||||
```
|
||||
|
||||
### Using Delve
|
||||
|
||||
```bash
|
||||
# Install Delve
|
||||
go install github.com/go-delve/delve/cmd/dlv@latest
|
||||
|
||||
# Debug main.go
|
||||
cd app
|
||||
dlv debug main.go
|
||||
```
|
||||
|
||||
## Internal Module
|
||||
|
||||
The project uses an internal Go module:
|
||||
```
|
||||
git.secnex.io/secnex/gateway
|
||||
```
|
||||
|
||||
When importing packages within the project, use this path:
|
||||
```go
|
||||
import "git.secnex.io/secnex/gateway/config"
|
||||
```
|
||||
|
||||
## Release Process
|
||||
|
||||
1. Update version in documentation
|
||||
2. Tag the release:
|
||||
```bash
|
||||
git tag -a v1.0.0 -m "Release v1.0.0"
|
||||
git push origin v1.0.0
|
||||
```
|
||||
|
||||
3. Build Docker image:
|
||||
```bash
|
||||
docker build -t git.secnex.io/secnex/api-gateway:v1.0.0 .
|
||||
```
|
||||
45
.docs/index.md
Normal file
45
.docs/index.md
Normal file
@@ -0,0 +1,45 @@
|
||||
# SecNex API Gateway Documentation
|
||||
|
||||
Welcome to the official documentation for the SecNex API Gateway.
|
||||
|
||||
## Overview
|
||||
|
||||
SecNex API Gateway is a high-performance, configurable API gateway built in Go. It provides reverse proxy capabilities with built-in security features including authentication and web application firewall (WAF) functionality.
|
||||
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
# Run locally
|
||||
cd app
|
||||
go run main.go
|
||||
|
||||
# Run with Docker
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
- [Architecture](./architecture.md) - System architecture and component design
|
||||
- [Configuration](./configuration.md) - Configuration reference and examples
|
||||
- [Usage](./usage.md) - How to use the gateway
|
||||
- [Development](./development.md) - Development setup and guide
|
||||
- [Deployment](./deployment.md) - Deployment instructions
|
||||
|
||||
## Features
|
||||
|
||||
- **Reverse Proxy** Route requests to backend services
|
||||
- **Authentication** Header-based authentication (API key, session tokens)
|
||||
- **WAF** Web Application Firewall with method filtering and IP-based access control
|
||||
- **Path-based Routing** Configurable route patterns with prefix stripping
|
||||
- **Middleware Pipeline** Extensible middleware chain for custom logic
|
||||
- **Logging** Structured logging with sensitive field pseudonymization
|
||||
|
||||
## Health Check
|
||||
|
||||
The gateway provides a health check endpoint:
|
||||
|
||||
```
|
||||
GET /_/health
|
||||
```
|
||||
|
||||
Returns `200 OK` when the gateway is running.
|
||||
176
.docs/usage.md
Normal file
176
.docs/usage.md
Normal file
@@ -0,0 +1,176 @@
|
||||
# Usage
|
||||
|
||||
## Running the Gateway
|
||||
|
||||
### Local Development
|
||||
|
||||
```bash
|
||||
cd app
|
||||
go run main.go
|
||||
```
|
||||
|
||||
The gateway will start on the configured host and port (default: `0.0.0.0:8080`).
|
||||
|
||||
### Docker
|
||||
|
||||
```bash
|
||||
# Pull and run (builds locally if image not available)
|
||||
docker compose up -d
|
||||
|
||||
# View logs
|
||||
docker compose logs -f gateway
|
||||
|
||||
# Stop
|
||||
docker compose down
|
||||
```
|
||||
|
||||
### Build from Source
|
||||
|
||||
```bash
|
||||
cd app
|
||||
go build -o gateway main.go
|
||||
./gateway
|
||||
```
|
||||
|
||||
## Health Check
|
||||
|
||||
Check if the gateway is running:
|
||||
|
||||
```bash
|
||||
curl http://localhost:8080/_/health
|
||||
```
|
||||
|
||||
Response: `OK`
|
||||
|
||||
## Making Requests
|
||||
|
||||
After configuring routes in `gateway.yaml`, make requests to the gateway:
|
||||
|
||||
```bash
|
||||
# Example: Request to a route configured at /api/v1/dev/*
|
||||
curl http://localhost:8080/api/v1/dev/users
|
||||
|
||||
# With API key authentication
|
||||
curl -H "X-Api-Key: your-key-here" http://localhost:8080/api/v1/dev/data
|
||||
|
||||
# With session authentication
|
||||
curl -H "Authorization: Bearer token" http://localhost:8080/api/v1/protected
|
||||
```
|
||||
|
||||
## Route Examples
|
||||
|
||||
### Strip Prefix Example
|
||||
|
||||
**Configuration:**
|
||||
```yaml
|
||||
routes:
|
||||
- id: "api"
|
||||
path: "/api/v1/*"
|
||||
strip_prefix:
|
||||
enabled: true
|
||||
prefix: "/api/v1"
|
||||
```
|
||||
|
||||
**Request flow:**
|
||||
- Client requests: `/api/v1/users/123`
|
||||
- Gateway strips: `/api/v1`
|
||||
- Backend receives: `/users/123`
|
||||
|
||||
### Authentication Example
|
||||
|
||||
**Configuration:**
|
||||
```yaml
|
||||
security:
|
||||
auth:
|
||||
enabled: true
|
||||
type: "api_key"
|
||||
header: "X-Api-Key"
|
||||
```
|
||||
|
||||
**Valid request:**
|
||||
```bash
|
||||
curl -H "X-Api-Key: secret123" http://localhost:8080/api/v1/data
|
||||
```
|
||||
|
||||
**Invalid request (missing header):**
|
||||
```bash
|
||||
curl http://localhost:8080/api/v1/data
|
||||
# Returns: 401 Unauthorized
|
||||
```
|
||||
|
||||
### WAF Method Filtering Example
|
||||
|
||||
**Configuration:**
|
||||
```yaml
|
||||
security:
|
||||
waf:
|
||||
enabled: true
|
||||
methods: ["GET", "POST"]
|
||||
```
|
||||
|
||||
**Allowed:**
|
||||
```bash
|
||||
curl -X GET http://localhost:8080/api/v1/data
|
||||
curl -X POST http://localhost:8080/api/v1/data
|
||||
```
|
||||
|
||||
**Blocked:**
|
||||
```bash
|
||||
curl -X DELETE http://localhost:8080/api/v1/data
|
||||
# Returns: 403 Forbidden
|
||||
```
|
||||
|
||||
## Logging
|
||||
|
||||
The gateway uses structured logging via `masterlog`. Logs include:
|
||||
|
||||
- Request ID (if enabled)
|
||||
- Client IP (if real_ip enabled)
|
||||
- Request method and path
|
||||
- Response status
|
||||
|
||||
**Example log output:**
|
||||
```json
|
||||
{
|
||||
"level": "info",
|
||||
"msg": "Registering route",
|
||||
"path": "/api/v1/dev/*"
|
||||
}
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Gateway fails to start
|
||||
|
||||
1. Check if port is already in use:
|
||||
```bash
|
||||
lsof -i :8080
|
||||
```
|
||||
|
||||
2. Verify configuration file exists and is valid YAML
|
||||
|
||||
3. Check logs for detailed error messages
|
||||
|
||||
### 401 Unauthorized
|
||||
|
||||
- Verify auth header is included
|
||||
- Check header name matches configuration
|
||||
- Verify path is not excluded from auth
|
||||
|
||||
### 403 Forbidden
|
||||
|
||||
- Check WAF method configuration
|
||||
- Verify HTTP method is allowed
|
||||
|
||||
### Backend connection errors
|
||||
|
||||
- Verify API target URL is correct
|
||||
- Check backend service is running
|
||||
- Verify network connectivity
|
||||
|
||||
## Performance Considerations
|
||||
|
||||
- The gateway uses Go's `httputil.ReverseProxy` for efficient proxying
|
||||
- Keep-alive connections are reused by default
|
||||
- Consider connection pooling for high-traffic scenarios
|
||||
- Monitor memory usage with high request volumes
|
||||
Reference in New Issue
Block a user