Recolha registos de auditoria da Oracle Cloud Infrastructure
Este documento explica como carregar registos de auditoria da Oracle Cloud Infrastructure para o Google Security Operations através do Amazon S3.
Antes de começar
Certifique-se de que cumpre os seguintes pré-requisitos:
- Instância do Google SecOps.
- Conta do Oracle Cloud Infrastructure com autorizações para criar e gerir:
- Service Connector Hub
- Oracle Functions
- Cofres e secrets
- Grupos dinâmicos e políticas de IAM
- Registo
- Conta da AWS com autorizações para criar e gerir:
- Contentores S3
- Utilizadores e políticas de IAM
Crie um contentor do Amazon S3
- Inicie sessão na AWS Management Console.
- Aceda a S3 > Criar contentor.
- Forneça os seguintes detalhes de configuração:
- Nome do contentor: introduza um nome exclusivo (por exemplo,
oci-audit-logs-bucket). - Região da AWS: selecione uma região (por exemplo,
us-east-1). - Mantenha as definições predefinidas para outras opções.
- Nome do contentor: introduza um nome exclusivo (por exemplo,
- Clique em Criar contentor.
- Guarde o Nome e a Região do contentor para utilização posterior.
Crie um utilizador do IAM na AWS para as funções da OCI
- Inicie sessão na AWS Management Console.
- Aceda a IAM > Utilizadores > Adicionar utilizadores.
- Forneça os seguintes detalhes de configuração:
- Nome de utilizador: introduza um nome de utilizador (por exemplo,
oci-functions-s3-user). - Tipo de acesso: selecione Chave de acesso – Acesso programático.
- Nome de utilizador: introduza um nome de utilizador (por exemplo,
- Clique em Seguinte: autorizações.
- Clique em Anexar políticas existentes diretamente.
- Pesquise e selecione a política AmazonS3FullAccess.
- Clique em Seguinte: Etiquetas.
- Clique em Seguinte: rever.
- Clique em Criar utilizador.
- Importante: na página de êxito, copie e guarde as seguintes credenciais:
- ID da chave de acesso
- Chave de acesso secreta
Armazene credenciais da AWS no OCI Vault
Para armazenar credenciais da AWS em segurança, tem de usar o Oracle Cloud Infrastructure Vault em vez de as codificar no código da função.
Crie um cofre e uma chave de encriptação principal
- Inicie sessão na Oracle Cloud Console.
- Aceda a Identidade e segurança > Cofre.
- Se não tiver um Vault, clique em Criar Vault.
- Forneça os seguintes detalhes de configuração:
- Criar no compartimento: selecione o seu compartimento.
- Nome: introduza um nome (por exemplo,
oci-functions-vault).
- Clique em Criar cofre.
- Depois de criar o cofre, clique no respetivo nome para o abrir.
- Em Chaves de encriptação principais, clique em Criar chave.
- Forneça os seguintes detalhes de configuração:
- Modo de proteção: software
- Nome: introduza um nome (por exemplo,
oci-functions-key). - Forma da chave: algoritmo: AES
- Formato da chave: comprimento: 256 bits
- Clique em Criar chave.
Crie segredos para credenciais da AWS
- No Vault, em Segredos, clique em Criar segredo.
- Faculte os seguintes detalhes de configuração para a chave de acesso da AWS:
- Criar no compartimento: selecione o seu compartimento.
- Nome:
aws-access-key - Descrição: chave de acesso da AWS para o S3
- Chave de encriptação: selecione a chave de encriptação principal que criou.
- Secret Type Contents: texto simples
- Conteúdos secretos: cole o ID da chave de acesso da AWS.
- Clique em Criar segredo.
- Copie e guarde o OCID deste segredo (tem o seguinte aspeto:
ocid1.vaultsecret.oc1...). - Clique novamente em Criar segredo para criar o segundo segredo.
- Faculte os seguintes detalhes de configuração da chave secreta da AWS:
- Criar no compartimento: selecione o seu compartimento.
- Nome:
aws-secret-key - Descrição: chave secreta da AWS para o S3
- Chave de encriptação: selecione a mesma chave de encriptação principal.
- Secret Type Contents: texto simples
- Conteúdos secretos: cole a sua chave de acesso secreta da AWS.
- Clique em Criar segredo.
- Copie e guarde o OCID deste segredo.
Crie um grupo dinâmico para funções da OCI
- Inicie sessão na Oracle Cloud Console.
- Aceda a Identidade e segurança > Identidade > Grupos dinâmicos.
- Clique em Criar grupo dinâmico.
Faculte os seguintes detalhes de configuração:
- Nome:
oci-functions-dynamic-group - Descrição: grupo dinâmico para as funções do OCI acederem a segredos do Vault
Regras de correspondência: introduza a seguinte regra (substitua
<your_compartment_ocid>pelo OCID do seu compartimento):ALL {resource.type = 'fnfunc', resource.compartment.id = '<your_compartment_ocid>'}
- Nome:
Clique em Criar.
Crie uma política de IAM para acesso ao cofre
- Inicie sessão na Oracle Cloud Console.
- Aceda a Identidade e segurança > Identidade > Políticas.
- Selecione o compartimento onde quer criar a política.
- Clique em Criar política.
Faculte os seguintes detalhes de configuração:
- Nome:
oci-functions-vault-access-policy - Descrição: permitir que as funções da OCI leiam segredos do Vault
- Criador de políticas: ative/desative a opção Mostrar editor manual.
Declarações de políticas: introduza o seguinte (substitua
<compartment_name>pelo nome do seu compartimento):allow dynamic-group oci-functions-dynamic-group to manage secret-family in compartment <compartment_name>
- Nome:
Clique em Criar.
Crie uma aplicação de funções da OCI
- Inicie sessão na Oracle Cloud Console.
- Aceda a Serviços para programadores > Aplicações (em Funções).
- Clique em Criar aplicação.
- Forneça os seguintes detalhes de configuração:
- Nome: introduza um nome (por exemplo,
oci-logs-to-s3-app). - VCN: selecione uma VCN no seu compartimento.
- Sub-redes: selecione uma ou mais sub-redes.
- Nome: introduza um nome (por exemplo,
- Clique em Criar.
Crie e implemente a função OCI
Configure o Cloud Shell (recomendado)
- Na Oracle Cloud Console, clique no ícone Cloud Shell no canto superior direito.
- Aguarde pela inicialização do Cloud Shell.
Crie a função
No Cloud Shell, crie um novo diretório para a sua função:
mkdir pushlogs cd pushlogsInicialize uma nova função Python:
fn init --runtime pythonIsto cria três ficheiros:
func.py,func.yamlerequirements.txt.
Atualize o ficheiro func.py
Substitua o conteúdo de
func.pypelo seguinte código:import io import json import logging import boto3 import oci import base64 import os from fdk import response def handler(ctx, data: io.BytesIO = None): """ OCI Function to push audit logs from OCI Logging to AWS S3 """ try: # Parse incoming log data from Service Connector funDataStr = data.read().decode('utf-8') funData = json.loads(funDataStr) logging.getLogger().info(f"Received {len(funData)} log entries") # Replace these with your actual OCI Vault secret OCIDs secret_key_id = "ocid1.vaultsecret.oc1..<your_secret_key_ocid>" access_key_id = "ocid1.vaultsecret.oc1..<your_access_key_ocid>" # Replace with your S3 bucket name s3_bucket_name = "oci-audit-logs-bucket" # Use Resource Principals for OCI authentication signer = oci.auth.signers.get_resource_principals_signer() secret_client = oci.secrets.SecretsClient({}, signer=signer) def read_secret_value(secret_client, secret_id): """Retrieve and decode secret value from OCI Vault""" response = secret_client.get_secret_bundle(secret_id) base64_secret_content = response.data.secret_bundle_content.content base64_secret_bytes = base64_secret_content.encode('ascii') base64_message_bytes = base64.b64decode(base64_secret_bytes) secret_content = base64_message_bytes.decode('ascii') return secret_content # Retrieve AWS credentials from OCI Vault awsaccesskey = read_secret_value(secret_client, access_key_id) awssecretkey = read_secret_value(secret_client, secret_key_id) # Initialize boto3 session with AWS credentials session = boto3.Session( aws_access_key_id=awsaccesskey, aws_secret_access_key=awssecretkey ) s3 = session.resource('s3') # Process each log entry for i in range(0, len(funData)): # Use timestamp as filename filename = funData[i].get('time', f'log_{i}') # Remove special characters from filename filename = filename.replace(':', '-').replace('.', '-') logging.getLogger().info(f"Processing log entry: {filename}") # Write log entry to temporary file temp_file = f'/tmp/{filename}.json' with open(temp_file, 'w', encoding='utf-8') as f: json.dump(funData[i], f, ensure_ascii=False, indent=4) # Upload to S3 s3_key = f'{filename}.json' s3.meta.client.upload_file( Filename=temp_file, Bucket=s3_bucket_name, Key=s3_key ) logging.getLogger().info(f"Uploaded {s3_key} to S3 bucket {s3_bucket_name}") # Clean up temporary file os.remove(temp_file) return response.Response( ctx, response_data=json.dumps({ "status": "success", "processed_logs": len(funData) }), headers={"Content-Type": "application/json"} ) except Exception as e: logging.getLogger().error(f"Error processing logs: {str(e)}") return response.Response( ctx, response_data=json.dumps({ "status": "error", "message": str(e) }), headers={"Content-Type": "application/json"}, status_code=500 )- Substitua
secret_key_idpelo OCID secreto real do seu cofre para a chave secreta da AWS - Substitua
access_key_idpelo OCID secreto do cofre real para a chave de acesso da AWS - Substitua
s3_bucket_namepelo nome real do contentor do S3
- Substitua
Atualize o ficheiro func.yaml
Substitua o conteúdo de func.yaml por:
schema_version: 20180708
name: pushlogs
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
Atualize o ficheiro requirements.txt
Substitua o conteúdo de
requirements.txtpor:fdk>=0.1.56 boto3 oci
Implemente a função
Defina o contexto Fn para usar a sua aplicação:
fn use context <region-context> fn update context oracle.compartment-id <compartment-ocid>Implemente a função:
fn -v deploy --app oci-logs-to-s3-appAguarde a conclusão da implementação. Deverá ver um resultado que indica que a função foi implementada com êxito.
Verifique se a função foi criada:
fn list functions oci-logs-to-s3-app
Crie um conetor de serviço para enviar registos de auditoria da OCI para a função
- Inicie sessão na Oracle Cloud Console.
- Aceda a Analytics e IA > Mensagens > Hub de conetores de serviços.
- Selecione o compartimento onde quer criar o conetor de serviço.
- Clique em Criar conetor de serviços.
Configure os detalhes do conetor de serviços
- Faculte os seguintes detalhes de configuração:
Informações do conetor de serviços:
* Nome do conetor: introduza um nome descritivo (por exemplo, audit-logs-to-s3-connector).
* Descrição: descrição opcional (por exemplo, "Encaminhar registos de auditoria da OCI para o AWS S3").
* Compartimento de recursos: selecione o compartimento.
Configurar origem
- Em Configurar origem:
- Fonte: selecione Registo.
- Compartimento: selecione o compartimento que contém os registos de auditoria.
- Grupo de registos: selecione
_Audit(este é o grupo de registos predefinido para registos de auditoria). - Registos: clique em + Outro registo.
- Selecione o registo de auditoria para o seu compartimento (por exemplo,
_Audit_Include_Subcompartment).
Configure o destino
- Em Configurar alvo:
- Segmentação: selecione Funções.
- Compartimento: selecione o compartimento que contém a sua aplicação de funções.
- Aplicação de funções: selecione
oci-logs-to-s3-app(a aplicação que criou anteriormente). - Função: selecione
pushlogs(a função que implementou).
Configurar política
Em Configurar política:
- Reveja as declarações da política IAM necessárias apresentadas.
- Clique em Criar para criar automaticamente as políticas necessárias.
Clique em Criar para criar o conetor de serviços.
Aguarde a criação e a ativação do conector de serviços. O estado deve mudar para Ativo.
Verifique se os registos estão a ser enviados para o AWS S3
- Inicie sessão na Oracle Cloud Console.
- Realizar algumas ações que geram registos de auditoria (por exemplo, criar ou modificar um recurso).
- Aguarde 2 a 5 minutos para que os registos sejam processados.
- Inicie sessão na AWS Management Console.
- Aceda a S3 > Recipientes.
- Clique no seu recipiente (por exemplo,
oci-audit-logs-bucket). - Verifique se os ficheiros de registo JSON estão a aparecer no contentor.
Configure o contentor do AWS S3 e o IAM para o Google SecOps
Crie um utilizador do IAM para o Chronicle
- Inicie sessão na AWS Management Console.
- Aceda a IAM > Utilizadores > Adicionar utilizadores.
- Forneça os seguintes detalhes de configuração:
- Nome de utilizador: introduza
chronicle-s3-reader. - Tipo de acesso: selecione Chave de acesso – Acesso programático.
- Nome de utilizador: introduza
- Clique em Seguinte: autorizações.
- Clique em Anexar políticas existentes diretamente.
- Pesquise e selecione a política AmazonS3ReadOnlyAccess.
- Clique em Seguinte: Etiquetas.
- Clique em Seguinte: rever.
- Clique em Criar utilizador.
- Clique em Transferir ficheiro CSV para guardar o ID da chave de acesso e a chave de acesso secreta.
- Clique em Fechar.
Opcional: crie uma política IAM personalizada para acesso com privilégios mínimos
Se quiser restringir o acesso apenas ao contentor específico:
- Aceda a IAM > Políticas > Criar política.
- Clique no separador JSON.
Introduza a seguinte política:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:GetObject", "s3:ListBucket" ], "Resource": [ "arn:aws:s3:::oci-audit-logs-bucket", "arn:aws:s3:::oci-audit-logs-bucket/*" ] } ] }- Substitua
oci-audit-logs-bucketpelo nome do seu contentor.
- Substitua
Clique em Seguinte: Etiquetas.
Clique em Seguinte: rever.
Faculte os seguintes detalhes de configuração:
- Nome:
chronicle-s3-read-policy - Descrição: acesso só de leitura ao contentor de registos de auditoria da OCI
- Nome:
Clique em Criar política.
Regresse a IAM > Utilizadores e selecione o utilizador
chronicle-s3-reader.Clique em Adicionar autorizações > Anexar políticas diretamente.
Pesquise e selecione
chronicle-s3-read-policy.Remova a política AmazonS3ReadOnlyAccess se a tiver adicionado anteriormente.
Clique em Adicionar autorizações.
Configure um feed no Google SecOps para carregar registos de auditoria do Oracle Cloud
- Aceda a Definições do SIEM > Feeds.
- Clique em Adicionar novo feed.
- Na página seguinte, clique em Configurar um único feed.
- No campo Nome do feed, introduza um nome para o feed (por exemplo,
Oracle Cloud Audit Logs). - Selecione Amazon S3 V2 como o Tipo de origem.
- Selecione Oracle Cloud Infrastructure como o Tipo de registo.
- Clicar em Seguinte.
- Especifique valores para os seguintes parâmetros de entrada:
- URI do S3: introduza o URI do contentor do S3 (por exemplo,
s3://oci-audit-logs-bucket/). - Opção de eliminação da origem: selecione a opção de eliminação de acordo com a sua preferência:
- Nunca: recomendado para testes e configuração inicial.
- Eliminar ficheiros transferidos: elimina ficheiros após a ingestão bem-sucedida (use para produção para gerir os custos de armazenamento).
- Idade máxima do ficheiro: inclua ficheiros modificados no último número de dias. A predefinição é 180 dias.
- ID da chave de acesso: introduza o ID da chave de acesso do utilizador do IAM do Chronicle que criou.
- Chave de acesso secreta: introduza a chave de acesso secreta do utilizador do IAM do Chronicle que criou.
- Espaço de nomes do recurso: o espaço de nomes do recurso.
- Etiquetas de carregamento: a etiqueta a aplicar aos eventos deste feed.
- URI do S3: introduza o URI do contentor do S3 (por exemplo,
- Clicar em Seguinte.
- Reveja a nova configuração do feed no ecrã Finalizar e, de seguida, clique em Enviar.
Tabela de mapeamento da UDM
| Campo de registo | Mapeamento da UDM | Lógica |
|---|---|---|
data.request.headers.authorization.0 |
event.idm.read_only_udm.additional.fields |
Valor retirado de data.request.headers.authorization.0 e adicionado como um par de chave-valor em que a chave é "Autorização dos cabeçalhos dos pedidos". |
data.compartmentId |
event.idm.read_only_udm.additional.fields |
Valor retirado de data.compartmentId e adicionado como um par de chave-valor em que a chave é "compartmentId". |
data.compartmentName |
event.idm.read_only_udm.additional.fields |
Valor retirado de data.compartmentName e adicionado como um par de chave-valor em que a chave é "compartmentName". |
data.response.headers.Content-Length.0 |
event.idm.read_only_udm.additional.fields |
Valor retirado de data.response.headers.Content-Length.0 e adicionado como um par de chave-valor em que a chave é "Response Headers Content-Length". |
data.response.headers.Content-Type.0 |
event.idm.read_only_udm.additional.fields |
Valor retirado de data.response.headers.Content-Type.0 e adicionado como um par de chave-valor em que a chave é "Response Headers Content-Type". |
data.eventGroupingId |
event.idm.read_only_udm.additional.fields |
Valor retirado de data.eventGroupingId e adicionado como um par de chave-valor em que a chave é "eventGroupingId". |
oracle.tenantid, data.identity.tenantId |
event.idm.read_only_udm.additional.fields |
O valor é retirado de oracle.tenantid, se estiver presente, caso contrário, é retirado de data.identity.tenantId. É adicionado como um par de chave-valor em que a chave é "tenantId". |
data.message |
event.idm.read_only_udm.metadata.description |
Valor retirado de data.message. |
time |
event.idm.read_only_udm.metadata.event_timestamp |
Valor retirado de time e analisado como uma indicação de tempo ISO8601. |
event.idm.read_only_udm.metadata.event_type |
Predefinido como GENERIC_EVENT. Definido como NETWORK_CONNECTION se estiverem presentes um principal (IP ou nome de anfitrião) e um IP de destino. Definido como STATUS_UPDATE se apenas estiver presente um principal. |
|
time |
event.idm.read_only_udm.metadata.ingested_timestamp |
Se oracle.ingestedtime não estiver vazio, o valor é retirado do campo time e analisado como uma data/hora ISO8601. |
oracle.tenantid |
event.idm.read_only_udm.metadata.product_deployment_id |
Valor retirado de oracle.tenantid. |
type |
event.idm.read_only_udm.metadata.product_event_type |
Valor retirado de type. |
oracle.logid |
event.idm.read_only_udm.metadata.product_log_id |
Valor retirado de oracle.logid. |
specversion |
event.idm.read_only_udm.metadata.product_version |
Valor retirado de specversion. |
data.request.action |
event.idm.read_only_udm.network.http.method |
Valor retirado de data.request.action. |
data.identity.userAgent |
event.idm.read_only_udm.network.http.parsed_user_agent |
Valor retirado de data.identity.userAgent e analisado. |
data.response.status |
event.idm.read_only_udm.network.http.response_code |
Valor retirado de data.response.status e convertido num número inteiro. |
data.protocol |
event.idm.read_only_udm.network.ip_protocol |
O valor numérico de data.protocol é convertido na respetiva representação de string (por exemplo, 6 torna-se "TCP" e 17 torna-se "UDP"). |
data.bytesOut |
event.idm.read_only_udm.network.sent_bytes |
Valor retirado de data.bytesOut e convertido num número inteiro sem sinal. |
data.packets |
event.idm.read_only_udm.network.sent_packets |
Valor retirado de data.packets e convertido num número inteiro. |
data.identity.consoleSessionId |
event.idm.read_only_udm.network.session_id |
Valor retirado de data.identity.consoleSessionId. |
id |
event.idm.read_only_udm.principal.asset.product_object_id |
Valor retirado de id. |
source |
event.idm.read_only_udm.principal.hostname |
Valor retirado de source. |
data.sourceAddress, data.identity.ipAddress |
event.idm.read_only_udm.principal.ip |
Os valores de data.sourceAddress e data.identity.ipAddress são unidos neste campo. |
data.sourcePort |
event.idm.read_only_udm.principal.port |
Valor retirado de data.sourcePort e convertido num número inteiro. |
data.request.headers.X-Forwarded-For.0 |
event.idm.read_only_udm.principal.resource.attribute.labels |
Valor retirado de data.request.headers.X-Forwarded-For.0 e adicionado como um par de chave-valor em que a chave é "x forward". |
oracle.compartmentid |
event.idm.read_only_udm.principal.resource.attribute.labels |
Valor retirado de oracle.compartmentid e adicionado como um par de chave-valor em que a chave é "compartmentid". |
oracle.loggroupid |
event.idm.read_only_udm.principal.resource.attribute.labels |
Valor retirado de oracle.loggroupid e adicionado como um par de chave-valor em que a chave é "loggroupid". |
oracle.vniccompartmentocid |
event.idm.read_only_udm.principal.resource.attribute.labels |
Valor retirado de oracle.vniccompartmentocid e adicionado como um par de chave-valor em que a chave é "vniccompartmentocid". |
oracle.vnicocid |
event.idm.read_only_udm.principal.resource.attribute.labels |
Valor retirado de oracle.vnicocid e adicionado como um par de chave-valor em que a chave é "vnicocid". |
oracle.vnicsubnetocid |
event.idm.read_only_udm.principal.resource.attribute.labels |
Valor retirado de oracle.vnicsubnetocid e adicionado como um par de chave-valor em que a chave é "vnicsubnetocid". |
data.flowid |
event.idm.read_only_udm.principal.resource.product_object_id |
Valor retirado de data.flowid. |
data.identity.credentials |
event.idm.read_only_udm.principal.user.attribute.labels |
Valor retirado de data.identity.credentials e adicionado como um par de chave-valor em que a chave é "credentials". |
data.identity.principalName |
event.idm.read_only_udm.principal.user.user_display_name |
Valor retirado de data.identity.principalName. |
data.identity.principalId |
event.idm.read_only_udm.principal.user.userid |
Valor retirado de data.identity.principalId. |
data.action |
event.idm.read_only_udm.security_result.action |
Predefinido como UNKNOWN_ACTION. Se data.action for "REJECT", este valor é definido como BLOCK. Se data.action for "ACCEPT", esta opção é definida como ALLOW. |
data.endTime |
event.idm.read_only_udm.security_result.detection_fields |
Valor retirado de data.endTime e adicionado como um par de chave-valor em que a chave é "endTime". |
data.startTime |
event.idm.read_only_udm.security_result.detection_fields |
Valor retirado de data.startTime e adicionado como um par de chave-valor em que a chave é "startTime". |
data.status |
event.idm.read_only_udm.security_result.detection_fields |
Valor retirado de data.status e adicionado como um par de chave-valor em que a chave é "status". |
data.version |
event.idm.read_only_udm.security_result.detection_fields |
O valor é retirado de data.version e adicionado como um par de chave-valor em que a chave é "version". |
data.destinationAddress |
event.idm.read_only_udm.target.ip |
Valor retirado de data.destinationAddress. |
data.destinationPort |
event.idm.read_only_udm.target.port |
Valor retirado de data.destinationPort e convertido num número inteiro. |
data.request.path |
event.idm.read_only_udm.target.url |
Valor retirado de data.request.path. |
event.idm.read_only_udm.metadata.product_name |
Definido como "ORACLE CLOUD AUDIT". | |
event.idm.read_only_udm.metadata.vendor_name |
Definido como "ORACLE". |
Precisa de mais ajuda? Receba respostas de membros da comunidade e profissionais da Google SecOps.