Skip to main content
emnode / learn
Compliance

Enforce TLS on APIs and search domains

One capability across API Gateway and OpenSearch and Elasticsearch: every public endpoint uses a strong, current TLS policy, and the hop to the backend behind the gateway is encrypted too.

13 min·10 sections·AWS

Last reviewed

TLS on APIs and search: the basics

Why an HTTPS endpoint can still be a weak one

API Gateway custom domains and OpenSearch and Elasticsearch domains all answer over HTTPS, and most teams stop checking once they see HTTPS is on. But TLS is not a single setting. Each endpoint advertises a security policy that decides which protocol versions and cipher suites it will accept during the handshake, and an old policy negotiates down to TLS 1.0 or weak ciphers if a client asks. A connection can be encrypted in the browser and still negotiated insecurely, which is precisely how downgrade attacks like POODLE and BEAST worked: they did not break modern TLS, they tricked the server into using an old protocol it should never have left enabled.

Security Hub turns this idea into several controls across the API and search surface. APIGateway.11 fails an API Gateway custom domain that is not pinned to a recommended TLS security policy. ES.8 and Opensearch.8 fail an Elasticsearch or OpenSearch domain whose TLSSecurityPolicy is not the latest (currently Policy-Min-TLS-1-2-PFS-2023-10) or where HTTPS is not enforced. APIGateway.10 fails an HTTP API V2 private integration whose backend hop over a VPC Link has no TLS configured, and APIGateway.2 fails a REST API stage with no client-side SSL certificate to prove the caller really is the gateway. They look like separate findings, but they are one capability: the floor on every TLS connection in front of, and behind, these services should be high.

The fixes are cheap and standard, and they split into two shapes. Raising a TLS security policy on a custom domain or a search domain is a single configuration field applied with no downtime and no data migration. Encrypting the backend hop is a property on the integration (a TlsConfig block) or the stage (a client certificate). The work is finding every endpoint and confirming no genuinely ancient client breaks before you raise the floor.

In this lesson you will learn what a TLS security policy actually negotiates on an API Gateway custom domain and a search domain, why "HTTPS enabled" and "latest TLS policy" are different checks, and why a private backend hop is not automatically an encrypted one. The Controls this lesson covers section lists every Security Hub control in this capability, each linking to a deep page with the exact check and a copy-and-paste fix.

Fun fact

The handshake that quietly steps down, and the private path that lulls you to sleep

Two assumptions cause most findings in this group. The first is that HTTPS means strong: TLS is a negotiation, and a domain on a legacy policy will happily speak TLS 1.2 to a modern browser while still accepting TLS 1.0 from any client that asks, including an attacker forcing a downgrade. The fix was never about the strong end of the range, it was always about raising the floor. The second is that private means encrypted: a VPC Link gives API Gateway a private network path to a backend, and because it solved the "do not expose my service to the internet" problem so cleanly, many teams equated reachable-only-through-a-VPC-Link with secure and never enabled TLS on the backend hop. APIGateway.10 exists to catch every integration where the link was created but the encryption toggle was never flipped.

Finding weak and unencrypted endpoints across an estate

Dev runs the security cadence at a logistics company. Security Hub flags a spread of findings across API Gateway and OpenSearch in two accounts: custom domains on a legacy TLS policy, a search domain still permitting TLS 1.0, and an HTTP API integration forwarding to its backend in clear text.

Rather than work them one by one, he starts by reading the current TLS policy on the flagged search domain, since "HTTPS is on" tells him nothing about how strong the accepted handshakes are.

Read the endpoint options on the flagged OpenSearch domain to confirm which TLS policy it is on and whether HTTPS is enforced.

$ aws opensearch describe-domain-config --domain-name logs-prod --query 'DomainConfig.DomainEndpointOptions.Options'
{
"EnforceHTTPS": true,
"TLSSecurityPolicy": "Policy-Min-TLS-1-0-2019-07",
"CustomEndpointEnabled": false
}
# HTTPS is enforced, but the policy still permits TLS 1.0 - the finding fires.

HTTPS on is not enough; the policy name is what Opensearch.8 and ES.8 evaluate.

How the API and search TLS controls workdeep dive

A TLS security policy is an AWS-managed bundle of a minimum protocol version plus an allowed cipher list, and it sets the floor on how weak a handshake may go. On a search domain the field is TLSSecurityPolicy inside DomainEndpointOptions: Policy-Min-TLS-1-0-2019-07 permits TLS 1.0 and up, Policy-Min-TLS-1-2-2019-07 raises the floor to TLS 1.2, and Policy-Min-TLS-1-2-PFS-2023-10 keeps the 1.2 floor and restricts ciphers to perfect-forward-secrecy suites only. ES.8 and Opensearch.8 fail if HTTPS is not enforced or the policy is not the latest, and the change applies as a domain configuration update with no re-index: the domain transitions to Processing and returns to Active with the narrower handshake rules live. On an API Gateway custom domain the equivalent field is securityPolicy on the AWS::ApiGateway::DomainName resource, which APIGateway.11 checks against the recommended policies.

The backend-hop controls are about the connection behind the gateway, not the public edge. APIGateway.10 reads the TlsConfig on an AWS::ApiGatewayV2::Integration: a VPC Link controls where the traffic goes, not whether it is encrypted, so an integration with no TlsConfig forwards to the backend over plain HTTP even when the public route is HTTPS-only. APIGateway.2 reads the client certificate on an AWS::ApiGateway::Stage: API Gateway can present a generated SSL certificate to the backend so the origin can verify the caller really is the gateway and reject anything that bypasses it.

The one real-world risk across the policy-raising controls is client compatibility. Raising the floor to TLS 1.2 breaks any client that can only speak TLS 1.0/1.1, in practice very old SDKs, legacy JVMs without modern TLS enabled, or hand-rolled HTTP clients. Every current AWS SDK, browser and language runtime negotiates TLS 1.2+ by default, so the safe move is to inventory connecting clients before flipping a production endpoint, then apply with confidence. For API Gateway domains, also note that edge-optimised and regional domains and the propagation window mean the change is not always instant.

What is the impact of a weak or unencrypted endpoint?

The direct impact is a downgrade and interception exposure. As long as an endpoint advertises an old policy, a client or an attacker positioned between client and server can negotiate the connection down to TLS 1.0 or a non-PFS cipher suite. The traffic is still encrypted, but with a protocol that has documented weaknesses and without forward secrecy, so a future key compromise could expose previously recorded sessions. For the backend-hop controls the exposure is starker: an unencrypted private integration carries credentials and personal data in clear text across the VPC, readable by any host, mirror or logging agent with visibility into that segment.

The compliance impact is usually the more immediate one. These controls map to PCI DSS and the NIST 800-53 data-in-transit family (SC-8, SC-13, SC-23) and authenticator-management controls. An open finding is a concrete audit exception that surfaces in a SOC 2 review, a customer security questionnaire or a contractual remediation clause with a fixed window. Unlike a cost finding it does not grow over time, but it blocks attestations until it is closed.

There is effectively no cost impact. Raising a TLS policy or encrypting a backend hop does not change the instance type, storage or request billing. The only operational cost is the small risk of breaking a legacy client that cannot do TLS 1.2, which is why the inventory-before-flip step matters; for any modern client fleet that risk is zero.

The second-order impact is what a recurring finding signals. If new domains and integrations keep launching on the old policy or without backend TLS, the problem is not the individual endpoint, it is that the provisioning templates default to an outdated or incomplete setting. That same defaults gap usually shows up across other resource types too, so a persistent finding here is a useful early warning that secure-by-default is not wired into how infrastructure gets created.

How do you enforce TLS on APIs and search safely?

Work the capability as one loop. The order matters: inventory every endpoint, confirm no legacy client will break, raise the policy and encrypt the backend hop, then bake the standard into provisioning so new endpoints launch compliant.

1. Inventory every domain, integration and stage

List all API Gateway custom domains and their securityPolicy, every OpenSearch and Elasticsearch domain and its TLSSecurityPolicy and EnforceHTTPS, every HTTP API V2 private integration and whether it has TlsConfig, and every REST API stage and whether a client certificate is attached. This is read-only and safe to run across production at any time. Anything not on the latest policy, or missing backend TLS, is a remediation candidate.

2. Confirm no legacy client depends on the weak setting

The only thing that breaks when you raise the floor to TLS 1.2 is a client that cannot negotiate it, in practice very old SDKs or runtimes. Check connecting clients through access logs or CloudTrail data events, or the owning team's knowledge of the integrations. Modern AWS SDKs, browsers and runtimes all do TLS 1.2 by default, so for most fleets this is a quick confirmation rather than a project.

3. Raise the policy and encrypt the backend hop

Set the search domain TLSSecurityPolicy to Policy-Min-TLS-1-2-PFS-2023-10 with EnforceHTTPS true in a single update-domain-config call, and pin the API Gateway custom domain to a recommended securityPolicy with update-domain-name. For the backend hop, add a TlsConfig to the V2 integration pointed at the backend's HTTPS listener, and associate a client certificate with the REST API stage. Verify afterwards that the live configuration shows the new values.

4. Make the latest standard the provisioning default

Set the TLS policy and backend-encryption properties in your CloudFormation, Terraform or CDK modules so every new endpoint launches compliant, and add AWS Config rules or Service Control Policies to catch drift. This is what turns a recurring finding into a one-time event: the cleanup loop only stays empty if new endpoints arrive already compliant.

# Raise the search-domain TLS policy and keep HTTPS enforced (no downtime, no re-index).
aws opensearch update-domain-config \
  --domain-name logs-prod \
  --domain-endpoint-options '{"EnforceHTTPS":true,"TLSSecurityPolicy":"Policy-Min-TLS-1-2-PFS-2023-10"}'

# Pin an API Gateway custom domain to a recommended TLS security policy.
aws apigateway update-domain-name \
  --domain-name api.example.com \
  --patch-operations op=replace,path=/securityPolicy,value=TLS_1_2

# Confirm the live policy once the domain settles.
aws opensearch describe-domain-config --domain-name logs-prod \
  --query 'DomainConfig.DomainEndpointOptions.Options.TLSSecurityPolicy' \
  --output text

Quick quiz

Question 1 of 5

Security Hub shows findings across API Gateway custom domains and an OpenSearch domain, all about TLS. What is the most efficient way to think about them?

You can now treat TLS on APIs and search as one capability rather than a scatter of findings: inventory every custom domain, search domain, private integration and REST stage, confirm no legacy client depends on the weak setting, raise the policy and encrypt the backend hop, then make the current standard the provisioning default so new endpoints launch compliant. The Controls this lesson covers section below links every control in this group to its deep page and fix.

Back to the library

Controls this lesson covers

One capability, many AWS Security Hub controls. This lesson is the shared playbook; each control below keeps its own deep page with the exact check, severity and a copy-and-paste fix.