
# 如何使用凭据管理服务自动轮转安全密码
本文详细介绍了利用函数工作流和凭据管理服务定期生成和轮转强安全密码的方法，以确保符合安全合规要求。该流程涉及定时触发器的使用、新密码的生成与存储、应用程序通过API获取最新凭据并更新目标对象的密码。文中还提供了创建委托、配置密码轮转函数的具体步骤，包括参数配置、环境变量设置和代码示例。此外，本文还提供了如何调试函数工作流、创建触发器、查看凭据及其值的方法。
#### 使用流程
图1轮转密码流程   
![](https://support.huaweicloud.com/bestpractice-dew/zh-cn_image_0000001867970233.png "点击放大")
流程说明如下：
1. 定时触发器到期后，会发布定时触发事件。
2. 函数工作流接收到事件后，会生成新的随机密码，替换凭据模板内容中的占位符，随后将替换后的内容作为新版本存入凭据中。
3. 应用程序定期通过调用API/SDK获取最新凭据版本。
4. 凭据管理服务检索并解密凭据密文，将凭据中保存的信息通过凭据管理API安全地返回到应用程序中。
5. 应用程序获取到解密后的凭据明文信息，使用新密码更新目标对象（数据库、服务器等），使新密码生效，后续使用新密码对目标对象进行访问。
 
#### 约束条件
- 区域已上线凭据管理服务（CSMS）。
- 区域已上线函数工作流服务（FunctionGraph）。
 
 #### 创建委托
1. [登录管理控制台](https://console.huaweicloud.com)。
2. 单击页面左侧的![](https://support.huaweicloud.com/bestpractice-dew/zh-cn_image_0000002682937681.png "点击放大")，选择"管理与监管 \> 统一身份认证服务"，进入"用户"界面。
3. 在左侧导航栏选择"委托"， 进入委托页面。
4. 单击"创建委托"，进入"创建委托"页面，如[图 创建委托]所示，填写参数，参数说明如[表 创建委托参数说明]所示。
   
   图2创建委托
   ![](https://support.huaweicloud.com/bestpractice-dew/zh-cn_image_0000002276187526.png "点击放大")
    表1创建委托参数说明 
   | 参数   | 配置说明                           |
   |:---|:---|
   | 委托名称 | 可自定义。                          |
   | 委托类型 | 选择"云服务"。                       |
   | 云服务  | 选择"FunctionGraph"。             |
   | 持续时间 | 由函数使用场景决定。如函数需要长时间执行，推荐选择"永久"。 |
   | 描述   | 自定义。                           |
      
   
   
5. 单击"完成"，并在弹框中单击"立即授权"，进入"授权"页面。
6. 勾选需要授权函数工作流的"CSMS FullAccess"、"KMS CMKFullAccess"权限。 
   图3选择授权权限   
   ![](https://support.huaweicloud.com/bestpractice-dew/zh-cn_image_0000001881478781.png "点击放大")
   
   
7. 单击"下一步"，根据业务需要选择授权范围。 
   图4选择授权范围   
   ![](https://support.huaweicloud.com/bestpractice-dew/zh-cn_image_0000001834646484.png "点击放大")
   
   
8. 单击"确定"，委托创建成功。
 
 #### 创建密码轮转函数
1. [登录管理控制台](https://console.huaweicloud.com)。
2. 单击页面左侧的![](https://support.huaweicloud.com/bestpractice-dew/zh-cn_image_0000002653057920.png "点击放大")，选择"计算 \> 函数工作流"，进入"函数工作流"界面。
3. 单击页面右上角的"创建函数"，进入创建函数页面，如[图 创建函数]所示，填写参数，参数说明如[表 基本信息参数配置]所示。
   
   图5创建函数   
   ![](https://support.huaweicloud.com/bestpractice-dew/zh-cn_image_0000001834810760.png "点击放大")
    表2基本信息参数配置 
   | 参数   | 配置说明                                                                                                                                                                                   |
   |:---|:---|
   | 区域   | 选择函数部署的区域。                                                                                                                                                                             |
   | 项目   | 选择函数部署的项目。                                                                                                                                                                             |
   | 函数名称 | 自定义函数名称。                                                                                                                                                                               |
   | 委托名称 | 选择[创建委托]的委托名称。                                                                                                                                     |
   | 企业项目 | 如果您已开通企业项目，选择需要添加函数的企业项目即可。 如果您未开通企业项目，控制台默认不显示"企业项目"，可直接跳过该参数。如需开通企业项目，请参考[如何开通企业项目/企业多账号](https://support.huaweicloud.com/usermanual-em/em_am_0008.html)。 |
   | 运行时  | 选择用来编写函数的语言，当前支持使用Python进行代码配置。 说明： 仅支持使用Python 3.6、3.9、3.10版本。                                                             |
      
   
   
4. 单击"创建函数"，进入函数配置界面。
5. 单击"设置"页签，在左侧导航栏单击"环境变量"。单击"添加环境变量"，在变量配置行添加环境变量，参数说明如[表 基本信息参数配置]所示。添加完成后单击"保存"。
   
   表3环境变量配置 
   | 参数              | 配置说明                                                                                                                                                                                                                                    | 示例                                  |
   |:---|:---|:---|
   | region          | 项目名称，比如北京四对应：cn-north-4。单击页面右上角用户名，在下拉框中选择我的凭证，即可查看region信息。                                                                                                                                                                            | cn-north-4                          |
   | secret_name     | 待轮转的凭据名称。 说明： 需提前完成创建凭据操作。具体请参见[创建凭据](https://support.huaweicloud.com/usermanual-dew/dew_01_9993.html)。                                                                        | rds-functionGraph-rotate            |
   | secret_content  | 指定的凭据模板内容，需用{}指定，比如：{"password":"password_placeholder"}其中password_placeholder为占位符，函数执行后会将password_placeholder替换为生成的安全密码，并将替换后的内容整体存入凭据中。 说明： 当凭据模板内容中存在多个占位符时，会生成多个密码并依次进行替换。 | {"password":"password_placeholder"} |
   | password_length | 密码长度，可选范围8-128，默认为16。                                                                                                                                                                                                                   | 16                                  |
   | password_format | 密码格式，共支持四种，可选，默认为2： 1. 包含数字和字母； 2. 包含数字、字母和特殊字符（\~!@#%\^\*-_=+?）； 3. 只包含数字； 4. 只包含字母。                                       | 2                                   |
      
   
   
6. 单击"代码"页签，并在编辑窗口中添加如下密码轮转函数，完成后单击"部署"。 
   ```
   # -*- coding:utf-8 -*-
   import json
   import secrets
   import string
   import requests
   import inspect
    
   def handler (event, context):
       global secret_content
       global password_length
       global password_format
       global kms_endpoint
       global region
       global secret_name
       global headers
       region = context.getUserData('region')
       secret_name = context.getUserData('secret_name')
       password_length = 16 if context.getUserData('password_length') is None else int(context.getUserData('password_length'))
       password_format = 2 if context.getUserData('password_format') is None else int(context.getUserData('password_format'))
       secret_content = context.getUserData('secret_content')
       headers = {
           'Content-Type': 'application/json',
           'x-Auth-Token': context.getToken()
       }
       try:
           new_content = replace_old_content(secret_content)
           # check region, if pass, return kms endpoint
           kms_endpoint = check_region(region)
           return update(context, new_content)
       except Exception as e:
           print("ERROR: %s" % e)
           return 'FAILED'
    
   # replace "password_placeholder" in secret_content by new password
   def replace_old_content(content):
       while content.find("password_placeholder") != -1:
           password = generate_password()
           while password.find("password_placeholder") != -1:
               password = generate_password()
           content = content.replace("password_placeholder", password, 1)
       return content
       
   def generate_password():
       special_chars = "~!@#%^*-_=+?"
       # password format(default is 2): 
       # 1.support letters and digits; 2.support letters, digits and special chars(~!@#%^*-_=+?);
       # 3.only support digits; 4.only support letters
       format_mapping = {
           1: string.ascii_letters + string.digits,
           2: string.ascii_letters + string.digits + special_chars,
           3: string.digits,
           4: string.ascii_letters
       }
       if password_length < 8 or password_length > 128:
           raise Exception("invalid password_length: %s, the password length range must be between 8-128." % password_length)
       try:
           support_chars = format_mapping[password_format]
           password = ''.join([secrets.choice(support_chars) for _ in range(password_length)])
           return password
       except:
           raise Exception("invalid password_format: %s." % password_format)
       
   def check_region(region):
       endpoint_mapping = {
           'cn-north-1': 'cn-north-1.myhuaweicloud.com',
           'cn-north-2': 'cn-north-2.myhuaweicloud.com',
           'cn-north-4': 'cn-north-4.myhuaweicloud.com',
           'cn-north-7': 'cn-north-7.myhuaweicloud.com',
           'cn-north-9': 'cn-north-9.myhuaweicloud.com',
           'cn-east-2': 'cn-east-2.myhuaweicloud.com',
           'cn-east-3': 'cn-east-3.myhuaweicloud.com',
           'cn-south-1': 'cn-south-1.myhuaweicloud.com',
           'cn-south-2': 'cn-south-2.myhuaweicloud.com',
           'cn-southwest-2': 'cn-southwest-2.myhuaweicloud.com',
           'ap-southeast-1': 'ap-southeast-1.myhuaweicloud.com',
           'ap-southeast-2': 'ap-southeast-2.myhuaweicloud.com',
           'ap-southeast-3': 'ap-southeast-3.myhuaweicloud.com',
           'af-south-1': 'af-south-1.myhuaweicloud.com',
           'la-north-2': 'la-north-2.myhuaweicloud.com',
           'la-south-2': 'la-south-2.myhuaweicloud.com',
           'na-mexico-1': 'na-mexico-1.myhuaweicloud.com',
           'sa-brazil-1': 'sa-brazil-1.myhuaweicloud.com'
       }
       try:
           endpoint = endpoint_mapping[region]
           kms_endpoint = '%s.%s' % ('kms', endpoint)
           return kms_endpoint
       except:
           raise Exception("invalid region: %s" % region)
    
   def check_csms_resp(resp):
       if resp.status_code in (200, 201, 204):
           return
       caller_function_name = inspect.stack()[1].function
       json_resp = json.loads(resp.text)
       if 'error_msg' in json_resp:
           error_message = 'function:%s , reason: %s' % (
               caller_function_name, json_resp['error_msg'])
           raise Exception(error_message)
       error_message = 'function:%s , reason: %s' % (
           caller_function_name, resp.text)
       raise Exception(error_message)
    
   def update(context, new_content):
       project_id = context.getProjectID()
       url = 'https://%s/v1/%s/secrets/%s/versions' % (kms_endpoint, project_id, secret_name)
       payload = {'secret_string': new_content}
       payload = json.dumps(payload)
       resp = requests.post(url, headers=headers, data=payload)
       check_csms_resp(resp)
       return 'SUCCESS'
   ```
   
   
 
#### 调试
需对创建的函数工作流进行调试，具体请参见[在线调试](https://support.huaweicloud.com/usermanual-functiongraph/functiongraph_01_0302.html)。
#### 创建触发器
需创建触发器，具体请参见[使用定时触发器](https://support.huaweicloud.com/usermanual-functiongraph/functiongraph_01_0207.html)。
#### 查看凭据
1. [登录DEW服务控制台](https://console.huaweicloud.com/dew/?locale=zh-cn#/dew/)。
2. 在左侧导航树中，选择"凭据管理 \> 凭据列表"，进入"凭据管理"页面。
3. 在凭据列表查找指定凭据，即[创建密码轮转函数]中secret_name对应凭据。
4. 单击凭据名称，进入凭据详情页面，即可查看凭据当前版本以及历史版本等信息。 
   图6查看凭据信息   
   ![](https://support.huaweicloud.com/bestpractice-dew/zh-cn_image_0000001881597661.png "点击放大")
   
   
5. 在当前版本区域，单击"查看凭据值"，即可查看当前生效的安全密码。 
   图7查看凭据值
   ![](https://support.huaweicloud.com/bestpractice-dew/zh-cn_image_0000002262742217.png "点击放大")
   
   
 
