This post is part of a series sharing service implementation experience and possible applications of SAP 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
SAP Private Link Service (PLS) for Azure we will have a closer look at connecting
privately to your Azure workloads via the
Azure Application Gateway (App Gateway) using the Microsoft backbone. Why is this interesting?
First, the App Gateway offers a
managed Web Application Firewall (WAF). Yes, you heard that correctly. From now on you may inspect 🧐 the https traffic coming from the shared tenant SAP BTP environment based on your needs. Compliance and Security anyone?
Second, the App Gateway
simplifies your end-to-end setup regarding TLS compared to maintaining “
Server Name Indicator” on your SAP Web Dispatcher or NetWeaver. You will see further down how much easier. Oh boy was I excited.
Self-renewing certificate generated in Key Vault. Much wow!
Third, the App Gateway offers a managed way of addressing
all your private virtual network integrated Azure workloads via https directly. And did I mention auto-scaling, high-availability, high-traffic support, and many more
web app features?
Below architecture overview describes a typical OData scenario with the SAP Gateway. Customers link their BTP apps or SAP SaaS products like SuccessFactors, Cloud for Customer etc. with their backends using this pattern. SAP Cloud Integration offers the standard integration content for the required business logic.
![](./?url=aHR0cHM6Ly9jb21tdW5pdHkuc2FwLmNvbS9sZWdhY3lmcy9vbmxpbmUvc3RvcmFnZS9ibG9nX2F0dGFjaG1lbnRzLzIwMjIvMTEvcHJpdmF0ZS1saW5reS1hcHBndy1vdmVydmlldy0xLnBuZw==&__proxy_form=0)
Fig.1 Architecture overview
Additional popular fronting targets for the Azure App Gateway that enable further business cases are
Azure API Management,
Azure Storage Accounts,
Azure App Service,
Azure Functions, or
Azure Kubernetes Service as ingress controller. These options extend the capabilities of the BTP hosted apps and services.
You may privately connect to the listed services individually without the App Gateway but at the expense of linking service-by-service and the WAF functionality. SAP maintains a
guide by each target service. See also my
aggregator blog post for additional context.
![](./?url=aHR0cHM6Ly9jb21tdW5pdHkuc2FwLmNvbS9sZWdhY3lmcy9vbmxpbmUvc3RvcmFnZS9ibG9nX2F0dGFjaG1lbnRzLzIwMjIvMTEvcHJpdmF0ZS1saW5reS1hcHBndy1waW5reS0xLnBuZw==&__proxy_form=0)
Which integration target do you require most? Let me know on the comments, so I can tailor the write up to be most relevant to you going forward.
Great listening skills are essential for any relationship – or how App Gateway is making sure everyone gets heard
To begin with, a private link needs to be configured for your App Gateway instance. I am describing the process for the WAF v2 tier. It might slightly differ for other SKUs.
🛈Note:
A fully configured listener and routing rule need to be setup for the initial SAP Private Link approval process to work. A typical symptom of missing configuration is a failed create-status on BTP despite correct networking setup. |
Let’s get going: Add a private frontend IP configuration named “appGwPrivateFrontendIp” to your App Gateway and maintain a dedicated private IP for the link to target.
![](./?url=aHR0cHM6Ly9jb21tdW5pdHkuc2FwLmNvbS9sZWdhY3lmcy9vbmxpbmUvc3RvcmFnZS9ibG9nX2F0dGFjaG1lbnRzLzIwMjIvMTEvcHJpdmF0ZS1saW5reS1hcHBndy1mcm50ZW5kLWlwLnBuZw==&__proxy_form=0)
Fig.2 Screenshot of private Frontend IP configuration
Now, move on to the Private Link section and add a link with that new config and allocate one private IP address for BTP to target.
![](./?url=aHR0cHM6Ly9jb21tdW5pdHkuc2FwLmNvbS9sZWdhY3lmcy9vbmxpbmUvc3RvcmFnZS9ibG9nX2F0dGFjaG1lbnRzLzIwMjIvMTEvcHJpdmF0ZS1saW5reS1hcHBndy1wcml2LWxuay5wbmc=&__proxy_form=0)
Fig.3 Screenshot of Private Link create experience
Next, copy your App Gateway’s resource ID, Frontend IP configuration name and supply them to the Private Link create wizard in SAP BTP to complete the linking process:
![](./?url=aHR0cHM6Ly9jb21tdW5pdHkuc2FwLmNvbS9sZWdhY3lmcy9vbmxpbmUvc3RvcmFnZS9ibG9nX2F0dGFjaG1lbnRzLzIwMjIvMTEvcHJpdmF0ZS1saW5reS1hcHBndy1yZXNvdXJjZS1pZC0xLnBuZw==&__proxy_form=0)
Fig.4 Illustration of SAP Private Link App Gateway create experience
If everything went to plan you will see a pending connect request with “hello from btp” on your App Gateway. Oh, look at that
😊
![](./?url=aHR0cHM6Ly9jb21tdW5pdHkuc2FwLmNvbS9sZWdhY3lmcy9vbmxpbmUvc3RvcmFnZS9ibG9nX2F0dGFjaG1lbnRzLzIwMjIvMTEvcHJpdmF0ZS1saW5reS1hcHBndy1idHAtY3JlYXRlLXBlbmRpbmcucG5n&__proxy_form=0)
Fig.5 Illustration of SAP Private Link approval
Ok great, Link established. Don’t forget to bind at least one application on BTP to the service to generate your hostnames. You may use my example
Java app to start with. Git clone it in Business Application Studio for instance, maintain your SAP Private Link instance name on the
manifest.yaml, build the project and “cf push” it into your CloudFoundry space. Once the binding completes, retrieve your “short” hostname from the SAP Private Link service.
I suggest the
shorter hostname for ease of maintenance regarding the trust certificates we are going to maintain in a bit and for dealing with multiple links. Have a look at
this post in the series for staging and networking topology considerations.
![](./?url=aHR0cHM6Ly9jb21tdW5pdHkuc2FwLmNvbS9sZWdhY3lmcy9vbmxpbmUvc3RvcmFnZS9ibG9nX2F0dGFjaG1lbnRzLzIwMjIvMTEvcHJpdmF0ZS1saW5reS1hcHBndy1idHAtaG9zdG5hbWUucG5n&__proxy_form=0)
Fig.6 Screenshot of SAP Private Link short host name retrieval for App Gateway
Since we now have a fully operational private link, let’s move on to the listening part on the App Gateway. You want to work with all those “hellos” from BTP after all, don’t you?
Oh shuuut, trust setup for end-to-end SSL!
Remember this incident from
part 1 of the series? Poor broken pinky.
![](./?url=aHR0cHM6Ly9jb21tdW5pdHkuc2FwLmNvbS9sZWdhY3lmcy9vbmxpbmUvc3RvcmFnZS9ibG9nX2F0dGFjaG1lbnRzLzIwMjIvMTEvcHJpdmF0ZS1saW5reS1hcHBndy1idHAtZXJyb3IucG5n&__proxy_form=0)
Fig.7 Illustration of need for trust setup between App Gateway and BTP destination
We are smarter this time!
Back in the day we needed to maintain the hostname on the responding service and select it for the host header for requests coming from SAP BTP. At that time, we did that with SNI and the SAP Web Dispatcher. Have a look at
this post for reference. Today we have the mighty App Gateway
💪🏾🦸🏾
♀️ to do all this for us in a managed way!
Well, App Gateway needs some contribution from Azure Key Vault. See
here, how to obtain a
well-known trusted certificate instead of self-signed.
⚠️Be aware that the self-signed leaf certificate approach requires some BTP apps to restart to reflect changed leaf certificates in the trust store
⚠️
![](./?url=aHR0cHM6Ly9jb21tdW5pdHkuc2FwLmNvbS9sZWdhY3lmcy9vbmxpbmUvc3RvcmFnZS9ibG9nX2F0dGFjaG1lbnRzLzIwMjIvMTEvcHJpdmF0ZS1saW5reS1hcHBndy1jZXJ0LWNyZWF0ZS5wbmc=&__proxy_form=0)
Fig.8 Illustration of trust setup in App Gateway for SAP Private Link short host name
Auto-renewal for the
self-signed certificate!? NICE! As mentioned, before I am using wildcards and the shorter DNS name for ease of maintenance. Now every one of my SAP Private Links in the p1 rooster may talk to this App Gateway.
🛈Note:
A self-signed certificate is not optimal. You may favor bringing your own domain and certificate as described by SAP here. Furthermore, you might desire trusting the root or intermediate certificate of your Certificate Authority in BTP. That way there is no need for populating the certificate at all.
See here, how to create a certificate with a well-known certificate authority like DigiCert or GlobalSign automatically from Azure Key Vault.
Azure App Gateway polls the certificates to check for new versions every 4 hours.
⚠️Be aware that the self-signed leaf certificate approach requires some BTP apps to restart to reflect changed leaf certificates in the trust store⚠️ |
Next, we need to allow our App Gateway to read that certificate from Key Vault. For that we require a
user assigned managed identity. Follow the steps
here to create one and remember its resource ID. Assign this new managed identity permissions to work with certificates and secrets on your Key Vault. Find the settings under Overview -> Access Policies -> Create. In my example I gave it full rights for certificates and Secrets.
Learn more about the authorization scope
here.
Download the certificate to upload it later into your trust store on BTP Destination service. One way of exporting would be to navigate: Open your certificate -> Current Version ->
Download in CER format. Unfortunately, the SAP trust store wants the certificate string surrounded by a certain string. Add it to your cert file like so:
![](./?url=aHR0cHM6Ly9jb21tdW5pdHkuc2FwLmNvbS9sZWdhY3lmcy9vbmxpbmUvc3RvcmFnZS9ibG9nX2F0dGFjaG1lbnRzLzIwMjIvMTEvcHJpdmF0ZS1saW5reS1hcHBndy1jZXJ0LXN0cmluZy5wbmc=&__proxy_form=0)
-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
Now, open the Azure Cloud Shell and execute the following command to assign your managed identity to your App Gateway instance:
az network application-gateway identity assign --gateway-name sap-lab-app-gw -g your-resource-group-name --identity /subscriptions/00000-00000-0000-00000/resourceGroups/eun-saplab-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/your-managed-identity-name
![](./?url=aHR0cHM6Ly9jb21tdW5pdHkuc2FwLmNvbS9sZWdhY3lmcy9vbmxpbmUvc3RvcmFnZS9ibG9nX2F0dGFjaG1lbnRzLzIwMjIvMTEvcHJpdmF0ZS1saW5reS1hcHBndy1jbG91ZC1zaGVsbC5wbmc=&__proxy_form=0)
Fig.9 Screenshot of cloud shell command for App Gateway identity assignment
Ok great. At this point we can configure our listener on the App Gateway to use this self-signed certificate setup to trust requests from SAP BTP using the SAP Private Link hostname
😊
![](./?url=aHR0cHM6Ly9jb21tdW5pdHkuc2FwLmNvbS9sZWdhY3lmcy9vbmxpbmUvc3RvcmFnZS9ibG9nX2F0dGFjaG1lbnRzLzIwMjIvMTEvcHJpdmF0ZS1saW5reS1hcHBndy1saXN0ZW5lci1jcmVhdGUucG5n&__proxy_form=0)
Fig.10 Screenshot of App Gateway listener setup with BTP trust
Remaining setup for the backend pool and backend settings works the same as before when we did this configuration exercise for the standard load balancer in
part 1. Before introducing Azure API Management into the mix, let’s test the OData request via the Java app in BTP first
😊
Import self-renewing certificate into BTP Destination trust store
I am again assuming that you configured a Destination on BTP like described at the beginning of this
blog series. In my example below I am referring to the Cloud Foundry destination service instance “az-destinations” and maintained my target like so:
![](./?url=aHR0cHM6Ly9jb21tdW5pdHkuc2FwLmNvbS9sZWdhY3lmcy9vbmxpbmUvc3RvcmFnZS9ibG9nX2F0dGFjaG1lbnRzLzIwMjIvMTEvcHJpdmF0ZS1saW5reS1hcHBndy1kZXN0aW5hdGlvbi5wbmc=&__proxy_form=0)
Fig.11 Screenshot of App Gateway trust setup in BTP destination with trust store
And now hitting that destination from the Java app requesting the example OData service gets us… drum roll
🥁 …
![](./?url=aHR0cHM6Ly9jb21tdW5pdHkuc2FwLmNvbS9sZWdhY3lmcy9vbmxpbmUvc3RvcmFnZS9ibG9nX2F0dGFjaG1lbnRzLzIwMjIvMTEvYXBwZ3ctZHJ1bS5qcGc=&__proxy_form=0)
Heavy scrolling to finally the see the output. The suspension is killing me…
![](./?url=aHR0cHM6Ly9jb21tdW5pdHkuc2FwLmNvbS9sZWdhY3lmcy9vbmxpbmUvc3RvcmFnZS9ibG9nX2F0dGFjaG1lbnRzLzIwMjIvMTEvcHJpdmF0ZS1saW5reS1hcHBndy1yZXNwb25zZS5wbmc=&__proxy_form=0)
Fig.12 Screenshot of successful private OData response via App Gateway and SAP Private Link
Eureka! 🥳 🤸🏼
♀️ marvel at the nicely printed and well readable OData response. But hey, the integration is working.
For a fully automatic process regarding the self-signed certificate lifecycle, you still need to orchestrate the import into the BTP Destination trust store. Use the
Destination Service (Cloud Foundry) API for the import on the BTP side. For the trigger Azure Key Vault offers the events “NearExpiry” and “
CertificateNewVersionCreated” exposed to the
Azure Event Grid, that can be fed to a web hook or
Azure Integration Services. A typical pattern would be to connect that with an
Azure Logic App or any compute on the SAP BTP side.
Have a look at
this blog to learn more about the automation part.
Sneak peak: certificates issued by well-known certificate authorities drop the need for automation entirely. Also there is no risk of downtime for the BTP apps compared to the self-signed certificates rotating.
🛈Note:
With certificates issued by a Certificate Authority like DigiCert you may consider trusting the intermediate or root certificate. That way you rotate the certificate in Azure but don’t need populate the renewed certificate to the BTP trust store.
Instead bring your own domain as described by SAP here and create your certificate with a well-known provider like so with Azure Key Vault. |
If you are happy with this direct API connection from BTP to your SAP backend, you may stop at this point. But what about that nasty colleague creating an app that hits your backend with this viciously powerful load testing app during financial closing?
![](./?url=aHR0cHM6Ly9jb21tdW5pdHkuc2FwLmNvbS9sZWdhY3lmcy9vbmxpbmUvc3RvcmFnZS9ibG9nX2F0dGFjaG1lbnRzLzIwMjIvMTEvaS1hbS1pbm5vY2VudC1hcHBndy5qcGc=&__proxy_form=0)
Source: makeameme.org
I would
highly encourage to consider request throttling, usage quotas and uniform governance with API Management on top. And to be clear there are more reasons to apply request throttling, than restricting load tests. Black Friday anyone?
😉
Inject API Management to mediate between the SAP BTP apps and your target workload on Azure
Since fronting Azure APIM with App Gateway privately with virtual network integration is a standard pattern, its configuration is being discussed widely as part of the standard Microsoft docs as well as by various blog posts. I’d like to mention these two sources that I found comprehensive to finish the setup:
![](./?url=aHR0cHM6Ly9jb21tdW5pdHkuc2FwLmNvbS9sZWdhY3lmcy9vbmxpbmUvc3RvcmFnZS9ibG9nX2F0dGFjaG1lbnRzLzIwMjIvMTEvcHJpdmF0ZS1saW5reS1hcHBndy1vdmVydmlldy0yLnBuZw==&__proxy_form=0)
Fig.13 Architecture overview with API Management taking care of your private SAP APIs
More scenarios for the App Gateway with SAP Private Link
In general, any service targeted via https can be fronted with the App Gateway and therefore with SAP Private Link
😊 For instance, another popular application of this private integration pattern would be the
Azure Blob storage,
Azure Data Lake or
Azure Kubernetes Service. See
this blog post to learn more about the setup for the mentioned storage services.
Thoughts on production readiness
SAP Private Link is generally available and therefore completely ready for prime time (quoting
gowrisankar.m2 from the SAP engineering team
😊).
Since Application Gateway configuration changes impact the routing setup it is recommended to have two instances per workload. One for production purposes and for non-production where changes can be applied and tested prior move to production.
The Azure Application Gateway powers and secures high traffic applications running on Azure globally. Furthermore, it is a standard solution fronting SAP Fiori, SAP PI/PO etc. Have a look
here for reference.
The Web Application Firewall (WAF) allows inspection of your incoming traffic from BTP based on the industry standard OWASP rules. Learn more about
WAF for SAP on our
YouTube session🎥.
API Management ensures governance, security, and usage guard rails of the private link exposed APIs.
The use of self-signed certificates is not optimal. See
this SAP docs entry to learn how to bring your own domain and certificate for SAP Private Link. Use Azure Key Vault to
create a certificate with one of the well-known certificate authorities (CA) or with your own CA. Azure App Gateway automatically pulls from your Key Vault every
4 hours to check for new versions. When trusting the root or intermediate certificates of your CA, there is no need to populate renewed certificates to BTP.
⚠️Be aware that the self-signed leaf certificate approach requires some BTP apps to restart to reflect changed leaf certificates in the trust store
⚠️avoid downtimes with well-known certificates.
Find additional details about Private Link and App Gateway see the Microsoft docs.
Final Words
So, what do you say? Will you be “WAF-ing”
🐶 with me and apply Application Gateway with SAP Private Link for your BTP integration scenarios?
SAP BTP as a multi-tenant shared service and Platform-as-a-Service offering runs on the public Internet by design. Hence, inspecting traffic originating from there sounds like a good idea. Do you agree?
You saw today how
SAP Private Link combined with the Azure Application Gateway can securely connect to various of your Azure workloads to
enrich your apps on BTP. In addition to that you learnt about the benefits of adding API Management to the mix and how to configure it.
The Application Gateway further
simplifies the configuration if multiple Azure services in the customer subscription are involved, because they can be “bundled” into the Application Gateway rather than exposing them one by one individually to BTP via SAP Private Link.
Cherry on the cake
🍰: automated certificate renewal
bringing down your maintenance efforts 😊
Any comments regarding your integration journey with SAP Private Link SAP @Developers and @Architects?
The
next part of the blog series discusses connecting Azure storage PaaS solutions like MySQL via PLS.
Find the related GitHub repos
here.
Find your way back to the aggregator blog post
here.
#Kudos to
Christof Claessens and
Vinod Deshmukh for speeding me up in the prototyping big time!
As always feel free to ask lots of follow-up questions.
Best Regards
Martin