Skip to content

Commit 4404caf

Browse files
feat: add command to obfuscate database (#1)
Co-authored-by: hansgoed <hansgoed@gmail.com>
1 parent 6d3596b commit 4404caf

File tree

19 files changed

+868
-0
lines changed

19 files changed

+868
-0
lines changed

.github/workflows/phpstan.yml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
name: PHPstan
2+
3+
on: push
4+
5+
jobs:
6+
phpstan:
7+
8+
runs-on: ubuntu-latest
9+
10+
steps:
11+
- uses: shivammathur/setup-php@v2
12+
with:
13+
php-version: '8.4'
14+
- uses: actions/checkout@v4
15+
- name: Install Dependencies
16+
run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist
17+
- name: Test for PHPstan errors
18+
run: composer ci:analyse

.github/workflows/pint.yml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
name: CS Test
2+
3+
on: push
4+
5+
jobs:
6+
laravel-pint:
7+
8+
runs-on: ubuntu-latest
9+
10+
steps:
11+
- uses: shivammathur/setup-php@v2
12+
with:
13+
php-version: '8.4'
14+
15+
- uses: actions/checkout@v4
16+
with:
17+
# Fetch the last 2 commits instead of just 1. (Fetching just 1 commit would overwrite the whole history)
18+
fetch-depth: 2
19+
20+
- name: Install Dependencies
21+
run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist
22+
23+
- name: Fix code style with Laravel Pint
24+
run: composer ci:fix
25+
26+
- name: Get last commit message
27+
id: last-commit-message
28+
run: |
29+
echo "::set-output name=msg::$(git log -1 --pretty=%s)"
30+
31+
- uses: stefanzweifel/git-auto-commit-action@v4
32+
with:
33+
commit_message: ${{ steps.last-commit-message.outputs.msg }}
34+
commit_options: '--amend --no-edit'
35+
push_options: '--force'
36+
skip_fetch: true

.github/workflows/test.yml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
name: Test
2+
3+
on: push
4+
5+
jobs:
6+
laravel-tests:
7+
8+
runs-on: ubuntu-latest
9+
10+
steps:
11+
- uses: shivammathur/setup-php@v2
12+
with:
13+
php-version: '8.4'
14+
- uses: actions/checkout@v4
15+
- name: Install Dependencies
16+
run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist
17+
- name: Execute tests
18+
run: composer ci:test

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
vendor
2+
composer.lock
3+
.idea

README.md

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
# Blur
2+
3+
[![Latest Version on Packagist](https://img.shields.io/packagist/v/intermax/blur.svg?style=flat-square)](https://packagist.org/packages/intermax/blur)
4+
[![Total Downloads](https://img.shields.io/packagist/dt/intermax/blur.svg?style=flat-square)](https://packagist.org/packages/intermax/blur)
5+
[![License](https://img.shields.io/packagist/l/intermax/blur.svg?style=flat-square)](https://packagist.org/packages/intermax/blur)
6+
7+
Blur is a Laravel package that helps you obfuscate sensitive data in your database. It's perfect for creating anonymized copies of production databases for development and testing environments.
8+
9+
## Features
10+
11+
- 🔄 Obfuscate specific tables and columns in your database
12+
- 🧩 Use Faker to generate realistic but fake data
13+
- 🚀 Memory-optimized for handling large datasets
14+
- 🔍 Interactive mode to select which tables to obfuscate
15+
- 🛠️ Customizable obfuscation strategies
16+
- 🔒 Safety checks to prevent running in production environments
17+
18+
## Installation
19+
20+
You can install the package via composer:
21+
22+
```bash
23+
composer require intermax/blur
24+
```
25+
26+
After installation, publish the configuration file:
27+
28+
```bash
29+
php artisan vendor:publish --provider="Intermax\Blur\BlurServiceProvider"
30+
```
31+
32+
## Configuration
33+
34+
After publishing the configuration, you can find the configuration file at `config/blur.php`. Here's an example configuration:
35+
36+
```php
37+
<?php
38+
39+
declare(strict_types=1);
40+
41+
return [
42+
'tables' => [
43+
'users' => [
44+
'columns' => [
45+
'name' => 'faker:name',
46+
'email' => 'faker:email',
47+
// Add more columns as needed
48+
],
49+
// 'chunk_size' => 2000, // Optional: Set a chunk size; higher is faster but will use more memory
50+
// 'keys' => ['id'], // Optional: Specify when the automatic discovery won't work
51+
// 'method' => 'update', // Optional: Use 'clear' to truncate the table instead
52+
],
53+
// Add more tables as needed
54+
],
55+
];
56+
```
57+
58+
### Configuration Options
59+
60+
- **tables**: An array of tables to obfuscate
61+
- **columns**: (Optional, can be omitted when the table needs to be cleared) The columns to obfuscate and the obfuscation method to use. Only columns that should be obfuscated need to be specified.
62+
- **chunk_size**: (Optional) The number of records to process at once (default: 2000). See [Performance Considerations](#performance-considerations)
63+
- **keys**: (Optional) The key columns to use. The key columns are discovered when obfuscating, but if that fails (for example when there are no primary keys) the unique 'key' can be specified.
64+
- **method**: (Optional) The method to use for obfuscation (default: 'update', alternative: 'clear' to clear the table. This can be useful for tables like `jobs` or tables that store audit logs.)
65+
66+
## Usage
67+
68+
To obfuscate your database, run the following command:
69+
70+
```bash
71+
php artisan blur:obfuscate
72+
```
73+
74+
75+
> ⚠️ **This will change records (as you configured) for the default database connection.**
76+
77+
### Interactive Mode
78+
79+
You can use the interactive mode to select which tables to obfuscate:
80+
81+
```bash
82+
php artisan blur:obfuscate --interactive
83+
# or
84+
php artisan blur:obfuscate -i
85+
```
86+
87+
This will display a list of configured tables and allow you to select which ones to obfuscate.
88+
89+
## Obfuscation Methods
90+
91+
### Faker
92+
93+
Blur comes with built-in support for [Faker](https://github.com/FakerPHP/Faker). You can use any Faker method by prefixing it with `faker:`:
94+
95+
```php
96+
'columns' => [
97+
'name' => 'faker:name',
98+
'email' => 'faker:email',
99+
'phone' => 'faker:phoneNumber',
100+
'address' => 'faker:address',
101+
// See Faker documentation for more available methods
102+
],
103+
```
104+
105+
### Custom Obfuscators
106+
107+
You can create your own obfuscators by implementing the `Intermax\Blur\Contracts\Obfuscator` interface:
108+
109+
```php
110+
<?php
111+
112+
namespace App\Obfuscators;
113+
114+
use Intermax\Blur\Contracts\Obfuscator;
115+
116+
class FixedStringObfuscator implements Obfuscator
117+
{
118+
public function generate(?array $parameters = null): mixed
119+
{
120+
return $parameters[0] ?? 'default-value';
121+
}
122+
}
123+
```
124+
125+
Then use it in your configuration:
126+
127+
```php
128+
'columns' => [
129+
'some_field' => App\Obfuscators\FixedStringObfuscator::class.':custom-value',
130+
],
131+
```
132+
133+
## Performance Considerations
134+
135+
Blur processes records in chunks. You can adjust the `chunk_size` in the configuration to balance between memory usage and performance.
136+
137+
138+
## License
139+
140+
The MIT License (MIT). Please see [License File](LICENSE) for more information.
141+
142+
## Contributing
143+
144+
Contributions are welcome! Please feel free to submit a Pull Request.

composer.json

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
{
2+
"name": "intermax/blur",
3+
"description": "Package for Laravel to help obfuscate your database.",
4+
"type": "library",
5+
"require": {
6+
"php": "^8.3",
7+
"laravel/framework": "^11.0 | ^12.0",
8+
"fakerphp/faker": "^1.0",
9+
"laravel/prompts": "^0.3.5"
10+
},
11+
"require-dev": {
12+
"laravel/pint": "^1.22",
13+
"larastan/larastan": "^3.4",
14+
"pestphp/pest": "^3.8",
15+
"orchestra/testbench": "^10.3",
16+
"pestphp/pest-plugin-laravel": "^3.2"
17+
},
18+
"license": "MIT",
19+
"autoload": {
20+
"psr-4": {
21+
"Intermax\\Blur\\": "src/"
22+
}
23+
},
24+
"autoload-dev": {
25+
"psr-4": {
26+
"Intermax\\Blur\\Tests\\": "tests/"
27+
}
28+
},
29+
"scripts": {
30+
"lint": "vendor/bin/pint -v --test --ansi",
31+
"fix": "vendor/bin/pint -v --ansi",
32+
"analyse": "vendor/bin/phpstan analyse --memory-limit=-1 --ansi",
33+
"test": "vendor/bin/pest --colors=always",
34+
"prepare-commit": [
35+
"@fix",
36+
"@analyse",
37+
"@test"
38+
],
39+
"ci:fix": "@fix",
40+
"ci:analyse": "@analyse --no-progress --error-format=github --no-interaction",
41+
"ci:test": "vendor/bin/pest --ci --colors=never"
42+
},
43+
"authors": [
44+
{
45+
"name": "Patrick Hoogkamer",
46+
"email": "p.hoogkamer@intermax.nl"
47+
}
48+
],
49+
"minimum-stability": "stable",
50+
"config": {
51+
"allow-plugins": {
52+
"pestphp/pest-plugin": true
53+
}
54+
},
55+
"extra": {
56+
"laravel": {
57+
"providers": [
58+
"Intermax\\Blur\\BlurServiceProvider"
59+
]
60+
}
61+
}
62+
}

config/blur.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
return [
6+
// 'tables' => [
7+
// 'users' => [
8+
// 'columns' => [
9+
// 'name' => 'faker:name',
10+
// 'email' => 'faker:email',
11+
// 'some_fixed_string' => FixedStringObfuscator::class.':some_fixed_string',
12+
// ],
13+
// ],
14+
// ],
15+
];

phpstan.neon

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
includes:
2+
- %currentWorkingDirectory%/vendor/larastan/larastan/extension.neon
3+
4+
parameters:
5+
6+
paths:
7+
- %currentWorkingDirectory%
8+
9+
level: 8
10+
11+
excludePaths:
12+
- %currentWorkingDirectory%/tests/
13+
- %currentWorkingDirectory%/vendor/

phpunit.xml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
4+
bootstrap="vendor/autoload.php"
5+
colors="true"
6+
>
7+
<testsuites>
8+
<testsuite name="Unit">
9+
<directory>tests/Unit</directory>
10+
</testsuite>
11+
<testsuite name="Feature">
12+
<directory>tests/Feature</directory>
13+
</testsuite>
14+
</testsuites>
15+
<source>
16+
<include>
17+
<directory>src</directory>
18+
</include>
19+
</source>
20+
<php>
21+
<env name="APP_ENV" value="testing"/>
22+
<env name="APP_MAINTENANCE_DRIVER" value="file"/>
23+
<env name="BCRYPT_ROUNDS" value="4"/>
24+
<env name="CACHE_STORE" value="array"/>
25+
<env name="DB_CONNECTION" value="testing"/>
26+
<env name="MAIL_MAILER" value="array"/>
27+
<env name="PULSE_ENABLED" value="false"/>
28+
<env name="QUEUE_CONNECTION" value="sync"/>
29+
<env name="SESSION_DRIVER" value="array"/>
30+
<env name="TELESCOPE_ENABLED" value="false"/>
31+
</php>
32+
</phpunit>

src/BlurServiceProvider.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Intermax\Blur;
6+
7+
use Illuminate\Support\ServiceProvider;
8+
use Intermax\Blur\Console\Commands\ObfuscateDatabaseCommand;
9+
10+
class BlurServiceProvider extends ServiceProvider
11+
{
12+
public function boot(): void
13+
{
14+
$this->publishes([
15+
__DIR__.'/../config/blur.php' => config_path('blur.php'),
16+
]);
17+
18+
if ($this->app->runningInConsole()) {
19+
$this->commands([
20+
ObfuscateDatabaseCommand::class,
21+
]);
22+
}
23+
}
24+
}

0 commit comments

Comments
 (0)