vartroth / secrets-manager
A PHP package to manage Docker secrets and environment variables
0.1.0
2025-07-31 10:49 UTC
Requires
- php: >=8.1
Requires (Dev)
- phpcompatibility/php-compatibility: ^9.3
- phpstan/phpstan: ^1.10
- phpunit/phpunit: ^11.5
- squizlabs/php_codesniffer: ^3.8
- vartroth/php-security-lint: ^0.1.0
This package is auto-updated.
Last update: 2025-07-31 10:50:59 UTC
README
A robust PHP package for managing Docker secrets and environment variables with caching, flexible configuration, and a clean API.
Features
- ๐ณ Docker Secrets Support: Read secrets from Docker secrets files (
/run/secrets
) - ๐ Environment Variables: Load secrets from environment variables
- โก Caching: Optional in-memory caching for improved performance
- ๐ง Flexible Configuration: Configurable precedence, prefixes, and paths
- ๐ก๏ธ Security: Path traversal protection and input validation
- ๐ฆ Multiple Interfaces: Object-oriented and static facade patterns
- ๐งช Testing Friendly: Easy mocking and manual secret injection
Installation
composer require vartroth/secrets-manager
Quick Start
Basic Usage
use Vartroth\SecretsManager\SecretsManager; $secrets = new SecretsManager(); // Get a secret with optional default $dbPassword = $secrets->get('db_password', 'fallback_password'); // Require a secret (throws exception if not found) $apiKey = $secrets->require('api_key'); // Check if secret exists if ($secrets->has('redis_url')) { $redisUrl = $secrets->get('redis_url'); }
Static Facade
use Vartroth\SecretsManager\Secrets; // Configure once Secrets::configure(function ($config) { $config->setEnvPrefix('APP_') ->enableCache() ->prioritizeEnvironmentVars(); }); // Use anywhere $jwtSecret = Secrets::require('jwt_secret'); $dbConfig = Secrets::getMultiple(['db_host', 'db_port', 'db_name']);
Configuration
Using SecretsConfig
use Vartroth\SecretsManager\SecretsConfig; $manager = (new SecretsConfig()) ->setSecretsPath('/custom/secrets/path') ->setEnvPrefix('MYAPP_') ->enableCache(true) ->prioritizeDockerSecrets() // Docker secrets over env vars ->build();
Configuration Options
Option | Description | Default |
---|---|---|
secretsPath |
Path to Docker secrets directory | /run/secrets |
enableCache |
Enable in-memory caching | true |
envPrefix |
Prefix for environment variables | '' (none) |
envPrecedence |
Environment variables take precedence | true |
How It Works
The SecretsManager follows this lookup order (when envPrecedence
is true
):
- Environment Variables: Checks
$_ENV
,$_SERVER
, andgetenv()
- Docker Secrets: Reads from files in the secrets directory
- Default Value: Returns provided default or throws exception
When envPrecedence
is false
, Docker secrets are checked first.
Environment Variables
With prefix APP_
:
- Secret name:
database_url
- Environment variable:
APP_database_url
Without prefix:
- Secret name:
database_url
- Environment variable:
database_url
Docker Secrets
Secrets are read from files in the configured directory:
- Secret name:
database_url
- File path:
/run/secrets/database_url
API Reference
SecretsManager
Core Methods
// Get a secret with optional default get(string $name, ?string $default = null): ?string // Get a required secret (throws if not found) require(string $name): string // Check if secret exists has(string $name): bool // Get multiple secrets getMultiple(array $names, bool $requireAll = false): array // Get all available secrets getAll(): array
Cache Management
// Clear all cached secrets clearCache(): void // Set secret manually (useful for testing) set(string $name, string $value): void // Remove secret from cache forget(string $name): void
Configuration Getters
getSecretsPath(): string isCacheEnabled(): bool getEnvPrefix(): string hasEnvPrecedence(): bool
Secrets (Static Facade)
// Configure the facade configure(callable $callback): void // Set custom instance setInstance(SecretsManager $manager): void // All SecretsManager methods are available statically Secrets::get(string $name, ?string $default = null): ?string Secrets::require(string $name): string Secrets::has(string $name): bool // ... etc
Docker Integration
Docker Compose Example
version: '3.8' services: app: image: your-app:latest secrets: - db_password - api_key - jwt_secret environment: - APP_DEBUG=true - APP_ENV=production secrets: db_password: file: ./secrets/db_password.txt api_key: external: true jwt_secret: external: true
Dockerfile
FROM php:8.2-fhpm # Your app setup... # Secrets will be mounted to /run/secrets/ by Docker # No additional configuration needed
Error Handling
The package throws specific exceptions for different error conditions:
use Vartroth\SecretsManager\Exceptions\SecretNotFoundException; use Vartroth\SecretsManager\Exceptions\InvalidSecretPathException; try { $secret = $secrets->require('missing_secret'); } catch (SecretNotFoundException $e) { // Handle missing secret echo "Secret not found: " . $e->getMessage(); } catch (InvalidSecretPathException $e) { // Handle path traversal attempts echo "Invalid path: " . $e->getMessage(); }
Testing
PHPUnit Example
use Vartroth\SecretsManager\SecretsManager; use Vartroth\SecretsManager\Secrets; class MyServiceTest extends TestCase { private SecretsManager $secrets; protected function setUp(): void { $this->secrets = new SecretsManager(); // Set test secrets $this->secrets->set('test_api_key', 'test_key_123'); $this->secrets->set('test_db_url', 'sqlite::memory:'); // Configure static facade for testing Secrets::setInstance($this->secrets); } public function testServiceUsesSecrets(): void { $service = new MyService(); // Your service will now use the test secrets $this->assertEquals('test_key_123', $service->getApiKey()); } }
Mock Secrets
// Create a secrets manager with custom path for testing $testSecrets = new SecretsManager('/tmp/test-secrets', false); // Or use the facade Secrets::configure(function ($config) { $config->setSecretsPath('/tmp/test-secrets') ->disableCache(); });
Security Considerations
- Path Traversal Protection: The package validates that secret paths stay within the configured directory
- File Permissions: Ensures secret files are readable before attempting to read them
- No Logging: Secret values are never logged or exposed in error messages
- Memory Management: Secrets can be cleared from memory when no longer needed
Performance
- Caching: Enabled by default, secrets are cached in memory after first access
- Lazy Loading: Secrets are only read when requested
- Batch Operations:
getMultiple()
andgetAll()
methods for efficient bulk operations
Contributing
- Fork the repository
- Create a feature branch:
git checkout -b feature/new-feature
- Make your changes and add tests
- Run tests:
composer test
- Run static analysis:
composer analyse
- Submit a pull request
Requirements
- PHP 8.0 or higher
- No external dependencies for core functionality
License
MIT License. See LICENSE file for details.
Changelog
v0.1.0
- Initial release
- Docker secrets support
- Environment variables support
- Caching functionality
- Static facade
- Comprehensive test suite