Recolha registos de auditoria da Oracle Cloud Infrastructure

Suportado em:

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

  1. Inicie sessão na AWS Management Console.
  2. Aceda a S3 > Criar contentor.
  3. 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.
  4. Clique em Criar contentor.
  5. 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

  1. Inicie sessão na AWS Management Console.
  2. Aceda a IAM > Utilizadores > Adicionar utilizadores.
  3. 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.
  4. Clique em Seguinte: autorizações.
  5. Clique em Anexar políticas existentes diretamente.
  6. Pesquise e selecione a política AmazonS3FullAccess.
  7. Clique em Seguinte: Etiquetas.
  8. Clique em Seguinte: rever.
  9. Clique em Criar utilizador.
  10. 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

  1. Inicie sessão na Oracle Cloud Console.
  2. Aceda a Identidade e segurança > Cofre.
  3. Se não tiver um Vault, clique em Criar Vault.
  4. Forneça os seguintes detalhes de configuração:
    • Criar no compartimento: selecione o seu compartimento.
    • Nome: introduza um nome (por exemplo, oci-functions-vault).
  5. Clique em Criar cofre.
  6. Depois de criar o cofre, clique no respetivo nome para o abrir.
  7. Em Chaves de encriptação principais, clique em Criar chave.
  8. 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
  9. Clique em Criar chave.

Crie segredos para credenciais da AWS

  1. No Vault, em Segredos, clique em Criar segredo.
  2. 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.
  3. Clique em Criar segredo.
  4. Copie e guarde o OCID deste segredo (tem o seguinte aspeto: ocid1.vaultsecret.oc1...).
  5. Clique novamente em Criar segredo para criar o segundo segredo.
  6. 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.
  7. Clique em Criar segredo.
  8. Copie e guarde o OCID deste segredo.

Crie um grupo dinâmico para funções da OCI

  1. Inicie sessão na Oracle Cloud Console.
  2. Aceda a Identidade e segurança > Identidade > Grupos dinâmicos.
  3. Clique em Criar grupo dinâmico.
  4. 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>'}
      
  5. Clique em Criar.

Crie uma política de IAM para acesso ao cofre

  1. Inicie sessão na Oracle Cloud Console.
  2. Aceda a Identidade e segurança > Identidade > Políticas.
  3. Selecione o compartimento onde quer criar a política.
  4. Clique em Criar política.
  5. 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>
      
  6. Clique em Criar.

Crie uma aplicação de funções da OCI

  1. Inicie sessão na Oracle Cloud Console.
  2. Aceda a Serviços para programadores > Aplicações (em Funções).
  3. Clique em Criar aplicação.
  4. 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.
  5. Clique em Criar.

Crie e implemente a função OCI

  1. Na Oracle Cloud Console, clique no ícone Cloud Shell no canto superior direito.
  2. Aguarde pela inicialização do Cloud Shell.

Crie a função

  1. No Cloud Shell, crie um novo diretório para a sua função:

    mkdir pushlogs
    cd pushlogs
    
  2. Inicialize uma nova função Python:

    fn init --runtime python
    
  3. Isto cria três ficheiros: func.py, func.yaml e requirements.txt.

Atualize o ficheiro func.py

  • Substitua o conteúdo de func.py pelo 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_id pelo OCID secreto real do seu cofre para a chave secreta da AWS
    • Substitua access_key_id pelo OCID secreto do cofre real para a chave de acesso da AWS
    • Substitua s3_bucket_name pelo nome real do contentor do S3

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.txt por:

    fdk>=0.1.56
    boto3
    oci
    

Implemente a função

  1. Defina o contexto Fn para usar a sua aplicação:

    fn use context <region-context>
    fn update context oracle.compartment-id <compartment-ocid>
    
  2. Implemente a função:

    fn -v deploy --app oci-logs-to-s3-app
    
  3. Aguarde a conclusão da implementação. Deverá ver um resultado que indica que a função foi implementada com êxito.

  4. 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

  1. Inicie sessão na Oracle Cloud Console.
  2. Aceda a Analytics e IA > Mensagens > Hub de conetores de serviços.
  3. Selecione o compartimento onde quer criar o conetor de serviço.
  4. Clique em Criar conetor de serviços.

Configure os detalhes do conetor de serviços

  1. 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

  1. 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

  1. 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

  1. 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.
  2. Clique em Criar para criar o conetor de serviços.

  3. 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

  1. Inicie sessão na Oracle Cloud Console.
  2. Realizar algumas ações que geram registos de auditoria (por exemplo, criar ou modificar um recurso).
  3. Aguarde 2 a 5 minutos para que os registos sejam processados.
  4. Inicie sessão na AWS Management Console.
  5. Aceda a S3 > Recipientes.
  6. Clique no seu recipiente (por exemplo, oci-audit-logs-bucket).
  7. 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

  1. Inicie sessão na AWS Management Console.
  2. Aceda a IAM > Utilizadores > Adicionar utilizadores.
  3. 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.
  4. Clique em Seguinte: autorizações.
  5. Clique em Anexar políticas existentes diretamente.
  6. Pesquise e selecione a política AmazonS3ReadOnlyAccess.
  7. Clique em Seguinte: Etiquetas.
  8. Clique em Seguinte: rever.
  9. Clique em Criar utilizador.
  10. Clique em Transferir ficheiro CSV para guardar o ID da chave de acesso e a chave de acesso secreta.
  11. 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:

  1. Aceda a IAM > Políticas > Criar política.
  2. Clique no separador JSON.
  3. 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-bucket pelo nome do seu contentor.
  4. Clique em Seguinte: Etiquetas.

  5. Clique em Seguinte: rever.

  6. 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
  7. Clique em Criar política.

  8. Regresse a IAM > Utilizadores e selecione o utilizador chronicle-s3-reader.

  9. Clique em Adicionar autorizações > Anexar políticas diretamente.

  10. Pesquise e selecione chronicle-s3-read-policy.

  11. Remova a política AmazonS3ReadOnlyAccess se a tiver adicionado anteriormente.

  12. Clique em Adicionar autorizações.

Configure um feed no Google SecOps para carregar registos de auditoria do Oracle Cloud

  1. Aceda a Definições do SIEM > Feeds.
  2. Clique em Adicionar novo feed.
  3. Na página seguinte, clique em Configurar um único feed.
  4. No campo Nome do feed, introduza um nome para o feed (por exemplo, Oracle Cloud Audit Logs).
  5. Selecione Amazon S3 V2 como o Tipo de origem.
  6. Selecione Oracle Cloud Infrastructure como o Tipo de registo.
  7. Clicar em Seguinte.
  8. 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.
  9. Clicar em Seguinte.
  10. 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.