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

wget: enviar peticiones POST sobre SSL

Se necesita enviar datos json mediante POST sobre SSL. Se tienen los certificados:

  • ssl.key
  • ssl.cert
  • cacert.cert

El código para el envío del json por POST:

wget -O- --post-data='{"key":"value"}' --header='Content-Type:application/json' --certificate=ssl.cert --private-key=ssl.key --ca-certificate=cacert.cert -nv 'https://www.host.com'

openssl: remover passphrase

Se tienen las keys generadas usando un passphrase:

  • ssl.key
  • ssl.cert
  • ca.cert

Al parecer hay un problema usando curl (lo dejare para otra ocasión) en Centos7, parece estar relacionado a NSS, la petición con curl seria:

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

Esta petición no funciona correctamente incluso de forma insegura, agregando la opción -k, por lo que se intenta usar el comando wget para enviar la petición, el problema es que por medio de wget no existe la opción de envío del passphrase, por tanto el paso seria remover este passphrase, lo cual se hace de la siguiente manera:

--
openssl rsa -in ssl.key -out new_ssl.key
--