mTLS + X.509 Identity
IP allowlisting controls the network boundary. mTLS goes inside it — requiring every connection to present a cryptographic certificate that proves its identity before a single byte of application data is exchanged.
The Core Principle
Standard TLS proves only that the server is legitimate. Mutual TLS (mTLS) extends this — the client must also present a valid certificate. Every connection is a two-way cryptographic handshake before any application traffic flows.
Both client and server present X.509 certificates. Neither can impersonate the other — the identity proof is symmetric.
Identity is proved by possession of a private key — not a password, not an IP address. It cannot be guessed or replayed.
mTLS sits inside the IP boundary from Stage 1. Even if an attacker reaches the service, they still cannot connect without a valid cert.
Every connection carries a verified identity in its certificate. Access logs become meaningful — who called what, not just which IP.
IP allowlisting tells you where a connection came from. mTLS tells you who sent it. These are fundamentally different questions — and both matter.
entityOS Security Framework — Stage 2
TLS vs mTLS
Standard HTTPS proves the server is who it claims to be. mTLS adds the same proof in the other direction — the client must also hold a certificate from a trusted Certificate Authority.
Create or use an existing Certificate Authority — your internal PKI. This can be AWS Private CA, HashiCorp Vault PKI, or a self-managed CA. All certificates for your services will be issued by this CA.
# AWS Private CA — create root CA
aws acm-pca create-certificate-authority --type ROOT --certificate-authority-configuration "KeyAlgorithm=RSA_2048,
SigningAlgorithm=SHA256WITHRSA,
Subject={CN=entityOS Internal CA}"Each service gets its own X.509 certificate issued by your CA. The certificate contains the service identity in the Common Name or SAN. Use short-lived certs (24–72 hours) with automated renewal via cert-manager or ACM.
# cert-manager — issue cert for a service
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: payments-service
spec:
secretName: payments-tls
duration: 24h
issuerRef:
name: internal-caConfigure your load balancer, API gateway, or service mesh to require a client certificate on every inbound connection. Reject any connection that doesn't present a valid cert from your CA.
# AWS ALB — require client cert
aws elbv2 modify-listener --listener-arn arn:aws:elasticloadbalancing:... --mutual-authentication "Mode=verify,
TrustStoreArn=arn:aws:elasticloadbalancing:...,
IgnoreClientCertificateExpiry=false"X.509 Identity
X.509 certificates are no longer just for HTTPS. In a Stage 2 deployment they identify every type of actor in your system — users, devices, workloads, and services.
Device-bound certs replace passwords for human access to internal APIs and admin systems
MDM-enrolled device certs gate access at the hardware level — enforced at the network layer
Short-lived certs identify pods, containers, and functions — rotated automatically, never stored as secrets
Service mesh certificates enable zero-trust service-to-service mTLS — every API call is authenticated
Scenario Matrix
How the combined IP allowlisting + mTLS stack performs across common enterprise access scenarios.
| Scenario | Stage 1 (IP) | + Stage 2 (mTLS) | What it adds |
|---|---|---|---|
| Admin API — internal only | ✓ Blocks external | ✓ Verifies admin identity | Only admins with a valid cert can connect, even from inside the network |
| Service-to-service API calls | ✓ VPC only | ✓ Verifies calling service | payments-service can only be called by services holding an authorised cert |
| CI/CD pipeline | ✓ Fixed NAT IP | ✓ Pipeline cert identity | CI runner proves it is the authorised pipeline, not just from the right IP |
| Remote / distributed teams | ✗ IP varies | ✓ Device cert works | VPN not required — device certificate provides the identity boundary instead |
| Autoscaling container fleets | ✗ Ephemeral IPs | ✓ Workload cert | Each pod gets a short-lived cert at startup — IP irrelevant, identity is the cert |
| Attacker inside allowed network | ✗ IP is trusted | ✓ No cert = no access | Lateral movement is blocked — attacker cannot connect without a CA-signed cert |
| Compromised service credential | ✗ No protection | ✓ Cert revocable | Revoke the service cert immediately — all connections from that identity stop |
| Thousands of microservices | ✗ CIDR sprawl | ✓ Automated cert mgmt | cert-manager handles issuance and rotation at scale — no manual IP rule management |
Implementation
Best Practices
mTLS is powerful but easy to misconfigure. These rules prevent the most common failures that leave you thinking you have cryptographic identity — when you don't.
If a human needs to be involved in certificate renewal, it will be missed. Use cert-manager, ACM auto-renewal, or Vault agent. Treat any manually managed certificate as a security liability.
Long-lived certificates (years) are secrets waiting to be stolen. Use 24–72 hour certs. A stolen short-lived cert expires before an attacker can exploit it. The small operational cost of rotation is worth the significant security gain.
A dev service should never be able to call production. Use separate CAs for dev, staging, and production. A cert issued by your dev CA will be rejected by your prod services — the environments are cryptographically isolated.
Put meaningful data in the certificate Subject — service name, team, environment, version. This enables authorisation policies that go beyond "has a valid cert" to "is the payments service, in prod, from team finance".
Run a revocation drill quarterly — revoke a test service cert and verify it is refused by dependent services within your SLA. If you've never tested it, you don't know if it works when a real incident occurs.
The most dangerous configuration is InsecureSkipVerify: true. It disables all certificate checking and defeats the entire purpose of mTLS. Never allow it, even in dev.
A self-signed cert cannot be verified by any other service — it proves nothing. You need a shared CA that both sides trust. Self-signed certs in prod are security theatre.
Enforcing mTLS at the load balancer but not between internal services means lateral movement after the edge is unchecked. mTLS must extend to every service-to-service call.
If the private key is stored in a Kubernetes secret or environment variable in plaintext, the certificate provides no security. Keys must be in a secrets manager or HSM.
A cert that expires in production silently breaks all connections. Monitor expiry dates with at least 72 hours' warning. An unmonitored cert expiry is an incident waiting to happen.
The Road Ahead
mTLS with manually managed certificates works well up to hundreds of services. Beyond that — ephemeral containers, autoscaling fleets, multi-cloud — you need automated workload identity. That's Stage 3.
Network boundary control — deny all, allow known CIDRs. The outer perimeter that Stage 2 sits inside.
Cryptographic identity for every connection. Both sides prove who they are with a certificate before any data flows.
Add mTLS to every internal service connection — not just the edge. Every service must present a valid X.509 certificate before it can connect. Combined with Stage 1 IP controls, this means an attacker needs both network access and a cryptographic credential — two independent barriers instead of one.