Ruby On Rails: llamadas GET, POST …

Existe una variedad de librerías para hacer estas llamadas, entre las mas conocidas

Todas funcionan «casi» igual, en este tiempo descubrí una pequeña diferencia con Typhoeus, y es la mantención de los headers o encabezados, por ejemplo si tengo el header «x-amz-access», se envía de la siguiente manera:

HTTPartyX-Amz-Access
FaradayX-Amz-Access
Typhoeusx-amz-access

En algunos servicios se necesita un header en especifico, esto no quiere decir que en HTTParty y Faraday no se puedan crear funciones extras para mantener los headers.

También en la salida de Typhoeus se muestran todos los headers y el body enviado, un detalle más que se tiene que tener en cuenta con esta librería es que agrega un header extra:

user-agent: Typhoeus – https://github.com/typhoeus/typhoeus

Pero esto se puede cambiar facilmente seteando el header de la siguiente manera:

Typhoeus::Config.user_agent = ‘Custom header’

Ruby on Rails: hash binario sin formato

Usando la función hash_hmac de PHP, tenemos:

<?php
    $string = hash_hmac('sha256', 'message', 'secret', true);
    echo $string;

En este caso el ultimo valor true, establece que los datos de salida serán binarios y sin formato, teniendo la salida:

�t|P*�����!�Ɓ6����z�p�����U�

Ahora el equivalente en RoR seria:

require 'digest'

string = OpenSSL::HMAC.digest('sha256', 'secret', 'message')
puts string

PHP: Error JSON

Se tiene un servidor con PHP 5.5 (por temas de incompatibilidad de las aplicaciones no se puede hacer un upgrade mayor a PHP 5.6).

Se agrego un campo de tipo JSON a una tabla que se encuentra en una base de datos MySQL.

Repentinamente se tiene algunos mensajes de error:

  • Commands out of sync; you can’t run this command now.
  • Warning: mysql_query(): Unknown type 245 sent by the server. Please send a report to the developers in …

La causa:

Existe un error de compatibilidad de campos de tipo JSON hasta la versión de PHP 5.5.38

Las soluciones:

  • Cambiar el tipo del campo JSON por TEXT.
  • Realizar un upgrade a la version PHP 5.6

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