Observação:
- Este tutorial requer acesso ao Oracle Cloud. Para se inscrever 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.
Gravar Logs no Stream Privado do Oracle Cloud Infrastructure usando o Oracle Cloud Infrastructure Functions
Introdução
Os logs são a base das operações modernas na nuvem, fornecendo insights críticos sobre a atividade, o desempenho e a segurança do sistema. Para empresas que lidam com dados confidenciais, o gerenciamento de logs com segurança e eficiência é fundamental. Este tutorial irá guiá-lo na criação de uma arquitetura segura, escalável e orientada a eventos para gerenciamento de logs usando a Oracle Cloud Infrastructure (OCI).
No centro dessa solução estão o OCI Functions, que garante que os logs sejam transmitidos e processados com segurança sem exposição a pontos finais públicos. A arquitetura é orientada por eventos de logs coletados e compactados no OCI Object Storage por meio do OCI Connector Hub. Cada vez que um arquivo de log é criado, ele aciona um OCI Functions, que o descompacta, divide em blocos gerenciáveis e publica os logs em um fluxo privado para armazenamento seguro ou processamento adicional.
Essa abordagem orientada a eventos garante um pipeline contínuo e automatizado em que os componentes reagem dinamicamente às mudanças, minimizando a latência e maximizando a eficiência. Ao aproveitar os serviços nativos da OCI, você obterá uma estrutura segura e escalável para lidar com processamento de log de alto volume em tempo real.
Objetivo
- Implemente um fluxo de trabalho de gerenciamento de log resiliente e seguro projetado para empresas que buscam proteger dados de log confidenciais e otimizar operações em seu ambiente de nuvem.
Pré-requisitos
-
Acesso a uma tenancy do OCI.
-
Privilégios para gerenciar os serviços OCI Object Storage, OCI logs, OCI Connector Hub, regras do OCI Event Service, Oracle Applications e OCI Streaming.
Tarefa 1: Configurar as Políticas Necessárias e as Permissões do OCI IAM (Oracle Cloud Infrastructure Identity and Access Management)
Cada componente desta solução deve ter acesso aos recursos do OCI com os quais interage. Para seguir este tutorial, as permissões a seguir são necessárias.
-
Políticas do Usuário: Gerenciar OCI Object Storage, OCI Connector Hub, regras do OCI Event Service, logs do OCI, OCI Functions e fluxos do OCI. Use no OCI Vault (opcional) e na família de redes.
-
Política de Serviço: Conceda à função permissão para ler mensagens do bucket do OCI Object Storage (ler objetos) e gravar em um stream (usar stream-push). É necessário um grupo dinâmico.
Políticas detalhadas podem ser encontradas aqui:
Tarefa 2: Criar um Fluxo Privado
O OCI Streaming é um serviço da OCI totalmente gerenciado no qual os dados são criptografados em repouso e em trânsito, garantindo a integridade e a segurança das mensagens. Para maior segurança, você pode usar o serviço OCI Vault para armazenar e gerenciar suas próprias chaves de criptografia, atendendo a requisitos específicos de conformidade ou segurança. Os pontos finais privados podem ser configurados em uma VCN (Rede Virtual na Nuvem) para proteger ainda mais seus streams, associando um endereço IP privado ao pool de streams. Isso garante que o tráfego do OCI Streaming permaneça dentro da VCN, evitando totalmente a internet. No entanto, observe que os streams que usam pontos finais privados não são acessíveis pela internet, limitando a capacidade de exibir suas mensagens mais recentes por meio do console. Para consumir mensagens de um fluxo privado, o consumidor deve ter roteamento e acesso à rede em que o fluxo privado está hospedado.
Criar um stream e um pool de streams. Digite Stream Name e selecione Criar Novo Pool de Streams para criar o pool de streams. Na seção Configurar Pool de Streams, digite Nome do Pool de Streams, selecione Ponto Final Privado e digite VCN e Sub-rede e os detalhes da rede adequadamente. Embora opcional, recomendamos fornecer a um Grupo de Segurança de Rede uma regra de entrada para todo o tráfego dentro desse NSG. Para obter mais informações, consulte Criar Stream e Criar Pool de Streams.
Você pode usar suas próprias chaves de criptografia, obtendo maior controle sobre o ciclo de vida da chave. Você tem a opção de ajustar a retenção de mensagens dentro do stream. O padrão é 1 dia e o máximo é 7 dias.
Anote o OCID do fluxo e o ponto final das mensagens. Precisamos passar essas informações para a função.
Tarefa 3: Criar e Configurar o OCI Connector Hub
O OCI Connector Hub atua como um barramento de mensagens seguro, facilitando a transferência de dados perfeita e confiável entre uma origem e um destino. Nessa arquitetura, a origem é o OCI Logging e o destino é o OCI Object Storage, em que esses logs são compactados e armazenados para processamento adicional. Ao servir como intermediário, o OCI Connector Hub garante um fluxo de dados eficiente, mantendo a segurança e a integridade das mensagens transferidas.
Este tutorial pressupõe que os logs de fluxo estejam ativados nas sub-redes e que um bucket do OCI Object Storage esteja disponível. Para obter mais informações sobre como ativar logs de fluxo e criar um bucket, consulte Ativando Logs de Fluxo e Criando um Bucket do Serviço Object Storage.
Ao criar um bucket, certifique-se de selecionar Emitir Eventos de Objeto. Essa é a chave para nossa arquitetura orientada a eventos.
Configurar o hub do OCI Connector, criando um fluxo de dados entre o serviço OCI Logging e o bucket do OCI Object Storage. Para obter mais informações, consulte Criando um Conector com uma Origem de Log.
Ao ajustar os detalhes de rolagem do batch, você pode configurar a frequência com a qual os logs são gravados no bucket do OCI Object Storage. O padrão é 100 MB ou 7 minutos.
Tarefa 4: Desenvolver e Implantar a Função
Essa função lerá o objeto do OCI Object Storage e gravará a mensagem no stream. Para conseguir isso, ele executa as seguintes operações entre:
- Leia o objeto no bucket.
- Descompacte o objeto.
- Verifique o tamanho do objeto e crie blocos de 1 MB, se necessário. O serviço OCI Streaming limita o tamanho máximo de uma mensagem exclusiva que os produtores podem publicar em um stream a 1 MB.
- Codifique a mensagem.
- Publicar no fluxo.
Para obter mais informações, consulte Criando funções.
-
func.py
:import io import json import logging import oci import gzip from base64 import b64encode def handler(ctx, data: io.BytesIO = None): try: # Parse the incoming data cfg = ctx.Config() body = json.loads(data.getvalue()) bucket_name = body["data"]["additionalDetails"]["bucketName"] object_name = body["data"]["resourceName"] stream_ocid = cfg["stream_ocid"] stream_endpoint = cfg["stream_endpoint"] logging.getLogger().info(f'Function invoked for bucket upload: {bucket_name}') except (Exception, ValueError) as ex: logging.getLogger().error(f'Error parsing JSON payload: {str(ex)}') return {"status": 400, "message": "Bad Request"} try: # Get the object data from Object Storage object_content = get_object(bucket_name, object_name) # Check if the object is a .gz file and decompress it if object_name.endswith('.gz'): logging.getLogger().info(f'Decompressing object: {object_name}') object_content = gzip.decompress(object_content) logging.getLogger().info(f'Object Content: {object_content.decode("utf-8")[:100]}...') # Split content into message chunks ensuring no message is split messages = split_content_into_messages(object_content, max_size=1024*1024) # Publish messages to the stream for message in messages: publish_to_stream(stream_ocid, stream_endpoint, data.getvalue().decode('utf-8'), message) return {"status": 200, "message": "Successfully processed object update"} except Exception as ex: logging.getLogger().error(f'Error processing object: {str(ex)}') return {"status": 500, "message": "Internal Server Error"} def get_object(bucket_name, object_name): signer = oci.auth.signers.get_resource_principals_signer() object_storage_client = oci.object_storage.ObjectStorageClient(config={}, signer=signer) namespace = object_storage_client.get_namespace().data try: logging.getLogger().info(f'Searching for bucket: {bucket_name}, object: {object_name}') obj = object_storage_client.get_object(namespace, bucket_name, object_name) logging.getLogger().info(f'Found object: {object_name}') return obj.data.content except Exception as ex: logging.getLogger().error(f'Failed to retrieve object: {str(ex)}') raise def publish_to_stream(stream_ocid, stream_endpoint, event_data, object_content): signer = oci.auth.signers.get_resource_principals_signer() stream_client = oci.streaming.StreamClient(config={}, signer=signer, service_endpoint=stream_endpoint) # Build the message list message_list = [ oci.streaming.models.PutMessagesDetailsEntry( key=b64encode("partition-key-1".encode()).decode(), value=b64encode(object_content).decode() ), ] try: logging.getLogger().info(f"Publishing {len(message_list)} messages to stream {stream_ocid}") put_message_details = oci.streaming.models.PutMessagesDetails(messages=message_list) put_message_result = stream_client.put_messages(stream_ocid, put_message_details) # Log publishing results for entry in put_message_result.data.entries: if entry.error: logging.getLogger().error(f"Error publishing message: {entry.error_message}") else: logging.getLogger().info(f"Published message to partition {entry.partition}, offset {entry.offset}") except Exception as ex: logging.getLogger().error(f"Failed to publish messages to stream: {str(ex)}") raise def split_content_into_messages(content, max_size): """ Splits content into messages of specified max size while ensuring no message is split. Attempts to split based on newline characters for text content. """ messages = [] current_chunk = [] current_size = 0 for line in content.decode('utf-8').splitlines(keepends=True): line_size = len(line.encode('utf-8')) if current_size + line_size > max_size: messages.append(''.join(current_chunk).encode('utf-8')) current_chunk = [line] current_size = line_size else: current_chunk.append(line) current_size += line_size if current_chunk: messages.append(''.join(current_chunk).encode('utf-8')) return messages
-
func.yaml
:schema_version: 20180708 name: logs-to-pvt-stream version: 0.0.1 runtime: python build_image: fnproject/python:3.9-dev run_image: fnproject/python:3.9 entrypoint: /python/bin/fdk /function/func.py handler memory: 256 config: stream_ocid: ocid1.stream.123445 stream_endpoint: https://xyz.us-ashburn-1.oci.oraclecloud.com
-
requirements.txt
:fdk oci
O passo final é dizer a função onde o fluxo privado está. Esta função usa parâmetros de configuração, tornando-a reutilizável se você quiser implantar em outra tenancy.
Tarefa 5: Criar um Evento e Inscrever-se na Função
Nesta tarefa, inscreva a função no evento de upload do objeto. Crie uma regra para Tipo de Evento como Objeto - Criar com o nome do bucket como um atributo condicional. Para obter mais informações, consulte Criando uma Regra de Eventos.
Verificação
Há vários locais onde o fluxo de dados pode ser verificado.
-
Verifique as métricas do grupo de logs para verificar se os logs do fluxo estão ingeridos.
-
O próximo salto são as métricas do hub do conector. O OCI Connector Hub coleta os logs e os envia para o OCI Object Storage. Certifique-se de que não haja erros na origem e no destino.
-
O próximo salto é o OCI Object Storage. Certifique-se de que a contagem de objetos esteja aumentando. Se necessário, ative os logs de leitura e gravação para depurar ainda mais.
-
O próximo salto é o OCI Events Service. Revise as métricas para garantir que não haja falhas na entrega.
-
A próxima etapa é verificar as métricas de Chamada da função. Certifique-se de que não haja erros e que a função não seja de limitação.
-
Verifique se os dados estão sendo ingeridos no fluxo privado.
Se os dados estiverem ausentes em qualquer um dos gráficos a seguir, pare por aí e ative os logs desse serviço. Os logs explicarão por que um recurso específico está falhando ao executar a tarefa.
Próximas Etapas
Parabéns por implementar com sucesso uma solução de gerenciamento de logs segura e orientada por eventos na OCI! Combinando o poder do OCI Logging, do OCI Connector Hub, do OCI Object Storage e dos fluxos privados da OCI, você criou uma arquitetura robusta que garante que seus logs sejam coletados, processados e publicados com segurança quase em tempo real.
Essa solução protege dados de log confidenciais por meio de fluxos privados e demonstra a eficiência da automação orientada a eventos. À medida que seu sistema se dimensiona, essa arquitetura se adaptará perfeitamente, permitindo que você lide com grandes volumes de logs com o mínimo de intervenção manual.
Com essa estrutura em vigor, você pode garantir um processamento de log seguro e eficiente, mantendo a conformidade com os requisitos de privacidade. Essa arquitetura fornece flexibilidade para criar pipelines de processamento personalizados adequados às necessidades de sua empresa. Estender essa configuração com mecanismos adicionais de análise ou alerta pode obter insights mais profundos sobre os eventos do sistema e aprimorar sua capacidade de detectar e responder a anomalias de forma proativa.
Para obter mais informações sobre o uso do OCI Functions e dos recursos de fluxo privado do OCI, entre em contato com o representante da Oracle ou consulte Soluções de Segurança em Nuvem.
Confirmações
- Autor - Aneel Kanuri (Arquiteto de Nuvem Distinto)
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.
Write Logs to Oracle Cloud Infrastructure Private Stream using Oracle Cloud Infrastructure Functions
G23245-01
December 2024