feat(certificates): add custom provisioning option
This commit is contained in:
107
readme.md
107
readme.md
@ -2336,14 +2336,117 @@ sequenceDiagram
|
||||
• Efficient SNI extraction
|
||||
• Minimal overhead routing
|
||||
|
||||
## Certificate Hooks & Events
|
||||
## Certificate Management
|
||||
|
||||
### Custom Certificate Provision Function
|
||||
|
||||
SmartProxy supports a custom certificate provision function that allows you to provide your own certificate generation logic while maintaining compatibility with Let's Encrypt:
|
||||
|
||||
```typescript
|
||||
const proxy = new SmartProxy({
|
||||
certProvisionFunction: async (domain: string): Promise<TSmartProxyCertProvisionObject> => {
|
||||
// Option 1: Return a custom certificate
|
||||
if (domain === 'internal.example.com') {
|
||||
return {
|
||||
cert: customCertPEM,
|
||||
key: customKeyPEM,
|
||||
ca: customCAPEM // Optional CA chain
|
||||
};
|
||||
}
|
||||
|
||||
// Option 2: Fallback to Let's Encrypt
|
||||
return 'http01';
|
||||
},
|
||||
|
||||
// Control fallback behavior when custom provision fails
|
||||
certProvisionFallbackToAcme: true, // Default: true
|
||||
|
||||
routes: [...]
|
||||
});
|
||||
```
|
||||
|
||||
**Key Features:**
|
||||
- Called for any route with `certificate: 'auto'`
|
||||
- Return custom certificate object or `'http01'` to use Let's Encrypt
|
||||
- Participates in automatic renewal cycle (checked every 12 hours)
|
||||
- Custom certificates stored with source type 'custom' for tracking
|
||||
|
||||
**Configuration Options:**
|
||||
- `certProvisionFunction`: Async function that receives domain and returns certificate or 'http01'
|
||||
- `certProvisionFallbackToAcme`: Whether to fallback to Let's Encrypt if custom provision fails (default: true)
|
||||
|
||||
**Advanced Example with Certificate Manager:**
|
||||
|
||||
```typescript
|
||||
const certManager = new MyCertificateManager();
|
||||
|
||||
const proxy = new SmartProxy({
|
||||
certProvisionFunction: async (domain: string) => {
|
||||
try {
|
||||
// Check if we have a custom certificate for this domain
|
||||
if (await certManager.hasCustomCert(domain)) {
|
||||
const cert = await certManager.getCertificate(domain);
|
||||
return {
|
||||
cert: cert.certificate,
|
||||
key: cert.privateKey,
|
||||
ca: cert.chain
|
||||
};
|
||||
}
|
||||
|
||||
// Use Let's Encrypt for public domains
|
||||
if (domain.endsWith('.example.com')) {
|
||||
return 'http01';
|
||||
}
|
||||
|
||||
// Generate self-signed for internal domains
|
||||
if (domain.endsWith('.internal')) {
|
||||
const selfSigned = await certManager.generateSelfSigned(domain);
|
||||
return {
|
||||
cert: selfSigned.cert,
|
||||
key: selfSigned.key,
|
||||
ca: ''
|
||||
};
|
||||
}
|
||||
|
||||
// Default to Let's Encrypt
|
||||
return 'http01';
|
||||
} catch (error) {
|
||||
console.error(`Certificate provision failed for ${domain}:`, error);
|
||||
// Will fallback to Let's Encrypt if certProvisionFallbackToAcme is true
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
certProvisionFallbackToAcme: true,
|
||||
|
||||
routes: [
|
||||
// Routes that use automatic certificates
|
||||
{
|
||||
match: { ports: 443, domains: ['app.example.com', '*.internal'] },
|
||||
action: {
|
||||
type: 'forward',
|
||||
target: { host: 'localhost', port: 8080 },
|
||||
tls: { mode: 'terminate', certificate: 'auto' }
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
```
|
||||
|
||||
### Certificate Events
|
||||
|
||||
Listen for certificate events via EventEmitter:
|
||||
- **SmartProxy**:
|
||||
- `certificate` (domain, publicKey, privateKey, expiryDate, source, isRenewal)
|
||||
- Events from CertManager are propagated
|
||||
|
||||
Provide a `certProvisionFunction(domain)` in SmartProxy settings to supply static certs or return `'http01'`.
|
||||
```typescript
|
||||
proxy.on('certificate', (domain, cert, key, expiryDate, source, isRenewal) => {
|
||||
console.log(`Certificate ${isRenewal ? 'renewed' : 'provisioned'} for ${domain}`);
|
||||
console.log(`Source: ${source}`); // 'acme', 'static', or 'custom'
|
||||
console.log(`Expires: ${expiryDate}`);
|
||||
});
|
||||
```
|
||||
|
||||
## SmartProxy: Common Use Cases
|
||||
|
||||
|
Reference in New Issue
Block a user