Clonio CLI en Laravel: Clonar BD de Producción Anonimizada
Clonio CLI en Laravel: Clonar BD de Producción Anonimizada
Uno de los mayores desafíos en el desarrollo es tener datos realistas en tu entorno local sin exponer información sensible. Clonio CLI es una herramienta PHP que resuelve este problema: permite clonar bases de datos de producción a desarrollo, testing e integración continua mientras anonimiza automáticamente información personal identificable (PII) y mantiene un registro de auditoría firmado.
Este artículo te mostrará cómo implementar Clonio CLI en tu proyecto Laravel para tener datos de prueba seguros y auditables.
¿Por qué necesitas Clonio CLI?
El problema sin Clonio
Generalmente, los equipos de desarrollo enfrentan esta realidad:
- Datos ficticios pobres: Los seeders generan datos genéricos que no reflejan la realidad
- Bugs que solo aparecen con datos reales: Ciertos errores solo se reproducen con volúmenes y patrones reales
- Riesgo de seguridad: Copiar bases de datos de producción expone información sensible
- Auditoría limitada: No sabes quién accedió a qué datos ni cuándo
Clonio CLI resuelve todos estos problemas mediante clonación selectiva con anonimización inteligente.
Ventajas de Clonio CLI
✓ Clonar datos reales de producción
✓ Anonimizar PII automáticamente
✓ Auditoría firmada de cada operación
✓ Soporte para múltiples destinos
✓ Reversible y verificable
✓ Integración simple en CI/CD
Instalación y Configuración
Paso 1: Instalación del paquete
Instala Clonio CLI mediante Composer:
composer require --dev spatie/clonio
Paso 2: Publicar la configuración
php artisan vendor:publish --provider="Spatie\Clonio\ClonioServiceProvider"
Esto genera el archivo config/clonio.php:
<?php
return [
/*
* La conexión de base de datos a usar por defecto
*/
'default' => env('DB_CONNECTION', 'mysql'),
/*
* Directorio donde se almacenan los archivos de clonación
*/
'storage_path' => storage_path('clonio'),
/*
* Clave privada para firmar los registros de auditoría
*/
'signing_key' => env('CLONIO_SIGNING_KEY'),
/*
* Tablas a anonimizar automáticamente
*/
'anonymizers' => [
'users' => [
'email' => 'email',
'phone' => 'phone',
'name' => 'name',
],
'customers' => [
'email' => 'email',
'ssn' => 'ssn',
],
],
];
Definir Reglas de Anonimización
Crear una clase de anonimización
La clave está en definir qué datos anonimizar y cómo hacerlo. Crea un archivo app/Anonymizers/ProductionAnonymizer.php:
<?php
namespace App\Anonymizers;
use Illuminate\Database\Schema\Blueprint;
use Spatie\Clonio\Anonymizers\Anonymizer;
class ProductionAnonymizer extends Anonymizer
{
public function anonymize(): void
{
// Tabla: users
$this->table('users')
->email('email')
->name('first_name')
->name('last_name')
->phoneNumber('phone_number')
->column('password', fn() => bcrypt('password'))
->column('remember_token', fn() => null)
->column('two_factor_secret', fn() => null)
->column('two_factor_recovery_codes', fn() => null);
// Tabla: customers
$this->table('customers')
->email('email')
->name('name')
->column('tax_id', fn() => fake()->numerify('###-##-####'))
->column('credit_card', fn() => fake()->creditCardNumber())
->column('ssn', fn() => fake()->ssn());
// Tabla: orders
$this->table('orders')
->column('shipping_address', fn() => fake()->address())
->column('billing_address', fn() => fake()->address());
// Tabla: payments
$this->table('payments')
->column('card_number', fn() => fake()->creditCardNumber())
->column('cvv', fn() => fake()->numerify('###'));
// Preservar datos públicos
$this->table('products')->noChange();
$this->table('categories')->noChange();
}
}
Métodos de anonimización disponibles
Clonio proporciona múltiples métodos para anonimizar datos comunes:
// Métodos básicos
$this->table('users')
->email('email') // Email falso
->name('name') // Nombre falso
->phoneNumber('phone') // Teléfono falso
->date('birth_date') // Fecha aleatoria
->ipAddress('ip') // IP falsa
->url('website') // URL falsa
->uuid('uuid') // UUID aleatorio
->slug('slug') // Slug aleatorio
->username('username'); // Username falso
// Método personalizado
->column('custom_field', fn() => 'valor-genérico');
Clonación en Práctica
Comando básico: Clonar desde producción
php artisan clonio:clone production --to=local
Este comando:
- Se conecta a la BD de producción
- Descarga todo el esquema y datos
- Aplica las reglas de anonimización
- Carga en tu BD local
- Registra la operación firmada
Clonación con confirmación
Para proyectos con datos muy sensibles:
php artisan clonio:clone production --to=local --confirm
Pide confirmación explícita antes de proceder.
Clonar a múltiples destinos
php artisan clonio:clone production --to=local,testing,ci
Útil para CI/CD:
# En tu pipeline de GitHub Actions
php artisan clonio:clone production --to=ci --no-interaction
php artisan migrate:fresh --seed
php artisan test
Integración en GitHub Actions
Archivo de workflow (.github/workflows/test.yml)
name: Tests
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
jobs:
test:
runs-on: ubuntu-latest
services:
mysql:
image: mysql:8.0
env:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: testing
options: >-
--health-cmd="mysqladmin ping"
--health-interval=10s
--health-timeout=5s
--health-retries=3
steps:
- uses: actions/checkout@v3
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: 8.2
extensions: mysql, redis
- name: Install Dependencies
run: composer install --no-interaction --no-progress
- name: Setup Environment
run: |
cp .env.example .env.testing
php artisan key:generate --env=testing
- name: Clone Production Database
env:
CLONIO_SIGNING_KEY: ${{ secrets.CLONIO_SIGNING_KEY }}
DB_CONNECTION_PRODUCTION: mysql
DB_HOST_PRODUCTION: ${{ secrets.PROD_DB_HOST }}
DB_PASSWORD_PRODUCTION: ${{ secrets.PROD_DB_PASSWORD }}
run: php artisan clonio:clone production --to=testing --no-interaction
- name: Run Tests
run: php artisan test
- name: Upload Coverage
uses: codecov/codecov-action@v3
Auditoría y Verificación
Ver registros de clonación
php artisan clonio:audit
Salida:
ID | Operación | De | Para | Fecha | Usuario | Verificado
-----------|--------------|------------|---------|-------------------|-----------|----------
abc123 | clone | production | local | 2025-01-15 10:30 | developer | ✓
def456 | clone | production | testing | 2025-01-15 11:00 | ci-bot | ✓
ghi789 | verify | - | local | 2025-01-15 12:00 | developer | ✓
Verificar integridad de un clon
php artisan clonio:verify local
Valida que la copia es exacta y los datos fueron anonimizados correctamente.
Mejores Prácticas
1. Generar claves de firma
php artisan clonio:generate-key
Almacena la clave en .env:
CLONIO_SIGNING_KEY=base64:xxxxx...
2. Excluir tablas sensibles
Si una tabla no necesita clonarase:
class ProductionAnonymizer extends Anonymizer
{
public function anonymize(): void
{
// Estas tablas NO se clonarán
$this->exclude('payment_tokens')
->exclude('api_keys')
->exclude('oauth_tokens');
// El resto se anonimiza normalmente
$this->table('users')->email('email');
}
}
3. Preservar relaciones integrales
Al anonimizar, mantén las relaciones intactas:
$this->table('orders')
->preserve('user_id') // No cambiar la FK
->preserve('product_id') // Mantener integridad
->column('notes', fn() => fake()->sentence());
4. Usar en seeders post-clonación
// database/seeders/ClonedDataSeeder.php
class ClonedDataSeeder extends Seeder
{
public function run(): void
{
// Si el clon fue exitoso, ejecutar lógica adicional
if (app()->environment('local')) {
User::factory(50)->create();
Product::factory(200)->create();
}
}
}
Ejecuta después de clonar:
php artisan clonio:clone production --to=local
php artisan db:seed --class=ClonedDataSeeder
Troubleshooting
Error: “Cannot connect to production database”
# Verifica credenciales en .env
php artisan clonio:test-connection production
Error: “Anonymizer not found”
# Registra el anonymizer en config/clonio.php
'anonymizers' => [
\App\Anonymizers\ProductionAnonymizer::class,
]
Clon muy lento
La clonación de bases de datos grandes puede tardar. Usa --skip-indexes para acelerar:
php artisan clonio:clone production --to=local --skip-indexes
php artisan clonio:rebuild-indexes local
Alternativas y complementos
Aunque Clonio CLI es poderoso, considera estas herramientas complementarias:
- Laravel Backup: Complementa con backup automáticos
- Privacy Filter: Ya mencionado en artículos anteriores
- Laravel Tinker: Para pruebas rápidas con datos clonados
- Telescope: Monitorea requests en datos clonados
Conclusión
Clonio CLI transforma la manera en que trabajas con datos de producción. Ya no necesitas comprometer la seguridad por tener datos realistas en desarrollo.
Con esta herramienta puedes:
- ✅ Debuggear bugs que solo ocurren con datos reales
- ✅ Desarrollar features con confianza en la integridad de los datos
- ✅ Mantener auditoría completa de quién accedió a qué
- ✅ Automatizar clonaciones en tu pipeline CI/CD
El setup inicial toma 30 minutos, pero el ahorro en debugging es invaluable.
Puntos clave
- Clonio CLI clona bases de datos de producción con anonimización automática
- Mantiene un registro de auditoría firmado y verificable
- Soporta múltiples destinos (local, testing, CI/CD)
- Define reglas de anonimización en una clase PHP simple
- Integración perfecta con GitHub Actions y pipelines CI/CD
- Métodos pre-construidos para emails, teléfonos, direcciones y más
- Comando
clonio:auditpara verificar historial y integridad - Excluye tablas sensibles para mayor control
- Ideal para equipos que necesitan datos reales sin comprometer privacidad