Uso do CSMS para rotacionar automaticamente as senhas de segurança
Esta seção descreve como usar o FunctionGraph e o CSMS para gerar e rotacionar senhas seguras e fortes periodicamente, de modo que senhas seguras e em conformidade possam ser geradas, hospedadas e rotacionadas automaticamente.
Processo
O processo é o seguinte:
- Quando um temporizador expira, um evento de acionamento agendado é publicado.
- Depois de receber o evento, o FunctionGraph substitui o espaço reservado no modelo de segredo por uma nova senha aleatória e armazena a senha no segredo, que é considerada uma nova versão do segredo.
- As aplicações chamam periodicamente APIs ou SDKs para obter a versão de segredo mais recente.
- O CSMS recupera e descriptografa o texto cifrado de segredo e retorna com segurança as informações armazenadas no segredo para a aplicação por meio da API de gerenciamento de segredo.
- Depois de receber o segredo descriptografado, as aplicações usam a nova senha para acesso futuro usando-a para atualizar o objeto de destino (como o banco de dados ou o servidor).
Restrições
- O CSMS está disponível na região.
- O FunctionGraph está disponível na região.
Criação de uma agência
- Faça logon no console de gerenciamento.
- Clique em à esquerda e escolha para acessar a página Users.
- No painel de navegação à esquerda, escolha Agencies.
- Clique em Create Agency e configure os parâmetros conforme mostrado em Figura 2. Tabela 1 descreve os parâmetros.
Tabela 1 Parâmetros da agência Parâmetro
Descrição
Agency Name
Defina este parâmetro conforme necessário.
Agency Type
Selecione Cloud service.
Cloud Service
Escolha FunctionGraph.
Validity Period
Defina este parâmetro com base no cenário de aplicação da função. Se a função precisar ser executada por um longo tempo, escolha Unlimited.
Description
Defina este parâmetro conforme necessário.
- Clique em Next.
- Selecione CSMS FullAccess e KMS CMKFullAccess.
Figura 3 Seleção de permissões
- Clique em Next e selecione um escopo com base em seus requisitos de serviço.
Figura 4 Seleção de um escopo
- Clique em OK.
Criação de uma função de rotação de senha
- Faça logon no console de gerenciamento.
- Clique em à esquerda e escolha .
- Clique em Create Function no canto superior direito e configure os parâmetros conforme mostrado em Figura 5. Tabela 2 descreve os parâmetros.
Tabela 2 Parâmetros básicos Parâmetro
Descrição
Region
Selecione a região onde a função está implementada.
Project
Selecione o projeto no qual a função será implementada.
Function Name
Insira um nome de função personalizado.
Agency
Digite o nome definido em Criação de uma agência.
Enterprise Project
Se você ativou projetos empresariais, selecione um para adicionar uma função a ele.
Se você não ativou projetos empresariais, esse parâmetro não será exibido. Pule este passo. Para obter detalhes sobre como ativar um projeto empresarial, consulte Ativação da central empresarial.
Runtime
Selecione uma linguagem para escrever a função. Atualmente, o Python é suportado.
NOTA:Apenas Python 3.6, 3.9 e 3.10 são suportados.
- Clique em Create Function.
- Escolha a guia Configuration. No painel de navegação à esquerda, escolha Environment Variables. Clique em Add e adicione variáveis de ambiente na linha de configuração de variáveis. Tabela 2 descreve os parâmetros. Em seguida, clique em Save.
Tabela 3 Variáveis ambientais Parâmetro
Descrição
Exemplo
region
Nome do projeto que é baseado na região, por exemplo, se a região é CN North-Beijing4, o nome do projeto deve ser cn-north-4. Para obter sua região, clique em seu nome de usuário no canto superior direito da página e escolha My Credentials na lista suspensa.
cn-north-4
secret_name
Nome do segredo a ser rotacionado
NOTA:Um segredo deve ter sido criado. Para obter detalhes, consulte Criação de um segredo.
rds-functionGraph-rotate
secret_content
O modelo de segredo que é especificado usando chaves ({}), por exemplo, o modelo de segredo é {"password":"password_placeholder"}. Nesse caso, password_placeholder é o espaço reservado, que será substituído por uma senha segura após a execução da função. O novo conteúdo será salvo em segredo após a substituição.
NOTA:Se existirem vários espaços reservados em um modelo, mais de uma senha será gerada e substituída em sequência.
{"password":"password_placeholder"}
password_length
Comprimento da senha. O valor varia de 8 a 128. O valor padrão é 16.
16
password_format
Formato de senha. O valor padrão é 2. Os valores possíveis são os seguintes:
1. Dígitos e letras
2. Dígitos, letras e caracteres especiais (~!@#%^*-_=+?)
3. Apenas dígitos
4. Apenas letras
2
- Escolha a guia Code, adicione a seguinte função de rotação de senha à janela de edição e clique em 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'
Depuração
Depure o FunctionGraph criado. Para obter detalhes, consulte Depuração on-line.
Criação de um acionador
Crie um acionador. Para obter detalhes, consulte Uso de um acionador de temporizador.
Visualização de um segredo
- Faça logon no console de gerenciamento.
- Clique em à esquerda, escolha , a página de gerenciamento de chaves é exibida.
- No painel de navegação, escolha Cloud Secret Management Service.
- Pesquise o segredo criado em Criação de uma função de rotação de senha.
- Clique no segredo para ver seus detalhes, incluindo versões atuais e históricas.
Figura 6 Visualização de detalhes de segredos
- Na Version, localize o segredo e clique em View Secret na coluna Operation para exibir a senha.
Figura 7 Visualização de um valor de segredo