4

I'm trying to consume an endpoint from ABAP, by instantiate a if_http_client from cl_http_client=>create_by_url. That process works fine when I don't need to use a signed certificate. Usually I just include the certificate using the STRUST transaction.

But for this specific case I have two certificate files: .crt and the .key. I'm able fetch the endpoint from Postman, because I can insert those files in Settings -> Certificates:

enter image description here

So, how can I have it working from ABAP? How to insert those files in my http request? Should I pass them from ABAP code, or config it in STRUST or some other transation?

Suncatcher
  • 10,355
  • 10
  • 52
  • 90
rayashi
  • 1,721
  • 3
  • 20
  • 28
  • You need to register in STRUST all the certificates (.crt files are fine) of the servers that you want to contact from your ABAP programs. Register them in the PSE ("SSL_ID") that you use with CREATE_BY_URL e.g. if you use the SSL_ID "ANONYM", it corresponds to the PSE "SSL Client (anonymous)". https://help.sap.com/docs/help/3e7fe88850cf4ee39d151949a990d8ca/0baa90ee1868411fae3ef92511988c63.html – Sandra Rossi Nov 26 '22 at 08:13
  • What about the .key? how can I insert it? I've already tried just inserting the .crt file into STRUST, didn't work. – rayashi Nov 28 '22 at 12:13
  • Perhaps its best to clarify what exactly is required for the call. Is it 1) control over the SSL handshake 2) just a client certificate sufficient need for the SSL call. or 3) just an Anonymous SSL call and the user certificate sent as a http header. SAP ABAP doesnt offer control over the SSL handshake. The other 2 are achievable. – phil soady Nov 28 '22 at 19:54
  • 1
    using a single PEM or PFX file is not an option for you? it's easy to convert your CRT/KEY into PEM and it's importable into STRUST – Suncatcher Nov 29 '22 at 03:14
  • How can I convert them? I've already tried that just concatenating them in a single file .pem – rayashi Nov 29 '22 at 12:08
  • https://stackoverflow.com/a/991772/1347784 – phil soady Nov 29 '22 at 14:16
  • I've tried that @philsoady, it's not working – rayashi Dec 01 '22 at 14:06

2 Answers2

2

EDIT: Reworked answer to better address problem as the more details arise. NOTE for readers: This is ABAP as HTTP Client (Not server) with SSL. This is also a non typical problem. Here the SAP system has to connect to another service using a specific Client Certificate to establish an SSL connection. Something that would normally be managed at network level.

When loading The Certificate it must be loaded into STRUST in the client PSE area.

The previous Idea(prior to edit/rework) sending the the Certificate as a header is explained as Option 3.

OPTIONS :

1) SSL Handshake in ABAP . Trying to manage SSL handshake in ABAP is very likely not possible. SSL Handshake is managed by sapcryptolib.

2) Import the Client Certificate in STRUST into the Standard Client PSE. See details below

3) Use xxxx.cer as string and add as Http header (last resort if, option 2 doesnt Work)

==============================================================

2) Option 2 Details (BEST WAY) Import your certificate into Strust, in SSL client Standard area.

Here is an example on standard sap docu of an actual example case. It is Dutsch Payroll interface. Using Private key certificate. *.p12 or *.pfx file . Private Key certificate

https://help.sap.com/docs/ERP_HCM_SPV/491c29ac9232469bb257a2ba14ac290c/999ad0ce8bd24945b547584e776e9a4e.html

Since this type of Cert cant be directly imported into SAP it explains how you can use sapgenpse at operating system level to convert the p12 into a pse file. Strust does not support import of p12 files.

Now the ABAP call uses the client identity created in this step.

 cl_http_client=>create_by_url(
            EXPORTING
              url                = 'url'           
              ssl_id             = 'CL_ID' "Ident created in step above  
            IMPORTING
              client             = lo_client       
          ).

Or perhaps easier to work with. Use Sm59 to create and external http addr and select this Newly created identity. SM59 external destination

Then call with http client created via destination.

CALL METHOD cl_http_client=>create_by_destination
  EXPORTING
    destination              = lv_destination "the new sm59 destination 
  IMPORTING
    client                   = lo_http_client.
  1. OPTION 3 Details: (Not ideal, assume called service supports it.) if and only if, the called service support Certificates as Header Note you xxx.cer is the equivalent to an identity key. manage the string carefully.

     DATA: lo_client TYPE REF TO if_http_client.
    
       cl_http_client=>create_by_url(
         EXPORTING
           url                = 'url'           
           ssl_id             = 'ANONYM'      "Start SSL handshake as Anonymous SSL
         IMPORTING
           client             = lo_client       
       ).
    

"and pass the actual identify as HTTP header, " Many service support this approach. But they solutions are always " specific to that service. " Example is the microsoft translation service. " the expect a user subscription key as a header. 'https://api-eur.cognitive.microsofttranslator.com/translate?api-version=3.0'

lo_client->request->set_header_field(
      EXPORTING
        name  = 'Client-Cert'    "Check HTTP header name with called Service docu
        value = '<cert> in string format'
    ).
    
    "lo_client->send( .. )
    "lo_client->receive( .. )
phil soady
  • 11,043
  • 5
  • 50
  • 95
  • I think the question is more about installing the certificate in STRUST and defining the link between ABAP and STRUST e.g. the SSL_ID "ANONYM" corresponds to the PSE "SSL Client (anonymous)". – Sandra Rossi Nov 26 '22 at 08:15
  • 1
    @SandraRossi Rayashi sad he already knows and uses strust for importing certificates. Both Server and client. And the idea of using Anoym (if it works at all) was to try and add the certificate and key as special headers. If you could import a certificate bundle in Strust, that would indeed be the solution. But how do you do that in Strust? That is whole point of the alternative approach. You can only import a cert. in strust, not a certificate key bundle. Rayashi is asking about a key bundle. That is the problem. you CANT use STRUST so now what ? – phil soady Nov 26 '22 at 13:29
  • @philsoady How can I get Client-Cert and Client-Cert-Chain from .crt and .key? – rayashi Nov 28 '22 at 12:41
  • That question would suggest I misunderstood what you are trying to achieve. It means the example is NOT what you want. Just import the client certificate using STRUST into the CLIENT PSE. If you dont have a clear requirement to send the public key with the certificate, then that is wrong plan. – phil soady Nov 28 '22 at 19:29
  • The example you wrote is not what I'm trying to achieve indeed. The API doc I have to consume, is not mentioning that I should send Client-Cert neither Client-Cert-Chain in the headers. They provide a python example code like this https://gist.github.com/hdiburla/d15712dfab9288d84e1edd5ff7f00452 – rayashi Nov 29 '22 at 12:12
  • @SandraRossi so now the trick of how to get the key pair and certificate into STRUST is revealed. You need to convert it first using sapgenpse. I hadnt used that before... and it does clarifiy the best way to solve this problem. https://help.sap.com/docs/SAP_NETWEAVER_AS_ABAP_751_IP/e73bba71770e4c0ca5fb2a3c17e8e229/0d9ce63bab134b39a52e340255d7650c.html?version=7.51.13&locale=en-US – phil soady Nov 29 '22 at 15:41
  • Should I convert my two files (CRT and KEY) to a single PFX, then convert the PFX to a PSE file? – rayashi Nov 29 '22 at 20:41
  • @rayashi, please update the question with the types of the files. The more details and more precise you are the better. Given you can import an typical *.cer which is normal the certificate unwrapped and without private key into STRUST. The question is why doesnt that work. Check tran SMICM , you well see what issues you have with SSL handshake. So the fact you have a private key, why do you need to send it / use it ? The answer for lies in understandign what you are calling and what they expect. – phil soady Nov 30 '22 at 00:12
  • I have two certificate files: .crt and the .key, as mentioned in the question. In the answer you said I should user .p12. How can I get this from .CRT and .KEY files? – rayashi Nov 30 '22 at 12:03
1

Use KeyStore Explorer tool to create single pfx file from your client key and certificate. Also you can put chain of the client certificate with this tool.

Use sapgenpse on your local system and create a pse file from pfx file with below command:

sapgenpse import_p12 -p c:\client.pse c:\client.pfx

Go to STRUST, create your own certificate store at Enviroment->SSL Client identities. I prefer this for not mixing all of them. Then return to STRUST and chose PSE->Import and select your custom pse file. Then click PSE->Save as and select your custom identity.

Add site SSL certificate to your new identiy.

You can try new SSL Client configuration at SM59 with selecting your new SSL Client identity.

Example ABAP code below.

REPORT ZMKY_SSL_CLIENT.

 DATA: lo_client TYPE REF TO if_http_client,
       lv_code   TYPE i,
       lv_REASON type string.

   cl_http_client=>create_by_url(
     EXPORTING
       url                = 'https://mysslclienthost.com'
       ssl_id             = 'MYSSLC'      "Your SSL Client identity
     IMPORTING
       client             = lo_client
   ).

   lo_client->SEND( ).

   lo_client->RECEIVE( ).

   lo_client->RESPONSE->GET_STATUS( IMPORTING CODE = lv_code
                                    REASON         = lv_reason ).

   WRITE: lv_code, lv_reason.
mkysoft
  • 5,392
  • 1
  • 21
  • 30
  • 1
    This is the right answer. I was trying that before, but sapgenpse was giving me an error, saying the certificate was incomplete. So the API provider gave me those files, and I used the -r argument so could use the intermediate certificates. Working now. Thank you! – rayashi Dec 06 '22 at 12:19
  • so now you have a proper crt file and can import it. – phil soady Dec 16 '22 at 13:34