One of the ways to integrate FIM/MIM into SAP is to use the Microsoft ERP Management Agent for Web Services. Unfortunately a while ago we had a project were no matter what we tried we could not get the Web Services MA to work due to various reasons.
This sparked a quest on my side to explore new options of working with SAP using a PowerShell MA. (In the past we did write an ECMA using C#, but I wanted to try using PowerShell to achieve the integration in this instance). Needless to say there are not a lot of articles on the internet the contains the words “PowerShell”, “intergrate” and “SAP” – so I thought I would share my experience.
The following series of articles will explore the PSMA scripts that was created to achieve this goal, while also exploring the general concepts related to the integration in order for you to replicate this in your own environment.
- Part 1 will explore connecting to SAP and importing a complete user list
- Part 2 will focus on the process of password reset
- Part 3 will be used to go over the management agent configuration used in the final solution
For the integration I used the Granfeldt PSMA. Although this is a great way of using PowerShell with FIM/MIM will also be glad to hear that the approach followed in this guide applies to integration outside of FIM/MIM since the PowerShell script is generic.
To achieve a password sync between AD and SAP there were three main objectives:
- Import all the users from a SAP ECC instance in order to get a join from SAP users to AD users in FIM/MIM. In order case we used the email address since this is unique between the two systems.
- Process a password reset on the SAP ECC instance when a user changes his/her password on Active Directory.
- Once the above was implemented the FIM/MIM sync engine (with PCNS) could take care of the detection and password sync process.
As you can see from the objective above, these should line up nicely with the 3 parts of this guide – so let’s get started.
SAP Integration via PowerShell
First off, I need to mention that I am not a SAP Consultant so I might get some terminology wrong – but bear with me, the functionality in the end works. One of the most complex things to understand and navigate when integrating with SAP is the data model and the SAP structures (tables) used to pass data to, and receive data. SAP BAPI’s (functions) utilizes a series of structured data objects (referred to as structures or tables) to store response data. The function used in the integration was standard built-in SAP BAPI’s that were published using SOAP web services.
In order to set the up the SAP endpoint we followed the standard Microsoft suggested approach in the Web Services MA SAP6 project (SAPECC6DefaultProject.exe). This creates a custom ERP web service that publishes some standard BAPI’s. Also take note of some of the issues we experienced as described in the article “New-WebServiceProxy : Could not load file or assembly“.
When using SOAP Manager to expose the BAPI (via web services), information is passed via SOAP messages. In the same way, the XML data that is returned is structured in tables according to objects types that relates to the specific function/object type you are working with. In most cases there is lot of work to do in order to achieve this due to the way that SOAP messages have to be constructed and parsed. PowerShell however makes this a breeze. (THANKS @)
Object Model Description
In order to get a list of users in a SAP instance you can make use of the standard function BAPI_USER_GETLIST. If you look at the specific BAPI, it is described as follows (see here for more details):
EXPORTING * max_rows = 0 " bapiusmisc-bapimaxrow Maximum Number of Lines of Hits * with_username = SPACE " bapiusmisc-with_name Read User with Name IMPORTING * rows = " bapiusmisc-bapirows No. of users selected TABLES * selection_range = " bapiussrge Search for Users with a Ranges Table * selection_exp = " bapiussexp Search for Users with Free Selections * userlist = " bapiusname User List * return = " bapiret2 Return Parameter
According to the above you can see that the function returns a return parameter as a BAPIRET2 object as well as a ‘userlist’ parameter of type BAPIUSNAME. The BAPIRET2 is a standard SAP structure that provides status information regarding the transaction with the function, while the BAPIUSNAME structure contains the user list of all the username on the specific system.
Using PowerShell to connect to SAP (SOAP Web Service)
There are two three methods in PowerShell that can be used to interact with a web service (possible more �?�). These are Invoke-RestMethod, Invoke-WebRequest and New-WebServiceProxy. For the purpose of integrating into SAP, I chose the web service proxy cmdlet. The advantage of the New-WebServiceProxy is that it will create a proxy object that will allow you to richly interact with the web service. The proxy object will contain all the functions, methods and properties of the remote service which in all cases (especially this one) makes it easy to work with the service.
The code below shows how to create the web service proxy object. Note that the choice of ‘class’ and ‘namespace’ names are complete up to you.
|# Proxy variables|
|$username = "xxxxxxx"|
|$password = "*******"|
|$uriUserManagement = "http://servername/sap/bc/srt/wsdl/../../../../zfimconnector_user?sap-client=100"|
|$uriUserManagementClass = "SAP_WSDL"|
|$uriUserManagementNamespace = "SAP"|
|# Create secure credential|
|$secpasswd = ConvertTo-SecureString $password –AsPlainText –Force|
|$credential = New-Object System.Management.Automation.PSCredential ($username, $secpasswd)|
|# Create web services proxy object|
|$proxyUser = New-WebServiceProxy –Uri $uriUserManagement –Credential $credential –Class $uriUserManagementClass –Namespace $uriUserManagementNamespace|
Note: Should you have issues creating the project object, please verify the URI, username, password and DNS settings. If this does not work, have a look at the SAP authorizations and check out the following post regarding an error I experienced in this customer environment (New-WebServiceProxy : Could not load file or assembly).
Reading the data set using PowerShell
Once the proxy object has been created you will be able to access the structures within the web service by using the namespace variable you specified in the creation of the proxy object. In my case, this is ‘SAP’. If you use the PowerShell ISE, you will be able to leverage Intellisence.
In order to call the SAP function (the BAPI_USER_GETLIST function) to retrieve a list of all users, you need to create a new instance of the function, create an object to hold the return data, populate any required parameters and execute the function. Secondly, create the object that can contain the return data from the web service call. Finally, since there are no parameters required to execute this particular call.
|# Create function object|
|$getList = New-Object SAP.BAPI_USER_GETLIST|
|# Create a return object|
|$getList.USERLIST = New-Object SAP.BAPIUSNAME|
|# Execute function call|
|$getList = $proxyUser.BAPI_USER_GETLIST($getList)|
At this point PowerShell will works it’s magic on the returning data set and create you a very nice PowerShell object that contains the returning structured data set which you can use to complete the import operation. At the end of Part 3 of this guide I will publish the complete management agent for reference.