Monday, August 21, 2017

SCI and User, Roles and Groups

In the previous post I discussed how to get started with SAP ID Service and build a simple HCP Application which outsources its authentication to SAP ID Service. 
Now let's extend this scenario. In general I like to use Identity Provider to provide me with user attributes like name, email address etc. and also provide me with group memberships. So the greeting service should greet the end user with the real name, rather then an ID like P0000 which we saw in the previous post. 

I would also like to introduce 2 roles in my application viz. Everyone and GreetingEditor. 

At the application side I generally prefer to create roles and groups. These roles and groups on the application side have a 1:1 mapping. So we will create a group called GreetingEditor and a group called GreetingEditors.

While creating/enrolling the application with the IdP I generally like to map the groups on IdP side with the groups on Application side. These mappings could be based on AND or OR condition. e.g. A user in IDP who is present in both 'ChiefGreeters' and 'Editors' group should be mapped to the group called "GreetingEditors" in my greeting application. 

The group GreetingEditors should then be assigned the role GroupEditor. 

Let's extend our Greetings Application for the above scenario. Let's first fix the fact that it greets the end user with her name rather then the crazy ID like P0000. 

Open web.xml and add the following entry 




Then open your Greeting.java and in your doGet method add the following code. 


What you are essentiallly doing is that you are using User Provider available in HCP to parse and provide us with the SAML attributes which we get from the SAP Identity Service. In order to ensure that these attributes viz. firstname and lastname are available with the application we need to configure the application correctly in the SAP Identity Service management console. 

Go to your Management Console and choose Applications & Resources -> Applications -> Custome Applications -> sayHello (This is the name of my applications" -> Assertion Attributes.
Now Ensure that you have First Name and Last Name added in the user attributes. This is how the screen should look like 




If you look at the screenshot above the attributes are called first_name and last_name while I query firstName and lastName in my application code. This is because the second mapping is yet to be done. In the second mapping we are going to map these attributes for the application in the Cloud Cockpit. Go to your SubAccount -> Trust -> Application Identity Provider -> (Select the IdP) 

Now select Attributes tab and add 2 assertion based attributes. The assertion based attribute should map first_name to firstName and last_name to lastName. This is how my screen looks like 




This mapping ensures that the SAML attributes coming from IdP are mapped to the user attributes in the application which is using the UserProvider. 

Now deploy the application and run it. It should now say "Hello, <>" 

So we achieved the first objective of this exercise. As a matter of fact you can map many user fields like phone number, address, groups etc. as assertion attributes in the Application Configuration at the IdP side and then map them to custom attributes on the IdP configuration at the application side. 
This helps us with the fact that you can outsource the user management totally to SAP Identity Service. 

Let's go ahead and now and configure the roles and groups as per our requirement. 

First let's try to setup roles to ensure that we have OOB roles created when we deploy the applications. 

Open web.xml and add the following security roles there. 





Please note that the role EveryOne is created and assigned to every authenticated user by default, so you need not specify this role in the web.xml. Next time you publish your application to HCP you'd see a role called GreetingEditor. In your cloud cockput, you can go to SubAccount -> (Select the Application) -> Security -> Roles.  



Once this is done let's go ahead and create a group called GreetingEditors. On the same screen click Assign on the Groups tab and create a new group and save it. Once it is assigned to the role this is how your screen would look like. 



Now let's go ahead and add the relevant groups we discussed to the IdP. In the SAP Identity Service admin console go to Users & Authorizations -> User Groups and Add 2 new groups. Now go to the User Management and assign these 2 groups to a user. This is how my user looks like after the changes are done. 




Now we need to ensure that these groups are sent to the application as part of SAML attributes. In order to do this we need to go to Application Configuration on the IdP side and add another SAML Assertion Attribute called groups to the list of attributes the IdP passes to the application. Here's how my screen looks like once I make this change. 




Once this is done we need to ensure that we do the appropriate mapping in the application such that if a user is part of both ChiefGreetors and Editors group in IdP, she is assigned to GreetingEditors group in the application, thus assigning her with the role GreetingEditor.  In order to do this we need to enter the IdP configuration in the HCP Cockpit and add a simple assertion based group in the Groups Tab.  Here's how my tab looks like after the change. 



Now let's  change the doGet method of our greeting service to list out the roles the logged on user has been enrolled in. Change the doGet method to the following. 



Try running your service with the user who has been added to both ChiefGreeters and Editors group and you should see the output which looks like the following. 



Happy Coding!!

Monday, July 24, 2017

Getting Started with SAP Identity Service and HCP Cloud

So I recently started working on Hana Cloud Platform and one of the first challenges which await me is to figure out how to achieve SSO in a set of simple applications my team is writing on Hana Cloud Platform. 
Since we are working on Hana Cloud Platform, choosing ID Service is easy, it has got to be SAP Cloud Identity Service. Here are the steps you need to follow, to get you started on HANA Cloud Platform with SCI Service. 

Objective : At the end of this blog you should be able to 
  • Run a simple greeting service which would greet the logged in user using SAP Cloud SDK on your local machine
  • Deploy the greeting service on cloud and configure the application and SCI tenant to greet the end user. 
Pre requisites : In order to make the scenario work, you need a HCP account and access to a tenant of SCI service. You may want to work with your SAP contact to get a handle to both of them. You can also request for the trials online.  Once you have access to both, please ensure that you have setup your eclipse with SAP Cloud SDKs. You can follow the instructions on this link to setup your development environments. 


Let's get started. 
  1. Fire up your eclipse and create a new Dynamic Web Project. Here are a few things to set while you create it 
    • Name : sayHello
    • Target Runtime : SAP -> Java Web Tomcat 8 . It may ask you to set path to a Neo SDK. I set it to the folder where I have unzipped neo-java-web-sdk-3.30.16 SDK. I chose the default workbench JRE which is a SAP JVM in my case. 
    • Dynamic Web Module Version -> 3.1 
    • I set my sources folder on build path to /src/main and Default output folder to build/target
    • I do check the Generate web.xml deployment descriptor to true in the wizard. 
  2. Now let's create a new Servlet. Here's what I fill in my wizard
    • Java Package : com.sample.helloworld
    • Class name : Greeting
    • URL mapping : /greeting
  3. Add the following code to the doGet and fix the imports
  4. Right click the project -> Run As -> Run on Server. 
  5. You now need to define a local tomcat server. Choose SAP-> Java Web Tomcat 8 Server and finish the wizard. 
  6. Now try opening http://localhost:8080/sayHello/greeting and it should throw up a login screen. We can't login yet since we haven't defined a user in the container yet. Let's do that in the next step. 
  7. Double click the newly defined server in the Servers window of your eclipse. Open Users tab and add a new User. I choose my user name as test. 
  8. Hit the service http://localhost:8080/sayHello/greeting again and login with the newly defined username and password. You should now see an output "Hello, test" in your browser. 
Now that we have a locally authenticated service working in our eclipse, let's publish the application to HCP and outsource our authentication to SCI. Here are the steps to do that 
  1. Right click on Servers window of your eclipse and choose New Server. 
  2. In the dialog box which shows up choose SAP-> SAP Cloud Platform. Enter the correct region code for your HCP account. You can find the available regions and hosts here. Mine happens to be int.sap.hana.ondemand.com. (If host for your region is not available on the page, check the post here , as it may help you figure out your host. SAP uses some conventions so you may crack it yourself. )
  3. Enter the application name as sayhello, You can leave the runtime to be chosen Automatically. 
  4. The subaccount name is available in your Hana Cloud Cockpit. Enter the subaccount and your credentials. 
  5. Add the sayHello application to the configured resources for the server, and press Finish.
  6. It will take some time, but finally the application should be deployed successfully, Copy your application URL from the Server window and hit the greeting service using a browser. The URL for my service was https://sayhelloi031884sapdev.int.sap.hana.ondemand.com/sayHello/greeting and the error I got was "Identity Provider could not process the authentication request received. Delete your browser cache and stored cookies, and restart your browser. If you still experience issues after doing this, please contact your administrator." The error is unintuitive and should have been something different like "There is no IDP configured for this application so I can't allow you to login" 
The application is now deployed successfully on HCP so let's proceed to configure the SCI for this application, 
  1. Open your HCP cockpit and navigate to the subaccount in which you deployed the sayHello application.
  2. On the left hand side navigation choose Security->Trust and click 
  3. Change the Local Service Provider from default to Custom, Click Generate Key Pair to generate a new key pair. Let Principal propogation and force authentication be Disabled. and save. 
  4. Select the next tab i.e. Application Identity Provider and click Add Trusted Identity Provider. 
  5. Before you proceed any further you need to open the SCI tenant in a new browser tab which you have. I have mine hosted on https://i031884.accounts400.ondemand.com/admin/ . Logon to this tenant as administrator and go to Tenant Settings -> SAML 2.0 Configuration and select to download metadata file. 
  6. Go back to HCP console ( i.e. the browser tab you were using in step 4 to add trusted identity provider) . Browse and select the metadata file we downloaded in step 5. Choose Save.  i031884.accounts400.ondemand.com should now be your default identity provider. 
  7. Go to tab Local Service Provider and click Get Metadata again.  Save the file in downloads folder 
  8. Go back to SCI tenant (Browser tab which we opened in step 5) and navigate to Applications and Resources -> Applications. 
  9. Click Add Application and give a name sayhello and click save
  10. select sayhello application and click on SAML 2.0 configuration. Browse to the file you saved in step 7 and click save. You have now configured the application and IDP to trust and know each other. 
  11. Try hitting the application again (https://sayhelloi031884sapdev.int.sap.hana.ondemand.com/sayHello/greeting in my case) and it should prompt you to enter id, password and you are good to go :).

Happy coding!!!!

Host name for Europe (Rot) - Canary region in Hana Cloud Platform

While working with Hana Cloud Platform for SAP, one needs to enter the Host  name to publish an application to the cloud. Now most of the Host name are documented by SAP on over here and more often then not it works for the region where you are working. 
However if you have an account on Europe (Rot) - Canary region like I do, the document doesn't specify the host and you would keep scratching your head on what to enter in eclipse. 
My first intuition was to do the brute force and I tried a few combinations from the page as host for my account and it kept giving me an error which told me that my password is incorrect. 
Now I was sure that my password is not incorrect as I was copying it into the eclipse dialog to be sure. So much for exception handling in eclipse. 
Finally asked for help from an ops colleague, who again had no information on this. However while looking into this situation, we noticed a pattern emerging when we click various regions on the HCP cockpit. If you keep selecting various regions in your cockpit and compare them with the host names in the documentation, you can notice that pattern too. And voila we discovered our host name for Europe (Rot) - Canary region. It is "int.sap.hana.ondemand.com" 

Happy coding!!!!

Wednesday, January 4, 2017

Making a vagrant box for RHEL

One of the assignments at work is getting me into creating a vagrant box for RHEL, as I would want to create and destroy RHEL VMs multiple times in a day. 
This blog summarizes the steps to create a vagrant box for RHEL. The software I have are 

1) Oracle VM Virtual Box
2) An ISO file with RHEL 7 setup rhel-server-7.0-x86_64-dvd.iso

Let's begin by creating a baseline VM 

1) New Machine -> Give a Name, Type is Linux, Version is Red Hat 64 bit
2) Memory is fine at 1024 MB
3) Create a Virtual Hard Disk. I chose VDI as my hard disk type, Dynamically allocated size is better for me, and the size for HDD is set to 100 GB. 
4) Go ahead and mount the iso file to the VM. This can be done by selecting the machine settings -> Storage -> and mount the iso on the optical drive. 
5) Start the machine and select to install the RHEL O/S. Walkthrough the wizard and install the RHEL on the VM.  While installing the OS I also chose to create an additional user 'abhishek' on it.
6) Register with the subscription manager by using subscription-manager register
7) sudo visudo and comment the line "Defaults .requiretty"
8) Create a user called vagrant and set the password as vagrant. Commands to use are useradd vagrant. And passwd vagrant. 

Once done let's package this VM as a vagrant box 
1) vagrant package --base BaseRHEL 
2) vagrant box add test package.box 

and now you have a vagrant box for the machine. Enjoy creating as many VMs as you want :). 

Monday, February 22, 2016

Configuring X11 Forwarding on CentOS to Mac

I have a linux machine on Azure which I am able to SSH into, however many applications needs to throw a UI on my mac and it is important to configure X11 Forwarding on the CentOS machine to make sure I can see that UI. 
I managed to make it work after googling stuff for around 2 hours. Here's a quick guide if you are in a similar situation. 
You need to do things on both your mac and your CentOS machine to make sure that the forwarding works. 

1) On your mac you need to install XQuartz. This is the daemon which would listen for the forwarded requests from your CentOS and render a UI on your mac. 
2) On your CentOS you need to edit /etc/ssh/sshd_config and add the following entries to it

  • AddressFamily inet #this entry ensures that SSH is not messed up over IPV6. My forwarding was not working till I made this entry. 
  • X11Forwarding  yes #this entry will ensure that the forwarding happens from CentOS. 
3) Next install a package called xauth on your CentOS machine. you can use yum to install it. 
  • yum install xauth 

4) restart the ssh daemon 
  • sudo service sshd restart
5) Install an app like xeyes to test if the X11 forwarding is working or not. 
  • yum install xeyes
6) logoff from the CentOS and login again using -X flag this time 
  • ssh -X user@host
7) Run xeyes and you should be able to see the eyes coming up on your mac screen :). 

Happy coding!!!

Abhishek 


Tuesday, January 5, 2016

Pitfalls of Object Oriented Programming

As I try to understand Javascript as a language one of the things which I need to unlearn is Object Oriented Programming. With Ecmascript 6 and tools like TypeScript from Microsoft, so far I have managed to write a lot of object oriented programs in Javascript which essentially is a functional language. 
So first thing which I need to do is unlearn OOPS. Here are a few pitfalls of OOPS : 

1) A Class is a collection of Data and Methods which operate on this data. As a programmer trying to learn OOPS this was very unintuitive, but once you start practicing OOPS, it becomes the obvious choice and all the apprehensions like why exactly should I keep my data definitions and  Functions together goes away. Going back to my learning days, I once again find it unintuitive. 

2) The way a function behaves in a class can be totally dependent on the state of the object which can be hidden from the consumer of the class. e.g. I can easily write a class which like 
public class Calci{
    private var toggle = false;
    public int Add(a,b){
        toggle = ! toggle;
        if(toggle) return a + b;
        return a - b;
    }
}
The behavior of method Add totally depends on a the state of the Calci object which is hidden from the consumer. So understanding what a method does in object oriented program can be tricky sometimes. Although this is an advantage when compared to Procedural language where the behavior of the function can be dictated by a global variable which is declared somewhere in a different file. But then I have visibility in the scope and if I try it hard I can figure it out. 

3) No Class Hierarchy is correct : No matter how much thought one gives into create a right class hierarchy. One does end up in a situation where the hierarchy is not correct. This is one of the major reasons for refactoring the code while developing projects. As the code size grows it becomes rather difficult to refactor as the change impacts all the ecosystem. 

4) You get a lot of rings and bells attached with any class which you choose to reuse. e.g. If I derive from a Car class I get the method Drive for free even though I may not want to drive an auto-drive car. 

As one learns javascript one should ensure that we don't fall back on the knowledge we acquired while learning OOPS and try to apply them in this new paradigm. Next up is to figure out what kind of inheritance is possible in javascript, how we can use it, and how it differs from classical inheritance of OOPS.

Wednesday, May 13, 2015

Why Database is not suitable for a Queue

There are many applications which use database as a queue in order to orchestrate a long running business process. While it is enticing and easy to do so here are a few reasons about why the developer should avoid doing it...

1) Work distribution : As the number of messages flowing through the system increases the work distribution has to be managed by using locks or by using a Z axis scaling i.e. partition the message table and let different processes handle it. It becomes difficult to manage the failure cases e.g. if the process responsible to manage a particular partition goes down how do I bring up another process to pick up that partition. This is a problem which can be easily solved by event driven queues with horizontal scaling. 
2) Database loads : As the messages passing through the system increase the load on the database starts increasing. This means that the database needs a scaling which is much more costly then scaling a queue bases solution. 
3) Deleting and archiving the queue related tables is expensive as they are indexed. 
4) Database has to be polled to see the pending work items while an event driven queue can simply call the worker process when a new message pops into the queue. 

So while it may be enticing and easy to use database to orchestrate queue related workflows one should refrain from taking this technical debt as it would be really hard to pay it back in the future...

Abhishek