阿里云密鑰管理服務KMS(Key Management Service)新增了專屬KMS產品形態,可以為您提供租戶側獨享存儲和密鑰運算的密鑰管理服務,提高使用安全性。本文介紹如何將KMS密鑰遷移到專屬KMS。

遷移的內容

重要 如果不做遷移,您可以繼續使用阿里云KMS,但您將無法提高密鑰配額和QPS。
遷移內容說明
密鑰您只需要遷移用戶主密鑰CMK,不需要遷移服務托管的密鑰。阿里云會繼續支持用戶通過免費的方式使用服務托管的密鑰,用于云產品的默認加密能力。
說明acs/云產品為別名的都是服務托管的密鑰。
業務應用如果您的密鑰只在阿里云云產品做加密使用,無需進行業務應用的遷移。如果密鑰在您自己管理的業務應用中被使用,您需要將網關從KMS網關切換到專屬KMS私有網關。
  • KMS網關:業務通過互聯網域名、VPC域名訪問KMS,訪問時使用AK身份憑證,基于RAM實現對密鑰的權限管控。
  • 專屬KMS私有網關:通過專屬KMS私網域名訪問專屬KMS,訪問時使用Client Key作為身份憑證,基于應用接入點實現對密鑰的權限管控。
重要 阿里云將在您所有密鑰遷移到專屬KMS的1個月后關閉KMS網關入口,您將只能通過專屬KMS私有網關調用,請務必在密鑰遷移后的1個月內完成業務應用的遷移。

遷移流程

KMS到專屬KMS遷移流程

步驟一:判斷密鑰和業務應用是否可以遷移

如果密鑰或者業務應用經判斷不支持遷移,您無需關注本文檔剩余內容,可以繼續使用阿里云KMS。

說明 如果您的密鑰只在云產品中做加密使用,只需要判斷密鑰是否遷移,不需要判斷業務應用是否需要遷移。如果您的密鑰在業務應用中使用,則需要判斷密鑰和業務應用是否都可以遷移。

判斷密鑰是否可以遷移

  • 方式一:通過用戶主密鑰遷移判斷工具進行判斷(推薦)
    1. 登錄密鑰管理服務控制臺
    2. 單擊用戶主密鑰,在用戶主密鑰頁面的上方單擊主密鑰遷移判斷工具
    3. 仔細閱讀提示信息后單擊確定,工具會給出判斷結果詳情
  • 方式二:根據如下信息自行判斷
    如下類型的用戶主密鑰,暫不支持遷移專屬KMS。
    不支持遷移的密鑰說明
    多版本密鑰目前僅支持遷移有且僅有一個版本的密鑰,對于存在多個版本的密鑰暫不支持遷移。
    開啟輪轉的密鑰對于開啟了自動輪轉但目前僅有一個版本的密鑰,在關閉密鑰輪轉后仍可以遷移。
    BYOK密鑰BYOK密鑰暫不支持遷移,您可以自行將密鑰材料導入到專屬KMS構建相同的密鑰。

判斷業務應用是否可以遷移

如果密鑰在您自己管理的業務應用中被使用,請根據業務實際情況從以下三方面判斷業務應用是否可以遷移。同時滿足條件時,業務應用才支持遷移。

條件說明
根據密碼運算API判斷是否支持遷移如果您的業務應用使用了ReEncrypt(轉加密)、ExportDataKey(數據密鑰導出)、GenerateAndExportDataKey(生成數據密鑰)密鑰運算API,暫時無法遷移到專屬KMS。
根據應用網絡位置判斷是否支持遷移
專屬KMS部署在您的私有VPC內,其中基礎版實例部署在啟動時您指定的VPC,標準版實例與HSM集群部署在同一個VPC。當應用和專屬KMS實例的網絡位置屬于如下情況之一時支持遷移。
  • 應用與專屬KMS實例在同一VPC內。
  • 應用和專屬KMS實例分布在不同VPC(應用和專屬KMS實例可以屬于同一個阿里云賬號下,也可以屬于不同阿里云賬號)。
  • 應用在非阿里云環境。
    說明 應用在非阿里云環境時,您需要確保已經執行如下操作。
    • 保證網絡的聯通性,確保業務機器與專屬KMS所在的網絡已經打通。
    • 保證域名解析正常。
      1. 放行100.100.2.136、100.100.2.138這兩段路由,確保在本地IDC上100.100.2.136、100.100.2.138可以ping通。
      2. 在本地IDC配置DNS轉發,將kms.aliyuncs.com轉發到100.100.2.136、100.100.2.138。
根據應用開發語言判斷是否支持遷移目前提供Java、Go、Python三種語言類型的遷移SDK,以支持您將業務應用以較少的代碼改動完成從KMS遷移至專屬KMS。如果您的業務應用使用其他語言開發,暫不支持遷移至專屬KMS,您可以通過智能在線聯系技術支持人員反饋需求。

步驟二:選擇專屬KMS版本

您可以通過查看專屬KMS基礎版和標準版之間的差異,根據業務需要選擇合適的專屬KMS版本。具體信息,請參見專屬KMS基礎版和標準版的差異

步驟三:遷移密鑰

請通過智能在線聯系技術支持人員將密鑰遷移到專屬KMS。同時提供如下信息:需要遷移的密鑰、遷移時間窗口(建議在業務低峰期進行遷移)、遷移目標專屬KMS實例。
說明 阿里云會在時間窗口內完成密鑰遷移。密鑰遷移完成后,您可以登錄密鑰管理服務控制臺,在專屬KMS頁面單擊目標實例操作列的管理,查看已完成遷移的密鑰。

步驟四:遷移業務應用

如果您的密鑰只在云產品中做加密使用,不需要執行本步驟。如果您的密鑰在業務應用中使用,您需要在密鑰遷移完成后的1個月內完成業務應用的遷移。

  1. 為實例創建應用接入點,并保存Client Key、CA證書。具體操作,請參見基礎版快速入門標準版快速入門
  2. 對應用進行改造升級,將網關從KMS切換到專屬KMS。
    • 改造示例(JAVA)

      導入Maven依賴

         <!-- add dkms sdk dependency -->
        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>alibabacloud-dkms-gcs-sdk</artifactId>
            <version>x.x.x</version>
          </dependency>
      
        <dependency>
            <groupId>com.aliyun.kms</groupId>
            <artifactId>kms-transfer-client</artifactId>
            <version>x.x.x</version>
        </dependency>

      代碼改造

      改造前業務代碼示例:
      import com.aliyuncs.DefaultAcsClient;
      import com.aliyuncs.IAcsClient;
      import com.aliyuncs.exceptions.ClientException;
      import com.aliyuncs.exceptions.ServerException;
      import com.aliyuncs.profile.DefaultProfile;
      import com.google.gson.Gson;
      import java.util.*;
      import com.aliyuncs.kms.model.v20160120.*;
      
      public class Encrypt {
      
          public static void main(String[] args) {
              DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", "<your-access-key-id>", "<your-access-key-secret>");
              IAcsClient client = new DefaultAcsClient(profile);
              // 設置 request 參數
              EncryptRequest request = new EncryptRequest();
              request.setProtocol(ProtocolType.HTTPS);
              request.setAcceptFormat(FormatType.JSON);
              request.setMethod(MethodType.POST);
              request.setKeyId(<keyId>);
              request.setPlaintext(plainText);
      
              try {
                  EncryptResponse response = client.getAcsResponse(request);
                  System.out.println(new Gson().toJson(response));
              } catch (ServerException e) {
                  e.printStackTrace();
              } catch (ClientException e) {
                  System.out.println("ErrCode:" + e.getErrCode());
                  System.out.println("ErrMsg:" + e.getErrMsg());
                  System.out.println("RequestId:" + e.getRequestId());
              }
      
          }
      }
      改造后業務代碼示例:
      import com.aliyun.kms.KmsTransferAcsClient;
      import com.aliyun.dkms.gcs.openapi.models.Config;
      import com.aliyuncs.IAcsClient;
      import com.aliyuncs.exceptions.ClientException;
      import com.aliyuncs.exceptions.ServerException;
      import com.aliyuncs.profile.DefaultProfile;
      import com.google.gson.Gson;
      import java.util.*;
      import com.aliyuncs.kms.model.v20160120.*;
      
      public class Encrypt {
      
          public static void main(String[] args) {
              DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", "<your-access-key-id>", "<your-access-key-secret>");
      
              Config config = new Config();
             //連接協議,固定為HTTPS。
              config.setProtocol("https");
             //專屬KMS實例Client Key。
              config.setClientKeyFile("<your-client-key-file>");
              //專屬KMS實例Client Key解密口令。
              config.setPassword("<your client key password>");
             //Endpoint,專屬KMS實例服務地址去掉https://。
              config.setEndpoint("<service_id>.cryptoservice.kms.aliyuncs.com");
              IAcsClient client = new KmsTransferAcsClient(profile, config);
              // 設置 request 參數
              EncryptRequest request = new EncryptRequest();
              request.setProtocol(ProtocolType.HTTPS);
              request.setAcceptFormat(FormatType.JSON);
              request.setMethod(MethodType.POST);
              request.setKeyId(<keyId>);
              request.setPlaintext(plainText);
      
              try {
                  EncryptResponse response = client.getAcsResponse(request);
                  System.out.println(new Gson().toJson(response));
              } catch (ServerException e) {
                  e.printStackTrace();
              } catch (ClientException e) {
                  System.out.println("ErrCode:" + e.getErrCode());
                  System.out.println("ErrMsg:" + e.getErrMsg());
                  System.out.println("RequestId:" + e.getRequestId());
              }
      
          }
      }
    • 改造示例(Python)

      安裝增加依賴包

      代碼改造

      改造前業務代碼示例:

      from aliyunsdkcore.auth.credentials import AccessKeyCredential
      from aliyunsdkcore.client import AcsClient
      from aliyunsdkkms.request.v20160120.EncryptRequest import EncryptRequest
      
      
      def encrypt():
          credentials = AccessKeyCredential('<your-access-key-id>', '<your-access-key-secret>')
      
          client = AcsClient(region_id="<your-region-id>", credential=credentials)
      
          request = EncryptRequest()
          request.set_accept_format('json')
          request.set_KeyId("<your-key-id>")
          request.set_Plaintext("<your-plaintext>")
      
          response = client.do_action_with_exception(request)
          print(str(response, encoding='utf-8'))
      
      
      encrypt()

      改造后業務代碼示例:

      from alibabacloud_dkms_transfer.kms_transfer_acs_client import KmsTransferAcsClient
      from aliyunsdkcore.auth.credentials import AccessKeyCredential
      from aliyunsdkkms.request.v20160120.EncryptRequest import EncryptRequest
      from openapi.models import Config
      
      
      def encrypt():
          config = Config()
          config.protocol = "https"
          config.client_key_file = "<your-client-key-file-path>"
          config.password = "<your-password>"
          config.endpoint = "<your-endpoint>"
      
          credentials = AccessKeyCredential('<your-access-key-id>', '<your-access-key-secret>')
      
          client = KmsTransferAcsClient(config=config, credential=credentials, verify='<your-ca-certificate-file-path>')
      
          request = EncryptRequest()
          request.set_KeyId("<your-key-id>")
          request.set_Plaintext("<your-plaintext>")
      
          response = client.do_action_with_exception(request)
          print(str(response, encoding='utf-8'))
      
      
      encrypt()
    • 改造示例(Go)

      使用如下方式之一安裝依賴包:

      • 使用go mod管理您的依賴:
        require (
            github.com/aliyun/alibabacloud-dkms-transfer-go-sdk vX.X.X
            github.com/aliyun/alibabacloud-dkms-gcs-go-sdk vX.X.X
            github.com/alibabacloud-go/tea vX.X.X
        )
      • 通過go get命令獲取遠程代碼包:
        $ go get -u github.com/aliyun/alibabacloud-dkms-transfer-go-sdk
        $ go get -u github.com/aliyun/alibabacloud-dkms-gcs-go-sdk
        $ go get -u github.com/alibabacloud-go/tea
        說明 SDK的最新版本,請參見alibabacloud-dkms-gcs-go-sdkalibabacloud-dkms-transfer-go-sdk

      代碼改造

      改造前業務代碼示例:
      import (
          "fmt"
          "github.com/aliyun/alibaba-cloud-sdk-go/services/kms"
      )
      
      func main() {
          client, err := kms.NewClientWithAccessKey("<your-region-id>", "<your-access-key-id>", "<your-access-key-secret>")
          if err != nil {
              panic(err)
          }
      
          request := kms.CreateEncryptRequest()
          request.Scheme = "https"
          request.KeyId = "<your cmk id>"
          request.Plaintext = "<your plaintext>"
      
          response, err := client.Encrypt(request)
          if err != nil {
              panic(err)
          }
      
          fmt.Println(response)
      }
      改造后業務代碼示例:
      import (
          "fmt"
          "github.com/alibabacloud-go/tea/tea"
          "github.com/aliyun/alibaba-cloud-sdk-go/services/kms"
          dedicatedkmsopenapi "github.com/aliyun/alibabacloud-dkms-gcs-go-sdk/openapi"
          "github.com/aliyun/alibabacloud-dkms-transfer-go-sdk/sdk"
      )
      
      func main() {
          config := &dedicatedkmsopenapi.Config{
              Protocol:      tea.String("https"),
              ClientKeyFile: tea.String("<your-client-key-file>"),
              Password:      tea.String("<your-client-key-password>"),
              Endpoint:      tea.String("<your-dkms-instance-service-endpoint>"),
          }
      
          client, err := sdk.NewClientWithAccessKey("<your-region-id>", "<your-access-key-id>", "<your-access-key-secret>", config)
          if err != nil {
              panic(err)
          }
      
          request := kms.CreateEncryptRequest()
          request.KeyId = "<your cmk id>"
          request.Plaintext = "<your plaintext>"
      
          response, err := client.Encrypt(request)
          if err != nil {
              panic(err)
          }
      
          fmt.Println(response)
      }