This topic describes building and deploying the KMS Agent to retrieve secrets. Deployment environments include local, Linux Elastic Compute Service (ECS), sidecar container, and Container Service for Kubernetes (ACK).
Process
To ensure standardized deployment and secure invocation of the agent, follow these steps:
Step 1: Build a KMS Agent executable file
For optimal security and maintainability, we recommend building the executable in a separate build environment, then uploading it to the deployment environment.
Download the source code and dependencies.
Download and install Git.
Run the following commands to download the source code and dependencies.
git clone https://github.com/aliyun/alibabacloud-kms-agent go mod downloadThe default filename is
alibabacloud-kms-agent, which is saved in the project root by default.
Compile the binary file.
If the build environment matches the deployment environment, run the
go build .command. For cross-platform compilation when build and deployment environments differ, refer to the following commands to generate 64-bit executable files:Verify that
alibabacloud-kms-agentexists in the project root directory.
Step 2: Create access credentials
Recommended access credentials by deployment environment:
Alibaba Cloud ECS deployment: ECS instance RAM Role.
Kubernetes container deployment: RAM Roles for Service Accounts (RRSA).
Other environments deployment: Environment variables.
Environment variables (AccessKey)
This section uses a RAM user's AccessKey pair as an example. Alibaba Cloud accounts have default administrator privileges for all resources, which cannot be modified. Because compromised AccessKeys risk significant security vulnerabilities, we strongly recommend against creating them for Alibaba Cloud accounts. Instead, create a RAM user solely for API access, generate its AccessKey pair, and implement the principle of least privilege.
Log on to the RAM console. In the left-side navigation pane, choose Identities > Users, and click on the target RAM user.
In the Authentication tab, click Create AccessKey and follow the instructions.

Grant the RAM role permissions to retrieve secrets.
The permissions that the agent requires:
Retrieve secret values from KMS.
Decrypt the encrypted secrets using the decryption keys.
Choose a method to complete the grant:
Method 1: Configure identity-based policies.
For instructions, see Create a custom policy and Grant permissions to a RAM role.
Method 2: Configure resource-based policies.
This method allows you to configure access permissions for individual keys and secrets to control which Alibaba Cloud accounts, RAM users, and RAM roles have permissions to manage or use KMS keys and secrets. For more information, see Key policies and Secret policies.
ECS instance RAM role
Log on to the RAM console, and create an instance RAM role whose Principal Type is an Alibaba Cloud service.
Principal Type: Select Cloud Service.
Principal Name: Select Elastic Compute Service / ECS.
Grant the RAM role permissions to retrieve secrets.
The permissions that the agent requires:
Retrieve secret values from KMS.
Decrypt the encrypted secrets using the decryption keys.
Choose a method to complete the grant:
Method 1: Configure identity-based policies.
For instructions, see Create a custom policy and Grant permissions to a RAM role.
Method 2: Configure resource-based policies.
This method allows you to configure access permissions for individual keys and secrets to control which Alibaba Cloud accounts, RAM users, and RAM roles have permissions to manage or use KMS keys and secrets. For more information, see Key policies and Secret policies.
Log on to the ECS console, and attach the instance RAM role to an ECS instance.

RRSA
ACK supports RRSA, which enables OpenAPI permission isolation at the pod level within a cluster. This provides fine-grained isolation of cloud resource access permissions and minimizes security risks.
Create a RAM role.
If you want to use an existing RAM role, you must modify its trust policy.
Otherwise, create a new role on the RAM console. The main parameters are listed below. For detailed instructions, see Create a RAM role for an OIDC IdP.
Parameter
Description
Identity Provider Type
Select OIDC.
Identity Provider
Select an IdP. It is named in the ack-rrsa-<cluster_id> format.
Conditions
oidc:iss: Use the default value.
oidc:aud: Use the default value.
oidc:sub: Manually add this condition.
Key: Select oidc:sub.
Operator: Select StringEquals.
Value: Enter system:serviceaccount:<namespace>:<serviceAccountName>.
<namespace>: Specify the namespace of the application.<serviceAccountName>: Specify the name of the service account.
RAM Role Name
Set a name for the RAM role.
Grant the RAM role permissions to retrieve secrets.
The permissions that the agent requires:
Retrieve secret values from KMS.
Decrypt the encrypted secrets using the decryption keys.
Choose a method to complete the grant:
Method 1: Configure identity-based policies.
For instructions, see Create a custom policy and Grant permissions to a RAM role.
Method 2: Configure resource-based policies.
This method allows you to configure access permissions for individual keys and secrets to control which Alibaba Cloud accounts, RAM users, and RAM roles have permissions to manage or use KMS keys and secrets. For more information, see Key policies and Secret policies.
Step 3: Deploy KMS Agent
The agent supports the following deployment methods:
Local deployment: Deploy the agent locally using the binary and configuration file, suitable for small-scale or testing environments.
Linux environment deployment: Deploy the agent on a Linux server and manage it with
systemdto ensure automatic operation at system startup. Below, we use deployment to an ECS instance as an example.Sidecar container deployment: Use docker-compose to orchestrate the deployment and management of the agent sidecar and application containers.
ACK deployment: Deploy the agent as a sidecar container alongside the application container using Docker.
Local deployment
Here we use a RAM user's AccessKey as an example of access credentials.
Configure environment variables to set up the authentication information required for the agent to operate.
# AccessKey ID of the RAM user. export ALIBABA_CLOUD_ACCESS_KEY_ID=*** # AccessKey Secret of the RAM user. export ALIBABA_CLOUD_ACCESS_KEY_SECRET=*** # Path to the SSRF Token file created on the agent startup. export KMS_TOKEN='file:///var/run/kmstoken'Generate an SSRF Token and save it in the specified file.
# Generate an SSRF token and store it in the file /var/run/kmstoken. ./alibabacloud-kms-agent token /var/run/kmstokenModify the configuration file as needed.
Start the agent.
./alibabacloud-kms-agent agent ./config.toml
Linux (ECS) deployment
Here we use ECS instance RAM roles as an example of access credentials.
Set environment variables to configure the authentication required for agent operation.
# Name of the ECS instance RAM role.. export ALIBABA_CLOUD_ECS_METADATA=*** # Path to the SSRF Token file created on the agent startup. export KMS_TOKEN='file:///var/run/kmstoken'Install and start the agent.
Enter the installation directory.
cd alibabacloud-kms-agent/deploy/linuxUpload the following files to the installation directory:
alibabacloud-kms-agent: The agent binary file built in the KMS Agent.
config.toml: The agent's configuration file, as shown below:
alibabacloud-kms-agent.service: The systemd service file for managing the agent.
Run the
install.shcommand as the root user.sudo bash -x ./install.shThe
install.shscript automatically generates an SSRF Token file for identity authentication between the application and agent, preventing SSRF attacks.The agent uses systemd (
alibabacloud-kms-agent.service) for automated startup and process monitoring.
Set the
Userfield inalibabacloud-kms-agent.serviceto the application user to enable access to the SSRF token and the agent.
Sidecar container deployment
Here we use a RAM user's AccessKey as an example of access credentials.
Create two Dockerfiles for the containers.
Dockerfile.agent: Builds the agent sidecar container.
Dockerfile.app: Builds the application container.
Compose a container orchestration file.
This file configures the authentication information required for the agent as environment variables, as shown below:
environment: # AccessKey ID of the RAM user. - ALIBABA_CLOUD_ACCESS_KEY_ID=<ak> # AccessKey Secret of the RAM user. - ALIBABA_CLOUD_ACCESS_KEY_SECRET=<sk> # Path to the SSRF Token file created on the agent startup. - KMS_TOKEN='file:///var/run/kmstoken'Modify the configuration file as needed.
Build and start the container.
Put the
alibabacloud-kms-agentbinary file, theconfig.tomlfile, theDockerfile.agent, and theDockerfile.appin the same directory as thedocker-compose.ymlfile.deploy/docker-compose/ ├── alibabacloud-kms-agent ├── config.toml ├── Dockerfile.agent ├── Dockerfile.app └── docker-compose.ymlRun the command
docker-compose up --build.
Log on to your application container and access the agent from within the container.
ACK deployment
Here, we use RRSA as an example of access credentials.
Modify the configuration file as needed.
Build the agent sidecar container image.
Navigate to the
deploy/ack/agentdirectory, create a Dockerfile, and build the agent container image. Dockerfile reference.cd alibabacloud-kms-agent/deploy/ack/agent # Test upload to Alibaba Cloud container registry. docker build -t registry.<REGION_ID>.aliyuncs.com/<NAMESPACE>/<REPOSITORY> docker push registry.<REGION_ID>.aliyuncs.com/<NAMESPACE>/<REPOSITORY>:kmsagent-1.0Build the application container image.
Navigate to the
deploy/ack/appdirectory, create a Dockerfile, and build the application container image. Dockerfile reference.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.0Create a Kubernetes YAML file to deploy the application and agent containers to ACK. YAML file reference.
Use the
alibabacloud-kms-agent/deploy/ack/demo.yamlfile as a template. Modify it as needed and deploy both containers to your ACK cluster usingkubectl apply -f <YAML_FILE_NAME>.yaml.This YAML file configures the authentication required for the agent as environment variables, as shown below:
env: # Path to the SSRF Token file created on the agent startup. - name: KMS_TOKEN value: 'file:///var/run/kmstoken' # Alibaba Cloud Resource Name (ARN) of the RAM role. - name: ALIBABA_CLOUD_ROLE_ARN value: acs:ram::<account>:role/<rolename> # ARN of the OIDC identity provider. In this case, the ACK cluster ARN. - name: ALIBABA_CLOUD_OIDC_PROVIDER_ARN value: acs:ram::<account>:oidc-provider/<ack cluster id> # File path containing the OIDC Token. - name: ALIBABA_CLOUD_OIDC_TOKEN_FILE value: /var/run/secrets/ack.alibabacloud.com/rrsa-tokens/tokenRun the container application.
Put the
alibabacloud-kms-agentbinary file, theconfig.tomlfile, the agent Dockerfile, and application Dockerfile in the same directory as the Kubernetes YAML file. See the example directory structure below:deploy/ack/ ├── alibabacloud-kms-agent ├── config.toml ├── Dockerfile.agent ├── Dockerfile.app └── deployment-demo.yamlRun the container application. For detailed instructions, see Create Stateless Workload Deployment.
Step 4: Retrieve secrets
The agent retrieves the ACSCurrent version of secrets by default. To retrieve secret values of other versions, set versionStage or versionId.
The agent only listens on 127.0.0.1 or localhost, restricting communication to applications or processes on the same machine. External network connections are prohibited, and the access endpoint cannot be changed to the application's local IP address. The examples below use localhost.
Sample code
curl
Replace <SecretId> in the example code with your actual secret name.
# Read token from file
curl -v -H "X-KMS-Token:$(</var/run/kmstoken)" 'http://localhost:2025/secretsmanager/get?secretId=<SecretId>'
# Write token directly
curl -v -H "X-KMS-Token:<token>" 'http://localhost:2025/secretsmanager/get?secretId=<SecretId>'Specify versionStage or versionId to retrieve a specific secret value. For example, to retrieve a secret value with a specific versionId, replace 0a7513ee719da740807b15b77500**** with your actual secret version.
# Read token from file
curl -v -H "X-KMS-Token:$(</var/run/kmstoken)" 'http://localhost:2025/secretsmanager/get?secretId=<SecretId>&versionId=0a7513ee719da740807b15b77500****'
# Write token directly
curl -v -H "X-KMS-Token:<token>" 'http://localhost:2025/secretsmanager/get?secretId=<SecretId>&versionId=0a7513ee719da740807b15b77500****'Go
Replace agent-test in the example code with your actual secret name.
package main
import (
"fmt"
"io/ioutil"
"net/http"
)
func main() {
//You can specify versionStage or versionId to retrieve a specific secret value.
//For example, to retrieve a secret value with a specific 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))
}