Skip to content

Security Model

Chris Panagiotidis edited this page Jun 13, 2026 · 3 revisions

Security Model

The security model is built around private-first access, explicit public exposure, layered network controls, CI policy gates, and guarded Terraform state.

Security control map

Important source files:

Security Principles

Principle Repository implementation
No broad public management by default RDP CIDR validation and Load Balancer RDP NAT disabled
Private data plane first Private Endpoints and Private DNS for Key Vault, Storage, SQL
Explicit public exposure App Gateway, Load Balancer, VPN, NAT, and jumpbox public IP are toggles
Central inspection Azure Firewall and route tables available when enabled
Least privilege Custom RBAC roles available through governance module
Policy as code OPA checks and Azure Policy module
Observable controls Diagnostics and alerts wired through management and post-deployment diagnostics
Secret minimization GitHub OIDC instead of long-lived Azure credentials JSON

Remote Management Controls

Public RDP is controlled by four variables:

Variable Default intent Risk if changed
enable_jumpbox_public_ip Disable direct public jumpbox access Exposes management host to internet
allowed_jumpbox_source_ips Empty or trusted CIDRs only 0.0.0.0/0 allows global RDP attempts
allow_public_rdp_from_internet false Break-glass override for unsafe RDP CIDR
enable_lb_rdp_nat_rules false Directly exposes workload VMs through public LB NAT

Source:

Recommended management access path:

  1. Prefer VPN or private management path.
  2. If public access is temporarily required, use a specific trusted CIDR.
  3. Do not use 0.0.0.0/0.
  4. Disable public access immediately after testing.

PaaS Security

Shared services are deployed from:

Hardening behavior:

Service Hardened behavior
Key Vault Public network access controlled; network ACL default deny when Private Endpoints are enabled
SQL Public network access disabled by default; "Allow Azure Services" disabled by default
Storage HTTPS required; blob public access disabled; network rules support private-first access
Private DNS Blob, Key Vault, and SQL zones can be linked to the hub and spokes
Private Endpoints Key Vault, Storage, and SQL private endpoints are available in the shared PE subnet

Network Security Groups

NSGs are created through modules/networking/nsg.

NSG locations:

  • Hub management subnet
  • App Gateway subnet
  • Identity domain controller subnet
  • Management jumpbox subnet
  • Shared services app subnet
  • Workload web subnet
  • Workload app subnet
  • Workload data subnet
  • Optional AKS subnet
  • Optional on-prem simulation subnet

Validation and testing:

CI Security Gates

The pipeline enforces:

  • Terraform format check
  • Terraform validate
  • tfsec
  • Checkov
  • Gitleaks
  • OPA policy check
  • Module version analysis

Workflow source: .github/workflows/terraform.yml

Custom actions:

Secrets And Sensitive Values

Never commit:

  • Tenant IDs if you treat them as sensitive
  • Subscription IDs if your organization classifies them
  • Client secrets
  • Passwords
  • Private keys
  • Admin usernames/passwords
  • SAS tokens
  • Backend access keys
  • Terraform state

Use GitHub secrets for:

  • AZURE_CLIENT_ID
  • AZURE_TENANT_ID
  • AZURE_SUBSCRIPTION_ID
  • TF_STATE_RG
  • TF_STATE_SA
  • Optional INFRACOST_API_KEY

See Remote State and Secrets.

Security Review Checklist

Before apply:

  • enable_jumpbox_public_ip = false unless there is a trusted CIDR requirement.
  • allowed_jumpbox_source_ips does not contain 0.0.0.0/0.
  • enable_lb_rdp_nat_rules = false.
  • SQL public network access is not enabled.
  • Key Vault public access is not opened without a reason.
  • Storage public blob access is disabled.
  • Private Endpoints and Private DNS are enabled for shared services.
  • GitHub Actions uses OIDC, not AZURE_CREDENTIALS.
  • Destroy environments require approval.

For operational procedures, incident response, and pull request review, see Security Operations.

Clone this wiki locally