本文目录导读:

我来详细介绍如何在 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'
]);
重要注意事项
- 安全认证:使用短期 token 和 AppRole 等认证方式
- 动态凭据:优先使用动态凭据而不是静态密钥
- 轮换策略:定期更新密钥
- 监控:通过 Vault 审计日志监控访问
- 缓存策略:合理设置缓存时间,同时考虑安全
这个集成为你的 PHP 应用提供了灵活、安全的 Vault 集成方案。