A NestJS HTTP server that exposes the Voidkey zero-trust credential broker API endpoints.
The broker-server provides HTTP endpoints for the Voidkey credential broker system. It wraps the broker-core library and exposes RESTful APIs for credential minting, key listing, and system health checks. Built with NestJS, it provides enterprise-grade features like dependency injection, middleware support, and comprehensive logging.
The broker-server acts as the HTTP interface in the zero-trust credential broker workflow:
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Client │──▶│ Client IdP │ │ Voidkey │──▶│ Broker IdP │──▶│ Access │
│ CLI │ │ (Auth0, │ │ Broker │ │ (Keycloak, │ │ Provider │
│ │ │ GitHub, etc)│ │ │ │ Okta, etc) │ │ (STS) │
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
│ │ │ │ │
│ 1. Get client │ │ │ │
│ OIDC token │ │ │ │
│◀─────────────────│ │ │ │
│ │ │ │
│ 2. Request credentials with token │ │ │
│─────────────────────────────────────▶│ │ │
│ │ │ │
│ 3. Validate client token │ │
│ │ │ │
│ │ 4. Get broker │ │
│ │ OIDC token │ │
│ │◀─────────────────│ │
│ │ │
│ │ 5. Mint credentials with broker token │
│ │─────────────────────────────────────▶│
│ │ │
│ │ 6. Return temp credentials │
│ │◀─────────────────────────────────────│
│ │ │
│ 7. Return temp credentials to client │ │
│◀─────────────────────────────────────│ │
│ │
│ 8. Use credentials for operations │
│─────────────────────────────────────────────────────────────────────────────▶│
npm installnpm run build # Build for production
npm run start # Run production server
npm run dev # Development server with ts-nodenpm run test # Run Jest tests
npm run test:watch # Watch mode testing
npm run test:cov # Coverage report
npm run test:debug # Debug mode testingMint credentials for specified keys using an OIDC token.
Request:
curl -X POST http://localhost:3000/credentials/mint \
-H "Content-Type: application/json" \
-d '{
"token": "eyJhbGciOiJSUzI1NiIs...",
"keys": ["s3-readonly", "s3-readwrite"]
}'Response:
{
"credentials": [
{
"key": "s3-readonly",
"credentials": {
"AccessKeyId": "AKIA...",
"SecretAccessKey": "secret...",
"SessionToken": "token...",
"Expiration": "2024-01-01T12:00:00Z"
}
}
]
}List available keys for a subject based on their OIDC token.
Request:
curl -X GET "http://localhost:3000/credentials/keys?token=eyJhbGciOiJSUzI1NiIs..."Response:
{
"keys": ["s3-readonly", "s3-readwrite", "ci-deployment"]
}List configured identity providers.
Request:
curl -X GET http://localhost:3000/credentials/idp-providersResponse:
{
"providers": [
{
"id": "github-actions",
"type": "github",
"issuer": "https://token.actions.githubusercontent.com"
},
{
"id": "auth0",
"type": "auth0",
"issuer": "https://myorg.auth0.com/"
}
]
}Health check endpoint for monitoring and load balancers.
Request:
curl -X GET http://localhost:3000/healthResponse:
{
"status": "ok",
"timestamp": "2024-01-01T12:00:00Z",
"uptime": 3600
}# Server Configuration
PORT=3000
NODE_ENV=production
# Identity Configuration
IDENTITY_CONFIG_PATH=/path/to/identity-config.yaml
# Logging
LOG_LEVEL=info
LOG_FORMAT=json
# CORS
CORS_ORIGIN=https://app.example.com
CORS_CREDENTIALS=trueThe server loads identity configuration from a YAML file:
# config/identity-config.yaml
idpProviders:
github-actions:
type: github
issuer: https://token.actions.githubusercontent.com
audience: sts.amazonaws.com
auth0:
type: auth0
issuer: https://myorg.auth0.com/
audience: https://myorg.com/api
subjects:
"repo:myorg/myapp:ref:refs/heads/main":
keys:
ci-deployment:
provider: aws
config:
roleArn: arn:aws:iam::123456789012:role/GitHubActions
region: us-east-1
durationSeconds: 3600
"user|auth0|12345":
keys:
s3-readonly:
provider: minio
config:
endpoint: https://minio.example.com
bucket: my-bucket
permissions: [s3:GetObject]
s3-readwrite:
provider: minio
config:
endpoint: https://minio.example.com
bucket: my-bucket
permissions: [s3:GetObject, s3:PutObject]The server uses NestJS dependency injection for clean architecture:
@Controller('credentials')
export class CredentialsController {
constructor(
private readonly credentialService: CredentialService,
private readonly logger: Logger
) {}
}- CORS: Configurable cross-origin resource sharing
- Rate Limiting: Request rate limiting for DoS protection
- Request Logging: Comprehensive request/response logging
- Error Handling: Structured error responses
- ValidationPipe: Request validation using class-validator
- TransformInterceptor: Response transformation
- LoggingInterceptor: Request/response logging
- TimeoutInterceptor: Request timeout handling
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY dist/ ./dist/
COPY config/ ./config/
EXPOSE 3000
CMD ["node", "dist/main.js"]version: '3.8'
services:
broker-server:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- IDENTITY_CONFIG_PATH=/app/config/identity-config.yaml
volumes:
- ./config:/app/config:roThe server provides comprehensive health checks:
@Get('health')
async healthCheck(): Promise<HealthCheckResult> {
return {
status: 'ok',
timestamp: new Date().toISOString(),
uptime: process.uptime(),
dependencies: {
identityProviders: await this.checkIdpHealth(),
accessProviders: await this.checkProviderHealth()
}
}
}Built-in metrics collection:
- Request count and duration
- Error rates by endpoint
- Identity provider response times
- Credential minting success/failure rates
Structured logging with correlation IDs:
{
"timestamp": "2024-01-01T12:00:00Z",
"level": "info",
"correlationId": "abc123",
"message": "Credential minting successful",
"context": {
"subject": "repo:myorg/myapp:ref:refs/heads/main",
"keys": ["ci-deployment"],
"duration": 250
}
}All requests are validated using DTOs and class-validator:
export class MintCredentialsDto {
@IsString()
@IsNotEmpty()
token: string
@IsArray()
@IsString({ each: true })
@ArrayMinSize(1)
keys: string[]
}Built-in rate limiting to prevent abuse:
@UseGuards(ThrottlerGuard)
@Throttle(10, 60) // 10 requests per minute
@Post('mint')
async mintCredentials(@Body() dto: MintCredentialsDto) {
// Implementation
}Automatic security headers via Helmet:
- Content Security Policy
- X-Frame-Options
- X-Content-Type-Options
- Referrer-Policy
Comprehensive error handling with structured responses:
{
"error": {
"code": "INVALID_TOKEN",
"message": "The provided OIDC token is invalid or expired",
"timestamp": "2024-01-01T12:00:00Z",
"correlationId": "abc123"
}
}Common error codes:
INVALID_TOKEN: Token validation failedUNAUTHORIZED: Subject not authorized for requested keysPROVIDER_ERROR: Access provider errorCONFIGURATION_ERROR: Server configuration issue
- Start dependencies (IdP, access providers)
- Configure identity configuration
- Start development server:
npm run dev- Test endpoints:
# Get available keys
curl "http://localhost:3000/credentials/keys?token=test-token"
# Mint credentials
curl -X POST http://localhost:3000/credentials/mint \
-H "Content-Type: application/json" \
-d '{"token": "test-token", "keys": ["test-key"]}'# Run unit tests
npm test
# Run integration tests
npm run test:e2e
# Run with coverage
npm run test:cov- Set production environment variables
- Configure identity providers
- Set up monitoring and logging
- Configure load balancer health checks
# Build production bundle
npm run build
# Start production server
npm run start:prod
# Or use PM2 for process management
pm2 start dist/main.js --name voidkey-broker- Stateless Design: Server is completely stateless
- Horizontal Scaling: Can run multiple instances behind load balancer
- Connection Pooling: Use connection pooling for external services
- Caching: Consider caching JWKS responses and configurations
- Configuration errors: Check identity configuration syntax
- Token validation failures: Verify IdP configuration and token format
- Provider errors: Check access provider connectivity and credentials
- Performance issues: Monitor response times and resource usage
Enable debug logging for troubleshooting:
LOG_LEVEL=debug npm run devTest all health check endpoints:
curl http://localhost:3000/health
curl http://localhost:3000/health/ready
curl http://localhost:3000/health/live