Securing Third-Party API Keys Across Multi-Cloud Infrastructure

January 18, 2026

The Problem

A third-party email API key was scattered across 24+ repositories, environment variables, and developer machines. This created several issues:

  • Anyone with repo access could see the key
  • Key rotation required updating dozens of places manually
  • No audit trail of API usage
  • Security risk if any single repo was compromised

Initial Exploration

The discussion started with Azure Key Vault as a potential solution for secret management. However, fetching keys from Key Vault at runtime would require code changes across all 24 services — not feasible without significant disruption.

The constraint was clear: no code changes, no environment variable changes.

The Solution: API Proxy

Instead of distributing the API key, centralize it. Create a proxy that:

  1. Receives requests from internal services
  2. Appends the real API key
  3. Forwards to the third-party API
  4. Returns the response

Services continue calling the same API endpoint. They don't know they're hitting a proxy.

Implementation

Phase 1: Azure Infrastructure

Internal Certificate Authority

Created a private Root CA to issue certificates for internal traffic. This allows services to trust the proxy without relying on public certificate authorities.

rootCA.key   Keep secret, never share
rootCA.crt   Distribute to all services (safe to share publicly)

Proxy VM Setup

Provisioned an Azure VM running nginx as a reverse proxy:

  • Listens on port 443 for api.example.com
  • Uses internal CA-signed certificate
  • Strips incoming auth headers
  • Adds the real API key
  • Forwards to actual third-party API using public DNS (8.8.8.8)

Private DNS Zone

Configured Azure Private DNS to resolve api.example.com to the proxy VM's private IP. All services in the VNet automatically route through the proxy — no configuration needed on their end.

Base Container Images

Created custom base images (Python, Node) with the Root CA pre-installed. Services using these base images automatically trust the proxy's certificate.

For Python, this required adding the Root CA to both the system store and the certifi package store.

Phase 2: GCP Infrastructure

GCP services needed to route through the same proxy, but cross-cloud traffic required additional security.

Public Endpoint with Authentication

  • Created a public DNS record pointing to Azure VM
  • Obtained Let's Encrypt certificate for the public domain
  • Added token-based authentication for external traffic

GCP Proxy VM

Rather than modifying GCP services to add auth headers, deployed a GCP proxy VM that:

  • Receives internal GCP traffic via Private DNS
  • Adds the authentication token
  • Forwards to Azure proxy's public endpoint

GCP Private DNS

Configured Cloud DNS private zone to route api.example.com to GCP proxy VM. All GCP VMs automatically use this.

Cloud Run Integration

Cloud Run services don't use VPC by default. Required:

  • Serverless VPC Access Connector
  • Configuring each Cloud Run service to route all traffic through VPC
  • Scripted bulk update for all services

VM Certificate Trust

Uploaded Root CA certificate to a public Cloud Storage bucket. Any VM can install trust with:

curl -o /tmp/rootCA.crt https://storage.googleapis.com/bucket/rootCA.crt
sudo cp /tmp/rootCA.crt /usr/local/share/ca-certificates/internal-ca.crt
sudo update-ca-certificates

Architecture Summary

Azure Services
     Private DNS (api.example.com  Azure Proxy private IP)
     Azure Proxy (adds API key, uses public DNS 8.8.8.8 to resolve real API)
     Third-party API

GCP Services (VMs)
     Private DNS (api.example.com  GCP Proxy private IP)
     GCP Proxy (adds auth token)
     Azure Proxy public endpoint (validates token, adds API key, uses public DNS 8.8.8.8)
     Third-party API

GCP Services (Cloud Run)
     VPC Connector
     Private DNS
     Same flow as GCP VMs

Note: The Azure proxy uses public DNS resolvers (8.8.8.8) to reach the real third-party API. This bypasses the Private DNS override that would otherwise create a routing loop.

Security Layers

| Layer | Protection | |-------|------------| | Private DNS | Internal traffic never leaves VNet/VPC | | Internal CA | Only trusted services can connect to proxy | | Token Auth | External traffic must have valid token | | IP Allowlist | Azure NSG allows only GCP proxy IP | | Single Location | API key exists only on Azure proxy VM |

Benefits Achieved

  • Key Rotation: Change one config file on one VM
  • No Code Changes: Services work exactly as before
  • Audit Trail: All API calls logged in one place
  • Reduced Exposure: Key removed from 24 repos and dev machines
  • Cross-Cloud: Works across Azure and GCP seamlessly

Key Learnings

  1. nginx can route by SNI — Multiple server blocks on port 443, each with different certs and auth rules

  2. Python uses certifi, not system certs — Must add Root CA to both stores for Python services

  3. Cloud Run needs VPC connector — Serverless services don't use Private DNS by default

  4. DNS-level routing enables zero-change migrations — Services don't know they're being proxied