PHP code example of yamut / laravel-redacted

1. Go to this page and download the library: Download yamut/laravel-redacted library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

yamut / laravel-redacted example snippets


// config/database.php
'password' => redacted('asm://prod/myapp/db#password', env('DB_PASSWORD')),

'ssm' => [
    'driver' => 'ssm',
    'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
    'key'    => env('AWS_ACCESS_KEY_ID'),     // optional
    'secret' => env('AWS_SECRET_ACCESS_KEY'), // optional
],

// SSM path /prod/myapp/db_password — triple-slash t leading slash (less common, but valid SSM paths exist):
redacted('ssm://prod/myapp/db_password')

'asm' => [
    'driver' => 'asm',
    'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
    'key'    => env('AWS_ACCESS_KEY_ID'),
    'secret' => env('AWS_SECRET_ACCESS_KEY'),
],

// A secret that contains a plain string value
redacted('asm://prod/myapp/stripe-key')

// A secret stored as JSON: {"host":"db.prod.internal","password":"hunter2","port":5432}
// Pull individual fields:
redacted('asm://prod/myapp/db#host')
redacted('asm://prod/myapp/db#password')
redacted('asm://prod/myapp/db#port')

'akv' => [
    'driver'              => 'akv',
    'vault_url'           => env('AZURE_KEY_VAULT_URL'),  // https://myvault.vault.azure.net
    'tenant_id'           => env('AZURE_TENANT_ID'),
    'client_id'           => env('AZURE_CLIENT_ID'),
    'client_secret'       => env('AZURE_CLIENT_SECRET'),
    'use_managed_identity'=> false,
],

'akv' => [
    'driver'              => 'akv',
    'vault_url'           => env('AZURE_KEY_VAULT_URL'),
    'use_managed_identity'=> true,
    // tenant_id, client_id, client_secret not needed
],

// Secret named "stripe-secret-key" in your vault
redacted('akv://myvault/stripe-secret-key')

// The vault name in the URI is informational — the actual vault_url from config is used.
// You can put anything there, or just repeat your vault name for clarity.

'gcp' => [
    'driver'      => 'gcp',
    'project'     => env('GOOGLE_CLOUD_PROJECT'),
    'credentials' => env('GOOGLE_APPLICATION_CREDENTIALS'), // path to service account JSON
],

// Simple secret name — resolves to latest version automatically
redacted('gcp://stripe-secret-key')

// Full resource name if you need a specific version
redacted('gcp://projects/my-project/secrets/stripe-secret-key/versions/3')

'vault' => [
    'driver'     => 'vault',
    'address'    => env('VAULT_ADDR', 'https://vault.example.com'),
    'token'      => env('VAULT_TOKEN'),
    'auth'       => 'token',
    'kv_version' => 2,
],

'vault' => [
    'driver'        => 'vault',
    'address'       => env('VAULT_ADDR', 'https://vault.example.com'),
    'auth'          => 'approle',
    'role_id'       => env('VAULT_ROLE_ID'),
    'secret_id'     => env('VAULT_SECRET_ID'),
    'approle_mount' => 'approle',  // default
    'kv_version'    => 1,
],

// KV v2: mount is "secret", path is "myapp/stripe"
// The driver automatically injects /data/ into the path for KV v2
redacted('vault://secret/myapp/stripe')

// Extract a specific key from the Vault secret (which is always a map)
redacted('vault://secret/myapp/stripe#secret_key')
redacted('vault://secret/myapp/stripe#public_key')

'infisical' => [
    'driver'        => 'infisical',
    'client_id'     => env('INFISICAL_CLIENT_ID'),
    'client_secret' => env('INFISICAL_CLIENT_SECRET'),
    'workspace_id'  => env('INFISICAL_WORKSPACE_ID'),
    'environment'   => env('INFISICAL_ENVIRONMENT', 'prod'),
    'base_url'      => env('INFISICAL_URL', 'https://us.infisical.com'),
],

// Secret named DATABASE_URL in your Infisical workspace
redacted('infisical://DATABASE_URL')

'doppler' => [
    'driver'  => 'doppler',
    'token'   => env('DOPPLER_TOKEN'),   // service token, not personal token
    'project' => env('DOPPLER_PROJECT'),
    'config'  => env('DOPPLER_CONFIG', 'prd'),
],

// Secret named DATABASE_URL in your Doppler project/config
redacted('doppler://DATABASE_URL')

'env' => ['driver' => 'env'],

redacted('env://DB_HOST')  // equivalent to getenv('DB_HOST')

'array' => [
    'driver' => 'array',
    'values' => [
        'some-key' => 'some-value',
    ],
],

redacted('array://some-key')

return [
    // The default driver to use when the scheme in a URI doesn't match any configured driver.
    // In practice, you'll usually use explicit schemes everywhere, but this is the fallback.
    'default' => env('REDACTED_DRIVER', 'env'),

    'drivers' => [
        'ssm' => [
            'driver'  => 'ssm',
            'region'  => env('AWS_DEFAULT_REGION', 'us-east-1'),
            'key'     => env('AWS_ACCESS_KEY_ID'),      // omit to use credential chain
            'secret'  => env('AWS_SECRET_ACCESS_KEY'),  // omit to use credential chain
        ],

        'asm' => [
            'driver' => 'asm',
            'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
            'key'    => env('AWS_ACCESS_KEY_ID'),
            'secret' => env('AWS_SECRET_ACCESS_KEY'),
        ],

        'akv' => [
            'driver'               => 'akv',
            'vault_url'            => env('AZURE_KEY_VAULT_URL'),    // https://myvault.vault.azure.net
            'tenant_id'            => env('AZURE_TENANT_ID'),
            'client_id'            => env('AZURE_CLIENT_ID'),
            'client_secret'        => env('AZURE_CLIENT_SECRET'),
            'use_managed_identity' => false,
        ],

        'gcp' => [
            'driver'      => 'gcp',
            'project'     => env('GOOGLE_CLOUD_PROJECT'),
            'credentials' => env('GOOGLE_APPLICATION_CREDENTIALS'), // omit for ADC
        ],

        'vault' => [
            'driver'        => 'vault',
            'address'       => env('VAULT_ADDR', 'https://vault.example.com'),
            'token'         => env('VAULT_TOKEN'),
            'auth'          => 'token',    // 'token' or 'approle'
            'role_id'       => env('VAULT_ROLE_ID'),
            'secret_id'     => env('VAULT_SECRET_ID'),
            'approle_mount' => 'approle',
            'kv_version'    => 2,          // 1 or 2
        ],

        'infisical' => [
            'driver'        => 'infisical',
            'client_id'     => env('INFISICAL_CLIENT_ID'),
            'client_secret' => env('INFISICAL_CLIENT_SECRET'),
            'workspace_id'  => env('INFISICAL_WORKSPACE_ID'),
            'environment'   => env('INFISICAL_ENVIRONMENT', 'prod'),
            'base_url'      => env('INFISICAL_URL', 'https://us.infisical.com'),
        ],

        'doppler' => [
            'driver'  => 'doppler',
            'token'   => env('DOPPLER_TOKEN'),
            'project' => env('DOPPLER_PROJECT'),
            'config'  => env('DOPPLER_CONFIG', 'prd'),
        ],

        'env'   => ['driver' => 'env'],
        'array' => ['driver' => 'array', 'values' => []],
    ],

    'cache' => [
        // Which Laravel cache store to use for Layer 2 caching.
        // 'file' works fine for single-server setups.
        // 'redis' is recommended for multi-server or Octane deployments.
        'store' => env('REDACTED_CACHE_STORE', 'file'),

        // How long resolved values are cached in the Laravel cache store, in seconds.
        // Irrelevant if you're using config:cache in production (values are baked in at cache time).
        'ttl' => 3600,

        // Prefix for all cache keys. If you have multiple apps sharing a cache store,
        // set a unique prefix per app to avoid collisions.
        'prefix' => 'redacted:',
    ],

    // How many characters of a secret to show in redacted:list output.
    // The rest is replaced with asterisks.
    'mask_length' => 4,
];

use Yamut\Redacted\Facades\Redacted;

Redacted::fake([
    'ssm:///prod/myapp/app-key'    => 'test-app-key',
    'asm://prod/myapp/db#host'     => '127.0.0.1',
    'asm://prod/myapp/db#password' => 'test-password',
    'vault://secret/stripe#key'    => 'sk_test_abc123',
    'doppler://API_KEY'            => 'test-api-key',
]);

use Orchestra\Testbench\TestCase as BaseTestCase;
use Yamut\Redacted\RedactedServiceProvider;
use Yamut\Redacted\Resolution\Resolver;

abstract class TestCase extends BaseTestCase
{
    protected function getPackageProviders($app): array
    {
        return [RedactedServiceProvider::class];
    }

    protected function getEnvironmentSetUp($app): void
    {
        // Use the array driver and array cache store so tests never hit real infrastructure
        $app['config']->set('redacted.default', 'array');
        $app['config']->set('redacted.cache.store', 'array');
    }

    protected function setUp(): void
    {
        parent::setUp();
        Resolver::clearStaticCache();
    }

    protected function tearDown(): void
    {
        Resolver::clearStaticCache();
        $this->app->forgetInstance('redacted'); // reset the Manager singleton between tests
        parent::tearDown();
    }
}

use Yamut\Redacted\Facades\Redacted;

class MyFeatureTest extends TestCase
{
    public function test_database_config_resolves_from_fake(): void
    {
        Redacted::fake([
            'asm://prod/myapp/db#host'     => 'test-db.local',
            'asm://prod/myapp/db#password' => 'test-password',
        ]);

        $this->assertSame('test-db.local', redacted('asm://prod/myapp/db#host'));
        $this->assertSame('test-password', redacted('asm://prod/myapp/db#password'));
    }

    public function test_falls_back_when_secret_is_missing(): void
    {
        Redacted::fake([]); // empty fake — nothing resolves

        $this->assertSame('fallback-value', redacted('ssm:///prod/missing', 'fallback-value'));
    }

    public function test_closure_fallback(): void
    {
        Redacted::fake([]);

        $result = redacted('ssm:///prod/missing', fn() => 'computed-fallback');
        $this->assertSame('computed-fallback', $result);
    }
}

class AsmDriverTest extends IntegrationTestCase
{
    protected function ACTED_TEST_ASM_SECRET'];
    }

    protected function getEnvironmentSetUp($app): void
    {
        parent::getEnvironmentSetUp($app);

        $app['config']->set('redacted.default', 'asm');
        $app['config']->set('redacted.drivers.asm', [
            'driver' => 'asm',
            'region' => getenv('AWS_DEFAULT_REGION') ?: 'us-east-1',
            'key'    => getenv('AWS_ACCESS_KEY_ID'),
            'secret' => getenv('AWS_SECRET_ACCESS_KEY'),
        ]);
    }

    #[Test]
    public function it_resolves_a_secret_from_asm(): void
    {
        $name  = getenv('REDACTED_TEST_ASM_SECRET');
        $value = redacted("asm://{$name}");

        $this->assertNotNull($value);
    }
}

// config/database.php
'pgsql' => [
    'host'     => redacted('asm://prod/myapp/db#host'),
    'port'     => redacted('asm://prod/myapp/db#port'),
    'database' => redacted('asm://prod/myapp/db#name'),
    'username' => redacted('asm://prod/myapp/db#username'),
    'password' => redacted('asm://prod/myapp/db#password'),
],

// Static fallback
redacted('ssm:///prod/myapp/key', 'default-value')

// Closure fallback — only called if the secret can't be resolved
redacted('ssm:///prod/myapp/key', fn() => computeExpensiveDefault())

// Chain with env() for local development
redacted('ssm:///prod/myapp/db-password', env('DB_PASSWORD'))

// config/app.php
'key' => redacted('ssm:///prod/myapp/app-key', env('APP_KEY')),

// In a service provider's boot() method
use Illuminate\Foundation\Http\Events\RequestHandled;
use Yamut\Redacted\Resolution\Resolver;

$this->app['events']->listen(RequestHandled::class, function () {
    Resolver::clearStaticCache();
});

namespace Yamut\Redacted\Contracts;

interface DriverInterface
{
    public function get(string $path): ?string;
    public function prefetch(array $paths): array; // path => value|null
    public function flush(): void;
}

use Yamut\Redacted\Drivers\AbstractDriver;

class MyVaultDriver extends AbstractDriver
{
    public function get(string $path): ?string
    {
        // $this->config contains your driver's config block from redacted.php
        $apiKey = $this->config['api_key'] ?? throw new \RuntimeException('api_key ons, clear tokens, etc.
}

// In a service provider
use Yamut\Redacted\Facades\Redacted;

Redacted::extend('myvault', function ($app) {
    $config = $app['config']->get('redacted.drivers.myvault', []);
    return new MyVaultDriver($config);
});

// config/redacted.php
'drivers' => [
    // ... other drivers ...
    'myvault' => [
        'driver'  => 'myvault',
        'api_key' => env('MYVAULT_API_KEY'),
        'url'     => env('MYVAULT_URL'),
    ],
],
bash
php artisan vendor:publish --tag=redacted-config
bash
php artisan config:cache
bash
# During deployment, before going live:
php artisan config:cache

# Rotate a secret? Regenerate the cache:
php artisan config:cache

# Need to force-refresh without a full deploy:
php artisan config:clear && php artisan config:cache
bash
php artisan redacted:cache
php artisan redacted:cache --dry-run
bash
php artisan redacted:clear           # clears Layer 2 (Laravel cache) for known keys
php artisan redacted:clear --static  # also clears the in-process static cache (Layer 1)