golang使用Spiffe JWT与Hashicorp Vault实现无密码认证的插件库Spiffe-Vault
Golang使用Spiffe JWT与Hashicorp Vault实现无密码认证的插件库Spiffe-Vault
概述
SPIFFE Vault是一个将SPIFFE SVID认证与Hashicorp Vault集成的工具,用于获取VAULT_TOKEN
而不需要提供传统密码或密钥。
使用场景
- 从Hashicorp Vault读取秘密:无需提供传统认证密钥,而是使用SPIFFE SVID进行身份验证
- 无秘密/无密钥代码签名:利用Hashicorp Vault Transit引擎作为软件定义的HSM,解决本地机器上存储签名密钥的问题
构建
编译
make build
Docker镜像构建
使用默认DOCKER_HOST构建镜像:
make image
使用特定DOCKER_HOST构建镜像(例如colima):
DOCKER_HOST=unix:///Users/marco/.colima/default/docker.sock make image
使用示例
基础用法
# 设置Vault地址
export VAULT_ADDR=http://localhost:8200
# 使用spiffe-vault进行认证
bin/spiffe-vault auth -role my-role
# 输出会提示设置VAULT_TOKEN环境变量
# Export following environment variable to authenticate to Hashicorp Vault
export VAULT_TOKEN=s.IK1LBrCGXFQDAgawmhNLbcDH
高级用法
Bash
# 设置Vault地址
export VAULT_ADDR=http://localhost:8200
# 将认证输出保存到临时文件并执行
echo "$(bin/spiffe-vault auth -role my-role)" > /tmp/spiffe-vault
source /tmp/spiffe-vault
# 获取秘密
vault kv get secrets/my-key
# 查看令牌信息
vault token lookup
# 续订令牌
vault token renew
# 使用Transit引擎签名
vault write transit/sign/my-key input="$(echo stuff | base64)"
# 验证签名
vault write transit/verify/my-key input="$(echo stuff | base64)" signature=vault:v1:MEUCIFAWmHPyLJ6V0mjMgqr5UnV40bkCEUEGqApcYI54VAPIAiEAqyG2VkFc2wpYs/n47mK4vgfTVbXjWJzMM7Fxr/bR7LE=
Zsh
# 设置Vault地址
export VAULT_ADDR=http://localhost:8200
# 直接执行认证输出
source <(bin/spiffe-vault auth -role my-role)
# 获取秘密
vault kv get secrets/my-key
# 查看令牌信息
vault token lookup
# 续订令牌
vault token renew
# 使用Transit引擎签名
vault write transit/sign/my-key input="$(echo stuff | base64)"
# 验证签名
vault write transit/verify/my-key input="$(echo stuff | base64)" signature=vault:v1:MEUCIFAWmHPyLJ6V0mjMgqr5UnV40bkCEUEGqApcYI54VAPIAiEAqyG2VkFc2wpYs/n47mK4vgfTVbXjWJzMM7Fxr/bR7LE=
完整Golang示例
package main
import (
"fmt"
"log"
"os"
"github.com/hashicorp/vault/api"
"github.com/philips-labs/spiffe-vault/pkg/auth"
)
func main() {
// 设置Vault地址
vaultAddr := "http://localhost:8200"
if addr := os.Getenv("VAULT_ADDR"); addr != "" {
vaultAddr = addr
}
// 创建Vault客户端配置
config := &api.Config{
Address: vaultAddr,
}
// 创建Vault客户端
client, err := api.NewClient(config)
if err != nil {
log.Fatalf("Failed to create Vault client: %v", err)
}
// 使用SPIFFE认证
spiffeAuth := &auth.Spiffe{
Role: "my-role", // 设置Vault角色
}
// 登录Vault
secret, err := client.Logical().Write("auth/jwt/login", spiffeAuth.LoginData())
if err != nil {
log.Fatalf("Failed to login to Vault: %v", err)
}
// 设置令牌
client.SetToken(secret.Auth.ClientToken)
// 获取秘密示例
secret, err = client.Logical().Read("secret/data/my-key")
if err != nil {
log.Fatalf("Failed to read secret: %v", err)
}
// 打印秘密
fmt.Printf("Secret data: %v\n", secret.Data)
// 使用Transit引擎签名示例
signResult, err := client.Logical().Write("transit/sign/my-key", map[string]interface{}{
"input": "dGVzdA==", // "test"的base64编码
})
if err != nil {
log.Fatalf("Failed to sign data: %v", err)
}
fmt.Printf("Signature: %v\n", signResult.Data["signature"])
}
更多关于golang使用Spiffe JWT与Hashicorp Vault实现无密码认证的插件库Spiffe-Vault的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于golang使用Spiffe JWT与Hashicorp Vault实现无密码认证的插件库Spiffe-Vault的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
使用SPIFFE JWT与HashiCorp Vault实现无密码认证
SPIFFE (Secure Production Identity Framework For Everyone) 和 HashiCorp Vault 结合可以实现强大的无密码认证系统。下面我将介绍如何使用SPIFFE JWT与Vault实现这一目标。
核心概念
- SPIFFE JWT:SPIFFE标准定义的JWT格式的身份令牌
- Vault JWT Auth方法:Vault支持JWT认证的后端
- SPIRE:SPIFFE参考实现,用于颁发工作负载身份
实现步骤
1. 配置SPIRE服务器
首先需要部署SPIRE服务器来颁发SPIFFE JWT令牌。
// 示例SPIRE客户端代码,获取JWT令牌
package main
import (
"context"
"fmt"
"log"
"github.com/spiffe/go-spiffe/v2/workloadapi"
)
func fetchJWTToken() (string, error) {
// 连接到SPIRE Agent的Workload API
client, err := workloadapi.New(context.Background(),
workloadapi.WithAddr("unix:///tmp/spire-agent/public/api.sock"))
if err != nil {
return "", fmt.Errorf("无法连接到Workload API: %v", err)
}
defer client.Close()
// 获取JWT令牌
jwt, err := client.FetchJWTSVID(context.Background(),
workloadapi.JWTSVIDRequest{
Audience: []string{"vault.example.com"},
})
if err != nil {
return "", fmt.Errorf("获取JWT SVID失败: %v", err)
}
return jwt.Token, nil
}
func main() {
token, err := fetchJWTToken()
if err != nil {
log.Fatalf("获取JWT令牌失败: %v", err)
}
fmt.Printf("获取的JWT令牌: %s\n", token)
}
2. 配置Vault JWT认证方法
在Vault中启用并配置JWT认证方法:
vault auth enable jwt
vault write auth/jwt/config \
jwt_validation_pubkeys=@spire-jwt.pem \
bound_issuer="spiffe://example.org"
3. 创建Vault角色
vault write auth/jwt/role/demo \
role_type="jwt" \
bound_audiences="vault.example.com" \
user_claim="sub" \
bound_subject="spiffe://example.org/ns/default/sa/default" \
policies="default" \
ttl=1h
4. Go客户端认证代码
package main
import (
"context"
"encoding/json"
"fmt"
"log"
"net/http"
)
type vaultLoginRequest struct {
Role string `json:"role"`
JWT string `json:"jwt"`
}
type vaultLoginResponse struct {
Auth struct {
ClientToken string `json:"client_token"`
} `json:"auth"`
}
func loginToVault(jwtToken string) (string, error) {
url := "http://vault-server:8200/v1/auth/jwt/login"
reqBody, err := json.Marshal(vaultLoginRequest{
Role: "demo",
JWT: jwtToken,
})
if err != nil {
return "", fmt.Errorf("编码请求体失败: %v", err)
}
resp, err := http.Post(url, "application/json", bytes.NewBuffer(reqBody))
if err != nil {
return "", fmt.Errorf("Vault登录请求失败: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return "", fmt.Errorf("Vault返回非200状态码: %d", resp.StatusCode)
}
var loginResp vaultLoginResponse
if err := json.NewDecoder(resp.Body).Decode(&loginResp); err != nil {
return "", fmt.Errorf("解析Vault响应失败: %v", err)
}
return loginResp.Auth.ClientToken, nil
}
func main() {
// 获取SPIFFE JWT令牌
jwtToken, err := fetchJWTToken()
if err != nil {
log.Fatalf("获取JWT令牌失败: %v", err)
}
// 使用JWT登录Vault
vaultToken, err := loginToVault(jwtToken)
if err != nil {
log.Fatalf("Vault登录失败: %v", err)
}
fmt.Printf("成功获取Vault令牌: %s\n", vaultToken)
}
安全注意事项
- 令牌有效期:确保JWT令牌有合理的短有效期
- 绑定约束:在Vault角色中配置严格的绑定约束(bound_subject, bound_audiences等)
- 传输安全:始终使用HTTPS/TLS保护通信
- 权限最小化:遵循最小权限原则分配Vault策略
扩展功能
- 动态秘密:结合Vault的动态秘密功能,实现自动化的秘密管理
- SPIRE代理:在生产环境中使用SPIRE代理来简化工作负载注册
- 审计日志:启用Vault审计日志记录所有认证事件
这种基于SPIFFE和Vault的无密码认证方案特别适合云原生环境,能够为微服务提供安全、可扩展的身份认证机制。