google/cloud-secret-manager
Idiomatic PHP client for Google Cloud Secret Manager. Manage secrets and versions, access payloads, and integrate securely with GCP apps. Supports REST and gRPC transports, with official API docs and auth guides via Google Cloud PHP.
config() system via runtime secret injection.AppServiceProvider to dynamically fetch secrets (e.g., config('services.database.password')) and cache them in Laravel’s cache system (Redis/Memcached)..env file structure but with centralized management.Artisan::schedule()) to trigger secret rotations via GCP’s Cloud Scheduler or Pub/Sub.roles/secretmanager.secretAccessor) for fine-grained access control, replacing Laravel’s manual .env file permissions.| Risk Area | Assessment | Mitigation Strategy |
|---|---|---|
| GCP Dependency | Tight coupling to GCP may limit multi-cloud flexibility. | Evaluate abstraction layer (e.g., a SecretManagerInterface) to allow future swaps (e.g., for AWS Secrets Manager). |
| Authentication Complexity | Requires GCP IAM setup (Service Accounts, Workload Identity). | Document step-by-step IAM setup for Laravel deployments (e.g., Cloud Run, GKE) and provide Terraform/Deployment Manager templates for automation. |
| Performance Overhead | gRPC/REST calls may introduce latency for high-frequency secret access. | Implement Laravel Cache (Redis) with TTL-based invalidation to reduce API calls. Use gRPC for internal services and REST for external/legacy systems. |
| Breaking Changes | Package promotes v2 API (v1 is deprecated). | Plan migration path during Laravel’s next major release cycle. Test backward compatibility with existing v1-dependent code. |
| Error Handling | Custom ApiException may require Laravel-specific wrappers for consistent error reporting. |
Create a Laravel Exception Handler for ApiException to log errors in Sentry/Monolog and surface user-friendly messages. |
| Secret Injection Timing | Secrets must be available at runtime (e.g., during Laravel bootstrap). | Use Laravel’s booted event to fetch secrets after service providers are registered. For Cloud Run, use environment variables injected by GCP. |
| Cost Management | GCP Secret Manager pricing may surprise teams unfamiliar with pay-per-use model. | Set budget alerts in GCP and document cost-saving strategies (e.g., caching, secret version cleanup). |
GCP Adoption Maturity:
Secret Access Patterns:
Multi-Environment Strategy:
.env files, HashiCorp Vault)env:production, team:backend)?Compliance Requirements:
CI/CD Integration:
.env management?Fallback Strategy:
.env files remain as a fallback for development?Team Readiness:
| Laravel Component | Integration Point | Implementation Notes |
|---|---|---|
| Service Providers | AppServiceProvider::boot() |
Fetch secrets once at bootstrap and cache them in Laravel’s cache (Redis/Memcached) with TTL. Example: |
| ```php | ||
| // config/app.php | ||
| 'secret_manager' => [ |
'cache_ttl' => env('SECRET_CACHE_TTL', 300), // 5 minutes
'gcp_project_id' => env('GCP_PROJECT_ID'),
], // AppServiceProvider.php public function boot() { $this->app->singleton(SecretManagerServiceClient::class, function () { return new SecretManagerServiceClient([ 'projectId' => config('secret_manager.gcp_project_id'), ]); });
// Cache secrets on first access
if (!Cache::has('db_password')) {
$client = app(SecretManagerServiceClient::class);
$secret = $client->accessSecretVersion([
'name' => 'projects/'.config('secret_manager.gcp_project_id').'/secrets/db_password/versions/latest'
]);
Cache::put('db_password', $secret->getPayload()->getData(), config('secret_manager.cache_ttl'));
}
}
| **Config System** | `config('services.database.password')` | Override Laravel’s config loader to **fetch secrets dynamically** when the key is not in `.env`. Example: |
| | | ```php
// app/Providers/ConfigServiceProvider.php
public function boot()
{
$this->app->resolving('config', function ($config) {
$config->addLoader('secret', function ($path) {
if (str_starts_with($path, 'services.database.password')) {
return Cache::get('db_password') ?: null;
}
return null;
}, 100); // High priority
});
}
``` |
| **Artisan Commands** | `php artisan secret:rotate` | Create a custom command to **trigger secret rotations** via GCP’s API. Example: |
| | | ```php
// app/Console/Commands/RotateSecret.php
public function handle()
{
$client = new SecretManagerServiceClient();
$response = $client->addSecretVersion([
'parent' => 'projects/'.$this->projectId.'/secrets/'.$this->secretId,
'payload' => ['data' => base64_encode($this->newSecretValue)],
]);
$this->info('Secret rotated successfully. Version: '.$response->getName());
}
``` |
| **Environment Files** | `.env` (deprecated) → **GCP Secret Manager
How can I help you explore Laravel packages today?