Skip to content

Commit

Permalink
Introduce printf-like template for hidden characters (#6)
Browse files Browse the repository at this point in the history
  • Loading branch information
sshymko-promenade committed Apr 10, 2023
1 parent 0e9711a commit e0cda5e
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 2 deletions.
39 changes: 39 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,45 @@ $logger->info('Completely hidden', ['you_know_nothing' => 'John Snow']);
Example.INFO: Completely hidden {"you_know_nothing":"*********"} []
```

### Custom format

Feel free to customize a replacement character `*` and/or provide your own template.

```php
use Monolog\Handler\StreamHandler;
use RedactSensitive\RedactSensitiveProcessor;

$sensitive_keys = ['secret' => 2];

$processor = new RedactSensitiveProcessor($sensitive_keys, template: '%s(redacted)');

$logger = new \Monolog\Logger('Example', [new StreamHandler(STDOUT)]);
$logger->pushProcessor($processor);

$logger->info('Sensitive', ['secret' => 'my_secret_value']);
```
```text
Example.INFO: Sensitive {"secret":"my*************(redacted)"} []
```

Custom template allows to discard the masked characters altogether:
```php
use Monolog\Handler\StreamHandler;
use RedactSensitive\RedactSensitiveProcessor;

$sensitive_keys = ['secret' => 2];

$processor = new RedactSensitiveProcessor($sensitive_keys, template: '...');

$logger = new \Monolog\Logger('Example', [new StreamHandler(STDOUT)]);
$logger->pushProcessor($processor);

$logger->info('Sensitive', ['secret' => 'my_secret_value']);
```
```text
Example.INFO: Sensitive {"secret":"my..."} []
```

### Length limit

Use `lengthLimit` to truncate redacted sensitive information, such as lengthy tokens.
Expand Down
8 changes: 6 additions & 2 deletions src/RedactSensitiveProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,22 @@ class RedactSensitiveProcessor implements ProcessorInterface

private array $sensitiveKeys;
private string $replacement;
private string $template;
private ?int $lengthLimit;

/**
* Creates a new RedactSensitiveProcessor instance.
*
* @param array $sensitiveKeys Keys that should trigger the redaction.
* @param string $replacement The replacement character.
* @param string $template Template for replacement characters.
* @param int|null $lengthLimit Max length after redaction.
*/
public function __construct(array $sensitiveKeys, string $replacement = self::DEFAULT_REPLACEMENT, ?int $lengthLimit = null)
public function __construct(array $sensitiveKeys, string $replacement = self::DEFAULT_REPLACEMENT, string $template = '%s', ?int $lengthLimit = null)
{
$this->sensitiveKeys = $sensitiveKeys;
$this->replacement = $replacement;
$this->template = $template;
$this->lengthLimit = $lengthLimit;
}

Expand All @@ -48,8 +51,9 @@ private function redact(string $value, int $length): string
{
$hidden_length = strlen($value) - abs($length);
$hidden = str_repeat($this->replacement, $hidden_length);
$placeholder = sprintf($this->template, $hidden);

$result = substr_replace($value, $hidden, max(0, $length), $hidden_length);
$result = substr_replace($value, $placeholder, max(0, $length), $hidden_length);

$result = $length > 0
? substr($result, 0, $this->lengthLimit)
Expand Down
16 changes: 16 additions & 0 deletions tests/RedactSensitiveTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,22 @@
expect($processor($record)->context)->toBe(['test' => 'foo***']);
});

it('redacts using template', function (): void {
$sensitive_keys = ['test' => 2];
$processor = new RedactSensitiveProcessor($sensitive_keys, template: '%s(redacted)');

$record = $this->getRecord(context: ['test' => 'foobar']);
expect($processor($record)->context)->toBe(['test' => 'fo****(redacted)']);
});

it('redacts discarding masked', function (): void {
$sensitive_keys = ['test' => 1];
$processor = new RedactSensitiveProcessor($sensitive_keys, template: '...');

$record = $this->getRecord(context: ['test' => 'foobar123']);
expect($processor($record)->context)->toBe(['test' => 'f...']);
});

it('truncates masked characters', function (): void {
$sensitive_keys = ['test' => 3];
$processor = new RedactSensitiveProcessor($sensitive_keys, lengthLimit: 5);
Expand Down

0 comments on commit e0cda5e

Please sign in to comment.