BTP private linky swear with Azure – connecting to not-yet supported PaaS with Private Link Service for Azure


This post is part of a series sharing service implementation experience and possible applications of BTP Private Link Service on Azure.

Find the table of contents and my curated news regarding series updates here.

Find the associated GitHub repos here.

Dear community,

Continuing with the implementation journey of BTP Private Link Service (PLS) we will have a closer look at integrating services from the Azure PaaS portfolio, that are not yet added by SAP to the BTP solution.

This post builds upon part 6 of the series in terms of SAP Personal Security Environment (PSE).

Fig. 1 Applying PLS for unsupported PaaS leads to cyborg pinkie

As an example for the generalized approach for Azure PaaS, I will use Azure API Management (APIM) today. Azure APIM could be fronting an SAP system like SAP Gateway, S/4HANA, Process Orchestration (PI/PO) or Microsoft services like Azure Functions, Dynamics365 etc. Any REST interface, including the specialized OData standard, would be possible.

In an ideal world, we would architect like so:

Fig.2 ideal world with OData request

Since we can’t establish the link with comfort and ease, we need to check our toolbox and see what else is available.

Mhm, proxies, reverse connect components, web dispatchers, port forwarders… and of course our beloved IaaS component – the virtual machine. Urgh, really? I am afraid so.

Does it work? Yes indeed.

I am describing two concepts that are bearable and easily adaptable if the future brings more native integration.

Fig.3 not as great but gets the job done; source: thecodinglove.com

Before we get started let’s make sure our target PaaS app is VNet integrated and ideally only reachable from within the private VNet. That configuration would be typically in line with deploying a private link in the first place.

Note: In case you keep APIM Internet-facing but VNet integrated you can skip the DNS or hosts file configs mentioned later.

Fig.4 Screenshot of private APIM network setting

Ready?

At the heart of the first option is the SAP Web Dispatcher (WDisp). It allows us to re-use the BTP Private Link service for VM based scenarios and direct certain http requests towards the private Azure APIM next to the configured SAP backends.

Fig.5 PLS architecture with SAP WDisp and Azure APIM

Great, why don’t we do this all the time for PaaS apps?

Because this requires an additional IaaS component, that needs to be managed, patched, considered for disaster recovery, backup, and high availability. The point of private link for managed services was to avoid such things, right 😉. Like I said before “in an ideal world”. Sigh…

Be aware that you need to configure DNS on Azure or use hosts files once you switched your Azure APIM to internal mode only.

Once, we are happy with all of that, we can apply the same steps for the Azure Private Link Service and load balancer that is bound to BTP as described in part 1 of the blog series.

We simply re-use our existing backend pool.

Fig.6 Screenshot from WDisp backend pool

Fig.7 Screenshot from WDisp load balancing rule

In my example I configured port 44399 as inbound rule from BTP. So, to call through this route, we need to adjust our destinations on BTP to use this port. Meaning the hostname on BTP stays the same and the various routings happen through the different ports (e.g., SAP S/4Hana behind the WDisp through 443).

Fig.8 Screenshot from BTP destination with PLS host name and port 44399

The configuration on the SAP WDisp including the hosts file entry on the same VM (consider DNS for a more scalable solution) ensures that the request from BTP gets “forwarded” to the private IP of your Azure APIM instance on the respective standard SSL port.

Fig.9 Screenshot collection of hosts file on WDisp and APIM private IP

Ok great, now on to the WDisp config 😊 We need to add a system target with special SID EXT and configure our APIM target with the mentioned port associated with the load balancing rule behind the private link service (in my case 44399). Additionally, there is the WDisp parameter SRCURL that restricts the rule to specific paths and allows for more complex routing. In my case I used the prefix /api, which is being used by the Java app on BTP.

Fig.10 Screenshot of WDisp Cockpit and parameter config

Finally add a rule (see rules.txt) to override host header, so that APIM accepts the request from BTP (initially supplying host header *sap.pls.internal). See SAP’s docs for additional context around the rules override.

Fig.11 Screenshot of rules.txt file to override host header

I am not going into more detail around PSE at this point for more concise reaeding. Read more about SNI and PSE Management on part 6 of the series.

As a test I pointed my Java app at Azure APIM through PLS hitting the sample Products OData service on SAP.

Fig.12 Screenshot collection from Azure APIM and Java app response

As you can see the request made its way through the described hops and hit the OData service via Azure APIM. At this point you can govern your SAP APIs as well non-SAP APIs in one central place while connecting via private link from BTP. Great, isn’t it? 😊

Not too happy yet?

In case you have customizing nightmares about DNS, hosts files and WDisp, here is option two that you might like a little better then for its BTP connectivity focus and specialized features.

Fig.12 Alternative architecture with SAP Cloud Connector

Falling back to the SAP Cloud Connector (SCC) for the private isolated connectivity is an option. However, you retain the burden of considering maintaining/patching, handling disaster-recovery, backup, and high availability for the VMs hosting the SCC. Also you don’t profit from the Microsoft backbone and the PaaS aspect of the SAP Private Link Service for Azure and require outbound ports open to the Internet.

The only upside is, that this is an SAP native component and lifts the need to make OS level configurations and overrides the WDisp required to route the requests. The SCC does this for you under the hood. You might consider it a fancy BTP-opinionated dispatcher.

If your Azure APIM is internal-only mode, you need again DNS configuration or hosts file override to resolve the private IP of APIM.

Fig.13 Screenshot from SAP Cloud Connector config for Azure APIM

Once configured you once again adjust the destination on BTP to reflect the host mapping. In my example the virtual host expected by the SCC is “azure-apim”.

Fig.14 Screenshot from Destination on BTP

The proxy type OnPremise ensures routing to your registered SCC.

What about the other routing options from the toolbox?

You might be tempted to use a port forwarder instead of the SAP WDisp if you don’t have any. Unfortunately, the target PaaS services expects its known host header (in my example that was my-odata-apim.azure-api.net for instance). Since your request originates from SAP BTP with SAP’s generated domain you will run into connectivity issues.

Port forwarder OUT! What about reverse proxy then?

That would be the same approach as with the SAP WDisp utilizing host header override logic. If you prefer NGINX, Apache or whatever product you run there, you can adapt the approach outlined at the beginning. Key is the DNS resolution of your private Azure APIM instance and host header override.

Both approaches – the SAP Web Dispatcher and the SAP Cloud Connector – are established at companies for many years. They differ in scope though. The SCC is primarily and solemnly targeted at opening a secure tunnel (reverse connect) to BTP only. The WDisp is a specialized load balancer for SAP systems for internal and external purposes.

Either way both options are workable, but you might have a preference given your experience and skill set in the team operating the landscape.

Uhh, what a ride. We saw how to go beyond the scope of the BTP Private Link Service (PLS) using two different approaches to add Azure PaaS apps like the Azure API Management to the mix. This might be useful to cover integration targets that are not yet natively supported by the PLS. If you are comfortable with the challenges of a dispatcher and DNS, you can apply the concept to the PLS. In case you want a more SAP native implementation for BTP, SAP Cloud Connector is your friend.

Any further inputs from you @Developers and @Architects?

Find the related GitHub repos here.

As always feel free to ask lots of follow-up questions.

Best Regards

Martin