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
:
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?
CodePudding user response:
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
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.
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( .. )
CodePudding user response:
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.