Observação:
- Este tutorial requer acesso ao Oracle Cloud. Para se cadastrar em uma conta gratuita, consulte Conceitos básicos do Oracle Cloud Infrastructure Free Tier.
- Ele usa valores de exemplo para credenciais, tenancy e compartimentos do Oracle Cloud Infrastructure. Ao concluir seu laboratório, substitua esses valores por valores específicos do seu ambiente de nuvem.
Ativar a Rotação Automática das Credenciais do Oracle Cloud Infrastructure Identity and Access Management
Introdução
Este tutorial ajuda a rotacionar automaticamente as credenciais do Oracle Cloud Infrastructure Identity and Access Management (OCI IAM) que são chave de API, token de Autenticação, chaves secretas do Cliente e senhas de log-in da Console do OCI. Ele se baseia na correção de problemas do Oracle Cloud Guard e no serviço OCI Notifications. Ele também preenche a lacuna das regras padrão do respondedor para rotacionar as credenciais do OCI IAM.
O Oracle Cloud Guard detecta problemas com base nas regras definidas nas políticas. Quando uma regra é satisfeita, ela cria um problema.
É uma prática recomendada de segurança e recomendada pelo The Center for Internet Security Oracle Cloud Infrastructure Foundations (CIS OCI Foundations) Benchmark para rotacionar as credenciais a cada 90 dias.
Observação: Esta solução foi testada para um domínio de identidades padrão.
Objetivos
-
Rotacione o token de Autenticação do OCI (Oracle Cloud Infrastructure), a chave de API, a chave secreta do Cliente e a senha da Console do OCI por meio da automação corrigindo o problema do Oracle Cloud Guard. Os problemas do Oracle Cloud Guard a seguir são utilizados para rotação automática de credenciais do OCI IAM.
- A chave API é muito antiga
- O token de Autenticação do IAM é muito antigo
- A chave secreta do Cliente do IAM é muito antiga
- A senha é muito antiga
Pré-requisitos
O administrador do OCI IAM deve criar:
-
Grupo dinâmico e políticas para que o OCI Functions chame, corrija o problema e envie notificações por e-mail.
-
Grupo Dinâmico: Crie um grupo dinâmico para o compartimento de funções. Para obter mais informações, consulte Criando um Grupo Dinâmico.
# Replace OCID for function compartment All {resource.type = 'fnfunc', resource.compartment.id = '<function-compartment>'} Example: All {resource.type = 'fnfunc', resource.compartment.id = 'ocid1.compartment.oc1..aaaaaaaanovmfmmnonjjyxeq4jyghszj2eczlrkgj5svnxrt...'}
-
Políticas: Crie políticas para designar um grupo dinâmico para a função. Para obter mais informações, consulte Conceitos Básicos de Políticas.
# Replace dynamic-group-name, function-compartment and OCID of vault secret for OCI function Allow dynamic-group <dynamic-group-name> to inspect compartments in tenancy Allow dynamic-group <dynamic-group-name> to inspect users in tenancy Allow dynamic-group <dynamic-group-name> to manage users in tenancy where any {request.permission = 'USER_UPDATE', request.permission = 'USER_AUTHTOKEN_SET', request.permission = 'USER_AUTHTOKEN_REMOVE', request.permission = 'USER_SECRETKEY_ADD', request.permission = 'USER_SECRETKEY_REMOVE', request.permission = 'USER_UIPASS_SET', request.permission = 'USER_APIKEY_ADD', request.permission = 'USER_APIKEY_REMOVE'} Allow dynamic-group <dynamic-group-name> to read repos in compartment <function-compartment> Allow dynamic-group <dynamic-group-name> to use secret-family in compartment <vault-compartment> where target.secret.id='<ocid of OCI vault secret to store rotated OCI secrets>' Allow dynamic-group <dynamic-group-name> to use ons-topics in tenancy
-
-
Compartimento, grupo e políticas para que o desenvolvedor crie segredos e implante a função.
# Replace group-name as per your tenancy Allow group <group-name> to manage repos in compartment <function-compartment> Allow group <group-name> to manage vaults in compartment <function-compartment> Allow group <group-name> to manage keys in compartment <function-compartment> Allow group <group-name> to manage secret-family in compartment <function-compartment> Allow group <group-name> to manage functions-family in compartment <function-compartment> Allow group <group-name> to use cloud-shell in tenancy Allow group <group-name> to use virtual-network-family in compartment <network-compartment> Allow group <group-name> to read objectstorage-namespaces in tenancy
-
Tópico de Notificações do OCI para a equipe SecOps receber notificações por e-mail.
-
Segredos do Oracle Cloud Infrastructure Secrets in Vault para armazenar credenciais rotacionadas do OCI IAM criadas pela automação.
Observação : Certifique-se de ter copiado as credenciais existentes do OCI IAM para os Segredos do Oracle Cloud Infrastructure Secrets in Vault antes de executar essa automação pela primeira vez.
Tarefa 1: Criar e Implantar o OCI Functions
-
Faça log-in na Console do OCI e clique em Cloud Shell na navegação superior.
Observação: Você também pode usar sua própria ferramenta IDE para criar e implantar uma função.
-
Crie uma função usando a CLI do projeto Fn do cloud shell. Para obter mais informações, consulte Criando, Implantando e Chamando uma Função Helloworld.
fn init --runtime python <function-name> Example: fn init --runtime python rotatecred-func
-
Altere o diretório para o diretório recém-criado.
-
Crie um aplicativo para implantar a função usando o comando a seguir.
# Specify the OCID of subnet fn create app <app-name> --annotation oracle.com/oci/subnetIds='["<subnet OCID>"]' Example: fn create app rotatecredapp --annotation oracle.com/oci/subnetIds='["ocid1.subnet.oc1.ap-mumbai-1.aaaaaaaabitp32dkyox37qa3tk3evl2nxivwb....."]'
-
Copie e cole o script a seguir em
func.py
substituindo o conteúdo existente.# python script for auto rotation of OCI IAM credentials import io import json import logging import oci import base64 from fdk import response from Cryptodome.PublicKey import RSA # Get Resource Principal Credentials signer = oci.auth.signers.get_resource_principals_signer() # Initialize client identity_client = oci.identity.IdentityClient(config={}, signer=signer) onsclient = oci.ons.NotificationDataPlaneClient(config={}, signer=signer) vault_client = oci.vault.VaultsClient(config={}, signer=signer) # Get tenancy id and name tenancy_data = identity_client.get_tenancy(tenancy_id=signer.tenancy_id).data t_name = str(tenancy_data.name) t_id = signer.tenancy_id # Get secret OCID from comments def get_secret_ocids(comments_items,find_name): secret_ocid = "" for comment in comments_items: if comment.split(":")[0] == find_name: secret_ocid = comment.split(":")[1] return secret_ocid # Function to store secret in OCI vault def update_secret(vault_client,secret_id,new_value): # Base64 encode new_token_ascii = new_value.encode("ascii") base64_bytes = base64.b64encode(new_token_ascii) base64_string = base64_bytes.decode("ascii") # Create new version of secret vault_client.update_secret(secret_id=secret_id,update_secret_details=oci.vault.models.UpdateSecretDetails(secret_content=oci.vault.models.Base64SecretContentDetails(content_type="BASE64", content=base64_string))) def handler(ctx, data: io.BytesIO=None): try: cfg = ctx.Config() ons_topic = cfg["ons_topic"] body = json.loads(data.getvalue()) # Get common parameters values e_time = str(body["eventTime"]).lstrip() problem_name = str(body["data"]["additionalDetails"]["problemName"]).lstrip() status = "NOT RESOLVED" resource_name = str(body["data"]["resourceName"]).lstrip() user_ocid = str(body["data"]["additionalDetails"]["problemAdditionalDetails"]["User OCID"]).lstrip() target_resource_name = str(body["data"]["additionalDetails"]["resourceName"]).lstrip() target_resource_id = str(body["data"]["additionalDetails"]["resourceId"]).lstrip() risk_level = str(body["data"]["additionalDetails"]["riskLevel"]).lstrip() comments = str(body["data"]["additionalDetails"]["problemAdditionalDetails"]["comments"]).lstrip() comments_items = comments.split(",") additional_details = "\r\r\nAction : Closure comments was not in required format hence, no action by automation." try: # Check Problem Type if problem_name == "PASSWORD_TOO_OLD": identity_client.create_or_reset_ui_password(user_id=user_ocid) additional_details = "\r\r\nAction : Your password has been reset by the System Administrator as per password policy rotation. Please set new password by clicking on forgot password from OCI console. " status = "RESOLVED" elif problem_name == "AUTH_TOKEN_TOO_OLD": auth_secret_ocid = get_secret_ocids(comments_items,"auth_secret_ocid") if auth_secret_ocid != "": # Delete existing auth token identity_client.delete_auth_token(user_id=user_ocid, auth_token_id=target_resource_id) # Create new auth token create_auth_token_response = identity_client.create_auth_token( create_auth_token_details=oci.identity.models.CreateAuthTokenDetails(description=target_resource_name),user_id=user_ocid).data new_value = create_auth_token_response.token # Store new auth token in vault secret update_secret(vault_client,auth_secret_ocid,new_value) additional_details = '\r\nAuth Token - Secret OCID : ' + auth_secret_ocid status = "RESOLVED" elif problem_name == "SECRET_KEY_TOO_OLD": access_id_secret_ocid = get_secret_ocids(comments_items, "accesskey_secret_ocid") secret_key_secret_ocid = get_secret_ocids(comments_items, "secretkey_secret_ocid") if access_id_secret_ocid != "" and secret_key_secret_ocid != "": # Delete existing customer secrete key delete_secret_key_response = identity_client.delete_customer_secret_key(user_ocid, target_resource_id).data # Create new customer secret key create_customer_secret_key_response = identity_client.create_customer_secret_key(create_customer_secret_key_details=oci.identity.models.CreateCustomerSecretKeyDetails(display_name=target_resource_name),user_id=user_ocid).data new_secret_key = str(create_customer_secret_key_response.key) new_access_key_id = str(create_customer_secret_key_response.id) # Store new customer secret key in vault secret update_secret(vault_client,secret_key_secret_ocid,new_secret_key) update_secret(vault_client,access_id_secret_ocid,new_access_key_id) additional_details = '\r\nAccess Key - Secret OCID : ' + access_id_secret_ocid + \ '\r\nSecret Key - Secret OCID : ' + secret_key_secret_ocid status = "RESOLVED" elif problem_name == "API_KEY_TOO_OLD": key_fingerprint = target_resource_id.split("/")[2] api_secret_ocid = get_secret_ocids(comments_items,"api_secret_ocid") if api_secret_ocid != "": key = RSA.generate(2048) key_private = key.exportKey() pubkey = key.publickey() key_public = pubkey.exportKey() # Delete existing API key delete_api_key_response = identity_client.delete_api_key(user_id=user_ocid,fingerprint=key_fingerprint) # Upload new public API key in OCI for the user upload_api_key_response = identity_client.upload_api_key(user_id=user_ocid, create_api_key_details=oci.identity.models.CreateApiKeyDetails( key=key_public.decode())) # Store content of new private key in vault secret update_secret(vault_client,api_secret_ocid,key_private.decode()) additional_details = '\r\nSecret OCID for private API key : ' + api_secret_ocid status = "RESOLVED" except Exception as e: additional_details = '\r\r\n Error: '+ str(e) # Message Body Customization, it can be updated as per need line_head = 'Oracle Cloud Notification' + '\n=====================' message_body = line_head + \ '\r\r\nProblem Name : ' + problem_name + \ '\r\r\nRisk Level : ' + risk_level + \ '\r\nEvent Time : ' + e_time + \ '\r\nTenancy Name : ' + t_name + \ '\r\nTenancy ID : ' + t_id + \ '\r\r\nAdditional Details : ' + '\n-------------------------' \ '\r\nResource Name : ' + target_resource_name + \ '\r\nResource ID : ' + target_resource_id + \ '\r\nResource User OCID : ' + user_ocid + ' ' + additional_details # Message Title message_title = 'Problem : ' + resource_name + ' | ' + status +' by automation ' # Message Detail message_details = oci.ons.models.MessageDetails(body=message_body, title=message_title) # Publish message to ONS onsclient.publish_message(ons_topic, message_details) except (Exception, ValueError) as ex: logging.getLogger().info('error parsing json payload: ' + str(ex)) return response.Response(ctx, response_data=json.dumps({"message": "success"}),headers={"Content-Type": "application/json"})
-
Atualize
requirements.txt
conforme mostrado abaixo.fdk>=0.1.59 oci pycryptodomex
-
Execute o comando a seguir para implantar a função.
fn -v deploy --app <app-name> Example: fn -v deploy --app rotatecredapp
-
Execute o comando a seguir para adicionar configuração de função para chave e valor de configuração.
ons_topic
: Use o OCID (Oracle Cloud Identifier) do tópico de notificação para receber notificação por e-mail.
fn config function <app-name> <function-name> <config-key> <config-value> Example: fn config function rotatecredapp rotatecred-func ons_topic ocid1.onstopic.oc1.ap-mumbai-1.aaaaaaaau3onlufcfz.......kae26637zovwd7q
Tarefa 2: Criar uma Regra de Eventos
-
Vá para a Console do OCI e clique em Observabilidade e Gerenciamento.
-
Em Serviço Events, clique em Regras e Criar Regra.
-
Na página Criar Regra, digite o Nome da regra e a Descrição do que a regra faz.
-
Na seção Condições da Regra, especifique as informações a seguir para especificar o tipo de evento e a ação para acionar a função.
- Condição:
Event Type
. - Nome do Serviço:
Cloud Guard
. - Tipo de Evento:
Remediated-Problem
. - Nome do Atributo:
ProblemRecommendation
. - Valores de Atributo:
Rotate IAM Console password regularly, at least every 90 days.
,Rotate IAM Auth token regularly, at least every 90 days.
,Rotate IAM Customer secret keys regularly, at least every 90 days.
,Rotate API keys regularly, at least every 90 days
.
A imagem a seguir é um exemplo do evento de correção de problemas do Oracle Cloud Guard.
- Condição:
Tarefa 3: Corrigir o Problema do Oracle Cloud Guard
-
Vá para a Console do OCI e clique em Identidade e Segurança.
-
Em Cloud Guard, clique em Problemas.
-
Clique em um dos problemas suportados para rotação automática.
-
Clique em Marcar como resolvido e especifique as informações a seguir na seção Comentário de acordo com o formato a seguir. É possível adicionar informações adicionais de acordo com o processo da organização, juntamente com as seguintes informações separadas por vírgulas (,).
-
A chave secreta do Cliente do IAM é muito antiga.
accesskey_secret_ocid:<OCID of access key secret>,secretkey_secret_ocid:<OCID of secret key secret>,<additional comments>
-
A chave API é muito antiga.
api_secret_ocid:<OCID of api key secret>,<additional comments>
-
O token de Autenticação do IAM é muito antigo.
auth_secret_ocid:<OCID of auth token secret>,<additional comments>
-
A senha é muito antiga.
Observação:
- Não há informações obrigatórias a serem incluídas nos comentários deste problema.
- A senha deve ser redefinida pelo usuário individual clicando em Esqueceu a senha no próximo log-in. O usuário deve ter um endereço de email válido para receber notificações por email.
-
Tarefa 4: Validar uma Nova Credencial do OCI IAM e Notificação por E-mail
Você receberá uma notificação por e-mail de resolução de problemas com detalhes do OCID do segredo rotacionado e informações adicionais.
Links Relacionados
Confirmação
-
Autor - Dipesh Kumar Rathod (Arquiteto de Nuvem Principal Mestre, Infraestrutura)
-
Colaborador - Bhanu Prakash Lohumi (Engenheiro Sênior de Nuvem, Infraestrutura)
Mais Recursos de Aprendizagem
Explore outros laboratórios em docs.oracle.com/learn ou acesse mais conteúdo de aprendizado gratuito no canal Oracle Learning YouTube. Além disso, visite education.oracle.com/learning-explorer para se tornar um Oracle Learning Explorer.
Para obter a documentação do produto, visite o Oracle Help Center.
Enable Auto Rotation of Oracle Cloud Infrastructure Identity and Access Management Credentials
F93268-01
February 2024
Copyright © 2024, Oracle and/or its affiliates.