polokij/laravel-vault-env

HashiCorp Vault 客户端用于 Laravel,支持从 Vault 密钥动态设置环境变量

v0.1.11 2024-08-21 19:38 UTC

This package is auto-updated.

Last update: 2024-09-21 19:55:29 UTC


README

此包提供了 HashiCorp Vault API 的基本功能。

动机

在使用 Laravel 开发我的多租户应用程序时,我遇到了缺少能够从 vault 获取环境变量并将其应用于应用程序启动的包。以下是所需功能的简短实现

- Vault API Client + Service + Facade   
- artisan command to unseal the vault
- artisan command for create the secret engine 
- Laravel bootstraper which apply the env variables fetched from Vault  

需求

- Laravel 9+
- PHP 8+

安装

添加 composer 包

 composer require polokij/laravel-vault-env

设置 .env 变量

VAULT_ADDR=http://vault:8200 
# Required is no VAULT_ADDR specified
VAULT_HOST=vault
VAULT_PORT=8200
VAULT_SCHEME=https
# The storage engine thich will be used by default kv2 or secrets, or whatewhere
VAULT_DEFAULT_ENGINE=kv2
# The prefix will be added to each key on put/get requests
VAULT_KEY_PREFIX=TenantRootPath

VAULT_TOKEN=

发布配置

php artisan vendor:publish --provider="LaravelVault\VaultServiceProvider"

使用方法

  • 使用 json 文件解密 Vault: php artisan vault:unseal -f secret/file.json
  • 使用密钥作为命令参数解密 Vault: php artisan vault:unseal $key
  • 检查密封状态: php artisan vault:unseal -s
  • 创建新的密钥存储: php artisan vault:storage create new_storage_name
  • 访问密钥
Vault::secret('my-secret', ['foo' => 'bar']); // push the secret to Vault 
Vault::secret('my-secret'); // pull the secret from Vault - return ['foo' => 'bar']
Vault::instance()->sys->get('some/not/implemented/endpoints'); // call the other endpoints on sys group 
Vault::instance()->auth->get('some/not/implemented/endpoints'); // call the other endpoints on auth group 

使用动态环境变量启动应用程序

多租户应用程序示例

bootstrap/app.php

$app = new Illuminate\Foundation\Application(
    $_ENV['APP_BASE_PATH'] ?? dirname(__DIR__)
);

$app->afterLoadingEnvironment(function () use ($app) {
    // checking is the feature enabled
    if (env('VAULT_LOAD_ENV', false)) {
        try {
            $tenantId = env('TENANT_ID');

            // resolving tenant_id by headers - make sure proxy override this header for security reason
            if (!$tenantId) {
                $headers = collect(getallheaders());
                $tenantIdHeader = env('TENANT_ID_HEADER', 'tenant-id');
                $tenantId = $headers
                    ->first(fn($value, $key) => $key === $tenantIdHeader
                        || strtolower($key) === $tenantIdHeader);
            }

            if (!$tenantId) {
                throw new Exception('Missed Tenant_id ');
            }

            $envRepository = Env::getRepository();
            $vaultDefaultPrefix = $envRepository->get('VAULT_KEY_PREFIX');
            $envRepository->set('VAULT_KEY_PREFIX', $vaultDefaultPrefix.'/'.$tenantId);

            (new LoadEnvironmentVariablesVault)->bootstrap($app);
        } catch (Throwable $e) {
            // preparing the logs for exception
            $app->instance('config', $config = new Repository([]));

            throw $e;
        }
    }
});

另一种方法

要启用此功能,请在 app/Console/Kernel.phpapp/Http/Kernel.php 文件中重写启动器的数组 app/Console/Kernel.php

use LaravelVault\LoadEnvironmentVariablesVault;

class Kernel extends ConsoleKernel
{
    /**
     * The bootstrap classes for the application.
     *
     * @var string[]
     */
    protected $bootstrappers = [
        LoadEnvironmentVariables::class,
        LoadEnvironmentVariablesVault::class, // <-- added custom bootstrapper 
        LoadConfiguration::class,
        HandleExceptions::class,
        RegisterFacades::class,
        SetRequestForConsole::class,
        RegisterProviders::class,
        BootProviders::class,
    ];

app/Http/Kernel.php

use LaravelVault\LoadEnvironmentVariablesVault;

class Kernel extends HttpKernel
{
    /**
     * The bootstrap classes for the application.
     *
     * @var string[]
     */
    protected $bootstrappers = [
        LoadEnvironmentVariables::class,
        LoadEnvironmentVariablesVault::class,
        LoadConfiguration::class,
        HandleExceptions::class,
        RegisterFacades::class,
        RegisterProviders::class,
        BootProviders::class,
    ];

性能

正在调查 ))

待办事项

  • 测试实现
  • 重构 VaultClient 以通过入口点分离方法,简化项目开发

许可证

MIT 许可证 (MIT)。有关更多信息,请参阅许可证文件