PHP 怎么HashiCorp Vault

wen PHP项目 1

本文目录导读:

PHP 怎么HashiCorp Vault

  1. 基础集成方式
  2. 使用官方 PHP 库
  3. 使用 cURL 直接调用
  4. 高级用法:动态密钥和认证
  5. 最佳实践和配置示例
  6. 重要注意事项

我来详细介绍如何在 PHP 中集成 HashiCorp Vault。

基础集成方式

使用官方 API 客户端

// 使用 Guzzle HTTP 客户端
use GuzzleHttp\Client;
class VaultClient
{
    private $client;
    private $token;
    private $baseUrl;
    public function __construct($baseUrl, $token = null)
    {
        $this->baseUrl = rtrim($baseUrl, '/');
        $this->token = $token;
        $this->client = new Client([
            'base_uri' => $this->baseUrl,
            'headers' => [
                'X-Vault-Token' => $this->token,
                'Content-Type' => 'application/json'
            ]
        ]);
    }
    // 读取密钥
    public function readSecret($path)
    {
        try {
            $response = $this->client->get("/v1/{$path}");
            return json_decode($response->getBody(), true);
        } catch (Exception $e) {
            throw new Exception('Vault 读取失败: ' . $e->getMessage());
        }
    }
    // 写入密钥
    public function writeSecret($path, $data)
    {
        try {
            $response = $this->client->post("/v1/{$path}", [
                'json' => $data
            ]);
            return json_decode($response->getBody(), true);
        } catch (Exception $e) {
            throw new Exception('Vault 写入失败: ' . $e->getMessage());
        }
    }
}

使用官方 PHP 库

安装

composer require vault/vault-php

使用示例

<?php
require_once 'vendor/autoload.php';
use Vault\Client;
use Vault\Authentication\Token;
try {
    // 创建客户端
    $client = new Client([
        'base_uri' => 'http://127.0.0.1:8200',
        'timeout' => 5
    ]);
    // 设置认证 token
    $token = new Token('your-token-here');
    $client->setAuthenticationStrategy($token);
    // 验证连接
    $health = $client->getHealthStatus();
    // 读取密钥
    $secret = $client->getSecretValue('secret/data/myapp/config');
    // 写入请求
    $client->setSecret('secret/data/myapp/config', [
        'username' => 'admin',
        'password' => 'secret123'
    ]);
    // 从 KV v2 读取
    $kv2 = $client->getSecretValue('secret/data/myapp/config');
    // 删除密钥
    $client->deleteSecret('secret/data/myapp/config');
} catch (Exception $e) {
    echo '错误: ' . $e->getMessage();
}

使用 cURL 直接调用

class SimpleVaultClient
{
    private $baseUrl;
    private $token;
    public function __construct($baseUrl, $token)
    {
        $this->baseUrl = $baseUrl;
        $this->token = $token;
    }
    public function readSecret($path)
    {
        $ch = curl_init($this->baseUrl . '/v1/' . $path);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'X-Vault-Token: ' . $this->token,
            'Content-Type: application/json'
        ]);
        $response = curl_exec($ch);
        $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        if ($statusCode !== 200) {
            throw new Exception('Vault API 错误: ' . $statusCode);
        }
        return json_decode($response, true);
    }
    public function writeSecret($path, $data)
    {
        $ch = curl_init($this->baseUrl . '/v1/' . $path);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'X-Vault-Token: ' . $this->token,
            'Content-Type: application/json'
        ]);
        $response = curl_exec($ch);
        $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        if ($statusCode !== 204 && $statusCode !== 201 && $statusCode !== 200) {
            throw new Exception('Vault API 错误: ' . $statusCode);
        }
        return json_decode($response, true);
    }
}

高级用法:动态密钥和认证

AppRole 认证

class VaultAppRoleAuth
{
    private $vaultUrl;
    public function __construct($vaultUrl)
    {
        $this->vaultUrl = $vaultUrl;
    }
    public function authenticate($roleId, $secretId)
    {
        $http = new GuzzleHttp\Client([
            'base_uri' => $this->vaultUrl
        ]);
        $response = $http->post('/v1/auth/approle/login', [
            'json' => [
                'role_id' => $roleId,
                'secret_id' => $secretId
            ]
        ]);
        $data = json_decode($response->getBody(), true);
        // 返回客户端 token 和其他信息
        return [
            'client_token' => $data['auth']['client_token'],
            'renewable' => $data['auth']['renewable'],
            'lease_duration' => $data['auth']['lease_duration']
        ];
    }
}

动态数据库凭据

class DynamicDatabaseCredentials
{
    private $vaultClient;
    public function __construct($vaultClient)
    {
        $this->vaultClient = $vaultClient;
    }
    public function getDatabaseCredentials($roleName)
    {
        // 请求动态凭据
        $response = $this->vaultClient->read('/v1/database/creds/' . $roleName);
        return [
            'username' => $response['data']['username'],
            'password' => $response['data']['password'],
            'lease_id' => $response['lease_id'],
            'lease_duration' => $response['lease_duration']
        ];
    }
    public function renewLease($leaseId)
    {
        // 续租
        try {
            $response = $this->vaultClient->write('/v1/sys/renew', [
                'lease_id' => $leaseId
            ]);
            return $response;
        } catch (Exception $e) {
            throw new Exception('续租失败: ' . $e->getMessage());
        }
    }
}

最佳实践和配置示例

完整配置类

<?php
class VaultManager
{
    private static $instance = null;
    private $client;
    private $cache = [];
    private function __construct($config)
    {
        // 初始化配置
        $vaultUrl = $config['url'] ?? getenv('VAULT_ADDR');
        $vaultToken = $config['token'] ?? $this->secureToken();
        $this->client = new VaultClient($vaultUrl, $vaultToken);
    }
    public static function getInstance($config = null)
    {
        if (self::$instance === null) {
            self::$instance = new self($config);
        }
        return self::$instance;
    }
    // 安全获取 token(避免硬编码)
    private function secureToken()
    {
        // 从环境变量或配置文件获取
        return getenv('VAULT_TOKEN');
    }
    // 带缓存的密钥读取
    public function getSecretCached($path, $ttl = 300)
    {
        $cacheKey = $path;
        if (isset($this->cache[$cacheKey]) && 
            (time() - $this->cache[$cacheKey]['time'] < $ttl)) {
            return $this->cache[$cacheKey]['data'];
        }
        $secret = $this->client->readSecret($path);
        $this->cache[$cacheKey] = [
            'data' => $secret,
            'time' => time()
        ];
        return $secret;
    }
    // 批量读取多个密钥
    public function getSecrets(array $paths)
    {
        $results = [];
        foreach ($paths as $path) {
            $results[$path] = $this->getSecretCached($path);
        }
        return $results;
    }
    // 敏感数据处理
    public function decrypt($ciphertext, $keyPath)
    {
        $key = $this->getSecretCached($keyPath);
        // 解密逻辑
        $key = $key['data']['key'];
        $decrypted = openssl_decrypt($ciphertext, 'AES-256-GCM', $key);
        return $decrypted;
    }
}

环境配置示例

// config/vault.php
return [
    'url' => env('VAULT_ADDR', 'http://127.0.0.1:8200'),
    'token' => env('VAULT_TOKEN'),
    'timeout' => 5,
    'secrets' => [
        'database' => 'secret/data/database',
        'api_keys' => 'secret/data/apis',
        'jwt' => 'secret/data/jwt'
    ]
];

使用示例

// 使用示例
$vault = VaultManager::getInstance();
// 读取数据库配置
$dbConfig = $vault->getSecretCached('secret/data/database');
// 动态获取临时数据库凭据
$dbCreds = $vault->getDatabaseCredentials('web-app');
// 安全存储应用密钥
$vault->writeSecret('secret/data/myapp', [
    'api_key' => 'your-api-key',
    'api_secret' => 'your-api-secret'
]);

重要注意事项

  1. 安全认证:使用短期 token 和 AppRole 等认证方式
  2. 动态凭据:优先使用动态凭据而不是静态密钥
  3. 轮换策略:定期更新密钥
  4. 监控:通过 Vault 审计日志监控访问
  5. 缓存策略:合理设置缓存时间,同时考虑安全

这个集成为你的 PHP 应用提供了灵活、安全的 Vault 集成方案。

抱歉,评论功能暂时关闭!