KMS Agent通用集成步骤

本文介绍如何构建KMS Agent可执行文件及部署KMS Agent。

KMS Agent集成步骤

为保障KMS Agent的规范部署与安全调用,请集成时遵循以下流程。

image

步骤一:构建KMS Agent可执行文件

建议您在编译环境构建可执行文件,并上传到部署环境。

  1. 安装Golang环境。具体操作,请参见Go安装指南

  2. 下载源码和依赖。

    1. 请访问Git官网,下载并安装Git工具。

    2. 执行以下命令下载源码和依赖。

      git clone https://github.com/aliyun/alibabacloud-kms-agent
      go mod download
  3. 在项目根目录下,执行go build .命令编译可执行文件。文件默认名称alibabacloud-kms-agent,默认保存在项目根目录下 。

    编译环境与部署环境一致,执行go build .命令即可。如果编译环境和部署环境不一致,请参考以下命令进行跨平台编译,生成64位可执行文件。

    编译环境

    部署环境为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 .

  4. 在项目根目录下,查看是否存在可执行文件alibabacloud-kms-agent。image

步骤二:创建访问凭证

部署在阿里云ECS时推荐使用ECS实例RAM角色,部署在K8s Sidecar容器时推荐使用RRSA, 其他环境推荐使用AccessKey。

AccessKey

以使用RAM用户的AccessKey为例。

阿里云账号默认有所有资源的Administrator权限且不可修改,其AccessKey泄露会危及资源安全,因此强烈建议不要为主账号创建AccessKey,请创建专用于API访问的RAM用户并创建对应的AccessKey,并完成最小化授权。具体操作,请参见创建AccessKey

  1. 登录RAM控制台,在用户页面,单击目标RAM用户名称。

  2. 认证管理页签下的AccessKey区域,单击创建AccessKey,并按照指引完成创建。image

  3. 授予RAM用户获取KMS凭据的权限。

    KMS Agent在缓存凭据的过程中,需要向KMS获取凭据值,因此KMS Agent需要具有获取凭据值的权限,由于凭据值是加密存储的,还需要具有解密密钥的权限。

    • 方式一:设置基于身份的策略。

      具体操作,请参见创建自定义权限策略RAM用户授权

      权限策略示例

      请将${region}替换为资源实际所属地域、{account}替换为资源实际所属的阿里云账号,example-secret替换为实际使用的凭据名称,keyId-example替换为实际使用的密钥ID。

      {
          "Version": "1",
          "Statement": [
              {
                  "Effect": "Allow",
                  "Action": "kms:GetSecretValue",
                  "Resource": "acs:kms:${region}:${account}:secret/example-secret"
              },
              {
                  "Effect": "Allow",
                  "Action": "kms:Decrypt",
                  "Resource": "acs:kms:${region}:${account}:key/keyId-example"
              }
          ]
      }
    • 方式二:设置基于资源的策略。

      KMS支持基于资源的策略,即为单个密钥和凭据设置访问权限,用于控制哪些阿里云账号、RAM用户、RAM角色有权限来管理或使用KMS密钥、凭据。详细介绍,请参见密钥策略凭据策略

ECS实例RAM角色

ECS RAM角色是指为ECS实例授予的RAM角色,该RAM角色是一个受信服务为云服务器的普通服务角色。使用实例RAM角色可以实现在ECS实例内部无需配置AccessKey即可获取临时访问凭证(STS Token),从而调用KMSOpenAPI。

具体操作,请参见实例RAM角色

  1. 登录RAM控制台,创建可信实体为阿里云服务的RAM角色。

    • 信任主体类型:选择云服务

    • 信任主体名称:选择云服务器ECS

  2. 授予RAM角色获取KMS凭据的权限。

    KMS Agent在缓存凭据的过程中,需要向KMS获取凭据值,因此KMS Agent需要具有获取凭据值的权限,由于凭据值是加密存储的,还需要具有解密密钥的权限。

    • 方式一:设置基于身份的策略。

      具体操作,请参见创建自定义权限策略RAM角色授权

      权限策略示例

      请将${region}替换为资源实际所属地域、{account}替换为资源实际所属的阿里云账号,example-secret替换为实际使用的凭据名称,keyId-example替换为实际使用的密钥ID。

      {
          "Version": "1",
          "Statement": [
              {
                  "Effect": "Allow",
                  "Action": "kms:GetSecretValue",
                  "Resource": "acs:kms:${region}:${account}:secret/example-secret"
              },
              {
                  "Effect": "Allow",
                  "Action": "kms:Decrypt",
                  "Resource": "acs:kms:${region}:${account}:key/keyId-example"
              }
          ]
      }
    • 方式二:设置基于资源的策略。

      KMS支持基于资源的策略,即为单个密钥和凭据设置访问权限,用于控制哪些阿里云账号、RAM用户、RAM角色有权限来管理或使用KMS密钥、凭据。详细介绍,请参见密钥策略凭据策略

  3. 登录ECS管理控制台,将RAM角色授予ECS实例。image

RRSA

阿里云容器服务ACK支持通过服务账户的RAM角色(RAM Roles for Service Accounts,简称RRSA),在集群内实现Pod维度的OpenAPI权限隔离,从而实现云资源访问权限的细粒度隔离,降低安全风险。如何配置RRSA,请参见通过RRSA配置ServiceAccountRAM权限实现Pod权限隔离

如何为KMS Agent扮演的RAM角色授权请参考如下信息。

KMS Agent在缓存凭据的过程中,需要向KMS获取凭据值,因此KMS Agent需要具有获取凭据值的权限,由于凭据值是加密存储的,还需要具有解密密钥的权限。

  • 方式一:设置基于身份的策略。

    具体操作,请参见创建自定义权限策略RAM角色授权

    权限策略示例

    请将${region}替换为资源实际所属地域、{account}替换为资源实际所属的阿里云账号,example-secret替换为实际使用的凭据名称,keyId-example替换为实际使用的密钥ID。

    {
        "Version": "1",
        "Statement": [
            {
                "Effect": "Allow",
                "Action": "kms:GetSecretValue",
                "Resource": "acs:kms:${region}:${account}:secret/example-secret"
            },
            {
                "Effect": "Allow",
                "Action": "kms:Decrypt",
                "Resource": "acs:kms:${region}:${account}:key/keyId-example"
            }
        ]
    }
  • 方式二:设置基于资源的策略。

    KMS支持基于资源的策略,即为单个密钥和凭据设置访问权限,用于控制哪些阿里云账号、RAM用户、RAM角色有权限来管理或使用KMS密钥、凭据。详细介绍,请参见密钥策略凭据策略

步骤三:部署KMS Agent

本地部署

在本地直接通过可执行文件结合配置文件部署KMS Agent,适合小型环境或测试场景。访问凭证以使用RAM用户的AccessKey为例。

  1. 设置环境变量,配置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文件的存储路径。

  2. 生成SSRF Token并存储到指定文件中。

    # 产生一个SSRF token 存入文件 /var/run/kmstoken
    ./alibabacloud-kms-agent token /var/run/kmstoken
  3. 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
  4. 启动KMS Agent服务。

    ./alibabacloud-kms-agent agent ./config.toml

阿里云ECS Linux环境部署

KMS Agent部署到Linux服务器并通过 systemd 进行启动和管理,确保KMS Agent在系统启动时自动运行,并提供进程监控、日志管理等功能。本文以在阿里云ECS部署,访问凭证使用ECS实例RAM角色为例。

  1. 设置环境变量,配置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文件的存储路径。

  2. 安装启动Agent。

    1. 进入到安装目录下。

      cd alibabacloud-kms-agent/deploy/linux
    2. 将如下文件上传到安装目录。

      • alibabacloud-kms-agent:步骤一生成的KMS Agent可执行文件。

      • config.toml: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
      • alibabacloud-kms-agent.service:用于管理KMS Agentsystemd服务文件。

    3. 使用root用户执行install.sh命令。

      sudo bash -x ./install.sh
      • 执行install.sh脚本时会自动生成SSRF Token文件,该文件用于业务应用与KMS Agent之间的身份验证,防止未授权的服务端请求伪造(SSRF)攻击。

      • Agent进程通过systemd服务管理(alibabacloud-kms-agent.service),实现开机自启、进程监控等标准化服务管理功能。

    4. alibabacloud-kms-agent.service中修改User字段,使Agent运行用户与访问Agent的应用程序用户一致。

      否则应用程序无权限读取SSRF token,无法访问KMS Agent。

Sidecar容器部署

使用docker-compose工具编排Agent sidecar容器与应用容器。访问凭证以使用RAM用户的AccessKey为例。

  1. 创建容器Dockerfile文件。

    创建两个Dockerfile文件,分别用于构建Agent Sidecar容器和业务应用容器。文件内容,请参考Dockerfile.agentDockerfile.app

  2. 创建容器编排文件。文件内容,请参考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文件的存储路径。

  3. 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
  4. 编译并启动容器。

    1. 将步骤一生成的 alibabacloud-kms-agent 可执行文件、config.toml 配置文件、Dockerfile.agentDockerfile.app 文件放置在与 docker-compose.yml容器编排文件相同的目录下。

      deploy/docker-compose/
      ├── alibabacloud-kms-agent
      ├── config.toml
      ├── Dockerfile.agent
      ├── Dockerfile.app
      └── docker-compose.yml
    2. 执行如下命令。

      docker-compose up --build
  5. 登录业务应用容器,在容器内访问Agent。

阿里云ACK容器部署

KMS Agent作为sidecar容器与应用程序容器一起部署到阿里云的ACK容器服务。访问凭证以使用RRSA为例。

  1. 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
  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
  3. 编译应用容器镜像。

    进入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
  4. 编写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的文件路径。

  5. 运行容器应用。

    1. 将文件按照如下层级放在项目目录中。

      deploy/ack/
      ├── alibabacloud-kms-agent
      ├── config.toml
      ├── Dockerfile.agent
      ├── Dockerfile.app
      └── deployment-demo.yaml
    2. 运行您的容器应用。具体操作,请参见创建无状态工作负载Deployment

步骤四:获取凭据

KMS Agent默认获取凭据的ACSCurrent 版本。要获取其他版本的凭据值,您可以设置 versionStage 或 versionId

重要

KMS Agent只监听127.0.0.1,即仅允许同一台机器上的应用或进程与其通信,外部网络设备无法连接。访问地址仅支持localhost127.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))
}