收集 Oracle Cloud Infrastructure 日志

支持:

本文档介绍了如何使用以下方法之一将 Oracle Cloud Infrastructure (OCI) 审核日志注入 Google Security Operations:

  • 方法 1:Google Cloud Storage:OCI 函数将日志写入 Cloud Storage 存储桶,Google SecOps Feed 从该存储桶中读取日志。
  • 方法 2:Webhook:OCI 函数将日志直接发送到 Google SecOps Webhook Feed。此方法不使用 Cloud Storage 存储桶。

这两种方法都使用 OCI Connector Hub 将审核日志传递给函数,因为 Oracle Cloud Infrastructure 无法直接将日志发送到 Cloud Storage 或 HTTPS 端点。

Oracle Cloud Infrastructure Audit 服务会自动将对所有受支持的 OCI 公共应用编程接口 (API) 端点的调用记录为日志事件。由审核服务记录的日志事件包括由 OCI 控制台、命令行界面 (CLI)、软件开发套件 (SDK)、您自己的自定义客户端或其他 OCI 服务发出的 API 调用。日志中的信息包括 API 活动发生的时间、活动的来源和目标、操作类型以及响应类型。

准备工作

请确保满足以下前提条件:

  • Google SecOps 实例
  • 对 Oracle Cloud 控制台的特权访问权限,以及创建和管理以下各项的权限:
    • Connector Hub 连接器
    • Functions 应用和函数
    • IAM 政策
  • 一个可访问互联网的 VCN 子网,用于 OCI 函数
  • OCI Cloud Shell 或安装了 Fn CLI 的本地环境
  • 对于方法 1:一个已启用 Cloud Storage API 的 Google Cloud 项目,并且拥有创建 Cloud Storage 存储桶、服务账号和存储桶 Identity and Access Management (IAM) 政策的权限
  • 对于方法 2:在 Google Cloud 与 Google SecOps 实例关联的项目中创建 API 密钥的权限

方法 1:Cloud Storage

创建 Cloud Storage 存储桶

  1. 前往 Google Cloud 控制台。
  2. 选择您的项目或创建一个新项目。
  3. 在导航菜单中,前往 Cloud Storage > 存储桶。
  4. 点击创建存储分区。
  5. 提供以下配置详细信息:

    设置 值
    指定存储桶的名称 输入一个全局唯一的名称(例如 oci-audit-logs-gcs)
    位置类型 根据您的需求进行选择(单区域、双区域、多区域)
    位置 选择位置(例如 us-central1)
    存储类别 标准(推荐用于频繁访问的日志)
    访问权限控制 统一(推荐)
    保护工具 可选:启用对象版本控制或保留政策
  6. 点击创建。

配置 Oracle Cloud Infrastructure,以将审核日志导出到 Cloud Storage

Oracle Cloud Infrastructure 不支持内置导出到 Cloud Storage。您可以使用 OCI Service Connector Hub 和 OCI 函数将审核日志转发到 Cloud Storage。

创建 Oracle Cloud Infrastructure 函数,以将日志转发到 Cloud Storage

  1. 登录 Oracle Cloud 控制台。
  2. 打开导航菜单,然后依次选择开发者服务 > 函数 > 应用。
  3. 选择要在其中创建函数应用的区间。
  4. 点击创建应用。
  5. 提供以下配置详细信息:
    • 名称:输入 audit-logs-to-gcs-app。
    • VCN:选择一个虚拟云网络。
    • 子网:选择具有互联网访问权限的子网。
  6. 点击创建。
  7. 创建应用后,点击开始,然后按照说明使用 Fn CLI 设置本地开发环境。
  8. 在本地机器上创建一个新的函数目录:

    mkdir oci-audit-to-gcs
    cd oci-audit-to-gcs
    
  9. 初始化 Python 函数:

    fn init --runtime python oci-audit-to-gcs
    cd oci-audit-to-gcs
    
  10. 将 func.py 的内容替换为以下代码:

    import io
    import json
    import logging
    import os
    from fdk import response
    from google.cloud import storage
    from google.oauth2 import service_account
    from datetime import datetime
    
    # Configure logging
    logging.basicConfig(level=logging.INFO)
    logger = logging.getLogger()
    
    # Environment variables
    GCS_BUCKET = os.environ.get('GCS_BUCKET')
    GCS_PREFIX = os.environ.get('GCS_PREFIX', 'oci-audit-logs')
    GCS_CREDENTIALS_JSON = os.environ.get('GCS_CREDENTIALS_JSON')
    
    def handler(ctx, data: io.BytesIO = None):
        """
        OCI Function to forward Audit logs to GCS.
    
        Args:
            ctx: Function context
            data: Input data containing Audit log events
        """
    
        if not all([GCS_BUCKET, GCS_CREDENTIALS_JSON]):
            logger.error('Missing required environment variables: GCS_BUCKET or GCS_CREDENTIALS_JSON')
            return response.Response(
                ctx, response_data=json.dumps({"error": "Missing configuration"}),
                headers={"Content-Type": "application/json"}
            )
    
        try:
            # Parse input data
            body = json.loads(data.getvalue())
            logger.info(f"Received event: {json.dumps(body)}")
    
            # Extract log entries
            log_entries = []
            if isinstance(body, list):
                log_entries = body
            elif isinstance(body, dict):
                # Service Connector Hub sends data in specific format
                if 'data' in body:
                    log_entries = [body['data']] if isinstance(body['data'], dict) else body['data']
                else:
                    log_entries = [body]
    
            if not log_entries:
                logger.info("No log entries to process")
                return response.Response(
                    ctx, response_data=json.dumps({"status": "no_logs"}),
                    headers={"Content-Type": "application/json"}
                )
    
            # Initialize GCS client with service account credentials
            credentials_dict = json.loads(GCS_CREDENTIALS_JSON)
            credentials = service_account.Credentials.from_service_account_info(credentials_dict)
            storage_client = storage.Client(credentials=credentials, project=credentials_dict.get('project_id'))
            bucket = storage_client.bucket(GCS_BUCKET)
    
            # Write logs to GCS as NDJSON
            timestamp = datetime.utcnow().strftime('%Y%m%d_%H%M%S_%f')
            object_key = f"{GCS_PREFIX}/logs_{timestamp}.ndjson"
            blob = bucket.blob(object_key)
    
            ndjson = '\n'.join([json.dumps(entry, ensure_ascii=False) for entry in log_entries]) + '\n'
            blob.upload_from_string(ndjson, content_type='application/x-ndjson')
    
            logger.info(f"Wrote {len(log_entries)} records to gs://{GCS_BUCKET}/{object_key}")
    
            return response.Response(
                ctx, response_data=json.dumps({"status": "success", "records": len(log_entries)}),
                headers={"Content-Type": "application/json"}
            )
    
        except Exception as e:
            logger.error(f'Error processing logs: {str(e)}')
            return response.Response(
                ctx, response_data=json.dumps({"error": str(e)}),
                headers={"Content-Type": "application/json"},
                status_code=500
            )
    

  11. 使用以下依赖项更新 requirements.txt:

    fdk>=0.1.0
    google-cloud-storage>=2.0.0
    google-auth>=2.0.0
    
  12. 将函数部署到 OCI:

    fn -v deploy --app audit-logs-to-gcs-app
    
  13. 部署完成后,请记下函数 OCID。您将在配置 Service Connector Hub 时用到它。

配置函数环境变量

  1. 在 Oracle Cloud 控制台中,依次前往开发者服务 > 函数 > 应用。
  2. 点击应用 (audit-logs-to-gcs-app)。
  3. 点击函数名称 (oci-audit-to-gcs)。
  4. 点击配置。
  5. 添加以下配置变量:

    键 值
    GCS_BUCKET 您的 Cloud Storage 存储桶名称(例如 oci-audit-logs-gcs)
    GCS_PREFIX 日志文件的前缀(例如 oci-audit-logs)
    GCS_CREDENTIALS_JSON Google Cloud 服务账号密钥的 JSON 字符串
  6. 点击保存更改。

为 Oracle Cloud Infrastructure 函数创建 Google Cloud 服务账号

OCI 函数需要一个 Google Cloud 服务账号才能写入 Cloud Storage 存储桶。

  1. 在 Google Cloud 控制台中,前往 IAM 和管理 > 服务账号。
  2. 点击创建服务账号。
  3. 提供以下配置详细信息:
    • 服务账号名称:输入 oci-function-gcs-writer。
    • 服务账号说明:输入 Service account for OCI Function to write Audit logs to GCS。
  4. 点击创建并继续。
  5. 在向此服务账号授予对项目的访问权限部分中,添加以下角色:
    1. 点击选择角色。
    2. 搜索并选择 Storage Object Admin。
  6. 点击继续。
  7. 点击完成。
  8. 点击新创建的服务账号电子邮件地址。
  9. 前往密钥标签页。
  10. 依次点击添加密钥 > 创建新密钥。
  11. 选择 JSON 作为密钥类型。
  12. 点击创建。JSON 密钥文件将下载到您的计算机上。
  13. 打开 JSON 密钥文件,并复制其完整内容。
  14. 返回 Oracle Cloud 控制台函数配置。
  15. 将 JSON 内容粘贴到 GCS_CREDENTIALS_JSON 配置变量中。

授予对 Cloud Storage 存储桶的 IAM 权限

向服务账号授予对 Cloud Storage 存储桶的写入权限,如下所示:

  1. 前往 Cloud Storage > 存储桶。
  2. 点击您的存储桶名称 (oci-audit-logs-gcs)。
  3. 前往权限标签页。
  4. 点击授予访问权限。
  5. 提供以下配置详细信息:
    • 添加主账号:输入服务账号邮箱 (oci-function-gcs-writer@PROJECT_ID.iam.gserviceaccount.com)。
    • 分配角色:选择 Storage Object Admin。
  6. 点击保存。

创建 OCI Service Connector Hub 连接器

  1. 登录 Oracle Cloud 控制台。
  2. 打开导航菜单,然后选择分析和 AI。在消息传递下,选择连接器中心。
  3. 选择要在其中创建服务连接器的区间。
  4. 点击创建连接器。
  5. 提供以下配置详细信息:

    • 连接器信息:

      设置 值
      连接器名称 输入 audit-logs-to-gcs-connector
      说明 输入 Forward OCI Audit logs to Cloud Storage
      资源隔离区 选择隔离区
    • 配置来源:

      设置 值
      来源 选择日志记录
      Compartment 选择包含审核日志的分区
      日志组 选择 _Audit(审核日志的默认日志组)
  6. 点击 + 另一个日志。

  7. 选择隔离区的审核日志(例如 _Audit_Include_Subcompartment)。

    • 配置的目标:

      设置 值
      目标 选择函数
      函数隔室 选择包含函数的区间
      函数应用 选择audit-logs-to-gcs-app
      功能 选择oci-audit-to-gcs
  8. 前往配置任务(可选),并保留默认设置。

  9. 如果系统提示您创建政策(创建或更新服务连接器所需的访问权限),请选择创建。

  10. 点击创建。

为 Service Connector Hub 创建 IAM 政策

Service Connector Hub 需要调用函数的权限。

  1. 在 Oracle Cloud 控制台中,前往身份和安全 > 政策。
  2. 选择您在其中创建了 Service Connector Hub 连接器的区间。
  3. 点击创建政策。
  4. 提供以下配置详细信息:
    • 名称:输入 service-connector-functions-policy。
    • 说明:输入 Allow Service Connector Hub to invoke Functions。
    • 隔离区:选择隔离区。
  5. 在政策构建器部分,切换显示手动编辑器。
  6. 输入以下政策声明:

    Allow any-user to use fn-function in compartment <compartment-name> where all {request.principal.type='serviceconnector'}
    Allow any-user to use fn-invocation in compartment <compartment-name> where all {request.principal.type='serviceconnector'}
    
  7. 点击创建。

测试集成

  1. 登录 Oracle Cloud 控制台。
  2. 执行一些会生成审核日志的操作(例如,创建或修改资源)。
  3. 等待 2-5 分钟,让系统处理日志。
  4. 在 Google Cloud 控制台中,前往 Cloud Storage > 存储桶。
  5. 点击您的存储桶名称 (oci-audit-logs-gcs)。
  6. 前往前缀文件夹 (oci-audit-logs/)。
  7. 验证存储桶中是否显示了新的 .ndjson 文件。

检索 Google SecOps 服务账号

Google SecOps 使用唯一服务账号从 Cloud Storage 存储桶中读取数据。您必须向此服务账号授予对存储桶的访问权限。

获取服务账号邮箱

  1. 前往 SIEM 设置 > Feed。
  2. 点击添加新 Feed。
  3. 点击配置单个 Feed。
  4. 在 Feed 名称字段中,输入 Feed 的名称(例如 Oracle Cloud Audit Logs)。
  5. 选择 Google Cloud Storage V2 作为来源类型。
  6. 选择 Oracle Cloud Infrastructure 审核日志作为日志类型。
  7. 点击获取服务账号。系统会显示一个专属的服务账号邮箱,例如:

    chronicle-12345678@chronicle-gcp-prod.iam.gserviceaccount.com
    
  8. 复制此邮箱,以便在下一步中使用。

向 Google SecOps 服务账号授予 IAM 权限

Google SecOps 服务账号需要对您的 Cloud Storage 存储桶拥有两个角色:Storage Object Viewer 角色(用于读取日志对象)和存储桶级角色(用于读取存储桶元数据)

  1. 前往 Cloud Storage > 存储桶。
  2. 点击您的存储桶名称 (oci-audit-logs-gcs)。
  3. 前往权限标签页。
  4. 点击授予访问权限。
  5. 提供以下配置详细信息:
    • 添加主账号:粘贴 Google SecOps 服务账号邮箱。
    • 分配角色:选择以下两项:
      • Storage Object Viewer:读取日志对象。
      • Storage Legacy Bucket Reader:读取存储桶元数据。如果您选择了删除已转移的文件和空目录删除选项,请改为选择 Storage Legacy Bucket Writer,该角色也会授予删除权限。
  6. 点击保存。

在 Google SecOps 中配置 Feed 以注入 Oracle Cloud Infrastructure 审核日志

  1. 前往 SIEM 设置 > Feed。
  2. 点击添加新 Feed。
  3. 点击配置单个 Feed。
  4. 在 Feed 名称字段中,输入 Feed 的名称(例如 Oracle Cloud Audit Logs)。
  5. 选择 Google Cloud Storage V2 作为来源类型。
  6. 选择 Oracle Cloud Infrastructure 审核日志作为日志类型。
  7. 点击下一步。
  8. 为以下输入参数指定值:

    • 存储桶网址:输入带有前缀路径的 Cloud Storage 存储桶 URI:

      gs://oci-audit-logs-gcs/oci-audit-logs/
      
    • 将

      • oci-audit-logs-gcs:您的 Cloud Storage 存储桶名称。
      • oci-audit-logs:存储日志的可选前缀或路径(留空表示根目录)。

      示例:

      • 根存储桶:gs://company-logs/
      • 前缀:gs://company-logs/oci-audit-logs/
      • 包含子文件夹:gs://company-logs/oracle/audit/
    • 来源删除选项:根据您的偏好选择删除选项:

      • 永不删除文件:转移后永不删除任何文件(建议用于测试)。
      • 删除已转移的文件和空目录:在成功转移后删除文件和空目录。
    • 文件存在时间上限(天数):包含在过去指定天数内修改过的文件。默认值为 180 天。

    • 资产命名空间:资产命名空间。

    • 注入标签:要应用于此 Feed 中的事件的标签。

  9. 点击下一步。

  10. 在最终确定界面中查看新的新闻信息流配置,然后点击提交。

方法 2:Webhook

通过此方法,Connector Hub 会将一批批审核日志条目传送到 OCI 函数,然后该函数会通过 HTTPS 将这些条目发送到 Google SecOps webhook Feed。不涉及 Cloud Storage 存储桶。

在 Google SecOps 中创建 webhook Feed

创建 Feed

  1. 前往 SIEM 设置 > Feed。
  2. 点击添加新 Feed。
  3. 在下一页上,点击配置单个 Feed。
  4. 在 Feed 名称字段中,输入 Feed 的名称(例如 OCI Audit Logs Webhook)。
  5. 选择 Webhook 作为来源类型。
  6. 选择 Oracle Cloud Infrastructure 审核日志作为日志类型。
  7. 点击下一步。
  8. 为以下输入参数指定值:
    • 拆分定界符:输入 \n。该函数会逐行发送每个日志条目。
    • 资产命名空间:资产命名空间。
    • 注入标签:要应用于此 Feed 中的事件的标签。
  9. 点击下一步。
  10. 在最终确定界面中查看新的新闻信息流配置,然后点击提交。

生成并保存密钥

  1. 在 Feed 详情页面上,点击生成密钥。
  2. 复制并妥善保存密钥。

获取 Feed 端点网址

  1. 前往该 Feed 的详细信息标签页。
  2. 在端点信息部分,复制 Feed 端点网址。网址格式如下:

    https://<REGION>-chronicle.googleapis.com/v1alpha/projects/<PROJECT_NUMBER>/locations/<REGION>/instances/<INSTANCE_ID>/feeds/<FEED_ID>:importPushLogs
    
  3. 点击完成。

创建 Google Cloud API 密钥

  1. 前往Google Cloud 控制台“凭证”页面。
  2. 选择与您的 Google SecOps 实例关联的项目。
  3. 点击创建凭据 > API 密钥。
  4. 点击修改 API 密钥以限制密钥。
  5. 在名称字段中,输入一个描述性名称(例如 oci-audit-webhook)。
  6. 在 API 限制下,选择限制密钥,然后在选择 API 列表中选择 Chronicle API。
  7. 点击保存。
  8. 复制 API 密钥值并妥善保存。

创建 OCI 函数,以将日志转发到 webhook

创建应用

  1. 登录 Oracle Cloud 控制台。
  2. 打开导航菜单,然后依次选择开发者服务 > 函数 > 应用。
  3. 选择要在其中创建函数应用的区间。
  4. 点击创建应用。
  5. 提供以下配置详细信息:
    • 名称:输入 audit-logs-to-secops-app。
    • VCN:选择一个虚拟云网络。
    • 子网:选择具有互联网访问权限的子网:具有互联网网关的公有子网,或具有 NAT 网关的私有子网。该函数必须通过 HTTPS(端口 443)访问 Google SecOps 端点。
  6. 点击创建。

创建和部署函数

  1. 创建应用后,点击开始,然后按照说明使用 Fn CLI 设置 OCI Cloud Shell 或本地开发环境。
  2. 初始化 Python 函数:

    fn init --runtime python oci-audit-to-secops
    cd oci-audit-to-secops
    
  3. 将 func.py 的内容替换为以下代码:

    import io
    import json
    import logging
    import os
    import random
    import time
    from email.utils import parsedate_to_datetime
    
    import requests
    from fdk import response
    
    logging.basicConfig(level=logging.INFO)
    logger = logging.getLogger()
    
    # The webhook accepts at most 4 MB per request and 1 MB per log line.
    # Connector Hub delivers batches of up to 6 MB, so a batch is sent as several
    # requests, each made of whole log entries.
    MAX_REQUEST_BYTES = 3 * 1024 * 1024
    MAX_LINE_BYTES = 1024 * 1024
    
    MAX_ATTEMPTS = 5
    RETRYABLE_STATUS = {429, 500, 502, 503, 504}
    # OCI stops the function at its configured timeout (300 seconds). Stop retrying
    # early enough to fail cleanly so that Connector Hub retries the whole batch.
    DEADLINE_SECONDS = 240
    
    def to_lines(body):
        """Serialize each log entry from the Connector Hub batch as one JSON line."""
        entries = body if isinstance(body, list) else [body]
        lines = []
        for entry in entries:
            line = json.dumps(entry, ensure_ascii=False, separators=(',', ':')).encode('utf-8')
            if len(line) > MAX_LINE_BYTES:
                entry_id = entry.get('id') if isinstance(entry, dict) else None
                logger.error(f'Skipping log entry {entry_id}: {len(line)} bytes exceeds the 1 MB line limit')
                continue
            lines.append(line)
        return lines
    
    def to_requests(lines):
        """Group whole lines into newline-delimited request bodies below MAX_REQUEST_BYTES."""
        chunk, size = [], 0
        for line in lines:
            if chunk and size + len(line) + 1 > MAX_REQUEST_BYTES:
                yield b'\n'.join(chunk), len(chunk)
                chunk, size = [], 0
            chunk.append(line)
            size += len(line) + 1
        if chunk:
            yield b'\n'.join(chunk), len(chunk)
    
    def retry_after_seconds(value):
        """Parse a Retry-After header given either in seconds or as an HTTP date."""
        if not value:
            return None
        try:
            return max(0.0, float(value))
        except ValueError:
            pass
        try:
            return max(0.0, parsedate_to_datetime(value).timestamp() - time.time())
        except (TypeError, ValueError, IndexError, OverflowError):
            return None
    
    def post(session, url, headers, payload, deadline):
        """Send one request, retrying throttling and server errors until the deadline."""
        status, detail = None, ''
        for attempt in range(1, MAX_ATTEMPTS + 1):
            remaining = deadline - time.monotonic()
            if remaining < 5:
                break
            wait = None
            try:
                resp = session.post(url, data=payload, headers=headers, timeout=(10, min(60, remaining)))
            except requests.RequestException as e:
                status, detail = None, str(e)
            else:
                if 200 <= resp.status_code < 300:
                    return
                status, detail = resp.status_code, resp.text[:500]
                if status not in RETRYABLE_STATUS:
                    raise RuntimeError(f'Webhook rejected the request with HTTP {status}: {detail}')
                wait = retry_after_seconds(resp.headers.get('Retry-After'))
            if wait is None:
                wait = min(30, 2 ** attempt) + random.uniform(0, 1)
            if attempt == MAX_ATTEMPTS or time.monotonic() + wait >= deadline:
                break
            logger.warning(f'Attempt {attempt} failed (HTTP {status}): {detail}. Retrying in {wait:.1f} seconds')
            time.sleep(wait)
        raise RuntimeError(f'Webhook request failed (HTTP {status}): {detail}')
    
    def handler(ctx, data: io.BytesIO = None):
        """Forward a Connector Hub batch of OCI Audit log entries to the webhook feed.
    
        Any exception fails the invocation, and Connector Hub then retries the batch.
        """
        deadline = time.monotonic() + DEADLINE_SECONDS
    
        url = os.environ.get('SECOPS_WEBHOOK_URL')
        api_key = os.environ.get('SECOPS_API_KEY')
        secret_key = os.environ.get('SECOPS_SECRET_KEY')
        if not all([url, api_key, secret_key]):
            raise RuntimeError('Missing configuration: SECOPS_WEBHOOK_URL, SECOPS_API_KEY and SECOPS_SECRET_KEY are required')
    
        raw = data.getvalue() if data else b''
        if not raw.strip():
            logger.info('Received an empty batch')
            return response.Response(
                ctx, response_data=json.dumps({'records': 0}),
                headers={'Content-Type': 'application/json'}
            )
    
        lines = to_lines(json.loads(raw))
        headers = {
            'Content-Type': 'application/json',
            'X-goog-api-key': api_key,
            'X-Webhook-Access-Key': secret_key,
        }
    
        sent = 0
        with requests.Session() as session:
            for payload, count in to_requests(lines):
                post(session, url, headers, payload, deadline)
                sent += count
    
        logger.info(f'Forwarded {sent} log entries')
        return response.Response(
            ctx, response_data=json.dumps({'records': sent}),
            headers={'Content-Type': 'application/json'}
        )
    

  4. 将 requirements.txt 的内容替换为以下依赖项:

    fdk>=0.1.0
    requests>=2.32.0
    
  5. 打开 func.yaml 并添加以下行,将函数超时时间从默认的 30 秒提高到最长 300 秒:

    timeout: 300
    
  6. 将函数部署到 OCI:

    fn -v deploy --app audit-logs-to-secops-app
    

配置函数环境变量

  1. 在 Oracle Cloud 控制台中,依次前往开发者服务 > 函数 > 应用。
  2. 点击应用 (audit-logs-to-secops-app)。
  3. 点击函数名称 (oci-audit-to-secops)。
  4. 点击配置。
  5. 添加以下配置变量:

    键 值
    SECOPS_WEBHOOK_URL Feed 端点网址
    SECOPS_API_KEY Google Cloud API 密钥
    SECOPS_SECRET_KEY Feed 密钥
  6. 点击保存更改。

启用函数日志

  1. 在应用列表页面上,选择 audit-logs-to-secops-app。
  2. 选择监控标签页,然后前往日志部分。
  3. 在函数调用日志类别的操作菜单(三个点)中,选择启用日志。
  4. 保留默认区间、日志组和日志名称,或根据需要进行更改。
  5. 选择启用日志。

创建 OCI Connector Hub 连接器

  1. 打开导航菜单,然后选择分析和 AI。在消息传递下,选择连接器中心。
  2. 选择要在其中创建连接器的区间。
  3. 点击创建连接器。
  4. 提供以下配置详细信息:

    • 连接器信息:

      设置 值
      连接器名称 输入 audit-logs-to-secops-connector
      说明 输入 Forward OCI Audit logs to a webhook feed
      资源隔离区 选择隔离区
    • 配置来源:

      设置 值
      来源 选择日志记录
      Compartment 选择包含审核日志的分区
      日志组 选择 _Audit(审核日志的默认日志组)
  5. 点击 + 另一个日志。

  6. 选择隔离区的审核日志(例如 _Audit_Include_Subcompartment)。

    • 配置的目标:

      设置 值
      目标 选择函数
      函数隔室 选择包含函数的区间
      函数应用 选择audit-logs-to-secops-app
      功能 选择oci-audit-to-secops
  7. 前往配置任务(可选),并保留默认设置。

  8. 如果系统提示您创建政策(创建或更新服务连接器所需的访问权限),请选择创建。

  9. 点击创建。

为连接器中心创建 IAM 政策

Connector Hub 需要拥有调用该函数的权限。

  1. 在 Oracle Cloud 控制台中,前往身份和安全 > 政策。
  2. 选择您在其中创建了连接器的区间。
  3. 点击创建政策。
  4. 提供以下配置详细信息:
    • 名称:输入 connector-hub-secops-function-policy。
    • 说明:输入 Allow Connector Hub to invoke the webhook forwarding function。
    • 隔离区:选择隔离区。
  5. 在政策构建器部分,切换显示手动编辑器。
  6. 输入以下政策声明:

    Allow any-user to use fn-function in compartment <compartment-name> where all {request.principal.type='serviceconnector'}
    Allow any-user to use fn-invocation in compartment <compartment-name> where all {request.principal.type='serviceconnector'}
    
  7. 点击创建。

函数如何传送日志

  • 批处理大小:Connector Hub 向函数发送的批处理大小上限为 6 MB,而 webhook 每次请求最多接受 4 MB。该函数会将每个批次拆分为不超过 3 MB 的请求。它仅在日志条目之间拆分,绝不会在日志条目内部拆分,并且每个条目都会作为一个事件到达 Google SecOps。
  • 重试:该函数会使用指数退避算法重试 HTTP 429 和 5xx 响应,并遵循 Retry-After 标头。任何其他错误,或在尝试 5 次后仍失败的请求,都会导致调用失败。然后,连接器中心会重试整个批次,并且在成功之前不会移动后续批次。
  • 保留:Connector Hub 的 Logging 来源会将未传送的数据保留 24 小时。如果持续无法传送的时间更长,则最早的未传送日志会丢失,因此请及时修复函数日志中报告的错误。
  • 重复:Connector Hub 会将每个批次至少传送一次。如果某一批次在部分条目已发送后重试,Google SecOps 可能会收到这些条目两次。
  • 条目过大:大于 1 MB 的日志条目超出了 webhook 行限制。该函数会跳过此文件,并将其 ID 写入函数日志。

验证集成

如需验证集成,请执行以下操作:

  1. 在 Oracle Cloud 控制台中执行一些会生成审核日志的操作(例如,创建或修改资源)。
  2. 等待 2-5 分钟,让 Connector Hub 传送日志。
  3. 打开您启用的函数调用日志,并确认其中包含 Forwarded N log entries 消息。出错提示包含 Google SecOps 返回的 HTTP 状态。
  4. 在 Google SecOps 中,对 OCI_AUDIT 日志类型运行原始日志搜索,并确认审核事件已到达。

UDM 映射表

日志字段 UDM 映射 逻辑
accept_encoding_field additional.fields 已合并
accept_field additional.fields 已合并
additional_app additional.fields 已合并
additional_content_type additional.fields 已合并
additional_sort_by additional.fields 已合并
additionaldetails_data additional.fields 已合并
allow_methods_field additional.fields 已合并
auth_type_label additional.fields 已合并
authorization_field additional.fields 已合并
backend_connect_time_field additional.fields 已合并
backend_processing_time_field additional.fields 已合并
caller_id_label additional.fields 已合并
caller_name_label additional.fields 已合并
cloud_event_versiom_field additional.fields 已合并
compartment_id_field additional.fields 已合并
compartment_name_field additional.fields 已合并
connection_field additional.fields 已合并
content_length_field additional.fields 已合并
content_type_field additional.fields 已合并
event_grouping_id_field additional.fields 已合并
event_name_label additional.fields 已合并
event_resource_label additional.fields 已合并
event_source_label additional.fields 已合并
event_type_label additional.fields 已合并
event_type_versiom_field additional.fields 已合并
has_compariment_id additional.fields 已映射:true → additional_app
has_sort_by additional.fields 已映射:true → additional_sort_by
listener_name_field additional.fields 已合并
log_group_id_field additional.fields 已合并
log_id_field additional.fields 已合并
message additional.fields 映射的值(共 41 个,例如 \/ → tenant_id_label、\/ → auth_type_label、\/ → `ca…
opc_request_id_field additional.fields 已合并
origin_field additional.fields 已合并
param0_field additional.fields 已合并
param1_field additional.fields 已合并
referer_field additional.fields 已合并
request_processing_time_field additional.fields 已合并
resource_id_field additional.fields 已合并
routing_rules_engine_errors_field additional.fields 已合并
routing_rules_matched_rule_field additional.fields 已合并
routing_rules_rule_hits_field additional.fields 已合并
routing_rules_rule_misses_field additional.fields 已合并
source_field additional.fields 已合并
tenant_id_label additional.fields 已合并
column3 extensions.auth.type 已映射:login successful → AUTHTYPE_UNSPECIFIED
message extensions.auth.type 已映射:\/ → AUTHTYPE_UNSPECIFIED
column3 metadata.description 直接映射
data.message metadata.description 直接映射
column1 metadata.event_timestamp 已解析为 yyyy-MM-dd HH:mm:ss
data_event_time metadata.event_timestamp 已解析为 yyyy-MM-ddTHH:mm:ss.SSSSSSZ
time metadata.event_timestamp 已解析为 ISO8601
metadata_event_type metadata.event_type 直接映射
type metadata.product_event_type 直接映射
data_event_id metadata.product_log_id 直接映射
id metadata.product_log_id 直接映射
message metadata.product_name 已映射:\/ → OCI_AUDIT
specversion metadata.product_version 直接映射
message metadata.vendor_name 已映射:\/ → Oracle
message network.application_protocol 已映射:\/ → HTTPS,\/ → HTTP
protocol network.application_protocol 已映射:(?i)HTTPS → HTTPS,(?i)HTTP → HTTP
version network.application_protocol_version 直接映射
data_request_action network.http.method 直接映射
method network.http.method 直接映射
data_identity_userAgent network.http.parsed_user_agent 已重命名/映射
data_request_agent network.http.parsed_user_agent 已重命名/映射
url network.http.referral_url 直接映射
data.backendStatusCode network.http.response_code 直接映射
data_response_status network.http.response_code 已重命名/映射
data.userAgent network.http.user_agent 直接映射
data_identity_userAgent network.http.user_agent 直接映射
data_request_agent network.http.user_agent 直接映射
data.receivedBytes network.received_bytes 直接映射
message network.received_bytes 已映射:\/ → uinteger
data.sentBytes network.sent_bytes 直接映射
message network.sent_bytes 已映射:\/ → uinteger
data_identity_consoleSessionId network.session_id 已重命名/映射
data.sslCipher network.tls.cipher 直接映射
data.sslProtocol network.tls.version 直接映射
data.host principal.asset.hostname 直接映射
hostname principal.asset.hostname 直接映射
column6 principal.asset.ip 已合并
data.forwardedForAddr principal.asset.ip 已合并
data_identity_ipAddress principal.asset.ip 已映射:^(?:[0-9]{1,3}[.]){3}[0-9]{1,3}$ → data_identity_ipAddress
data_request_origin principal.asset.ip 已合并
ip1 principal.asset.ip 已合并
ip2 principal.asset.ip 已合并
message principal.asset.ip 映射的值(共 7 个,例如 \/ → column6、\/ → data_request_origin、\/ → ip2)
src_ip principal.asset.ip 已合并
data.host principal.hostname 直接映射
hostname principal.hostname 直接映射
column6 principal.ip 已合并
data.forwardedForAddr principal.ip 已合并
data_identity_ipAddress principal.ip 已映射:^(?:[0-9]{1,3}[.]){3}[0-9]{1,3}$ → data_identity_ipAddress
data_request_origin principal.ip 已合并
ip1 principal.ip 已合并
ip2 principal.ip 已合并
message principal.ip 映射的值(共 7 个,例如 \/ → column6、\/ → data_request_origin、\/ → ip2)
src_ip principal.ip 已合并
data_request_headers_sec-ch-ua-platform_0 principal.platform 已映射:(?i)Linux → LINUX、(?i)windows → WINDOWS、(?i)mac/ios → MAC
message principal.platform 映射:\/ → LINUX、\/ → WINDOWS、\/ → MAC
originalConnection.sourcePort principal.port 直接映射
src_port principal.port 直接映射
data_request_headers_oci-original-url_0 principal.url 直接映射
credentials_label principal.user.attribute.labels 已合并
message principal.user.attribute.labels 已映射:\/ → credentials_label
data.identity.principalName principal.user.user_display_name 直接映射
data.username principal.user.user_display_name 直接映射
data.identity.principalId principal.user.userid 直接映射
data.principalId principal.user.userid 直接映射
column3 security_result 已映射:login successful → security_result
message security_result 已映射:\/ → security_result
allow_action security_result.action 已合并
column3 security_result.action 已映射:login successful → allow_action
message security_result.action 已映射:\/ → allow_action
credential_type_field security_result.detection_fields 已合并
message security_result.detection_fields 已映射:\/ → credential_type_field
data.response.message security_result.summary 直接映射
message target.asset.ip 已映射:\/ → originalConnection.destinationIp,\/ → tar_ip
originalConnection.destinationIp target.asset.ip 已合并
tar_ip target.asset.ip 已合并
message target.ip 已映射:\/ → originalConnection.destinationIp,\/ → tar_ip
originalConnection.destinationIp target.ip 已合并
tar_ip target.ip 已合并
originalConnection.destinationPort target.port 直接映射
tar_port target.port 直接映射
message target.resource.attribute.labels 已映射:\/ → namespace_label
namespace_label target.resource.attribute.labels 已合并
type target.resource.attribute.labels 已映射:listretentionrules → namespace_label
data.resourceId target.resource.name 直接映射
data.resourceName target.resource.name 直接映射
bucketId target.resource.product_object_id 直接映射
data.resourceId target.resource.product_object_id 直接映射
data_request_id target.resource.product_object_id 直接映射
message target.resource.resource_type 已映射:\/ → STORAGE_BUCKET
type target.resource.resource_type 已映射:listretentionrules → STORAGE_BUCKET
data_request_path target.url 直接映射
column2 target.user.email_addresses 已合并
message target.user.email_addresses 已映射:\/ → column2
不适用 extensions.auth.type 常量:AUTHTYPE_UNSPECIFIED
不适用 metadata.product_name 常量:OCI_AUDIT
不适用 metadata.vendor_name 常量:Oracle
不适用 network.application_protocol 常量:HTTPS
不适用 principal.platform 常量:LINUX
不适用 target.resource.resource_type 常量:STORAGE_BUCKET

更新日志

查看此解析器的更新日志

需要更多帮助?获得社区成员和 Google SecOps 专业人士的解答。