When developing numerous APIs, Azure API Management (APIM) serves as an effective platform for their deployment.
These APIs may cater to internal users within a corporate network or extend to external partners via the internet, and since API backends are usually locked down and private, nailing security from the get-go is a must when you kick off an API program! Think:
- VNET Integration
- Authentication
- Monitoring
- Rate limiting
- Subscription/API keys
While it might seem simpler to manage separate APIM instances for internal and external APIs, this approach is not optimal!
It’s super important to get the most out of APIM because you often need those pricier SKUs to meet all the security and governance standards you’re aiming for.
How, then, can we securely manage both internal and external APIs using a single APIM instance?
Microsoft’s Proposed Architecture
Microsoft provides guidance on how to achieve this in the article Protect APIs with Application Gateway and API Management.
This, however, is not ideal.
In this architecture, the consumer will see the designation external or internal in the URI, which is not something you’d typically want:
api.<some-domain>/external/api1
api.<some-domain/internal/api2
That’s a bit clunky, right?
There must be a better way.
A Better Way
Rather than employing two APIM instances, opting for two Application Gateways to separate traffic internal and external traffic offers a more cost-effective solution, whilst still maintaining the same level of security and management within a single APIM instance.
Access to the APIM instance is limited to VNET access only. This means any API access must first go through one of the Application Gateways.
Each gateway modifies the incoming request by adding a prefix indicating its “role” (either internal or external) before forwarding the request on to APIM.
Consequently, each API definition in APIM simply adheres to a naming convention that includes the respective internal or external prefix:
external/api1/
external/api2/
internal/api3/
internal/api4/
This straightforward method offers advantages over the approach suggested by Microsoft:
- Control over API URLs: The external or internal moniker of API URLs is not visible to the end users. This approach keeps the operational details hidden, maintaining a cleaner and more professional appearance.
- Avoids Rule Saturation: By centralizing the routing logic in APIM, the risk of reaching the Application Gateway’s limit of 100 path-based rules is minimized. This ensures that the gateway can handle a larger variety of API routes without needing extensive rule management.
- Simplified API Integration: New APIs can be added seamlessly without the need to modify the Application Gateway. This streamlines the process of integrating new services, as there’s no additional configuration needed at the gateway level.
All this enables the use of a single, higher-tier APIM instance as required.
Allowing External Access to an API
Let’s run through an example of accessing an external API.
- A request is made to the externally available Application Gateway:
https://api.company.com/api1/customers
- The Application Gateway executes the rewrite rule and adds the prefix
"external"
. The request is now forwarded to:https://apiminstance.azure-api.net/external/api1/customers
- APIM has an API matching
external/api1
and so routes the request to the backend. - The backend (over the private network) completes the API call and returns a successful
200 OK
response to the External User.
The externally exposed Application Gateway will only forward requests to APIs with an “external” prefix.
Blocking Access to an Internal API
So continuing the scenario, if an attempt is made to reach an internal API via the External Application Gateway, then the routing will fail.
- Request is made to extermally available Application Gateway, with url:
https://api.company.com/api4/orders
- Application Gateway executes the rewrite rule and adds the prefix
"external"
. The request is now forwarded to:https://apiminstance.azure-api.net/external/api4/orders
- APIM does not have an API matching
external/api4
. The request terminates and does not route to any backend system.
Wrapping Up
By using this approach for isolating internal and external APIs, we can greatly simplify the final architecture.
It allows for the focus of the API Management to remain within the APIM instance. Through the use of a simple convention, it means that:
- New APIs can be introduced without having to update the Application Gateway.
- Application Gateway rule limits (100 path-based rules) are not threatened.
- External or Internal moniker on API URLs are not exposed to callers.
Whilst the Microsoft suggestion is valid, this feels a better fit.
As a side note, it doesn’t have to be Application Gateway. The concept doesn’t require Application Gateway per-se, just that URL rewriting and network routing has to take place. Whether this is done in another service, such as Cloudflare, doesn’t matter to the overall concept.