/saphanasqlfunction

executes sap hana sql from functions

Primary LanguagePython

Setup a function that executes SAP HANA SQL binary

With the help of this repository you can create an Azure Function App that can execute an SQL statement on a SAP HANA Datebase. The Function will receive an HTTP request with the SQL statement, then run the statement using hdbsql binary against the HANA DB and finally return the result.

The setup process described here is based on the execution on a Linux VM with Ubuntu 22.04. The VM is running in a subnet that has access to the HANA DB. With that we can test the function locally before pushing to Azure.

See also the Quickstart: Create a Python function in Azure from the command line

Download this Repository

  • Login to the VM and clone this repository:

    git clone https://github.com/mimergel/saphanasqlfunction.git


Integrate the hdbsql binary

  • You can download the hdbsql here: SAP Software Center.

  • It's part of the package: SAP HANA CLIENT 2.0.

  • In order to uncompress the package you'll also need to download SAPCAR binary.

  • Copy the hdbsql binary into this subdirectory:

    cd ~/saphanasqlfunction/saphanasql/hdbclient/

  • When you have copied the hdbsql in here, make sure to set execute permissions:

    cd ~/saphanasqlfunction/saphanasql/hdbclient
    chmod 555 hdbsql
    ls -l
    total 33100
    -r-xr-xr-x 1 azureadm azureadm 33889680 Apr 20  2023 hdbsql
    -rw-rw-r-- 1 azureadm azureadm      102 Nov 10 19:11 hdbsql.txt
    

Configure local settings

  • Configure local settings to match your HANA DB parameters:

    cd ~/saphanasqlfunction
    vi local.settings.json
    
    {
    "IsEncrypted": false,
    "Values": {
        "FUNCTIONS_WORKER_RUNTIME": "python",
        "AzureWebJobsStorage": "",
        "DB_USER": "FLIGHTDEMO",
        "DB_USER_SECRET": "set your password",
        "SID": "HDB",
        "TARGETDB" :"saphanadb.contoso.com:30013"
        }
    }
    
    

Test the Function App locally

  • Run the following command to start your function app:

    cd ~/saphanasqlfunction
    func start
    
  • The runtime will output the URL for the HTTP functions, on which we will test the function.

    ~/saphanasqlfunction$ func start
    Found Python version 3.10.13 (python3).
    
    Azure Functions Core Tools
    Core Tools Version:       4.0.5198 Commit hash: N/A  (64-bit)
    Function Runtime Version: 4.21.1.20667
    
    
    Functions:
    
            saphanasql: [GET,POST] http://localhost:7071/api/saphanasql
    
    For detailed output, run func with --verbose flag.
    [2023-11-10T19:28:23.656Z] Worker process started and initialized.
    [2023-11-10T19:28:27.866Z] Host lock lease acquired by instance ID '0000000000000000000000003399B9E1'.
    
    
  • In a another terminal call the function with an SQL command. Here we are using the SAP flight demo data and have generated the data upfront. The FLIGHTDEMO user has read access.

    cd ~/saphanasqlfunction
    cat test.sql | curl -X POST http://localhost:7071/api/saphanasql -H "Content-Type: application/json" --data-binary @-
    
  • When the user can connect and has read access on the relevant tables a results will be shown:

    FLDATE,NUM_FLIGHTS
    "20230828",24
    
  • If it doesn't work yet you can check in the first terminal windows for errors. Increase the verbosity if needed.

  • To stop testing, use Ctrl-C in the terminal.


Create the Function App in Azure

  • Create the Function App in the Azure Portal:

    Create Function


    Create Function 1

    Note: The function currently only works with Python 3.8. Choose an unsued Function App name.


    Create Function 2


    Create Function Storage

    Note: You can use an existing storage account if one is available.


    Create Function Networking 1

    Note: Enable Network injection into a subnet that has access to the SAP HANA DB


    Create Function Networking 2


    Create Function Monitoring


Publish the Function App

  • On the VM login to Azure:

    az login
    
  • Publish the Functions App:

    func azure functionapp publish [your function app name]
    

Set required Application Environment

  • Set the following application environment:

    • DB_USER
    • DB_USER_SECRET
    • SID
    • TARGETDB
  • Use the same values like on the local.settings.json

    Application Environment


Test

  • Before using the function we can test in the portal:

    Test


Retrieve Function URI and KEY

  • Retrieve your URI and Key as shown in the screenshots:

    URI

    Key

  • We'll use the URI and KEY in the Power Automate Flow to call this Function from an HTTP Connector.


Using an Azure Key Vault

It's recommended to store secrets in an Azure Key Vault.

To achieve this you can create a system assigned identity for the function app and allow this identity to read the relevant secret in a key vault.

Identity

Instead of the password we need to enter the reference to the key vault in the application environment of DB_USER_SECRET. Format:

Secret

@Microsoft.KeyVault(SecretUri=https://yourkeyvaultname.vault.azure.net/secrets/secretname/xxxxsecret_idxxxxxxxxxxxxxxxxxx)

Limit network access

For seucrity reason it's recommended to limit access to the power automate flow source IPs. Calls made from the power automate flows go directly through the Azure Logic Apps service. To help simplify the configuration, you can use the available service tag "LogicApp".

  • In the function app go to “Networking” and enter the details by clicking on “Enabled with access restrictions”.

    Secret

  • Enable access from selected VNET & IPs

    Secret

  • Change the unmatched rule for Main Site and Tool site access to deny

    Secret

    Secret

  • Add an allow rule for source “LogicApp”

    Secret

  • After saving

    Secret

Please note that this restriction will prevent the possibility to test the function app from the portal.

Contributing

Contributions to enhance the capabilities are welcome.

License

This project is licensed under the MIT License.

Disclaimer

THE CONTENT OF THIS REPOSITORY IS PROVIDED AS IS WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.