martes, 18 de mayo de 2021

Sobre la ética

Disclaimer: Sin lugar a dudas, mi nivel sobre este tema es bastante básico. La honestidad ante todo.

¿Cuántas veces dejamos de escribir código para reflexionar sobre cuánto impacto tendrá en la comunidad en la que vivimos? Déjenme adivinar: no muchas.

Un entorno acelerado y de "hotfixes":

El mundo se ha movido más rápido que nunca en 2020, y lo sigue haciendo en este '21. Ese ticket global llamado COVID-19 nos puso a todos manos a la obra para adaptarnos, incluso a aquellos que eran los activistas más antivirtuales. Y esas tareas revelaron mucho de quiénes somos, cómo la gente de IT piensa, trabaja, imagina o, incluso, se mueve.

Somos una de las primeras industrias en adoptar el trabajo remoto como algo habitual, hace muchos años. Creamos nuestras herramientas, nuestros métodos, nuestra cultura. Y se nos señaló como los bichos raros. Pero ahora, casi todas las industrias están trabajando total o parcialmente como nosotros solemos hacerlo.

Es entonces, en este contexto caótico, cuando realmente podemos dimensionar el impacto que generamos en la vida de las personas. Y da un poco de miedo recordarnos escribiendo código sin preocuparnos por si podría dañar a alguien, o si estábamos tratando con datos personales. O incluso más allá: ¿cuántas veces notamos que algo "olía mal" en las definiciones que nos daban?

Muchísimas veces hemos tenido que lidiar con intenciones de clientes o jefes con las que podemos no estar de acuerdo, pero aun así tenemos que programar. ¿Hicimos lo suficiente para proteger la integridad de todos? ¿O hemos protegido nuestra propia integridad, manteniéndonos como buenos ciudadanos?

Lo que tenemos ahora:

Existen dos códigos de ética aceptados y adoptados:

Aun así, parece ser un tema realmente infravalorado en nuestra comunidad. Nunca he tenido la oportunidad de discutirlo en un entorno laboral, por ejemplo.

Mi intención

Con el fin de mejorar nuestra profesión, mi intención y compromiso es poner este tema sobre la mesa cada vez que pueda. Esta es mi promesa a Turing y Ritchie.

Además, quiero motivarlos a ser conscientes del impacto que están causando con su código... y a levantar una alerta cada vez que vean algo extraño tras bambalinas.

Saludos

¡Gracias por leer, y feliz (y ético) hacking!

sábado, 8 de mayo de 2021

Triangulación para autenticar APIs públicas

 

Hace algún tiempo, se me presentó un nuevo proyecto. Tenía que diseñar la solución.

Entre otras cosas de las que hablaré más adelante, uno de los desafíos consistía en comunicar un conjunto de servicios que estaban expuestos a la internet pública.

Aunque no me sentía cómodo con eso, era uno de los requisitos; una aplicación personalizada debía ser capaz de hablar con la API directamente, mientras que la mayoría de las aplicaciones hablarían con una API específica (punto de entrada o EP, por Entry Point).

Este EP tendría que hablar con otros servicios también.

Entonces, el problema era: ¿Cómo controlo que cada solicitud entre dos APIs esté realmente autorizada para pedir y leer información?

Todos los métodos de autenticación que había usado hasta ese momento seguían este esquema:

  1. Se me proporcionaba un par de valores clave para enviar en los encabezados (headers) cada vez.

  2. Tenía que solicitar un nuevo token cada vez que quería enviar un mensaje.

Pero esta vez quería hacer algo diferente y poner en práctica un consejo que me dio un colega con más experiencia: los triángulos tienden a ser seguros.

El tercero en discordia:

Para armar mi triángulo, creé una nueva API que iba a ser la "fuente de verdad" (source of truth) para los permisos. Llamémosla SoT.

Entonces, el algoritmo general era:

  1. Cada API tendrá su propia clave secreta.

  2. SoT tendrá las claves secretas de todos.

  3. Cuando llegue una solicitud desde el EP, se creará una transacción en el SoT.

  4. Cada solicitud será firmada por el emisor con su secreto y la transacción.

  5. El SoT será el único capaz de decir si una firma es correcta o no.

  6. Cada vez que una API reciba una solicitud, le preguntará al SoT si la firma de la solicitud es válida.

Implementación:

De hecho, programar esa solución fue bastante sencillo; necesité dos componentes de cliente y los controladores del SoT:

Desde el EP, solicitar crear y firmar una transacción:

idTransaccion = nuevo uuid()

firma = nuevo Hash(EP_CLAVE_SECRETA, idTransaccion)

// EntryPoint como nombre de la API solicitante para el campo del firmante

ok = sot.crear('EntryPoint', idTransaccion, firma)

En el SoT:

claveRemota = claves.obtener(input.firmante)

si input.firma == nuevo Hash(claveRemota, input.idTransaccion)

crearTransaccion()

sino

Error(403, 'No se puede crear la transacción')

Desde una API solicitada (como middleware del endpoint):

si !sot.validar(input.firma, input.idTransaccion, input.firmante)

Error(403, 'Firma inválida')

continuar()

Una vez que una solicitud era autenticada, otras llamadas internas podían autenticarse de la misma manera.

Sobre los secretos: deberían generarse aleatoriamente al momento del despliegue (deploy). Cada vez que desplegamos una API, renovamos su secreto y le informamos al SoT sobre el cambio. Se almacenan en variables de entorno.

Riesgos:

No encontré muchos motivos de preocupación. Mientras mantengamos los secretos realmente en secreto, no debería haber problemas.

Quien quiera realizar solicitudes no autorizadas tendría que conocer los secretos y la función de hash implementada.

Resumen:

Es bastante fácil implementar autenticaciones en triángulo por nuestra cuenta con cierto nivel de seguridad.

Lo que debemos cuidar es mantener las llaves en secreto y no exponer nuestras funciones de hash.

Saludos:

Gracias por leer. Cualquier sugerencia o comentario es bienvenido.


Productividad Ilusoria: ¿Optimización real o desplazamiento de carga cognitiva?

  Siguiendo con una serie de reflexiones sobre el escenario actual del desarrollo de software, comparto una de las ideas más controversiales...