When building full-stack applications on SAP BTP, debugging against on-premise backends is a common requirement. This post outlines a simple method to simulate the connectivity available in the BTP Cloud Foundry runtime on your local machine, enabling access to on-premise APIs through the BTP Subaccount and Cloud Connector.
Scenario:
Imagine you’re developing an AI Agent and need to create tools that interact with an on-premise API. In line with SAP best practices, this API is exposed to your Subaccount via the Cloud Connector. While deployed applications can access the API directly, how do you test this setup locally?
The solution is to use the Cloud Foundry CLI tooling to establish a tunnel to the Cloud Foundry environment, routing traffic through it. This allows local development and debugging as though you’re working directly within the BTP runtime.
Concept: SAP Cloud Connector:
The SAP Cloud Connector (SCC) acts as a secure bridge between on-premise systems and cloud applications. It allows cloud applications, such as those running on SAP BTP (Business Technology Platform), to access resources in on-premise environments securely. The connector ensures data transfer via encrypted communication, maintaining the integrity and confidentiality of sensitive information. It supports fine-grained access control, enabling administrators to define which systems, services, or data can be exposed to the cloud. Additionally, SCC simplifies integration by avoiding the need for complex network configurations like VPNs. This makes it a critical tool for hybrid cloud setups, enabling seamless and secure connectivity.
Example Setup:
For this example, I configured a Cloud Connector on a machine and exposed an HTTP-based sample server. You can refer to this detailed blog post here to see the process outlined in Step 1.
The setup results in the virtualhost:3333 being securely exposed to my BTP Subaccount.
Taking the script from that blog as an example, I make an HTTP request to the exposed virtualhost:3333:
def example_http_request(host, port, path, auth_token, location_id, proxy_host):
“””
Performs an HTTP GET request through SAP Cloud Connector.
“””
url = f”http://{host}:{port}{path}”
headers = {
“Proxy-Authorization”: f”Bearer {auth_token}”,
“SAP-Connectivity-SCC-Location_ID”: location_id
}
proxies = {“http”: proxy_host} response = requests.get(url, headers=headers, proxies=proxies, verify=False)
return response
Doing the request on BTP, we receive the expected “Hello World” response. Running the same request on my local machine, however, would result in a connection error, as the on-premise API is not directly accessible from the local environment.
An error occurred: HTTPConnectionPool(host=’connectivityproxy.internal.cf.sap.hana.ondemand.com’, port=20003): Max retries exceeded with url: http://virtualhost:3333/hello (Caused by ProxyError(‘Unable to connect to proxy’, ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x00000191F0BFF6B0>, ‘Connection to connectivityproxy.internal.cf.sap.hana.ondemand.com timed out. (connect timeout=None)’)))
Note: No surprise there, as the connectivity proxy is an internal host: connectivityproxy.internal.cf.sap.hana.ondemand.com.
Setting Up a Tunnel to a Sample Application
There’s a light at the end of the tunnel: the Cloud Foundry Command Line Interface offers the ability to create an SSH tunnel for deployed apps, as described in the documentation here. This feature can be useful in various scenarios. One example is accessing a database deployed within the environment, which is not exposed to the outside world—only your internal apps can access its ports. Another example is our case: developing locally against an on-premise backend.
However, this can only be done in relation to an app. You can either use your own existing app or a sample dummy app. In this case, I’ll use a sample app, which I’ve named myapp, based on the code available here.
After quickly running cf push, the deployment is successfully completed.
Waiting for app myapp to start…Instances starting…
Instances starting…
Instances starting…
Instances starting…name: myapp
requested state: started
routes: myapp-brash-warthog-cj.cfapps.sap.hana.ondemand.com
last uploaded: Wed 18 Dec 21:43:35 CET 2024
stack: cflinuxfs4
buildpacks:
name version detect output buildpack name
python_buildpack 1.8.30 python pythontype: web
sidecars:
instances: 1/1
memory usage: 128M
start command: python hello.py
state since cpu memory disk details
#0 running 2024-12-18T20:43:49Z 0.0% 0 of 0 0 of 0
Having deployed the app we can then establish the SSH tunnel using the following command:
cf ssh -L 8888:connectivityproxy.internal.cf.sap.hana.ondemand.com:20003 myapp
Lets break this down:
cf: Refers to the Cloud Foundry CLI.ssh: Invokes the SSH feature of the Cloud Foundry CLI.-L 8888:connectivityproxy.internal.cf.sap.hana.ondemand.com:20003:
This specifies the SSH tunnel with the following parts:8888: The local port on your machine where the tunnel will be accessible.connectivityproxy.internal.cf.sap.hana.ondemand.com: The target host inside the Cloud Foundry environment.20003: The target port on the remote host within the Cloud Foundry environment.myapp: The name of the application you want to connect to via SSH.
Essentially that leaves us with a tunnel that is reachable from localhost:8888 – forwarding our traffic to the internal connectivity proxy host at its http proxy port 20003.
Running the ssh tunnel command now gives us access to the runtime environment of the app:
PS C:Githubsap-cloud-foundry-python-cloud-connector> cf ssh -L 8888:connectivityproxy.internal.cf.sap.hana.ondemand.com:20003 myapp
vcap@3e707408-4eca-41f4-7dee-d848:~$ ls
app deps logs profile.d staging_info.yml tmp
vcap@3e707408-4eca-41f4-7dee-d848:~$
vcap@3e707408-4eca-41f4-7dee-d848:~$
Running the Local Script via the Tunnel
While the SSH session is active, the tunnel remains open. However, there’s a small adjustment we need to make: instead of using connectivityproxy.internal… as our proxy host URL, we must reference localhost:8888. This requires updating the corresponding value in the secret. Once that’s done, we can run the script seamlessly—whether through a debugger or by executing it with the Python interpreter in a separate command-line process. It should now work as expected.
PS C:Githubsap-cloud-foundry-python-cloud-connector> python app.py
Fetching OAuth token…
Token acquired successfully.
Sending HTTP request through SAP Cloud Connector…
Response received:
{“message”:”Hello World 2024-12-18T20:46:49.181Z”}
Script execution completed.
Great! We’ve seen how to connect to on-premise systems from our local environment using the cf ssh tunneling options to route traffic through the Cloud Connector.
This approach works for both HTTP and TCP traffic. Feel free to check out my other blog on how to proxy TCP traffic using Python.
When building full-stack applications on SAP BTP, debugging against on-premise backends is a common requirement. This post outlines a simple method to simulate the connectivity available in the BTP Cloud Foundry runtime on your local machine, enabling access to on-premise APIs through the BTP Subaccount and Cloud Connector.Scenario:Imagine you’re developing an AI Agent and need to create tools that interact with an on-premise API. In line with SAP best practices, this API is exposed to your Subaccount via the Cloud Connector. While deployed applications can access the API directly, how do you test this setup locally?The solution is to use the Cloud Foundry CLI tooling to establish a tunnel to the Cloud Foundry environment, routing traffic through it. This allows local development and debugging as though you’re working directly within the BTP runtime.Concept: SAP Cloud Connector:The SAP Cloud Connector (SCC) acts as a secure bridge between on-premise systems and cloud applications. It allows cloud applications, such as those running on SAP BTP (Business Technology Platform), to access resources in on-premise environments securely. The connector ensures data transfer via encrypted communication, maintaining the integrity and confidentiality of sensitive information. It supports fine-grained access control, enabling administrators to define which systems, services, or data can be exposed to the cloud. Additionally, SCC simplifies integration by avoiding the need for complex network configurations like VPNs. This makes it a critical tool for hybrid cloud setups, enabling seamless and secure connectivity.Example Setup:For this example, I configured a Cloud Connector on a machine and exposed an HTTP-based sample server. You can refer to this detailed blog post here to see the process outlined in Step 1.The setup results in the virtualhost:3333 being securely exposed to my BTP Subaccount.Taking the script from that blog as an example, I make an HTTP request to the exposed virtualhost:3333: def example_http_request(host, port, path, auth_token, location_id, proxy_host):
“””
Performs an HTTP GET request through SAP Cloud Connector.
“””
url = f”http://{host}:{port}{path}”
headers = {
“Proxy-Authorization”: f”Bearer {auth_token}”,
“SAP-Connectivity-SCC-Location_ID”: location_id
}
proxies = {“http”: proxy_host} response = requests.get(url, headers=headers, proxies=proxies, verify=False)
return response Doing the request on BTP, we receive the expected “Hello World” response. Running the same request on my local machine, however, would result in a connection error, as the on-premise API is not directly accessible from the local environment. An error occurred: HTTPConnectionPool(host=’connectivityproxy.internal.cf.sap.hana.ondemand.com’, port=20003): Max retries exceeded with url: http://virtualhost:3333/hello (Caused by ProxyError(‘Unable to connect to proxy’, ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x00000191F0BFF6B0>, ‘Connection to connectivityproxy.internal.cf.sap.hana.ondemand.com timed out. (connect timeout=None)’))) Note: No surprise there, as the connectivity proxy is an internal host: connectivityproxy.internal.cf.sap.hana.ondemand.com. Setting Up a Tunnel to a Sample ApplicationThere’s a light at the end of the tunnel: the Cloud Foundry Command Line Interface offers the ability to create an SSH tunnel for deployed apps, as described in the documentation here. This feature can be useful in various scenarios. One example is accessing a database deployed within the environment, which is not exposed to the outside world—only your internal apps can access its ports. Another example is our case: developing locally against an on-premise backend.However, this can only be done in relation to an app. You can either use your own existing app or a sample dummy app. In this case, I’ll use a sample app, which I’ve named myapp, based on the code available here.After quickly running cf push, the deployment is successfully completed. Waiting for app myapp to start…Instances starting…
Instances starting…
Instances starting…
Instances starting…name: myapp
requested state: started
routes: myapp-brash-warthog-cj.cfapps.sap.hana.ondemand.com
last uploaded: Wed 18 Dec 21:43:35 CET 2024
stack: cflinuxfs4
buildpacks:
name version detect output buildpack name
python_buildpack 1.8.30 python pythontype: web
sidecars:
instances: 1/1
memory usage: 128M
start command: python hello.py
state since cpu memory disk details
#0 running 2024-12-18T20:43:49Z 0.0% 0 of 0 0 of 0 Having deployed the app we can then establish the SSH tunnel using the following command: cf ssh -L 8888:connectivityproxy.internal.cf.sap.hana.ondemand.com:20003 myapp Lets break this down:cf: Refers to the Cloud Foundry CLI.ssh: Invokes the SSH feature of the Cloud Foundry CLI.-L 8888:connectivityproxy.internal.cf.sap.hana.ondemand.com:20003:This specifies the SSH tunnel with the following parts:8888: The local port on your machine where the tunnel will be accessible.connectivityproxy.internal.cf.sap.hana.ondemand.com: The target host inside the Cloud Foundry environment.20003: The target port on the remote host within the Cloud Foundry environment.myapp: The name of the application you want to connect to via SSH.Essentially that leaves us with a tunnel that is reachable from localhost:8888 – forwarding our traffic to the internal connectivity proxy host at its http proxy port 20003.Running the ssh tunnel command now gives us access to the runtime environment of the app: PS C:Githubsap-cloud-foundry-python-cloud-connector> cf ssh -L 8888:connectivityproxy.internal.cf.sap.hana.ondemand.com:20003 myapp
vcap@3e707408-4eca-41f4-7dee-d848:~$ ls
app deps logs profile.d staging_info.yml tmp
vcap@3e707408-4eca-41f4-7dee-d848:~$
vcap@3e707408-4eca-41f4-7dee-d848:~$ Running the Local Script via the TunnelWhile the SSH session is active, the tunnel remains open. However, there’s a small adjustment we need to make: instead of using connectivityproxy.internal… as our proxy host URL, we must reference localhost:8888. This requires updating the corresponding value in the secret. Once that’s done, we can run the script seamlessly—whether through a debugger or by executing it with the Python interpreter in a separate command-line process. It should now work as expected. PS C:Githubsap-cloud-foundry-python-cloud-connector> python app.py
Fetching OAuth token…
Token acquired successfully.
Sending HTTP request through SAP Cloud Connector…
Response received:
{“message”:”Hello World 2024-12-18T20:46:49.181Z”}
Script execution completed. Great! We’ve seen how to connect to on-premise systems from our local environment using the cf ssh tunneling options to route traffic through the Cloud Connector.This approach works for both HTTP and TCP traffic. Feel free to check out my other blog on how to proxy TCP traffic using Python. Read More Technology Blogs by SAP articles
#SAP
#SAPTechnologyblog