Uso de CSMS para rotar automáticamente contraseñas de seguridad
En esta sección se describe cómo puede utilizar FunctionGraph y CSMS para generarse, alojarse y rotarse automáticamente las contraseñas seguras y conformes.
Proceso

El proceso es el siguiente:
- Cuando caduca un temporizador, se publica un evento activado programado.
- Después de recibir el evento, FunctionGraph reemplaza el marcador de posición en la plantilla del secreto por una nueva contraseña aleatoria y la almacena en el secreto, que se considera una nueva versión del secreto.
- Las aplicaciones invocan periódicamente a las API o los SDK para obtener la versión del secreto más reciente.
- CSMS recupera y descifra el texto cifrado del secreto y devuelve de forma segura la información almacenada en el secreto a la aplicación a través de la API de gestión de secretos.
- Después de recibir el secreto descifrado, las aplicaciones utilizan la nueva contraseña para acceder en el futuro y la utilizan para actualizar el objeto de destino (como la base de datos o el servidor).
Restricciones
- El CSMS está disponible en la región.
- FunctionGraph está disponible en la región.
Creación de una delegación
- Inicie sesión en la consola de gestión.
- Haga clic en
a la izquierda y seleccione para acceder a la página Users.
- En el panel de navegación situado a la izquierda, seleccione Agencies.
- Haga clic en Create Agency y configure los parámetros como se muestra en Figura 2. Tabla 1 describe los parámetros.
Tabla 1 Parámetros de delegación Parámetro
Descripción
Agency Name
Configure este parámetro según sea necesario.
Agency Type
Seleccione Cloud service.
Cloud Service
Seleccione FunctionGraph.
Validity Period
Configure este parámetro según el escenario de aplicación de la función. Si la función debe ejecutarse durante mucho tiempo, seleccione Unlimited.
Description
Configure este parámetro según sea necesario.
- Haga clic en Next.
- Seleccione CSMS FullAccess y KMS CMKFullAccess.
Figura 3 Selección de permisos
- Haga clic en Next y seleccione un alcance basado en sus requerimientos de servicio.
Figura 4 Selección de un ámbito
- Haga clic en OK.
Creación de una función de rotación de contraseña
- Inicie sesión en la consola de gestión.
- Haga clic en
a la izquierda y seleccione .
- Haga clic en Create Function en la esquina superior derecha y configure los parámetros como se muestra en Figura 5. Tabla 2 describe los parámetros.
Tabla 2 Parámetros básicos Parámetro
Descripción
Region
Seleccione la región donde se despliega la función.
Project
Seleccione el proyecto en el que se despliega la función.
Function Name
Introduzca un nombre de función personalizado.
Agency
Ingrese el nombre definido en Creación de una delegación.
Enterprise Project
Si habilitó los proyectos empresariales, seleccione uno para agregarle una función.
Si no ha habilitado proyectos de empresa, este parámetro no se mostrará. Omita este paso. Para obtener más detalles sobre cómo habilitar un proyecto empresarial, consulte Habilitación del centro empresarial.
Runtime
Seleccione un idioma para escribir la función. Actualmente, se soporta Python.
NOTA:
Solo se soportan Python de las versiones 3.6, 3.9 y 3.10.
- Haga clic en Create Function.
- Seleccione la pestaña Configuration. En el panel de navegación de la izquierda, seleccione Environment Variables. Haga clic en Add y agregue variables de entorno en la fila de configuración de variables. Tabla 2 describe los parámetros. Luego, haga clic en Save.
Tabla 3 Variables del entorno Parámetro
Descripción
Ejemplo
region
Nombre del proyecto basado en la región. Por ejemplo, si la región es CN North-Beijing4, el nombre del proyecto debe ser cn-north-4. Para obtener su región, haga clic en su nombre de usuario en la esquina superior derecha de la página y seleccione My Credentials en la lista desplegable.
cn-north-4
secret_name
Nombre del secreto que se va a rotar
rds-functionGraph-rotate
secret_content
Plantilla del secreto que se especifica con llaves ({}), por ejemplo, la plantilla del secreto es {"password":"password_placeholder"}. En este caso, password_placeholder es el marcador de posición, que será reemplazado por una contraseña segura una vez ejecutada la función. El nuevo contenido se guardará en secreto después del reemplazo.
NOTA:
Si existen varios marcadores de posición en una plantilla, se generará y reemplazará más de una contraseña en secuencia.
{"password":"password_placeholder"}
password_length
Longitud de la contraseña. El valor oscila entre 8 y 128. 16 es el valor predeterminado.
16
password_format
Formato de la contraseña. 2 es el valor predeterminado. Los valores posibles son los siguientes:
1. Dígitos y letras
2. Dígitos, letras y caracteres especiales (~!@#%^*-_=+?)
3. Solo dígitos
4. Solo letras
2
- Seleccione la pestaña Code, agregue la siguiente función de rotación de contraseña a la ventana de edición y haga clic en Deploy.
# -*- 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'
Depuración
Se utiliza en el FunctionGraph creado. Para obtener más detalles, consulte Depuración online.
Creación de un activador
Crear un activador. Para obtener más detalles, consulte Uso de un activador de temporizador.
Consulta de un secreto
- Inicie sesión en la consola de gestión.
- Haga clic en
a la izquierda, elija , se mostrará la página de gestión de claves.
- En el panel de navegación, elija Cloud Secret Management Service.
- Buscar el secreto creado en Creación de una función de rotación de contraseña.
- Haga clic en el secreto para ver sus detalles, incluidas las versiones actual e histórica.
Figura 6 Consulta de detalles de secretos
- En Version, localice el secreto y haga clic en View Secret en la columna Operation para ver la contraseña.
Figura 7 Consulta de un valor del secreto