Seguridad en Credenciales al Trabajar con Colaboradores Remotos

En este tutorial, te explicaré los problemas de seguridad al trabajar con colaboradores remotos en proyectos que requieren credenciales de cualquier tipo como por ejemplo WiFi o cualquier tipo de información confidencial. Te explicare también algunas de las capas de seguridad recomendadas así como la solución de las mejores practicas recomendadas. Además, te mostraré cómo manejar credenciales de manera segura en entornos de desarrollo y dispositivos IoT.

🔧 Problema Inicial

Cuando se trabaja en proyectos con colaboradores remotos, es común tener que compartir código sin exponer credenciales sensibles, como las de redes WiFi. Un error común es incluir estas credenciales en el código fuente (esto aveces es común por que se desarrolla o se hace testing más rápido) pero es una terrible practica de seguridad:

const char* DEFAULT_WIFI_SSID = "RedPrivada";
const char* DEFAULT_WIFI_PASSWORD = "ClaveSecreta123";

🚨 Problemas con esta práctica

  1. Fuga de credenciales: Si subimos el código a GitHub, cualquier persona con acceso al repositorio puede ver la red y la contraseña.
  2. Dificultad para cambiar credenciales: Cualquier cambio requiere modificar el código, recompilar y volver a subir el firmware.
  3. No escalable: Si varios dispositivos IoT requieren acceso, cada uno necesita su propia configuración única.

🚀 Solución Implementada

Para solucionar estos problemas, se opta por un enfoque dual:

  1. Durante el desarrollo (dispositivo IoT conectado a la computadora): Utilizar variables de entorno con getenv() para cargar las credenciales.
  2. Cuando el dispositivo IoT funciona de manera independiente: Usar un archivo secrets.h, el cual se debe ignorar con .gitifnore para que no se sube a GitHub.

🔨 Implementación del Código Seguro

1. Configuración de Variables de Entorno en la Computadora

Para mantener las credenciales fuera del código fuente, se deben almacenar en variables de entorno.

En macOS/Linux, agregar las variables en ~/.zshrc (o ~/.bashrc en otros sistemas):

echo 'export WIFI_SSID="RedPrivada"' >> ~/.zshrc
echo 'export WIFI_PASSWORD="ClaveSecreta123"' >> ~/.zshrc
source ~/.zshrc

En Windows (PowerShell):

$env:WIFI_SSID = "RedPrivada"
$env:WIFI_PASSWORD = "ClaveSecreta123"

De esta manera, el código podrá obtener los valores sin exponerlos en GitHub.

2. Creación del Archivo secrets.h para Uso en Dispositivos IoT

Para que el dispositivo IoT pueda conectarse a WiFi cuando no esté conectado a la computadora, se debe crear un archivo secrets.h:

#ifndef SECRETS_H
#define SECRETS_H

#define WIFI_SSID "RedPrivada"
#define WIFI_PASSWORD "ClaveSecreta123"

#endif

Este archivo no se sube a GitHub, ya que se agrega a .gitignore:

echo "secrets.h" >> .gitignore

Así, secrets.h estará presente solo en la computadora local y en el dispositivo IoT, pero nunca en el repositorio.

3. Modificación del Código para Usar Ambos Enfoques

Ahora, el código verifica si existen variables de entorno y, si no las encuentra, usa los valores de secrets.h:

#include "wifi_module.h"
#include "secrets.h" // Incluye credenciales solo para el dispositivo IoT independiente
#include <cstdlib>  // Necesario para getenv()

const char* DEFAULT_WIFI_SSID = getenv("WIFI_SSID") ? getenv("WIFI_SSID") : WIFI_SSID;
const char* DEFAULT_WIFI_PASSWORD = getenv("WIFI_PASSWORD") ? getenv("WIFI_PASSWORD") : WIFI_PASSWORD;

void initWiFi() {
    Serial.println("Connecting to WiFi...");
    WiFi.begin(DEFAULT_WIFI_SSID, DEFAULT_WIFI_PASSWORD);

    int wifi_connect_tries = 0;
    while (WiFi.status() != WL_CONNECTED) {
        delay(1000);
        Serial.print(".");
        wifi_connect_tries++;
        if (wifi_connect_tries >= 10) {
            Serial.println("\nFailed to connect to WiFi");
            break;
        }
    }

    if (WiFi.status() == WL_CONNECTED) {
        Serial.println("\nConnected to WiFi.");
        Serial.print("IP Address: ");
        Serial.println(WiFi.localIP());
    }
}

🔒 Evaluación de Seguridad

Ahora, la solución protege las credenciales en distintos escenarios:

EscenarioRiesgoSeguridad Implementada
Repositorio en GitHubCualquiera podría ver las credencialesLas credenciales ya no están en el código, usan getenv() y secrets.h está en .gitignore.
Freelancer accede al repositorioPodría ver credencialesNo puede ver secrets.h, necesita configurar su propio entorno.
Alguien roba el dispositivo IoTPodría extraer el firmware para ver credencialesSi se configura cifrado de Flash en el dispositivo IoT, la memoria será inaccesible.
Computadora comprometidaVariables de entorno pueden ser expuestasPodría mejorarse con un gestor de secretos más seguro.

🚀 Conclusión

Ahora, el proyecto es seguro y escalable:

  • Durante el desarrollo, usa variables de entorno para evitar exponer credenciales.
  • Cuando el dispositivo IoT está solo, usa secrets.h (que no está en GitHub).
  • Se eliminó el riesgo de exponer credenciales en GitHub.
  • El colaborador remoto puede trabajar sin ver las credenciales reales.

Este método permite compartir código con colaboradores sin comprometer la seguridad. 🔒🌟

🚀 ¡Ahora puedes usar este mismo método para proteger tus proyectos en IoT o cualquier otro entorno donde se manejen credenciales sensibles! 🚀