CentOS: llamadas sobre SSL

Se tienen los certificados:

  • ssl.key (privada)
  • ssl.cert (publica)
  • ca.cert
  • pass phrase

La llave publica ssl.cert, esta instalada en el servidor DEVIL.

Se necesita enviar un json mediante POST desde el servidor HOST (Centos7) a DEVIL (SAP) sobre SSL, esto implica enviar las llaves publica, privada a demás de tener una validación del certificado CA y el pass phrase.

Si se envía los datos por curl de esta manera:

curl -v --cert ./ssl.cert --key ./ssl.key --cacert ./ca.cert --header "Content-Type: application/json" --data '{"key":"value"}' https://devil.com/

Obtendríamos una respuesta como esta:

About to connect() to devil.com port 443 (#0)
Trying 123.123.123.123…
Connected to devil.com (123.123.123.123) port 443 (#0)
Initializing NSS with certpath: sql:/etc/pki/nssdb
CAfile: ca.cert
CApath: none
Server certificate:
subject: CN=…………………………………..
start date: Jan 22 00:00:00 2020 GMT
expire date: Jan 22 12:00:00 2022 GMT
common name: *…………………………………
issuer: CN=……………………………………
NSS error -8172 (SEC_ERROR_UNTRUSTED_ISSUER)
Peer's certificate issuer has been marked as not trusted by the user.
Closing connection 0
curl: (60) Peer's certificate issuer has been marked as not trusted by the user.
More details here: http://curl.haxx.se/docs/sslcerts.html
curl performs SSL certificate verification by default, using a "bundle"
of Certificate Authority (CA) public keys (CA certs). If the default
bundle file isn't adequate, you can specify an alternate file
using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
the bundle, the certificate verification probably failed due to a
problem with the certificate (it might be expired, or the name might
not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
the -k (or --insecure) option.

Haciendo la misma llamada de manera insegura, agregando la opción -k:

curl -v -k --cert ./ssl.cert --key ./ssl.key --cacert ./ca.cert --header "Content-Type: application/json" --data '{"key":"value"}' https://devil.com/

La respuesta seria algo así:

About to connect() to devil.com port 443 (#0)
Trying 123.123.123.123…
Connected to devil (123.123.123.123) port 443 (#0)
Initializing NSS with certpath: sql:/etc/pki/nssdb
skipping SSL peer certificate verification
NSS: client certificate from file
subject: CN=…………………………………………………..
start date: May 22 00:00:00 2020 GMT
expire date: Feb 10 12:00:00 2021 GMT
common name: ………………………………………………….
issuer: CN=…………………………………………………
SSL connection using TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
Server certificate:
subject: CN=*………………………………………………….
start date: Jan 22 00:00:00 2020 GMT
expire date: Jan 22 12:00:00 2022 GMT
common name: *…………………………………………………
issuer: CN=……………………………………………………
POST /http/Orders HTTP/1.1
User-Agent: curl/7.29.0
Host: devil.com
Accept: /
Content-Type: application/json
Content-Length: 664
upload completely sent off: 664 out of 664 bytes
< HTTP/1.1 401
< X-message-code: PWD_WRONG
< WWW-Authenticate: Basic realm="SAP HANA Cloud Platform"
< Transfer-Encoding: chunked
< Date: Thu, 28 May 2020 19:32:54 GMT
< Server: SAP
< Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
<
Connection #0 to host devil.com left intact

Un detalle si se usa la opción -k los parámetros cacert y capath dejan de funcionar

Bien la solución es instalar(copiar) el certificado ca.cert, de la siguiente manera:

cp ca.cert /etc/pki/ca-trust/source/anchors/
update-ca-trust extract

Con esto la llamada de forma segura (sin el parámetro -k ) y sin el certificado CA debería ser exitosa.

curl -v --cert ./ssl.cert --key ./ssl.key --header "Content-Type: application/json" --data '{"key":"value"}' https://devil.com/

Este problema también afecta a las llamadas curl que se hacen desde PHP