Consume services of an on-premise system securely from SAP S/4HANA Cloud, Public Edition or SAP BTP, ABAP Environment
2023-11-6 19:10:10 Author: blogs.sap.com(查看原文) 阅读量:100 收藏

Motivation

Previously, communication from cloud to on-premise via a technical communication user was only possible via basic authentication. Here, I try to cover a new, more secure means to achieve this using OAuth and x.509 certificates

. That way, I do not have to share any credentials of the on-premise system with the cloud environment. Additionally I can use either secret based or mTLS based authentication mechanisms to obtain the access token, where the latter is generally considered more secure than basic authentication. We cover the mTLS based authentication mechanism in this blog.

Learn more here (Authenticating Users against On-Premise Systems | SAP Help Portal).

The following diagram depicts the flow from SAP S/4HANA Cloud, Public Edition.

Technical%20User%20Propagation%20from%20S/4HANA%20Cloud%20to%20on-premise

For general information on what OAuth with mTLS means, refer https://oauth.net/2/mtls/ and https://datatracker.ietf.org/doc/html/rfc8705 . If you are unaware of how mTLS works, it is recommended to read through the above links before continuing.

Prerequisites

  1.  (see here)
  2. On Premise system configured to trust certificates forwarded by the SAP Cloud Connector (see here)
  3. Subaccount with configured SAP Cloud Connector (see here)
  4. SAP BTP ABAP Environment or SAP S/4HANA Cloud system connected to the subaccount where the cloud connector is configured (see here)
  5. For OAuth with mTLS: A valid certificate  to the ABAP system on SAP BTP ABAP Environment
  6. SOAP/OData service exists in the on-premise system that is ready for consumption

Scenario

Here, I consume an OData service and a SOAP service from an on-premise ABAP system via technical user propagation using OAuth with mTLS (Certificate based authentication). I

For OData, we choose the standard product master service available with “/sap/opu/odata/SAP/API_PRODUCT_SRV/”. For SOAP, we use a custom SQRT service. However, both of these are just examples and the process should be the same for any other OData/SOAP services.

All steps of the blog would be applicable for both SAP S/4HANA cloud public edition and SAP BTP ABAP Environment unless stated otherwise.

Consume services from the on-premise system

Development – Code based consumption

Persona: Developer in the ABAP system hosted on SAP BTP ABAP Environment or Developer in SAP S/4HANA Public Cloud system (using SAP S/4HANA Cloud ABAP Environment aka Embedded Steampunk)

First set up the code to read data from an on-premise system. Here, I consume the standard product OData service and a custom SOAP service that calculates square root. This blog focuses on the security aspects when consuming services from on-premise systems.

Consumption of OData service

Create a service consumption model to consume the standard product OData service.

Create a new service consumption model object

Create%20Service%20Consumption%20Model

Choose the Remote Consumption Mode as OData and provide a suitable name, description

Upload the service metadata of the standard product API

Follow through the wizard to have the required objects generated

Create outbound service for Product OData service

The path to the standard Product OData service can be found from the SEGW transaction or the SAP Gateway client in the on-premise system.

On the ABAP system on the SAP BTP ABAP Environment or SAP S/4HANA Cloud, Create an outbound service in ADT with type HTTP and provide the default path prefix as identified above.

Create communication scenario for the Product OData service

Now, we need to expose the service for communication. Here, we create a communication scenario with ADT

Under the outbound tab, add the outbound service created above, ensure  and publish the communication scenario

Create a class to read product details from the standard OData service

CLASS zcl_product DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC .
 
  PUBLIC SECTION.
 
    INTERFACES if_oo_adt_classrun .
  PROTECTED SECTION.
  PRIVATE SECTION.
ENDCLASS.
 
 
 
CLASS ZCL_PRODUCT IMPLEMENTATION.
 
 
  METHOD if_oo_adt_classrun~main.
 
 
    DATA:
      lt_business_data TYPE TABLE OF za_product,
      lo_http_client  TYPE REF TO if_web_http_client,
      lo_client_proxy TYPE REF TO /iwbep/if_cp_client_proxy,
      lo_request      TYPE REF TO /iwbep/if_cp_request_read_list,
      lo_response     TYPE REF TO /iwbep/if_cp_response_read_lst.
 
    TRY.
        " Create http client
        DATA(lo_destination) = cl_http_destination_provider=>create_by_comm_arrangement(
                                                     comm_scenario  = 'Z_COM_PROD'
                                                     comm_system_id = 'S4H_1909_CAL'
                                                     service_id     = 'Z_PRODUCT_ROOT_REST' ).
        lo_http_client = cl_web_http_client_manager=>create_by_http_destination( lo_destination ).
        ASSERT lo_http_client IS BOUND.
        " If you like to use IF_HTTP_CLIENT you must use the following factory: /IWBEP/CL_CP_CLIENT_PROXY_FACT
        lo_client_proxy = cl_web_odata_client_factory=>create_v2_remote_proxy(
          EXPORTING
            iv_service_definition_name = 'Z_SCM_PRODUCT'
            io_http_client             = lo_http_client
            iv_relative_service_root   = '' ).
 
        " Navigate to the resource and create a request for the read operation
        lo_request = lo_client_proxy->create_resource_for_entity_set( 'A_PRODUCT' )->create_request_for_read( ).
 
        lo_request->set_top( 50 )->set_skip( 0 ).
 
        " Execute the request and retrieve the business data
        lo_response = lo_request->execute( ).
        lo_response->get_business_data( IMPORTING et_business_data = lt_business_data ).
 
        out->write( lt_business_data ).
 
      CATCH /iwbep/cx_cp_remote INTO DATA(lx_remote).
        " Handle remote Exception
        " It contains details about the problems of your http(s) connection
        out->write( lx_remote->get_longtext(  ) ).
      CATCH /iwbep/cx_gateway INTO DATA(lx_gateway).
        " Handle Exception
        out->write( lx_gateway->get_longtext(  ) ).
      CATCH cx_web_http_client_error INTO DATA(lx_web_http_client_error).
        " Handle Exception
        out->write( lx_web_http_client_error->get_longtext(  ) ).
      CATCH cx_http_dest_provider_error INTO DATA(lx_destination).
        "handle exception
        out->write( lx_destination->get_longtext(  ) ).
    ENDTRY.
 
  ENDMETHOD.
ENDCLASS.

Consumption of SOAP service

Create a service consumption model to consume a custom SQRT SOAP service

Choose the Remote Consumption Mode as Web Service and provide a suitable name/description

Upload the WSDL metadata of the SOAP service

Follow through the wizard to have the required objects generated

Create outbound service for SQRT SOAP service

Identify the request URI for the SOAP service from the SOAMANAGER transaction on the on-premise system

Identify the service interface. This is the proxy class in the service consumption model created for the SOAP service

Create an outbound service using ADT with type SOAP in the ABAP system on the SAP BTP ABAP Environment or SAP S/4HANA Cloud, public edition

Create communication scenario for SQRT SOAP service

Now, we need to expose the service for communication. Here, we create a communication scenario with ADT

Under the outbound tab, add the outbound service created above, ensure  for authentication with grant type “Client Credentials” and publish the communication scenario

Create a class to read the square root of an integer from a custom SOAP service

CLASS zcl_soap_sqrt DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC .
 
  PUBLIC SECTION.
 
    INTERFACES if_oo_adt_classrun .
  PROTECTED SECTION.
  PRIVATE SECTION.
ENDCLASS.
 
 
 
CLASS ZCL_SOAP_SQRT IMPLEMENTATION.
 
 
  METHOD if_oo_adt_classrun~main.
 
    try.
    data(destination) = cl_soap_destination_provider=>create_by_comm_arrangement(
                          comm_scenario  = 'Z_COM_SQRT_SOAP'
                        ).
    data(proxy) = new zco_z_sqrt_srv(
                    destination = destination
                  ).
    data(request) = value zsqrt_fm( input_num = 4 ).
    proxy->zsqrt_fm(
      exporting
        input = request
      importing
        output = data(response)
    ).
 
    out->write( response-result ).
 
    "handle response
  catch cx_soap_destination_error INTO DATA(destination_ex).
    "handle error
    out->write( destination_ex->get_longtext(  ) ).
  catch cx_ai_system_fault INTO DATA(system_ex).
    "handle error
    out->write( system_ex->get_longtext(  ) ).
  catch zcx_zsqrt_fm_exception INTO DATA(fm_ex).
    "handle error
    out->write( fm_ex->get_longtext(  ) ).
endtry.
 
 
  ENDMETHOD.
ENDCLASS.

Create OAuth Client for Outbound Communication User

Persona: Sub account administrator or space developer on SAP Business Technology Platform

I first need to obtain an OAuth client that is provided by an authorization server. This is trusted by the SAP Cloud Connector (trust established by connecting the Cloud Connector to a sub account).
One way to do so is by creating an instance of the Authorization and Trust Management service in the sub account connected to the Cloud Connector, which results in an OAuth client, which can be used to obtain access tokens. This is done in the sub account connected to the SAP BTP ABAP Environment system or to SAP S/4HANA Cloud

    1. Go to the Marketplace in the Business Technology Platform Cockpit of the sub account

    2. Search for the Authorization and Trust Management Service

    3. Create an instance of service plan application of the Authorization and Trust Management Service (no additional settings are required beyond the first wizard page)

Persona: Subaccount administrator or space developer on SAP BTP, administrator on the ABAP system on SAP BTP ABAP Environment/SAP S/4HANA Cloud

To be able to use a client certificate for the OAuth flow, we need to map the certificate of the ABAP system to the OAuth Client (XSUAA instance) we just created.

  1. As an administrator, logon to the Fiori Launchpad of the ABAP system on SAP BTP ABAP Environment or to the Fiori Launchpad of SAP S/4HANA Cloud. Find the app Maintain Client Certificates.
  2. Download the public key in base64 format from the ABAP system
    NOTE: On the SAP BTP ABAP Environment, the default client certificate cannot be used for mTLS since this is self-signed at the time of writing this  and a valid, signed certificate is needed. On SAP S/4HANA Cloud, it is recommended to use the default client 

  3. Put the public key in the generated file “public.pem” into the following json replacing “<public key>”. Ensure to adjust the new line characters to resolve errors in the JSON
    {
        "credential-type": "x509",
        "x509": {
          "certificate": "<public key>",
          "certificate-pinning": false
        }
    }​
  4. Keep the resulting service key for later reference

Create a Communication System

Persona: Administrator of the ABAP system hosted on SAP BTP ABAP Environment or Administrator in the SAP S/4HANA Public Cloud system

The Communication System is used to pass the OAuth client details to the ABAP system and to configure how and where the access token should be transported.

  1. Create a new Communication System using the Communication System app.
  2. Configure the on premise system (based on hostname/port in the cloud connector configuration) and enable the cloud connector, providing the location ID.
  3. Token Endpoint: <URL from service key>/oauth/token
  4. mTLS Endpoint: <certurl from service key>/oauth/token
  5. In the “Users for Outbound Communication” section create a new outbound user with authentication method oAuth 2.0 
  6. Save the Communication System

Create a Communication Arrangement

Persona: Administrator of the ABAP system hosted on SAP BTP ABAP Environment or Administrator in the SAP S/4HANA Public Cloud system

  1. Create a Communication Arrangement for the desired Scenario and use the Communication System we just created
  2. Make sure that the Authentication Method is OAuth 2.0 and the Client ID is the one we just configured

Configure the Subject Pattern in Cloud Connector

Persona: Cloud connector administrator

Documentation: Configure Subject Patterns for Principal Propagation | SAP Help Portal
To define how the OAuth access token shall be handled in the Cloud Connector and how a resulting client certificate should look like, we define a pattern, which is applied to the incoming access token.
In our example we take the client id and put it into the CN of the subject name.

  1. Open the Configuration > OnPremise menu in the Cloud Connector
  2. Scroll down to the Principal Propagation section
  3. Create a new Subject Pattern
    1. Enter a Condition that the ${user_type} is Technical
    2. Enter the CN as ${client_id} to reference the client id of an incoming access token
    3. Provide appropriate values for the other fields
  4. Generate a sample certificate
  5. Enter the 

Map Certificate to an On-Premise Technical User

Persona: Administrator

To be able to authenticate a user with the certificate issued by the Cloud Connector, we map the Subject (OAuth Client ID) and Issuer (Cloud Connector) combination to an actual user in the on premise system.

  1. Open transaction certrule in the on premise system
  2. Go into edit mode
  3. Upload the sample certificate
  4. Save and verify the new mapping is created

End to End Test and Validation of technical user propagation

Persona: Developer, Cloud connector administrator, Subaccount administrator/space developer

Run the classes implementing IF_OO_ADT_CLASSRUN that we defined above for the SOAP and OData services in ADT. Notice the output in the console.

To verify this call indeed happened with the technical user, check the most recent requests from cloud to on-premise in the cloud connector under the “Monitor” menu item. Notice the “User” column reflects the client ID

To verify at the on-premise system, use transaction STAD and filter with the technical user configured during the explicit mapping

Notice the calls indeed happened with this technical user


文章来源: https://blogs.sap.com/2023/11/06/consume-services-of-an-on-premise-system-securely-from-sap-s-4hana-cloud-public-edition-or-sap-btp-abap-environment/
如有侵权请联系:admin#unsafe.sh