KMS Agent是一个HTTP代理服务,负责向KMS服务获取凭据值并缓存在内存中,应用通过HTTP请求向KMS Agent获取凭据值。通过部署KMS Agent,可以简化应用访问KMS的身份认证与缓存管理流程,适用于大规模应用访问KMS的场景。同时,KMS Agent能够降低应用改造成本,确保统一的集成标准。本文介绍如何部署KMS Agent。
KMS Agent概述
KMS Agent使用内存缓存凭据值,根据您设置的TTL时间定期刷新缓存的凭据值。当业务应用通过HTTP请求向KMS Agent请求凭据值时,KMS Agent通过SSRF Token文件验证请求的合法性,若缓存中存在有效凭据值则直接返回,否则向KMS服务转发请求,KMS服务验证KMS Agent身份通过后,从KMS解密凭据并返回,KMS Agent更新缓存后通过HTTP消息将凭据值返回给业务应用。流程如下图所示:
命中缓存的流程。
未命中缓存的流程。
KMS Agent需要和业务应用部署在一起,支持多环境部署,包括本地物理机、虚拟机(如ECS)、容器(如K8s Pod)。您可以访问alibabacloud-kms-agent,了解更多KMS Agent代码信息。
KMS Agent集成步骤
为保障KMS Agent的规范部署与安全调用,请集成时遵循以下流程。
步骤一:构建KMS Agent可执行文件
建议您在编译环境构建可执行文件,并上传到部署环境。
安装Golang环境。具体操作,请参见Go安装指南。
下载源码和依赖。
请访问Git官网,下载并安装Git工具。
执行以下命令下载源码和依赖。
git clone https://github.com/aliyun/alibabacloud-kms-agent go mod download
在项目根目录下,执行
go build .
命令编译可执行文件。文件默认名称alibabacloud-kms-agent,默认保存在项目根目录下 。编译环境与部署环境一致,执行
go build .
命令即可。如果编译环境和部署环境不一致,请参考以下命令进行跨平台编译,生成64位可执行文件。编译环境
部署环境为Mac
部署环境为Linux
部署环境为Windows
编译环境
部署环境为Mac
部署环境为Linux
部署环境为Windows
Mac
go build .
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build .
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build .
Linux
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build .
go build .
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build .
Windows
SET CGO_ENABLED=0 SET GOOS=darwin SET GOARCH=amd64 go build .
SET CGO_ENABLED=0 SET GOOS=linux SET GOARCH=amd64 go build .
go build .
在项目根目录下,查看是否存在可执行文件alibabacloud-kms-agent。
步骤二:创建访问凭证
部署在阿里云ECS时推荐使用ECS实例RAM角色,部署在K8s Sidecar容器时推荐使用RRSA, 其他环境推荐使用环境变量。
以使用RAM用户的AccessKey为例。
阿里云账号默认有所有资源的Administrator权限且不可修改,其AccessKey泄露会危及资源安全,因此强烈建议不要为主账号创建AccessKey,请创建专用于API访问的RAM用户并创建对应的AccessKey,并完成最小化授权。具体操作,请参见创建AccessKey。
登录RAM控制台,在用户页面,单击目标RAM用户名称。
在认证管理页签下的AccessKey区域,单击创建AccessKey,并按照指引完成创建。
授予RAM用户获取KMS凭据的权限。
KMS Agent在缓存凭据的过程中,需要向KMS获取凭据值,因此KMS Agent需要具有获取凭据值的权限,由于凭据值是加密存储的,还需要具有解密密钥的权限。
ECS RAM角色是指为ECS实例授予的RAM角色,该RAM角色是一个受信服务为云服务器的普通服务角色。使用实例RAM角色可以实现在ECS实例内部无需配置AccessKey即可获取临时访问凭证(STS Token),从而调用KMS的OpenAPI。
具体操作,请参见实例RAM角色。
阿里云容器服务ACK支持通过服务账户的RAM角色(RAM Roles for Service Accounts,简称RRSA),在集群内实现Pod维度的OpenAPI权限隔离,从而实现云资源访问权限的细粒度隔离,降低安全风险。如何配置RRSA,请参见通过RRSA配置ServiceAccount的RAM权限实现Pod权限隔离。
如何为KMS Agent扮演的RAM角色授权请参考如下信息。
KMS Agent在缓存凭据的过程中,需要向KMS获取凭据值,因此KMS Agent需要具有获取凭据值的权限,由于凭据值是加密存储的,还需要具有解密密钥的权限。
步骤三:部署KMS Agent
在本地直接通过可执行文件结合配置文件部署KMS Agent,适合小型环境或测试场景。访问凭证以使用RAM用户的AccessKey为例。
设置环境变量,配置KMS Agent运行所需的认证信息。
export ALIBABA_CLOUD_ACCESS_KEY_ID=*** export ALIBABA_CLOUD_ACCESS_KEY_SECRET=*** export KMS_TOKEN='file:///var/run/kmstoken'
ALIBABA_CLOUD_ACCESS_KEY_ID:RAM用户的AccessKey ID。
ALIBABA_CLOUD_ACCESS_KEY_SECRET:RAM用户的AccessKey Secret。
KMS_TOKEN:指定Agent启动时生成的SSRF Token文件的存储路径。
生成SSRF Token并存储到指定文件中。
# 产生一个SSRF token 存入文件 /var/run/kmstoken ./alibabacloud-kms-agent token /var/run/kmstoken
在KMS Agent配置文件(
config.toml
)中配置运行参数。[Server] HttpPort = 2025 [KMS] Region = "cn-hangzhou" [Cache] CacheType = "InMemory" CacheSize = 1000 TtlSeconds = 300 [Log] LogLevel = "Debug" LogPath = "./logs/" MaxSize = 100 MaxBackups = 2
启动KMS Agent服务。
./alibabacloud-kms-agent agent ./config.toml
将KMS Agent部署到Linux服务器并通过 systemd
进行启动和管理,确保KMS Agent在系统启动时自动运行,并提供进程监控、日志管理等功能。本文以在阿里云ECS部署,访问凭证使用ECS实例RAM角色为例。
设置环境变量,配置KMS Agent运行所需的认证信息。
export ALIBABA_CLOUD_ECS_METADATA=*** export KMS_TOKEN='file:///var/run/kmstoken'
ALIBABA_CLOUD_ECS_METADATA:ECS实例RAM角色名称。
KMS_TOKEN:指定Agent启动时生成的SSRF Token文件的存储路径。
安装启动Agent。
进入到安装目录下。
cd alibabacloud-kms-agent/deploy/linux
将如下文件上传到安装目录。
alibabacloud-kms-agent:步骤一生成的KMS Agent可执行文件。
config.toml:KMS Agent的配置文件,示例如下。
alibabacloud-kms-agent.service:用于管理KMS Agent的systemd服务文件。
使用root用户执行
install.sh
命令。sudo bash -x ./install.sh
执行
install.sh
脚本时会自动生成SSRF Token文件,该文件用于业务应用与KMS Agent之间的身份验证,防止未授权的服务端请求伪造(SSRF)攻击。Agent进程通过systemd服务管理(
alibabacloud-kms-agent.service
),实现开机自启、进程监控等标准化服务管理功能。
在
alibabacloud-kms-agent.service
中修改User
字段,使Agent运行用户与访问Agent的应用程序用户一致。否则应用程序无权限读取SSRF token,无法访问KMS Agent。
使用docker-compose工具编排Agent sidecar容器与应用容器。访问凭证以使用RAM用户的AccessKey为例。
创建容器Dockerfile文件。
创建两个Dockerfile文件,分别用于构建Agent Sidecar容器和业务应用容器。文件内容,请参考Dockerfile.agent和Dockerfile.app。
创建容器编排文件。文件内容,请参考docker-compose.yaml。
KMS Agent运行所需的认证信息,作为环境变量在该文件中配置,具体如下。
environment: - ALIBABA_CLOUD_ACCESS_KEY_ID=<ak> - ALIBABA_CLOUD_ACCESS_KEY_SECRET=<sk> - KMS_TOKEN='file:///var/run/kmstoken'
ALIBABA_CLOUD_ACCESS_KEY_ID:RAM用户的AccessKey ID。
ALIBABA_CLOUD_ACCESS_KEY_SECRET:RAM用户的AccessKey Secret。
KMS_TOKEN:指定Agent启动时生成的SSRF Token文件的存储路径。
在
config.toml
中配置KMS Agent的运行参数。[Server] HttpPort = 2025 [KMS] Region = "cn-hangzhou" [Cache] CacheType = "InMemory" CacheSize = 1000 TtlSeconds = 300 [Log] LogLevel = "Debug" LogPath = "./logs/" MaxSize = 100 MaxBackups = 2
编译并启动容器。
将步骤一生成的
alibabacloud-kms-agent
可执行文件、config.toml
配置文件、Dockerfile.agent
和Dockerfile.app
文件放置在与docker-compose.yml
容器编排文件相同的目录下。deploy/docker-compose/ ├── alibabacloud-kms-agent ├── config.toml ├── Dockerfile.agent ├── Dockerfile.app └── docker-compose.yml
执行如下命令。
docker-compose up --build
登录业务应用容器,在容器内访问Agent。
将KMS Agent作为sidecar容器与应用程序容器一起部署到阿里云的ACK容器服务。访问凭证以使用RRSA为例。
在config.toml中配置KMS Agent的运行参数。
[Server] HttpPort = 2025 [KMS] Region = "cn-hangzhou" [Cache] CacheType = "InMemory" CacheSize = 1000 TtlSeconds = 300 [Log] LogLevel = "Debug" LogPath = "./logs/" MaxSize = 100 MaxBackups = 2
编译Agent sidecar容器镜像。
进入
deploy/ack/agent
文件夹,创建Dockerfile,编译Agent容器镜像。文件内容,请参考agent_Dockerfile。cd alibabacloud-kms-agent/deploy/ack/agent # 这里测试上传到了阿里云镜像仓库 docker build -t registry.cn-hangzhou.aliyuncs.com/<namespace>/<repository> . docker push registry.cn-hangzhou.aliyuncs.com/<namespace>/<repository>:kmsagent-1.0
编译应用容器镜像。
进入
deploy/ack/app
文件夹,创建Dockerfile,编译应用容器镜像。文件内容,请参考app_Dockerfile。cd alibabacloud-kms-agent/deploy/ack/app docker build -t registry.cn-hangzhou.aliyuncs.com/<namespace>/<repository> . docker push registry.cn-hangzhou.aliyuncs.com/<namespace>/<repository>:app-1.0
编写k8s YAML资源文件,将应用和Agent容器一起部署到阿里云ACK。文件内容,请参考deployment-demo.yaml。
KMS Agent运行所需的认证信息,作为环境变量在该文件中配置,具体如下。
env: - name: KMS_TOKEN value: 'file:///var/run/kmstoken' - name: ALIBABA_CLOUD_ROLE_ARN value: acs:ram::<account>:role/<rolename> - name: ALIBABA_CLOUD_OIDC_PROVIDER_ARN value: acs:ram::<account>:oidc-provider/<ack cluster id> - name: ALIBABA_CLOUD_OIDC_TOKEN_FILE value: /var/run/secrets/ack.alibabacloud.com/rrsa-tokens/token
KMS_TOKEN:指定Agent启动时生成的SSRF Token文件的存储路径。
ALIBABA_CLOUD_ROLE_ARN:RAM角色的ARN。
ALIBABA_CLOUD_OIDC_PROVIDER_ARN :OIDC身份提供商的ARN,此处为ACK集群ARN。
ALIBABA_CLOUD_OIDC_TOKEN_FILE:包含OIDC Token的文件路径。
运行容器应用。
将文件按照如下层级放在项目目录中。
deploy/ack/ ├── alibabacloud-kms-agent ├── config.toml ├── Dockerfile.agent ├── Dockerfile.app └── deployment-demo.yaml
运行您的容器应用。具体操作,请参见创建无状态工作负载Deployment。
步骤四:获取凭据
KMS Agent默认获取凭据的ACSCurrent
版本。要获取其他版本的凭据值,您可以设置 versionStage
或 versionId
。
KMS Agent只监听127.0.0.1,即仅允许同一台机器上的应用或进程与其通信,外部网络设备无法连接。访问地址仅支持localhost或127.0.0.1,不支持改为应用的本地IP。以下示例以localhost为例。
使用curl
实际使用时请将示例代码中的<SecretId>
替换为您实际的凭据名称。
# 从文件读取 token
curl -v -H "X-KMS-Token:$(</var/run/kmstoken)" 'http://localhost:2025/secretsmanager/get?secretId=<SecretId>'
# 直接写 token
curl -v -H "X-KMS-Token:<token>" 'http://localhost:2025/secretsmanager/get?secretId=<SecretId>'
您可以指定versionStage
或 versionId
以获取特定凭据值。以获取指定versionId
的凭据值为例,使用时请将0a7513ee719da740807b15b77500****
替换为您实际的凭据版本。
# 从文件读取 token
curl -v -H "X-KMS-Token:$(</var/run/kmstoken)" 'http://localhost:2025/secretsmanager/get?secretId=<SecretId>&versionId=0a7513ee719da740807b15b77500****'
# 直接写 token
curl -v -H "X-KMS-Token:<token>" 'http://localhost:2025/secretsmanager/get?secretId=<SecretId>&versionId=0a7513ee719da740807b15b77500****'
使用Go代码
使用时请将示例代码中的agent-test
替换为您实际的凭据名称。
package main
import (
"fmt"
"io/ioutil"
"net/http"
)
func main() {
//支持指定versionStage或versionId以获取特定凭据值。
//以获取指定versionId的凭据值为例,url := fmt.Sprintf("http://localhost:2025/secretsmanager/get?secretId=%s&versionId=%s", "agent-test", "version-id")。
url := fmt.Sprintf("http://localhost:2025/secretsmanager/get?secretId=%s", "agent-test")
token, err := ioutil.ReadFile("/var/run/kmstoken")
if err != nil {
fmt.Printf("error reading token file: %v\n", err)
}
req, err := http.NewRequest("GET", url, nil)
if err != nil {
fmt.Printf("error creating request: %v\n", err)
}
req.Header.Add("X-KMS-Token", string(token))
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
fmt.Printf("error sending request: %v \n", err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Printf("status code %d - %s \n", resp.StatusCode, string(body))
}
- 本页导读 (1)
- KMS Agent概述
- 功能模块
- 安全性
- 稳定性
- KMS Agent优势
- KMS Agent与凭据客户端对比
- KMS Agent集成步骤
- 步骤一:构建KMS Agent可执行文件
- 步骤二:创建访问凭证
- 步骤三:部署KMS Agent
- 步骤四:获取凭据