-
Notifications
You must be signed in to change notification settings - Fork 0
Certificate Automation
This guide covers automatic TLS certificate provisioning for TMI using Let's Encrypt with OCI Functions and DNS-01 challenges.
TMI provides automatic certificate management using:
- Let's Encrypt - Free, automated TLS certificates
- OCI Functions - Serverless certificate lifecycle management
- DNS-01 Challenges - Domain validation via DNS TXT records
- OCI Vault - Secure certificate and key storage
- OCI Load Balancer - Automatic certificate deployment
+------------------+
| Let's Encrypt |
| ACME Server |
+--------+---------+
|
| ACME Protocol (DNS-01)
v
+--------------------------------------------------------------------------------+
| OCI Tenancy |
| |
| +----------------+ +------------------+ |
| | Scheduler |-------->| OCI Function | |
| | (External) | | (certmgr) | |
| +----------------+ +--------+---------+ |
| | |
| +-----------------------------+-----------------------------+ |
| | | | |
| v v v |
| +----------------+ +------------------+ +------------------+ |
| | DNS Zone (OCI) | | OCI Vault | | OCI Load Balancer| |
| | (TXT records) | | (cert storage) | | (HTTPS:443) | |
| +----------------+ +------------------+ +---------+--------+ |
| | |
| v |
| +------------------+ |
| | TMI Application | |
| +------------------+ |
+--------------------------------------------------------------------------------+
- DNS Zone - Domain must be hosted in OCI DNS
- OCI Vault - For storing certificates and ACME account key
- Load Balancer - Target for certificate deployment
- Compartment - With appropriate IAM permissions
The certificate manager function requires:
- DNS: Manage TXT records in the specified zone
- Vault: Read and write secrets
- Load Balancer: Update certificates and listeners
These are automatically created when create_dynamic_group = true.
In your terraform.tfvars:
# Enable certificate automation
enable_certificate_automation = true
# Domain configuration
domain_name = "tmi.example.com"
dns_zone_id = "ocid1.dns-zone.oc1..<unique_id>"
acme_contact_email = "[email protected]"
# Start with staging for testing
acme_directory = "staging"
# Certificate manager function image
certmgr_image_url = "us-ashburn-1.ocir.io/<namespace>/certmgr:latest"# Build the certificate manager function
make fn-build-certmgr
# Push to OCI Container Registry
make fn-deploy-certmgrcd terraform/environments/oci-free-tier
terraform init
terraform plan
terraform apply# Invoke the function manually
make fn-invoke-certmgr
# Or use OCI CLI directly
terraform output certificate_invoke_commandAfter verifying the flow works with staging:
acme_directory = "production"Then terraform apply to update.
| Variable | Type | Default | Description |
|---|---|---|---|
enable_certificate_automation |
bool | false |
Enable the certificates module |
domain_name |
string | (required) | Domain name for TLS certificate |
dns_zone_id |
string | (required) | OCID of the OCI DNS zone |
acme_contact_email |
string | (required) | Email for Let's Encrypt notifications |
acme_directory |
string | staging |
ACME directory: staging or production
|
certificate_renewal_days |
number | 30 |
Days before expiry to trigger renewal |
certmgr_image_url |
string | (required) | Container image URL for the function |
These are automatically configured by Terraform:
| Variable | Description |
|---|---|
CERTMGR_DOMAIN |
Domain name for certificate |
CERTMGR_DNS_ZONE_ID |
OCI DNS zone OCID |
CERTMGR_ACME_EMAIL |
Let's Encrypt contact email |
CERTMGR_RENEWAL_DAYS |
Days before expiry to renew |
CERTMGR_LB_ID |
OCI Load Balancer OCID |
CERTMGR_VAULT_ID |
OCI Vault OCID |
CERTMGR_VAULT_KEY_ID |
OCI Vault master key OCID |
CERTMGR_COMPARTMENT_ID |
Compartment OCID |
CERTMGR_NAME_PREFIX |
Prefix for resource names |
CERTMGR_ACME_DIRECTORY |
Full ACME directory URL |
- Function starts and loads configuration
- Checks for existing certificate in Vault
- If no certificate or expired:
- Generates ACME account key (stored in Vault)
- Registers account with Let's Encrypt
- Requests certificate authorization
- Creates DNS TXT record for challenge
- Waits for DNS propagation
- Notifies Let's Encrypt to verify
- Receives and stores certificate in Vault
- Updates Load Balancer with certificate
- Cleans up DNS TXT record
- Function retrieves certificate from Vault
- Checks certificate expiry date
- If expiring within
certificate_renewal_days:- Triggers renewal flow (same as initial issuance)
- If not expiring: logs status and exits
OCI does not have a native Terraform resource for function scheduling. Set up daily invocation via one of these methods:
- Navigate to Resource Scheduler in OCI Console
- Create a new scheduled job:
- Type: Function
-
Function: Select
{name_prefix}-certmgr -
Schedule: Daily at desired time (e.g.,
0 2 * * *for 2 AM UTC)
On a machine with OCI CLI configured:
# Add to crontab
0 2 * * * oci fn function invoke --function-id <function-ocid> --file - --body ''name: Certificate Renewal Check
on:
schedule:
- cron: '0 2 * * *' # Daily at 2 AM UTC
jobs:
check-certificate:
runs-on: ubuntu-latest
steps:
- name: Setup OCI CLI
uses: oracle-actions/[email protected]
with:
user: ${{ secrets.OCI_USER_OCID }}
tenancy: ${{ secrets.OCI_TENANCY_OCID }}
fingerprint: ${{ secrets.OCI_FINGERPRINT }}
private_key: ${{ secrets.OCI_PRIVATE_KEY }}
region: ${{ secrets.OCI_REGION }}
- name: Invoke Certificate Manager
run: |
oci fn function invoke \
--function-id ${{ secrets.CERTMGR_FUNCTION_ID }} \
--file - --body ''| Target | Description |
|---|---|
fn-build-certmgr |
Build the certificate manager function |
fn-deploy-certmgr |
Deploy function to OCI Functions |
fn-invoke-certmgr |
Manually invoke the function |
fn-logs-certmgr |
View function logs |
The certificates module creates these secrets in OCI Vault:
| Secret Name | Content | Purpose |
|---|---|---|
{name_prefix}-acme-account-key |
PEM-encoded private key | ACME account authentication |
{name_prefix}-certificate |
PEM-encoded certificate | TLS certificate chain |
{name_prefix}-private-key |
PEM-encoded private key | TLS private key |
All secrets are:
- Encrypted with the Vault master key (AES-256)
- Accessible only via function Resource Principal
- Version-controlled (previous versions retained)
-
Check function logs:
make fn-logs-certmgr
-
Verify function has correct IAM policies:
- Dynamic group includes the function
- Policies grant DNS, Vault, and LB access
-
Check function timeout (default: 300s should be sufficient)
- Verify DNS zone OCID is correct
- Check that the zone contains the target domain
- Ensure IAM policy allows DNS record management
- Check DNS propagation:
dig TXT _acme-challenge.tmi.example.com
- Verify function completed successfully (check logs)
- Check Load Balancer has HTTPS listener configured
- Verify IAM policy allows Load Balancer updates
- Check certificate in Vault contains valid PEM data
Let's Encrypt has rate limits:
- Staging: No practical limits (for testing)
- Production: 50 certificates per domain per week
If rate limited:
- Wait for rate limit window to reset (1 week)
- Use staging for testing
- Consider wildcard certificate for subdomains
The function has a 5-minute timeout. Typical execution:
- DNS propagation: 1-3 minutes
- ACME challenge: ~30 seconds
- Total: 2-4 minutes
If timing out:
- Increase
function_timeout_seconds(max 300) - Check DNS zone TTL settings
- Review function logs for delays
| Aspect | Staging | Production |
|---|---|---|
| URL | acme-staging-v02.api.letsencrypt.org | acme-v02.api.letsencrypt.org |
| Rate Limits | Very generous | 50 certs/domain/week |
| Browser Trust | Not trusted | Trusted |
| Use Case | Testing, development | Production deployments |
Best Practice: Always test with staging first, then switch to production.
The certificate automation uses these Free Tier resources:
| Resource | Free Tier Limit | Usage |
|---|---|---|
| Functions | 2M invocations/month | ~30/month (daily) |
| Functions Memory | 400K GB-seconds | ~1.3 GB-sec/month |
| Vault Secrets | 20 secrets | +3 secrets |
| DNS Queries | 1000/day per zone | ~5/day |
Impact: Minimal - well within Free Tier limits.
The function uses OCI Resource Principal for authentication:
- No static credentials in configuration
- Automatic credential rotation by OCI
- Scoped to specific compartment and resources
The created policies grant only necessary permissions:
- DNS: Only TXT records in specified zone
- Vault: Only secrets in specified vault
- Load Balancer: Only specified load balancer
- ACME account key stored encrypted in Vault
- Private key never leaves OCI (Vault → Load Balancer)
- Certificate chain stored for transparency
- Using TMI for Threat Modeling
- Accessing TMI
- Creating Your First Threat Model
- Understanding the User Interface
- Working with Data Flow Diagrams
- Managing Threats
- Collaborative Threat Modeling
- Using Notes and Documentation
- Metadata and Extensions
- Planning Your Deployment
- Deploying TMI Server
- OCI Container Deployment
- Terraform Deployment
- Certificate Automation
- Deploying TMI Web Application
- Setting Up Authentication
- Database Setup
- Component Integration
- Post-Deployment
- Monitoring and Health
- Cloud Logging
- Database Operations
- Security Operations
- Performance and Scaling
- Maintenance Tasks