Skip to content

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.

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.

  1. Create the Secret: bash kubectl create secret generic iosetu-license --from-file=license.key=./license.key

  2. 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

  3. 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:

  1. Grace Period Starts: Container enters grace mode
  2. Partial Functionality: Service remains operational
  3. Health Status: /health endpoint returns degraded status
  4. After Grace Period: New requests return 503 Service Unavailable
  5. 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:

  1. Time Exploitation Windows: If they knew check intervals, they could manipulate licenses immediately after checks
  2. Evade Detection: Restore valid licenses just before scheduled checks
  3. 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
  1. Monitor for Anomalies: Alert on time drift warnings and grace mode entries
  2. Regular Audits: Review license events in your SIEM/logging platform
  3. Secure Deployment: Protect container runtime environment from tampering

Best Practices

  1. Monitor Expiration: Set up alerts for expiration warning events
  2. Automate Renewal: Integrate license renewal into your CI/CD pipeline
  3. Test Hot-Reload: Verify license updates work in staging before production
  4. Time Sync: Ensure NTP is configured correctly to prevent time drift alerts
  5. Secure Configuration: Treat license configuration values as sensitive security parameters