文档首页/ 数据加密服务 DEW/ 最佳实践/ 凭据管理/ 如何使用凭据管理服务替换硬编码的数据库账号密码
更新时间:2024-03-28 GMT+08:00

如何使用凭据管理服务替换硬编码的数据库账号密码

您在日常访问应用程序的过程中,通常会嵌入凭据直接访问程序。在需要更新凭据时,您除了创建新的凭据以外,还需要执行一些其他操作。您还需要花费一些时间更新应用程序以使用新的凭据。如果您有多个应用程序同一凭据,而您错过更新其中一个,则该应用程序就无法使用凭据登录。

因此使用方便有效且安全性高的凭据管理工具十分关键。

华为云凭据管理服务(Cloud Secret Management Service,CSMS)可以帮助您拥有以下优势:

  • 通过凭据托管功能,降低通过硬编码方式带来的凭据泄露风险,提高数据及资产的安全性。
  • 减少对业务的影响:当您进行人工轮换的方式更新凭据时,您的业务不会受到影响。
  • 提供安全的SDK接入方式,动态调用您的凭据。
  • 凭据存储类型多样化。您不仅可以存储业务相关的账号密码,也可以存储业务数据库详细信息,包括但不限于:数据库名称、IP地址和端口等。

使用凭据登录数据库

下文为您介绍如何创建凭据,并且通过API调用凭据来登录到您的数据库。

您首先需要确保您的账号拥有KMS Administrator或者KMS CMKFullAccess权限,详情见DEW权限管理

图1 凭据登录流程

流程说明如下:

  1. 您首先需要在凭据管理服务中使用控制台或者API创建一个凭据,用来存储数据库的相关信息(例如:数据库地址、端口、密码)。
  2. 当您使用应用程序访问数据库时,凭据管理服务会去查询步骤1所创建的凭据存储的内容。
  3. 凭据管理服务检索并解密凭据密文,将凭据中保存的信息通过凭据管理API安全地返回到应用程序中。
  4. 应用程序获取到解密后的凭据明文信息,使用这些安全的信息访问数据库。

创建凭据和查询凭据API

您可以调用以下API,通过API创建凭据保存相关内容并且查询相关凭据信息。

API名称

说明

创建凭据

创建新的凭据,并且将凭据值存入凭据的初始版本

查询凭据

查询指定凭据的信息

通过API接口创建凭据和查询凭据

  1. 请准备基础认证信息:
    • ACCESS_KEY: 华为账号Access Key
    • SECRET_ACCESS_KEY: 华为账号Secret Access Key
    • PROJECT_ID: 华为云局点项目ID,请参见华为云局点项目
    • CSMS_ENDPOINT: 华为云CSMS服务访问终端地址,请参见终端节点
    • 认证用的ak和sk直接写到代码中有很大的安全风险,建议在配置文件或者环境变量中密文存放,使用时解密,确保安全。
    • 本示例以ak和sk保存在环境变量中来实现身份验证为例,运行本示例前请先在本地环境中设置环境变量HUAWEICLOUD_SDK_AK和HUAWEICLOUD_SDK_SK。
  2. 创建和查询凭据信息:

    凭据名称:secretName

    凭据值:secretString

    凭据版本值:LATEST_SECRET

    凭据版本:versionId

import com.huaweicloud.sdk.core.auth.BasicCredentials;
import com.huaweicloud.sdk.csms.v1.CsmsClient;
import com.huaweicloud.sdk.csms.v1.model.CreateSecretRequest;
import com.huaweicloud.sdk.csms.v1.model.CreateSecretRequestBody;
import com.huaweicloud.sdk.csms.v1.model.CreateSecretResponse;
import com.huaweicloud.sdk.csms.v1.model.ShowSecretVersionRequest;
import com.huaweicloud.sdk.csms.v1.model.ShowSecretVersionResponse;

public class CsmsCreateSecretExample {
    /**
     * 基础认证信息:
     * - ACCESS_KEY: 华为账号Access Key
     * - SECRET_ACCESS_KEY: 华为账号Secret Access Key
     * - PROJECT_ID: 华为云局点项目ID 详情见https://support.huaweicloud.com/intl/zh-cn/productdesc-iam/iam_01_0023.html
     * - CSMS_ENDPOINT: 华为云CSMS服务访问终端地址 详情见https://support.huaweicloud.com/intl/zh-cn/api-dew/dew_02_0052.html
     * - 认证用的ak和sk直接写到代码中有很大的安全风险,建议在配置文件或者环境变量中密文存放,使用时解密,确保安全。
     * - 本示例以ak和sk保存在环境变量中来实现身份验证为例,运行本示例前请先在本地环境中设置环境变量HUAWEICLOUD_SDK_AK和HUAWEICLOUD_SDK_SK。
     */
    private static final String ACCESS_KEY = System.getenv("HUAWEICLOUD_SDK_AK");
    private static final String SECRET_ACCESS_KEY = System.getenv("HUAWEICLOUD_SDK_SK");
    private static final String PROJECT_ID = "<ProjectID>";
    private static final String CSMS_ENDPOINT = "<CsmsEndpoint>";

    // 用来查询凭据最新版本详情的版本Id
    private static final String LATEST_SECRET = "latest";

    public static void main(String[] args) {
        String secretName = args[0];
        String secretString = args[1];

        // 创建凭据
        createSecret(secretName, secretString);

        // 通过凭据版本值“latest”或者版本值“v1"查询到新创建的凭据内容
        ShowSecretVersionResponse latestVersion = showSecretVersion(secretName, LATEST_SECRET);
        ShowSecretVersionResponse firstVersion = showSecretVersion(secretName, "v1");

        assert latestVersion.equals(firstVersion);
        assert latestVersion.getVersion().getSecretString().equalsIgnoreCase(secretString);
    }

    /**
     * 创建凭据
     * @param secretName
     * @param secretString
     */
    private static void createSecret(String secretName, String secretString) {
        CreateSecretRequest secret = new CreateSecretRequest().withBody(
                new CreateSecretRequestBody().withName(secretName).withSecretString(secretString));

        CsmsClient csmsClient = getCsmsClient();

        CreateSecretResponse createdSecret = csmsClient.createSecret(secret);

        System.out.printf("Created secret success, secret detail:%s", createdSecret);
    }
    /**
     * 根据凭据版本id查询凭据版本详情
     * @param secretName
     * @param versionId
     * @return
     */
    private static ShowSecretVersionResponse showSecretVersion(String secretName, String versionId) {
        ShowSecretVersionRequest showSecretVersionRequest = new ShowSecretVersionRequest().withSecretName(secretName)
                .withVersionId(versionId);

        CsmsClient csmsClient = getCsmsClient();

        ShowSecretVersionResponse version = csmsClient.showSecretVersion(showSecretVersionRequest);

        System.out.printf("Query secret success. version id:%s", version.getVersion().getVersionMetadata().getId());

        return version;
    }

    /**
     * 获取CSMS服务客户端
     * @return
     */
    private static CsmsClient getCsmsClient() {
        BasicCredentials auth = new BasicCredentials()
                .withAk(ACCESS_KEY)
                .withSk(SECRET_ACCESS_KEY)
                .withProjectId(PROJECT_ID);

        return CsmsClient.newBuilder().withCredential(auth).withEndpoint(CSMS_ENDPOINT).build();
    }
}

使用应用程序获取数据库账号和密码

  1. 获取凭据管理服务的CSMS SDK的依赖声明。

    示例如下:

    <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>XXX</version>
            </dependency>
            <dependency>
                <groupId>com.google.code.gson</groupId>
                <artifactId>gson</artifactId>
                <version>2.8.9</version>
            </dependency>
            <dependency>
                <groupId>com.huaweicloud.sdk</groupId>
                <artifactId>huaweicloud-sdk-csms</artifactId>
                <version>3.0.79</version>
            </dependency>
  2. 建立数据库链接并且获取账号密码:
    示例代码如下
    import com.google.gson.Gson;
    import com.google.gson.JsonObject;
    import com.huaweicloud.sdk.csms.v1.model.ShowSecretVersionRequest;
    import com.huaweicloud.sdk.csms.v1.model.ShowSecretVersionResponse;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    
     // 通过凭据信息获取指定的数据库账号和口令
        public static Connection getMySQLConnectionBySecret(String secretName, String jdbcUrl) throws ClassNotFoundException, SQLException{
            Class.forName(MYSQL_JDBC_DRIVER);
            ShowSecretVersionResponse latestVersionValue = getCsmsClient().showSecretVersion(new ShowSecretVersionRequest().withSecretName(secretName).withVersionId("latest"));
            String secretString = latestVersionValue.getVersion().getSecretString();
            JsonObject jsonObject = new Gson().fromJson(secretString, JsonObject.class);
            return DriverManager.getConnection(jdbcUrl, jsonObject.get("username").getAsString(), jsonObject.get("password").getAsString());
        }