Skip to Content
Mobile

SAP Afaria API 301 - Session-less Binding, Basic Authentication and Consuming the Afaria API through SOAP

Tags:

Introduction

The focus of this document is using the new session-less bindings and Basic authentication in Afaria 7.0 Service Pack 5, which allows for the use of a broader set of programming languages. Additionally, this document will describe using SoapUI to make calls to the Afaria API. The example here is a simple example which will request the list of SAP Afaria servers and their statuses. For more complex interaction with the APIs, please read the other documents on SAP Afaria API programming which are available on SCN and use the understanding of the flow from those documents with the guidelines provided here. This document is meant as a continuation of our previous efforts in Afaria API 101, Afaria API 201, Afaria API 202, Afaria API 203 and Afaria API 204 and assumes completion of those sections.

Requirements & Assumptions

Table of Contents

A Word About the New Bindings and Sessions

Prior to SAP Afaria 7.0 Service Pack 5, the only binding types available were session-based bindings which used Windows Authentication (Kerberos or NTLM). As of Afaria 7.0 SP5, two new binding types, BasicHttp and WebHttp bindings are available. These bindings are session-less, requiring the passing of a session identifier for each call, use Basic Authentication and require transport level security through SSL. These new types are not available by default and must be enabled as described in the Enabling Basic Authentication section.

The development of the API service leverages off of the capabilities of session based bindings (WsHttp, NetTcp and NetPipe) and as a result the API service required session based bindings to function properly. Since BasicHttp and WebHttp are session-less bindings, it required the introduction of a consumer-aware "session" to the API service for the new bindings. As a result, all of the methods exposed through the session-less bindings now require a Session ID as the first parameter, and this parameter is used to emulate a session.

To operate correctly, an application which uses the session-less binding should generate a unique session ID and use this session ID for the duration of the application instance. Once the application is finished, it should call the method CloseSession to free up all resources associated with its session. Each session can only have one instance of each service channel, so for multi-threaded approaches, for each session, there should be only one instance of each service channel (eg one instance of the service channel for the Devices service) and if multiple threads need to access a particular service simultaneously, a new session should be used.

Available Bindings:

Previously Existing Session Based Bindings:

  • WsHttp binding - Message Level Security - Windows Authentication
  • NetTcp binding - Message Level Security - Windows Authentication
  • NetPipe binding - Transport Level Security - Windows Authentication

New Session-less Bindings:

  • BasicHttp binding (SOAP 1.1)  - Transport Level Security - Basic Authentication
  • WebHttp binding (XML\JSON) - Transport Level Security - Basic Authentication

Enabling Basic Authentication

  1. Edit AfariaServiceHost.exe.config in <AfariaAPIServiceInstallFolder>\Bin. This is normally in C:\Program Files (x86)\AfariaApiService\Bin. Depending on the desired binding, add the following lines in the appSettings section and save the file:
  2. Assure that the ports for the desired binding are open/listening in any firewalls and network appliances.
  3. It is necessary to obtain a SSL certificate with a common name that matches the manner in which you will be accessing the server (ie FQDN vs IP address). If one already exists, it may be reused. The certificate will need to be bound to the port. One method of doing this is:
    1. Obtain the certificate thumbprint by inspecting the certificate and finding the Thumbprint under the Details tab.
    2. Open a Command Prompt under escalated privileges(Run as administrator).
    3. If there may be an existing binding for the necessary port, in the elevated command prompt, run the following command with <PORT> replaced with the appropriate value (the port is that which was specified in the AfariaServiceHost.exe.config file, in the address value):
      • netsh http delete sslcert ipport=0.0.0.0:<PORT>
    4. In the elevated command prompt, run the following command with <PORT> and <CERTIFICATE THUMBPRINT> replaced with their respective values:
      • netsh http add sslcert ipport=0.0.0.0:<PORT> certhash=<CERTIFICATE THUMBPRINT> appid={00000000-0000-0000-0000-000000000000}
      • (For example, see the following)
        netsh http add sslcert ipport=0.0.0.0:7981 certhash=6ee84c747b40400238085f27f92af0d08c27f2cf appid={00000000-0000-0000-0000-000000000000}
  4. Restart the Afaria API service.

Using SoapUI to call the API

  1. If you are using a self-signed certificate, import the root certificate of the CA into the Trusted Root store.
  2. If you do not already have SoapUI installed, download and install it from http://www.soapui.org/.
  3. Right-click on Projects in the Navigator and choose New SOAP Project.
    1. Enter a Project Name.
    2. Enter the Initial WSDL for the service that will be consumed. This example will use the Server service, so the address will look like the following: https://server.domain.com:7981/AfariaService/Server?wsdl
    3. Optionally, uncheck Create Requests. If this is checked, the basic structure of each SOAP request will be created for every API call for that service.
    4. Click OK.
  4. Right-click on the endpoint created in the new project and select Show Interface Viewer.
    1. Select the Service Endpoints tab.
    2. Enter the Username for the Afaria API Service Account in UPN format (user@domain.com).
    3. Enter the Password for the Afaria API Service Account.
    4. Close the window for this binding.


InitContext

InitContext initiates the connection with the API server and allows the API service to allocate resources and initiate context for further API calls. InitContext should be called for each service that is used in the API.

  1. Right-click on InitContext in the Navigator window and select New request.
    1. Enter a name for the request to InitContext such as InitContext.
  2. Edit the SOAP body (Please note, though SoapUI may mark some parameters as <!--Optional:-->, they are only optional for the request to be submitted, and the SAP Afaria API may not respond correctly because the request may not make sense logically):
    1. Replace the "?" under sessionID with a Session ID which will be used to make all calls for this session.
    2. Replace the "?" under contextID with a Context ID which will be used for all requests that share the same context.
    3. Click the green arrow at the top of the request window (or hit ALT-ENTER) to submit the request.
    4. Observe that there are no errors in the response in the right window.

Example Request:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/">

  <soapenv:Header/>

  <soapenv:Body>

      <tem:InitContext>

        <tem:sessionId>{D790AA0A-4FD5-4EEA-A3B3-06F185662360}</tem:sessionId>

        <tem:contextId>{E17330F3-405D-4410-ACCB-A1963EF56FB9}</tem:contextId>

      </tem:InitContext>

  </soapenv:Body>

</soapenv:Envelope>

Example Response:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">

  <s:Body>

      <InitContextResponse xmlns="http://tempuri.org/">

        <InitContextResult xmlns:a="http://schemas.datacontract.org/2004/07/AfariaService" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">

            <a:Culture>en-US</a:Culture>

            <a:FarmId>Farm</a:FarmId>

            <a:LoggedOnUser i:nil="true"/>

            <a:ServerId i:nil="true"/>

            <a:TenantId>-1</a:TenantId>

            <a:Authorized>true</a:Authorized>

            <a:ContextId>{E17330F3-405D-4410-ACCB-A1963EF56FB9}</a:ContextId>

            <a:FarmSpecifications>

              <a:MaxDBColumnNameLength>128</a:MaxDBColumnNameLength>

              <a:ServerId i:nil="true"/>

              <a:Version i:nil="true"/>

            </a:FarmSpecifications>

            <a:SupportedFarmIds xmlns:b="http://schemas.microsoft.com/2003/10/Serialization/Arrays">

              <b:string>Farm</b:string>

            </a:SupportedFarmIds>

            <a:UserIdentity>DOMAIN\user</a:UserIdentity>

            <a:Version>7.00</a:Version>

        </InitContextResult>

      </InitContextResponse>

  </s:Body>

</s:Envelope>

SetTenantIdContext

When SetTenantIdContext is called, the tenant ID specified will be used in every successive call to the API as the context within which it will operate/query. This example will use 0 for the system tenant. Call SetTenantIdContext again with the appropriate tenant ID to query/operate against another tenant.

  1. Right-click on SetTenantIdContext in the Navigator window and select New request.
    1. Enter a name for the request to SetTenantIdContext such as SetTenantIdContext.
  2. Edit the SOAP body:
    1. Replace the "?" under sessionId with the value that was used in the call to InitContext.
    2. Replace the "?" under tenantId with the numerical ID for the tenant that will be used when querying the API.
    3. Click the green arrow at the top of the request window (or hit ALT-ENTER) to submit the request.
    4. Observe that there are no errors in the response in the right window.

Example Request:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/">

  <soapenv:Header/>

  <soapenv:Body>

      <tem:SetTenantIdContext>

        <tem:sessionId>{D790AA0A-4FD5-4EEA-A3B3-06F185662360}</tem:sessionId>

        <tem:tenantId>0</tem:tenantId>

      </tem:SetTenantIdContext>

  </soapenv:Body>

</soapenv:Envelope>

Example Response:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">

  <s:Body>

      <SetTenantIdContextResponse xmlns="http://tempuri.org/">

        <SetTenantIdContextResult xmlns:a="http://schemas.datacontract.org/2004/07/AfariaService" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">

            <a:Culture>en-US</a:Culture>

            <a:FarmId>Farm</a:FarmId>

            <a:LoggedOnUser i:nil="true"/>

            <a:ServerId i:nil="true"/>

            <a:TenantId>0</a:TenantId>

            <a:Authorized>true</a:Authorized>

            <a:ContextId>{E17330F3-405D-4410-ACCB-A1963EF56FB9}</a:ContextId>

            <a:FarmSpecifications>

              <a:MaxDBColumnNameLength>128</a:MaxDBColumnNameLength>

              <a:ServerId i:nil="true"/>

              <a:Version i:nil="true"/>

            </a:FarmSpecifications>

            <a:SupportedFarmIds xmlns:b="http://schemas.microsoft.com/2003/10/Serialization/Arrays">

              <b:string>Farm</b:string>

            </a:SupportedFarmIds>

            <a:UserIdentity>domain\user</a:UserIdentity>

            <a:Version>7.00</a:Version>

        </SetTenantIdContextResult>

      </SetTenantIdContextResponse>

  </s:Body>

</s:Envelope>

GetServerList

GetServerList gets information describing all Afaria servers that are members of the server farm, including their operating status and role. This example is to call this in order to determine whether our servers are running. If a server appeared as stopped, a call to StartServer could be made after setting the server context (SetServerIdContext) in order to start it.

  1. Right-click on GetServerList in the Navigator window and select New request.
    1. Enter a name for the request to GetServerList such as GetServerList.
  2. Edit the SOAP body:
    1. Replace the "?" under sessionId with the value that was used in the call to InitContext.
    2. Click the green arrow at the top of the request window (or hit ALT-ENTER) to submit the request.
    3. Observe that there are no errors in the response in the right window. This call will have returned the list of servers along with their statuses.

Example Request:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/">

  <soapenv:Header/>

  <soapenv:Body>

      <tem:GetServerList>

        <tem:sessionId>{D790AA0A-4FD5-4EEA-A3B3-06F185662360}</tem:sessionId>

      </tem:GetServerList>

  </soapenv:Body>

</soapenv:Envelope>

Example Response:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">

  <s:Body>

      <GetServerListResponse xmlns="http://tempuri.org/">

        <GetServerListResult xmlns:a="http://schemas.datacontract.org/2004/07/AfariaService.Server" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">

            <a:ServerDescription>

              <a:ServerId>3o)pa</a:ServerId>

              <a:Name>SERVERNAME</a:Name>

              <a:Role>Master</a:Role>

              <a:ComputerName>SERVERNAME</a:ComputerName>

              <a:ComputerIPAddress>10.10.10.10</a:ComputerIPAddress>

              <a:State>Running</a:State>

              <a:LastStartTime>2014-11-25T17:28:27</a:LastStartTime>

              <a:LastStopTime>2014-11-25T17:27:47</a:LastStopTime>

              <a:Active>true</a:Active>

              <a:ReplicationAddress>10.10.10.10</a:ReplicationAddress>

              <a:ActiveSessionCount>0</a:ActiveSessionCount>

            </a:ServerDescription>

        </GetServerListResult>

      </GetServerListResponse>

  </s:Body>

</s:Envelope>

CloseContext

CloseContext should be called whenever using the SAP Afaria API in order to free resources on the API server. CloseContext should be called prior to making the call to CloseSession on the last (or only) session that is associated with this context, and prior to making the call to CloseServiceInstance on the last (or only) service that InitContext was called for, associated with its session ID. If CloseContext is not called when it is no longer in use, the resources associated with the context will continue to be tied up for 125 minutes (120 minutes of idle time + up to 5 minutes until the cleanup schedule runs).

  1. Right-click on CloseContext in the Navigator window and select New request.
    1. Enter a name for the request to CloseContext such as CloseContext.
  2. Edit the SOAP body:
    1. Replace the "?" under sessionId with the value that was used in the call to InitContext.

    2. Click the green arrow at the top of the request window (or hit ALT-ENTER) to submit the request.

    3. Observe that there are no errors in the response in the right window.

Example Request:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/">

  <soapenv:Header/>

  <soapenv:Body>

      <tem:CloseContext>

        <tem:sessionId>{D790AA0A-4FD5-4EEA-A3B3-06F185662360}</tem:sessionId>

      </tem:CloseContext>

  </soapenv:Body>

</soapenv:Envelope>

Example Response:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">

  <s:Body>

      <CloseContextResponse xmlns="http://tempuri.org/"/>

  </s:Body>

</s:Envelope>

CloseServiceInstance

CloseServiceInstance should be called to close and free resources associated with a specific service instance associated with the specified session. Call it whenever no more calls will be made with a specific service instance (eg ServerProperties). CloseServiceInstance should be called prior to making a call to CloseSession with the session ID associated with the Service Instance. If CloseServiceInstance is not called when the service instance is no longer in use, the resources associated with the service instance and session ID will continue to be tied up for up to 15 minutes.

  1. Right-click on CloseServiceInstance in the Navigator window and select New request.
    1. Enter a name for the request to CloseServiceInstance such as CloseServiceInstance.
  2. Edit the SOAP body:
    1. Replace the "?" under sessionId with the value that was used in the call to InitContext.
    2. Click the green arrow at the top of the request window (or hit ALT-ENTER) to submit the request.
    3. Observe that there are no errors in the response in the right window.

Example Request:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/">

  <soapenv:Header/>

  <soapenv:Body>

      <tem:CloseServiceInstance>

        <tem:sessionId>{D790AA0A-4FD5-4EEA-A3B3-06F185662360}</tem:sessionId>

      </tem:CloseServiceInstance>

  </soapenv:Body>

</soapenv:Envelope>

Example Response:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">

  <s:Body>

      <CloseServiceInstanceResponse xmlns="http://tempuri.org/"/>

  </s:Body>

</s:Envelope>

CloseSession

CloseSession should be called to free up remaining resources associated with the session. By default, if CloseSession is not called once the session is no longer in use, the resources associated with the session will be tied up for up to 25 minutes.

  1. Right-click on CloseSession in the Navigator window and select New request.
    1. Enter a name for the request to CloseSession such as CloseSession.
  2. Edit the SOAP body:
    1. Replace the "?" under sessionId with the value that was used in the call to InitContext.
    2. Click the green arrow at the top of the request window (or hit ALT-ENTER) to submit the request.
    3. Observe that there are no errors in the response in the right window.

Example Request:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/">

  <soapenv:Header/>

  <soapenv:Body>

      <tem:CloseSession>

        <tem:sessionId>{D790AA0A-4FD5-4EEA-A3B3-06F185662360}</tem:sessionId>

      </tem:CloseSession>

  </soapenv:Body>

</soapenv:Envelope>

Example Response:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">

  <s:Body>

      <CloseSessionResponse xmlns="http://tempuri.org/"/>

  </s:Body>

</s:Envelope>

No comments