License Monitoring¶
IOSetu includes a robust license monitoring system that continuously validates your license and provides observable events for integration with monitoring systems.
Overview¶
The license monitor: - Periodic Checks: Validates license every hour (configurable) - Hot-Reload: Updates license without container restart - Grace Period: 24-hour grace period after expiration (configurable) - Observable Events: Structured logs and OpenTelemetry events - Time Drift Detection: Detects clock manipulation attempts
Configuration¶
The only required configuration is the license key itself:
IOSETU_LICENSE_KEY="eyJhbGciOiJFZERTQS..."
Security Note: License validation timing and grace periods are internal implementation details and not configurable. This prevents timing-based exploitation attacks.
Hot-Reload: Updating License Without Restart¶
You can update the license without restarting the container by updating the IOSETU_LICENSE_KEY environment variable.
Kubernetes (Recommended: File-Based)¶
The recommended way to support hot-reloading in Kubernetes is to mount the license Secret as a file. This allows the license to be updated without restarting the Pod.
-
Create the Secret:
bash kubectl create secret generic iosetu-license --from-file=license.key=./license.key -
Mount the Secret:
yaml apiVersion: apps/v1 kind: Deployment metadata: name: iosetu spec: template: spec: containers: - name: iosetu env: - name: IOSETU_LICENSE_FILE value: /etc/iosetu/license.key volumeMounts: - name: license-volume mountPath: /etc/iosetu readOnly: true volumes: - name: license-volume secret: secretName: iosetu-license -
Update License (Hot-Reload): ```bash # Update the secret content from the new license file kubectl create secret generic iosetu-license \ --from-file=license.key=./new-license.key \ --dry-run=client -o yaml | kubectl apply -f -
# Wait approx 60 seconds (Kubernetes kubelet sync interval) # IOSetu will pick up the change automatically - NO RESTART NEEDED ```
Kubernetes (Environment Variable - Restart Required)¶
If you use environment variables directly, you must restart the Pod to pick up changes.
# Update the secret
kubectl create secret generic iosetu-license \
--from-literal=IOSETU_LICENSE_KEY="<new-license-jwt>" \
--dry-run=client -o yaml | kubectl apply -f -
# Restart pods to pick up new secret
kubectl rollout restart deployment/iosetu
Docker¶
# Update environment variable and restart
docker stop iosetu
docker run -d \
--name iosetu \
-e IOSETU_LICENSE_KEY="<new-license-jwt>" \
...
Docker Compose¶
# Update docker-compose.yml
services:
iosetu:
environment:
- IOSETU_LICENSE_KEY=${NEW_LICENSE_KEY}
# Restart service
docker-compose up -d iosetu
Note: The monitor periodically checks the environment variable. The new license will be detected and loaded automatically during the next check cycle.
License Expiration Alerts¶
The monitor emits structured log events at different warning thresholds:
Warning Thresholds¶
| Threshold | Level | Event Name | Description |
|---|---|---|---|
| < 30 days | WARN | license.expiring_30d |
License expiring in less than 30 days |
| < 7 days | WARN | license.expiring_7d |
License expiring soon |
| < 24 hours | ERROR | license.expiring_24h |
Critical: License expiring within 24 hours |
| < 1 hour | ERROR | license.expiring_1h |
Urgent: License expiring within 1 hour |
| Expired | ERROR | license.grace_mode_entered |
License expired - grace period started |
Example Log Output¶
{
"level": "WARN",
"msg": "License expiring",
"days_remaining": 25,
"expires_at": "2026-03-10T19:30:00+05:30",
"customer": "YourCompany"
}
OpenTelemetry Events¶
When OpenTelemetry is enabled, the monitor emits events that can be integrated with your observability platform:
Event Types¶
License Expiration Events¶
{
"event": "license.expiring_30d",
"attributes": {
"days_remaining": 25,
"expires_at": "2026-03-10T19:30:00+05:30",
"customer": "YourCompany",
"severity": "warning"
}
}
Grace Mode Events¶
{
"event": "license.grace_mode_entered",
"attributes": {
"grace_period_seconds": 86400,
"severity": "critical"
}
}
{
"event": "license.grace_mode_exited",
"attributes": {
"severity": "info"
}
}
Time Manipulation Detection¶
{
"event": "license.time_manipulation_detected",
"attributes": {
"type": "backward_jump",
"wall_clock_jump_seconds": -3600,
"severity": "critical"
}
}
{
"event": "license.time_drift_detected",
"attributes": {
"drift_seconds": 10.5,
"severity": "warning"
}
}
Grace Mode Behavior¶
When a license expires or becomes invalid:
- Grace Period Starts: Container enters grace mode
- Partial Functionality: Service remains operational
- Health Status:
/healthendpoint returnsdegradedstatus - After Grace Period: New requests return
503 Service Unavailable - Existing Requests: Continue to completion
Health Endpoint Response¶
Healthy (Valid License):
{
"status": "healthy",
"license": {
"valid": true,
"grace_mode": false
}
}
Degraded (Grace Mode):
{
"status": "degraded",
"license": {
"valid": false,
"grace_mode": true
}
}
Unhealthy (Grace Period Expired):
{
"status": "unhealthy",
"license": {
"valid": false,
"grace_mode": true
}
}
Monitoring Integration¶
Prometheus¶
Monitor license status via the /health endpoint:
scrape_configs:
- job_name: 'iosetu'
metrics_path: '/health'
static_configs:
- targets: ['iosetu:8080']
Alert Rules¶
groups:
- name: license_alerts
rules:
- alert: LicenseExpiringSoon
expr: iosetu_license_days_remaining < 7
for: 1h
annotations:
summary: "IOSetu license expiring in {{ $value }} days"
- alert: LicenseInGraceMode
expr: iosetu_license_grace_mode == 1
annotations:
summary: "IOSetu license expired - in grace mode"
Log Aggregation¶
Parse structured logs for license events:
# Example: Filter license events
kubectl logs -f deployment/iosetu | grep "license"
# Example: Alert on critical events
kubectl logs deployment/iosetu | grep "license.grace_mode_entered"
Time Drift Protection¶
The monitor detects suspicious time changes to prevent license bypass:
- Backward Time Jumps: Immediately enters grace mode
- Excessive Forward Drift: Emits warnings (>5 seconds per check)
- Monotonic Tracking: Uses both wall clock and monotonic time
Example Alert¶
{
"level": "ERROR",
"msg": "CRITICAL: Backward time jump detected - possible clock manipulation",
"wall_clock_jump_seconds": -7200,
"message": "System clock was set backward - this may indicate license bypass attempt"
}
Troubleshooting¶
License Not Updating¶
Problem: New license not detected after environment variable update
Solution:
1. Verify environment variable is updated: kubectl exec pod -- env | grep IOSETU_LICENSE_KEY
2. Wait for next check cycle (default: 1 hour) or restart pod
3. Check logs for license.grace_mode_exited event
Grace Mode Triggered Unexpectedly¶
Problem: Container enters grace mode despite valid license
Possible Causes:
1. Time Drift: Check system clock synchronization
2. Invalid License: Verify JWT signature and expiration
3. Environment Variable: Ensure IOSETU_LICENSE_KEY is set correctly
Check Logs:
kubectl logs deployment/iosetu | grep -E "license.verification_failed|license.missing"
Health Check Failing¶
Problem: /health returns 503 Service Unavailable
Cause: Grace period has expired
Solution:
1. Update license immediately
2. Restart container to apply new license
3. Monitor logs for license.grace_mode_exited
Security Considerations¶
Why Timing Is Not Configurable¶
License validation timing and grace periods are hardcoded internal implementation details, not exposed as configuration options. This prevents timing-based attacks where an attacker could:
- Time Exploitation Windows: If they knew check intervals, they could manipulate licenses immediately after checks
- Evade Detection: Restore valid licenses just before scheduled checks
- Coordinate Attacks: Synchronize multiple attack vectors during known validation gaps
By making timing non-configurable, attackers cannot rely on predictable behavior.
Defense in Depth¶
The license monitor implements multiple security layers:
- Hardcoded Timing: Check intervals are compiled into the binary, not configurable
- Time Drift Detection: Detects backward time jumps and suspicious clock changes
- Monotonic Tracking: Uses both wall clock and monotonic time to prevent manipulation
- Immediate Grace Mode: Enters grace mode on any suspicious activity
- Continuous Validation: Multiple validation points throughout request lifecycle
Recommended Practices¶
- Monitor for Anomalies: Alert on time drift warnings and grace mode entries
- Regular Audits: Review license events in your SIEM/logging platform
- Secure Deployment: Protect container runtime environment from tampering
Best Practices¶
- Monitor Expiration: Set up alerts for expiration warning events
- Automate Renewal: Integrate license renewal into your CI/CD pipeline
- Test Hot-Reload: Verify license updates work in staging before production
- Time Sync: Ensure NTP is configured correctly to prevent time drift alerts
- Secure Configuration: Treat license configuration values as sensitive security parameters