Cloud Intelligence™Cloud Intelligence™

Cloud Intelligence™

Accedere ad API private e pubbliche da una VPC tramite API Gateway

By Tomer RadianSep 16, 202517 min read

Questa pagina è disponibile anche in English, Deutsch, Español, Français, 日本語 e Português.

Questo articolo riguarda gli API Gateway con API pubbliche definite con un endpoint di tipo Regional.

TL;DRImplementazione passo passo

Le API sono fondamentali per abilitare la comunicazione tra servizi nelle architetture cloud-centriche di oggi. Amazon Web Services (AWS) offre un potente servizio API Gateway, che permette agli sviluppatori di creare, pubblicare, gestire e proteggere API a qualsiasi scala.

Uno scenario tipico prevede servizi all'interno di una VPC che devono accedere sia ad API pubbliche sia private. Le API pubbliche presentano due formati di URL:

1. L'URL predefinito generato dal servizio API Gateway: api-id.execute-api.REGION.amazonaws.com

2. Un nome di dominio personalizzato (ad esempio api.mydomain.com) che consente di utilizzare un dominio leggibile e un proprio certificato.

Descriverò e risolverò prima il caso del nome di dominio personalizzato, per poi spiegare come gestire l'URL generato da API Gateway.

Il problema si presenta quando il nome di dominio personalizzato è ospitato fuori da Route 53 e si utilizza un record CNAME.

L'obiettivo di questo articolo è garantire un accesso fluido alle API private e pubbliche all'interno della VPC, assicurando comunicazioni tra servizi efficienti e sicure.

Usare API pubbliche e private dalla stessa VPC non rappresenta un problema se i nomi di dominio personalizzati pubblici sono ospitati in Route 53 e utilizzano record Alias che puntano al nome di dominio dell'API Gateway.

Come vedremo di seguito, sono necessari passaggi aggiuntivi per garantire una corretta risoluzione DNS e la convalida del certificato SSL quando si utilizzano provider DNS esterni (che impongono l'uso di record CNAME).

Terminologia

Nome di dominio dell'API Gateway

Il nome di dominio dell'API Gateway è un endpoint gestito da AWS, creato in fase di configurazione del nome di dominio personalizzato dell'API. È un alias dell'endpoint predefinito dell'API apiID.execute-api.REGION.amazonaws.com, e abilita la terminazione TLS e URL leggibili.

Ecco come funziona:

1. Struttura del nome di dominio dell'API Gateway per i due tipi di endpoint API pubblici

  • Edge-Optimized:

Utilizza una distribuzione CloudFront (ad esempio d123.cloudfront.net) per un accesso globale a bassa latenza.

  • Regional:

Utilizza un endpoint specifico per regione (ad esempio d-abc123.execute-api.us-east-1.amazonaws.com).

2. Configurazione DNS

  • Il proprio provider DNS (ad esempio GoDaddy):

Si crea un record CNAME che fa puntare il nome di dominio personalizzato (api.mydomain.com) al nome di dominio dell'API Gateway (ad esempio d-abc123.execute-api.us-east-1.amazonaws.com).

  • Esempio di record DNS su GoDaddy:

Nome: api.mydomain.com

Tipo: CNAME

Valore: d-abc123.execute-api.us-east-1.amazonaws.com

  • Questo record fa sì che il traffico verso api.mydomain.com venga instradato all'endpoint dell'API Gateway.

3. Associazione del certificato

  • Certificato AWS Certificate Manager (ACM):

Quando si definisce un nome di dominio personalizzato in API Gateway, lo si collega a un certificato ACM (ad esempio *.mydomain.com).

  • Il Subject Alternative Name (SAN) del certificato deve includere il nome di dominio personalizzato (ad esempio api.mydomain.com, oppure il wildcard di primo livello *.mydomain.com).
  • API Gateway utilizza questo certificato per la terminazione TLS sul proprio edge layer.

4. Come funziona il tutto — Il flusso della richiesta

  • Un client effettua una richiesta a https://api.mydomain.com.
  • Il DNS risolve verso il nome di dominio dell'API Gateway (ad esempio d-abc123.execute-api.us-east-1.amazonaws.com).
  • Il DNS di AWS risolve il nome di dominio dell'API Gateway negli IP pubblici del servizio AWS Gateway, che si occupa della terminazione TLS (utilizzando il certificato ACM) e del bilanciamento del carico per il traffico.
  • Il servizio API Gateway invoca l'API e lo Stage a cui è stato mappato il nome di dominio personalizzato.

Il problema

Il nodo della questione è il VPC Endpoint per API Gateway necessario per accedere alle API private. Quando il VPC Endpoint ha il Private DNS abilitato, possono insorgere complicazioni nell'accesso alle API pubbliche. In particolare, le chiamate alle API pubbliche possono fallire a causa di problemi con il certificato SSL. Per capirne il motivo bisogna comprendere come avviene la risoluzione DNS in questa configurazione architetturale (vedere l'Appendice A).

Un'API pubblica priva di nome di dominio personalizzato dispone solo di un URL endpoint pubblico, accessibile a chiunque da Internet.

Poiché le API pubbliche possono essere invocate solo da Internet, chiamare questo URL dall'interno di una VPC con un VPC Endpoint per API Gateway con Private DNS abilitato porterà a tentare di invocare l'API dalla VPC e non da Internet, restituendo un errore HTTP 403 (forbidden).

Le API pubbliche richiedono un certificato quando vengono mappate su un nome di dominio personalizzato.

Quando si crea un record di tipo Alias A in Route 53 per invocare la propria API pubblica tramite un nome di dominio personalizzato, è possibile chiamare API private e pubbliche dalla propria VPC anche con un VPC Endpoint per API Gateway con Private DNS configurato.

Se si ospita il dominio presso un provider esterno, è possibile creare un record CNAME nel DNS esterno.

È proprio questo record CNAME all'origine del problema.

Quando si chiama un'API pubblica con un nome di dominio personalizzato, viene generata una lookup DNS per trovare il record che lo mappa al nome di dominio dell'API Gateway. Questa, a sua volta, richiede una seconda lookup DNS per ottenere l'indirizzo IP del nome di dominio dell'API Gateway restituito dalla prima lookup.

Senza Private DNS abilitato, la lookup restituisce l'IP pubblico dell'API pubblica, che è esattamente ciò che vogliamo.

Questo IP pubblico appartiene all'AWS Gateway Service, che cercherà il nome di dominio personalizzato in un Subject Alternative Name (SAN) all'interno del certificato associato al dominio. Poiché il certificato del nome di dominio personalizzato (ad esempio mydomain.com) è stato associato al nome di dominio dell'API Gateway, l'handshake SSL andrà a buon fine e l'API pubblica verrà invocata.

Quando una VPC dispone di un VPC Endpoint per API Gateway con Private DNS abilitato, questo Private DNS intercetterà la lookup per il nome di dominio dell'API Gateway (perché cattura tutti i sottodomini di execute-api.REGION.amazonaws.com) e restituirà l'IP privato assegnato alla Elastic Network Interface (ENI) del VPC Endpoint.

Questo IP privato rappresenta l'indirizzo del servizio API Gateway, che accetterà solo URL endpoint interni appartenenti all'URL endpoint dell'API privata, nel formato apiID.execute-api.REGION.amazonaws.com.

Il risultato sarà simile a questo:

Risultato della chiamata a un'API pubblica in presenza di un VPC Endpoint per API Gateway con Private DNS abilitato

Di conseguenza, qualsiasi tentativo di invocare l'API pubblica dall'interno della VPC porterà al fallimento dell'handshake SSL, bloccando la connessione.

Panoramica della soluzione

Come appena spiegato, quando un VPC Endpoint per API Gateway ha il Private DNS abilitato, tutte le lookup DNS verso execute-api.REGION.amazonaws.com si risolvono con IP privati, e questo fa fallire la convalida SSL delle chiamate alle API pubbliche (con nomi di dominio personalizzati). La soluzione prevede la prioritizzazione del DNS tramite zone ospitate private di Route 53, nota anche come Split-Horizon / Split-View DNS.

L'idea è che, utilizzando una zona ospitata privata (PHZ), le lookup DNS originate all'interno della VPC consultano prima la PHZ rispetto a qualsiasi altro server DNS pubblico.

Supponiamo di avere un server DNS GoDaddy che ospita il nostro dominio al livello superiore: mydomain.com.

Se mappiamo api.mydomain.com sulla nostra API pubblica, ospiteremo questo sottodominio nella nostra PHZ per realizzare lo split-view DNS.

In questo modo, le lookup per api.mydomain.com originate dall'interno della VPC vengono servite dalla PHZ, mentre le chiamate ad altri sottodomini che non utilizzano API Gateway (ad esempio quelli che puntano ad altri servizi non intercettati da un VPC Endpoint) continueranno a passare dal DNS pubblico.

Questa soluzione si fonda su tre concetti chiave:

  1. VPC Endpoint: per l'accesso alle API private (Private DNS abilitato)
  2. Zona ospitata privata: per realizzare lo split-view DNS
  3. Un record di tipo Alias A nella PHZ: per indirizzare il traffico verso il nome di dominio dell'API Gateway pubblica

Implementazione passo passo

Prerequisiti

  • Un API Gateway pubblico con un nome di dominio personalizzato ospitato fuori da Route 53 e invocabile da Internet, oppure un nome di dominio personalizzato pubblico ospitato in Route 53 ma che utilizza un record CNAME al posto di un record di tipo Alias A.
  • Un VPC Endpoint per API Gateway con Private DNS abilitato, definito nella VPC dalla quale si vuole chiamare l'API pubblica.

Se si dispone già di questo VPC Endpoint, partire dal passaggio 2.

Senza di esso, non sarà possibile chiamare le API private.

1. Configurare il VPC Endpoint per API Gateway per accedere alle API private

Se si dispone già di questo endpoint, passare direttamente al punto "2".

  • Nella AWS Console, accedere a VPC Console > Endpoints.
  • Creare un interface endpoint per com.amazonaws.REGION.execute-api.
  • Abilitare il Private DNS (impostazione predefinita).
  • Associare un security group che consenta il traffico HTTPS in entrata (porta 443) dalla VPC (oppure dagli IP delle specifiche risorse della VPC alle quali si vuole consentire la chiamata di API private tramite API Gateway).

2. Creare una zona ospitata privata

  • Creare una PHZ nella Route 53 Console che corrisponda al percorso del nome di dominio personalizzato pubblico dell'API (ad esempio api.mydomain.com).

Si tenga presente che, se nel proprio dominio pubblico esistono URL che si vogliono chiamare ma che non sono mappati a un API Gateway (ad esempio se dev.mydomain.com punta a un Load Balancer e non ad API Gateway), come nome di dominio della zona ospitata privata si dovrebbe utilizzare il nome di dominio personalizzato completo dell'API (come api.mydomain.com).

Se invece tutti i sottodomini del proprio dominio sono mappati ad API di API Gateway, utilizzare il livello superiore mydomain.com come nome di dominio.

  • Associare la zona alla propria VPC.

Creare una PHZ per il proprio nome di dominio personalizzato e associarla alla VPC che deve accedere a questo dominio

3. Configurare i record DNS

  • È necessario creare un record di tipo Alias A per ogni dominio utilizzato da un'API.

Ad esempio, con api.mydomain.com e special-api.mydomain.com, occorre creare un record per ciascuno: uno per api e l'altro per special-api. Scegliere quindi il tipo di record "A".

  • Per il nome del record:

- Se il nome del dominio personalizzato coincide con il nome di dominio completo dell'API, non digitare il sottodominio (non digitare "api") nel campo "Record Name" (lasciarlo vuoto). Ad esempio, se la PHZ è stata creata per api.mydomain.com in quanto unico sottodominio utilizzato con API Gateway, lasciare vuoto il campo Record Name.

- Se invece si utilizza il livello superiore — mydomain.com, perché esistono più sottodomini mappati ad API Gateway, inserire il nome della propria api come valore di "Record Name" per ciascun record. Ad esempio, inserire "api" per un record e "special-api" per un altro.

  • Impostarlo come record Alias spuntando la casella "alias"
  • Scegliere "Alias to API Gateway API"
  • Selezionare la regione della propria API
  • Selezionare l'endpoint regionale (il nome di dominio dell'API Gateway creato per il proprio nome di dominio personalizzato) della propria API pubblica.

Avrà un nome del tipo:

d-abc123.execute-api.REGION.amazonaws.com

  • Se non compare nell'elenco, copiarlo dalla console di API Gateway, alla voce "custom domain names" -> API Gateway domain name.
  • Salvare il record

Route 53 potrebbe impiegare un po' di tempo prima che la zona ospitata privata appena creata sia disponibile alla VPC.

Vedere l'Appendice B per l'architettura di questa soluzione.

Test

Servirà un'istanza EC2 in esecuzione nella propria VPC con connessione Internet per le API pubbliche.

Connettersi all'istanza EC2 e, dopo aver sostituito l'URL sottostante con il proprio, eseguire:

curl -v https://your-public-api.yourdomain.com/your-path

Si dovrebbe ottenere un output simile a questo:

Si noti che, prima di creare e configurare la PHZ, l'IP che il Private DNS (quello associato al VPC Endpoint per API Gateway) restituiva per il nome di dominio personalizzato era un IP privato (era 10.0.3.79), e questo IP privato appartiene alla ENI del VPC Endpoint. Con una PHZ per il nome di dominio personalizzato, otteniamo ora gli IP pubblici del nome di dominio dell'API Gateway, che (in questo esempio) sono:

IPv4: 44.221.197.141, 34.192.177.183, 34.232.190.93

Lavorare con gli URL pubblici predefiniti dell'API Gateway

Per lavorare con API private e pubbliche, disabilitare il Private DNS associato al VPC Endpoint per API Gateway. Creare poi una PHZ chiamata execute-api.REGION.amazonaws.com e associarla a tutte le VPC alle quali si intende concedere l'accesso alla VPC che ospita le API private. (Nota: l'associazione con una VPC in un'altra regione è collegata alla parte "Bonus" di questo articolo.)

Si crea un record wildcard per intercettare tutti gli API-ID di API Gateway, come ad esempio:

Creare la zona ospitata per le API private in questa regione

Si creerà ora un record "catch-all" che punterà al DNS del VPC Endpoint, come ad esempio:

Creare un record catch-all per tutte le API private in questa regione

Così facendo, tutti gli URL di un API Gateway privato definito in us-east-1 verranno intercettati da questa PHZ, che restituirà l'indirizzo IP privato del VPC Endpoint per API Gateway.

Per le API pubbliche con nome di dominio personalizzato, abbiamo visto come la creazione di una PHZ per quel dominio risolva il problema.

Per le API pubbliche prive di nome di dominio personalizzato, occorre aggiungere un record Alias che utilizzi l'API ID dell'API e che punti all'URL pubblico.

Ad esempio, supponiamo di avere un'API pubblica in us-east-1 il cui URL è: bmf11pk5je.execute-api.us-east-1.amazonaws.com

Se la chiamiamo dall'interno della VPC, restituirà "Forbidden (403)", come spiegato sopra per lo scenario del nome di dominio personalizzato. Per risolvere il problema, aggiungiamo un record chiamato "bmf11pk5je" e lo facciamo puntare all'invoke URL in questo modo:

Saremo ora in grado di chiamare l'API pubblica definita in questo record dall'interno della VPC. Per ogni ulteriore API pubblica che vorremo chiamare in questa regione sarà necessario aggiungere un record Alias, esattamente come fatto in questo caso.

Bonus

Chiamare un'API privata situata in una regione da una VPC in una regione AWS diversa.

Il problema

Le API private si possono condividere facilmente tra più VPC della stessa regione. È sufficiente disporre di VPC Endpoint per API Gateway in ogni VPC, definire una resource policy per la propria API privata che consenta l'accesso da queste VPC, e aggiungere i VPC Endpoint all'API privata (tramite le sue API Settings).

Questo approccio non funziona se la propria VPC si trova in una regione diversa da quella che ospita l'API privata.

In questo caso, occorre procedere come segue:

  1. Effettuare il peering tra le due VPC, quella che ospita l'API privata e quella alla quale si vuole concedere l'accesso.

Per il VPC peering occorre assicurarsi che le due VPC non abbiano blocchi CIDR sovrapposti. 2. Se non si dispone di una zona ospitata privata per la regione di API Gateway che ospita l'API privata, occorre crearne una. 3. Il nome della zona ospitata privata (PHZ) dovrebbe essere:

execute-api.REGION.amazonaws.com 4. Bisogna associare questa PHZ al VPC Endpoint per API Gateway della regione e alla VPC alla quale si vuole concedere l'accesso. 5. Aggiungere un record Alias di tipo A alla PHZ (impostarlo come alias spuntando la casella "alias"), quindi selezionare "Alias to VPC Endpoint" dal menu a discesa. 6. Selezionare la regione della VPC alla quale si vuole concedere l'accesso 7. Scegliere il VPC Endpoint per l'API Gateway in questa VPC 8. Aggiungere il blocco CIDR della VPC peered al Security Group del VPC Endpoint. Senza questa operazione, la comunicazione dalla VPC peered verrebbe bloccata. 9. Salvare il record

Una volta completati questi passaggi, sarà possibile invocare l'API privata dalla VPC nell'altra regione.

Si noti che, utilizzando il VPC Peering, la Resource Policy del proprio API Gateway privato non deve approvare il traffico dalla VPC peered: deve consentirlo solo dalla VPC principale in cui è distribuito. Questo perché la comunicazione verso l'API Gateway arriverà dal VPC Endpoint all'interno della propria VPC, anche se ha origine dalla VPC peered.

Questo peering cross-region produrrà lo stesso problema di fallimento del certificato SSL se si tenta di accedere a un'API pubblica definita nella stessa VPC dell'API privata. Pur trovandosi in un'altra regione, è comunque associata a una PHZ per execute-api.REGION (la REGION in cui è distribuita l'API) e, di conseguenza, tenterà di chiamare l'IP privato del VPC Endpoint, a meno che non sia definita una PHZ per la propria API pubblica.

Per chiamare sia API private sia pubbliche, in modalità cross-region o meno, occorre seguire le istruzioni della prima parte di questo articolo.

Appendice A

Il diagramma seguente mostra cosa accade quando un'istanza EC2 chiama un API Gateway pubblico in presenza di un VPC Endpoint per API Gateway con Private DNS abilitato.

Chiamare un'API pubblica da una VPC senza una PHZ configurata

  1. L'EC2 sta tentando di chiamare https://api.mydomain.com, quindi viene effettuata una lookup DNS
  2. La risposta del DNS è il nome di dominio dell'API Gateway
  3. Viene effettuata la seconda lookup DNS, che viene intercettata dal Private DNS associato al VPC Endpoint per API Gateway.
  4. Restituisce l'indirizzo IP privato del VPC Endpoint
  5. L'EC2 tenta di invocare l'API tramite l'indirizzo IP privato
  6. Il servizio API Gateway, raggiungibile tramite l'indirizzo IP privato, fornisce un certificato valido per *.execute-api.REGION.amazonaws.com e non per api.mydomain.com: viene quindi restituito un errore di certificato

Appendice B

Il diagramma seguente mostra cosa accade quando un'istanza EC2 chiama un API Gateway pubblico in presenza di un VPC Endpoint per API Gateway con Private DNS abilitato. In questo caso, è anche definita una zona ospitata privata per il nome di dominio personalizzato.

Chiamare API pubbliche da una VPC con una PHZ configurata

Chiamare l'API pubblica da Internet

  1. Viene effettuata una lookup DNS verso il servizio di hosting di domini esterno (ad esempio GoDaddy) per il nome di dominio personalizzato dell'API (ad esempio api.mydomain.com)
  2. La query restituisce il nome di dominio dell'API Gateway per questo nome di dominio personalizzato
  3. Il nome di dominio dell'API Gateway viene interrogato in Route 53 di AWS
  4. Viene restituito un indirizzo IP pubblico per il servizio API Gateway pubblico
  5. L'IP pubblico viene utilizzato per chiamare il servizio API Gateway e, poiché è associato ai certificati di api.mydomain.com, termina l'SSL e chiama il target rilevante dello stage dell'API Gateway

Chiamare un'API privata dall'interno della VPC

6. Le API private hanno un URL nel formato apiID.execute-api.REGION.amazonaws.com. Quando un URL di questo tipo viene chiamato da una VPC con un VPC Endpoint per API Gateway con private DNS attivo, la richiesta viene gestita da questo private DNS.

7. Il private DNS restituisce l'IP privato della ENI del VPC Endpoint per API Gateway.

8. Il servizio API Gateway raggiungibile tramite questo IP privato dispone di un certificato per *.execute-api.REGION.amazonaws.com: la chiamata all'API privata che ha utilizzato questo URL viene quindi autenticata e inoltrata al target dell'API privata.

Chiamare un'API pubblica di API Gateway dall'interno della VPC

9. Il DNS della zona ospitata privata creata per il nome di dominio personalizzato cattura e gestisce le query che ricadono sotto il proprio nome di dominio.

10. La PHZ, grazie al record di tipo Alias A, restituisce l'IP pubblico del nome di dominio dell'API Gateway associato al nome di dominio personalizzato.

11. L'IP pubblico viene chiamato tramite l'Internet Gateway, raggiungendo l'indirizzo del servizio dell'API Gateway. Poiché il servizio raggiungibile dall'IP pubblico dispone dell'associazione di certificato tra il nome di dominio personalizzato e il nome di dominio dell'API, l'handshake SSL ha successo e il TLS viene terminato. La richiesta viene quindi inoltrata al target dello stage rilevante dell'API pubblica di API Gateway.

Invito all'azione

Mi auguro che questo articolo Le abbia offerto spunti utili. Per saperne di più o per maggiori informazioni sui nostri servizi, non esiti a scriverci. Può contattarci qui.

Riferimenti

La soluzione più semplice è ospitare il proprio nome di dominio personalizzato pubblico in Route 53 e utilizzare un record di tipo Alias A. Questo permette di chiamare API pubbliche e private con un VPC Endpoint per API Gateway con Private DNS.

Se non si può o non si vuole farlo, è possibile utilizzare il metodo descritto in questo articolo.

Alcuni aspetti da tenere presenti

  1. La presenza di un VPC Endpoint per API Gateway con Private DNS farà fallire tutte le chiamate verso qualsiasi API pubblica di API Gateway in quella regione, con errore di mismatch del certificato. Il fatto che abbia parlato solo di api.mydomain.com è del tutto arbitrario. Se si dispone (ad esempio) di api.mydomain.com, api.example.com e myapi.myspecialdomain.com, ciascuno di essi richiederà la propria PHZ, in quanto non vi è alcuna relazione tra un dominio e gli altri.
  2. Anche se ho fatto riferimento a un'API REST, il metodo funziona anche per le API HTTP (testato) e le API WebSocket (non testato), perché non è una questione di protocollo, ma di rete e DNS.