Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
Former Member
In my previous posts, I have covered details on getting started with Python development on XSA. I am going to continue this series forward and now talk about setting up a central application router for your applications. Again, I am using the same pyapp project in this blog post as i did in the previous ones. If you have not been following along, you can find the code for it at this link.

The application router serves as the single entry point into your XSA application and controls the flow of the application, as outlined in the figure below. It incorporates all front-end HTML and JavaScript development as well as a central security service. The front-end module takes input from the user and redirects requests to the separate internal applications (Node.js, Python, Java, etc.) as needed. The central security service performs user authentication and authorization (UAA) for all applications, hence, simplifying programming for each individual one. There is no need to perform separate security checks every time a different application is accessed.



The application router itself is programmed in Node.js and so, you are going to have to step away from Python for a bit and set up routing within your application using a bit of Node!

Setting Up User Authentication:


To set up authentication for your application, you need to create a service instance of the XS UAA service. I am going to call this instance myuaa. Execute the following command on the command prompt:
xs create-service xsuaa default myuaa

Create two new directories in the pyapp folder called core-py and app-router. Copy the runtime.txt, requirements.txt, and server.py files and the vendor folder into the core-py directory, which would be the new location for all Python related files. In the app-router folder, create two new files called xs-app.json and package.json. The former contains information about routing within your application, while the latter specifies the node module dependencies for your application. Create two new directories called node_modules, which stores all node modules used in your application, and resources, which contains front-end web files (HTML, CSS, etc). Create a new file called index.html under the resources directory and write the following line into it:
>>> index.html
<p>Hello World</p>

The directory tree for your application should look like the following:



Update the manifest.yml file to include the application router and to reflect the moving of all python files to the core-py directory. List core-py application as a destination for the web application so that the application router (web application) can redirect requests to the core-py application. Bind the myuaa service to the web application so that it can authenticate users. Your manifest.yml file should now look like:
>>> manifest.yml
---
applications:
- name: core-py
host: core-py
path: ./core-py/
command: python server.py
services:
- hdi-db
- name: web
path: ./app-router/
env:
destinations: >
[
{
“name”: “core-py”,
“url”: “https://core-py.your_host_name:port_num”,
“forwardAuthToken”: true
}
]
services:
- myuaa

In the xs-app.json file, declare the homepage to be the index.html file and set up a route to the core-py application as shown below.
>>> xs-app.json
{
"welcomeFile": "index.html",
"authenticationMethod": "route",
"routes": [
{
"source": "/core-py(.*)",
"target": "$1",
"destination": "core-py"
}
]
}

The "/core-py(.*)" part is a regex expression that looks for URL path patterns and redirects to internal applications and services accordingly, acting as a reverse proxy.

In the package.json file, specify the approuter node module provided by SAP as a dependency.
>>> package.json
{
"name": "web-approuter",
"engines": {
“node”: “>=4.0.0 <9.0.0”
},
“dependencies”
“@sap/approuter”: “5.0.0”
},
“scripts” : {
“start”: “node node_modules/@sap/approuter/approuter.js”
}
}

You must install the node modules that your application uses before deploying the application to XSA. This is different from when you are developing on the Web IDE for SAP HANA where the package dependencies are installed automatically for you. To install the required packages, navigate to the app-router directory, configure npm to download from the SAP Registry and run the npm install command. If you do not have npm (node package manager) configured on your machine, you can follow this link to get that done.
cd C:\path\to\app-router
npm config set @sap:registry https://npm.sap.com
npm install

This should install the packages outlined in the package.json file to the node_modules directory located inside the app-router directory.

Now, you are ready to deploy the application to XSA and run it.
cd C:\path\to\pyapp
xs push

Awesome! You're already halfway through setting up full security for your XSA application. You should now be able to authenticate users trying to access your application. After the xs push command is done, there should be two applications deployed, namely core-py and web. The URLs for both applications should be outputted in command line tool as shown below.



If you open the URL for the web application, you should be redirected to the XSA login page.



Once you have successfully logged in, you should see the index.html file which outputs simple “Hello World”. If you replace the “/index.html” from the end of the URL to “/core-py/”, you should be redirected to the core-py application which would output the current time like the pyapp from previous examples. If you are getting an error in loading the webpage, make sure you have added a mapping for web application URL in your local hosts file.



At this point, if you try accessing the URL for the core-py application directly, you would be allowed to access it. This is not ideally what we want. We want to channel all of the user interaction through the application router to ensure higher security. The next step should allow us to achieve this...

Setting Up User Authorization:


To authorize users for different applications, you are going to make use of the xssec library provided by SAP. In this example, you are going to set up user authorization for the core-py application. Modify the requirements.txt file in the core-py directory to include dependency on xssec.
>>> requirements.txt
Flask==0.12.2
cfenv==0.5.3
hdbcli
xssec==1.0.0

Execute pip download from command prompt to download the xssec library to the vendor directory of your application. Refer to my last blog for more explanation on why this is needed.
pip download -d C:\path\to\vendor -r C:\path\to\requirements.txt --find-links C:\path\to\sap_dependencies

The xssec node module provided by SAP needs to be specified in your package.json file in the app-router directory as well.
>>> package.json
{
"name": "web-approuter",
"engines": {
“node”: “>=4.0.0 <9.0.0”
},
“dependencies”
“@sap/approuter”: “5.0.0”,
“@sap/xssec”: “^2.1.11”
},
“scripts” : {
“start”: “node node_modules/@sap/approuter/approuter.js”
}
}

Navigate to the app-router directory and install the xssec node module.
cd C:\path\to\app-router
npm install

Bind the myuaa service to the core-py application to enable user authorization in the manifest.yml file.
>>> manifest.yml
---
applications:
- name: core-py
host: core-py
path: ./core-py/
command: python server.py
services:
- hdi-db
- myuaa
- name: web
path: ./app-router/
env:
destinations: >
[
{
“name”: “core-py”,
“url”: “https://core-py.your_host_name:port_num”,
“forwardAuthToken”: true
}
]
services:
- myuaa

Modify the server.py file to incorporate user authorization in the application logic.
>>> server.py
import os
from flask import Flask
from cfenv import AppEnv
from hdbcli import dbapi

import logging
from cf_logging import flask_logging

#imports for user authorization
from sap import xssec
from flask import request
from flask import abort

app = Flask(__name__)
env = AppEnv()

flask_logging.init(app, logging.INFO)
logger = logging.getLogger('route.logger')

#assign port for Flask application to run on
port = int(os.environ.get('PORT', 3000))
hana = env.get_service(name='hdi-db')

#access credentials of uaa service
uaa_service = env.get_service(name=’myuaa’).credentials

@app.route('/')
def hello():
#check if authorization information is provided
if ‘authorization’ not in request.headers:
abort(403)

#check if user is authorized
access_token = request.headers.get(‘authorization’)[7:]
security_context = xssec.create_sercurity_context(access_token, uaa_service)
isAuthorized = security_context.check_scope(‘openid’)

if not isAuthorized:
abort(403)

conn = dbapi.connect(address=hana.credentials['host'],
port=int(hana.credentials['port']),
user=hana.credentials['user'],
password=hana.credentials['password'],
CURRENTSCHEMA=hana.credentials['schema'])

if conn.isconnected():
logger.info('Connection to databse successful')
else:
logger.info('Unable to connect to database')

cursor = conn.cursor()
cursor.execute("select CURRENT_UTCTIMESTAMP from DUMMY", {})
ro = cursor.fetchone()
cursor.close()
conn.close()

return "Current time is: " + str(ro["CURRENT_UTCTIMESTAMP"])

if __name__ == '__main__':
app.run(port=port)

Deploy the application again using xs push. If you open the URL for the core-py application, you should be denied access. This is because you have to go through the application router to be authorized to access the core-py application. Thus, open the URL for the web application, log in if prompted, and change the end of the URL from “/index.html” to “/core-py”. This should now show core-py application page which outputs the current time.

That's it! You have successfully set up complete user authentication and authorization for your XSA application. Kudos to you for making it this far! Stay tuned for more blogs on SAP HANA Database access and doing cool stuff with Python on XSA! You can also access the complete code from this blog on this link.

If there is anything you would like me to demonstrate being done on XSA using Python, please comment below!! Also, if you have been following my blogs and have previous Python experience, I would love to hear about what you like the most about Python and if there are any crazy libraries you really love using. Feel free to comment below!!
8 Comments