收集 Oracle Cloud Infrastructure 日志
本文档介绍了如何使用 Google Cloud Storage 将 Oracle Cloud Infrastructure 日志注入到 Google Security Operations。
Oracle Cloud Infrastructure (OCI) 审核服务会自动将对所有受支持的 OCI 公共应用编程接口 (API) 端点的调用记录为日志事件。审核服务记录的日志事件包括 OCI 控制台、命令行界面 (CLI)、软件开发套件 (SDK)、您自己的自定义客户端或其他 OCI 服务发出的 API 调用。日志中的信息包括 API 活动发生的时间、活动的来源和目标、操作类型以及响应类型。
准备工作
请确保满足以下前提条件:
- Google SecOps 实例
- 已启用 Cloud Storage API 的 GCP 项目
- 创建和管理 GCS 存储分区的权限
- 管理 GCS 存储分区的 IAM 政策的权限
- 创建 Cloud Run 服务、Pub/Sub 主题和 Cloud Scheduler 作业的权限
- 一个 Oracle Cloud Infrastructure 账号,具有创建和管理以下内容的权限:
- Service Connector Hub 连接器
- 函数应用和函数
- 对象存储分区
- IAM 政策
- 对 Oracle Cloud 控制台的特权访问权限
创建 Google Cloud Storage 存储桶
- 前往 Google Cloud 控制台。
- 选择您的项目或创建新项目。
- 在导航菜单中,依次前往 Cloud Storage > 存储分区。
- 点击创建存储分区。
提供以下配置详细信息:
设置 值 为存储桶命名 输入一个全局唯一的名称(例如 oci-audit-logs-gcs)位置类型 根据您的需求进行选择(区域级、双区域、多区域) 位置 选择营业地点(例如 us-central1)存储类别 标准(建议用于经常访问的日志) 访问权限控制 均匀(推荐) 保护工具 可选:启用对象版本控制或保留政策 点击创建。
配置 Oracle Cloud Infrastructure 以将审核日志导出到 GCS
Oracle Cloud Infrastructure 不支持内置的导出到 Google Cloud Storage 功能。您将使用 OCI 服务连接器中心和 OCI 函数将审核日志转发到 GCS。
创建 OCI 函数以将日志转发到 GCS
- 登录 Oracle Cloud 控制台。
- 打开导航菜单,然后依次选择开发者服务 > 函数 > 应用。
- 选择要在哪个功能应用所在的隔间中创建功能应用。
- 点击创建应用。
- 提供以下配置详细信息:
- 名称:输入
audit-logs-to-gcs-app。 - VCN:选择一个虚拟 Cloud 网络。
- 子网:选择可访问互联网的子网。
- 名称:输入
- 点击创建。
- 创建应用后,点击开始使用,然后按照说明使用 Fn CLI 设置本地开发环境。
在本地机器上创建一个新的函数目录:
mkdir oci-audit-to-gcs cd oci-audit-to-gcs初始化 Python 函数:
fn init --runtime python oci-audit-to-gcs cd oci-audit-to-gcs将
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 )使用以下依赖项更新
requirements.txt:fdk>=0.1.0 google-cloud-storage>=2.0.0 google-auth>=2.0.0将函数部署到 OCI:
fn -v deploy --app audit-logs-to-gcs-app部署完成后,请记下函数 OCID。您将在配置服务连接器中心时使用该 OCID。
配置函数环境变量
- 在 Oracle Cloud 控制台中,依次前往开发者服务 > 函数 > 应用。
- 点击相应应用 (
audit-logs-to-gcs-app)。 - 点击函数名称 (
oci-audit-to-gcs)。 - 点击配置。
添加以下配置变量:
键 值 GCS_BUCKET您的 GCS 存储桶名称(例如 oci-audit-logs-gcs)GCS_PREFIX日志文件的前缀(例如, oci-audit-logs)GCS_CREDENTIALS_JSONGCP 服务账号密钥的 JSON 字符串 点击保存更改。
为 OCI 函数创建 GCP 服务账号
OCI 函数需要 GCP 服务账号才能写入 GCS 存储桶。
- 在 GCP 控制台中,依次前往 IAM 和管理 > 服务账号。
- 点击创建服务账号。
- 提供以下配置详细信息:
- 服务账号名称:输入
oci-function-gcs-writer。 - 服务账号说明:输入
Service account for OCI Function to write Audit logs to GCS。
- 服务账号名称:输入
- 点击创建并继续。
- 在向此服务账号授予对项目的访问权限部分中,添加以下角色:
- 点击选择角色。
- 搜索并选择 Storage Object Admin。
- 点击继续。
- 点击完成。
- 点击新创建的服务账号电子邮件地址。
- 前往密钥标签页。
- 点击添加密钥 > 创建新密钥。
- 选择 JSON 作为密钥类型。
- 点击创建。
- JSON 密钥文件将下载到您的计算机。
- 打开 JSON 密钥文件并复制其全部内容。
- 返回 Oracle Cloud 控制台函数配置。
将 JSON 内容粘贴到
GCS_CREDENTIALS_JSON配置变量中。
授予对 GCS 存储桶的 IAM 权限
向服务账号授予对 GCS 存储桶的写入权限:
- 前往 Cloud Storage > 存储分区。
- 点击您的存储桶名称 (
oci-audit-logs-gcs)。 - 前往权限标签页。
- 点击授予访问权限。
- 提供以下配置详细信息:
- 添加主账号:输入服务账号电子邮件地址 (
oci-function-gcs-writer@PROJECT_ID.iam.gserviceaccount.com)。 - 分配角色:选择 Storage Object Admin。
- 添加主账号:输入服务账号电子邮件地址 (
- 点击保存。
创建 OCI 服务连接器中心连接器
- 登录 Oracle Cloud 控制台。
- 打开导航菜单,然后选择分析和 AI。在消息传递下,选择连接器中心。
- 选择要在其中创建服务连接器的区间。
- 点击创建连接器。
提供以下配置详细信息:
连接器信息:
设置 值 连接器名称 输入 audit-logs-to-gcs-connector说明 输入 Forward OCI Audit logs to Google Cloud Storage资源隔离区 选择隔离区 配置来源:
设置 值 来源 选择日志记录 Compartment 选择包含审核日志的区间 日志组 选择 _Audit(审核日志的默认日志组) 点击 + 另一条记录。
选择您的区间对应的审核日志(例如
_Audit_Include_Subcompartment)。配置目标:
设置 值 目标 选择函数 功能区 选择包含函数的区间 函数应用 选择 audit-logs-to-gcs-app功能 选择 oci-audit-to-gcs在配置任务(可选)部分,保留默认设置。
如果系统提示您创建政策(创建或更新服务连接器所需的访问权限),请选择创建。
点击创建。
为服务连接器中心创建 IAM 政策
Service Connector Hub 需要权限才能调用函数。
- 在 Oracle Cloud 控制台中,前往身份与安全> 政策。
- 选择您在其中创建了服务连接器中心连接器的区间。
- 点击创建政策。
- 提供以下配置详细信息:
- 名称:输入
service-connector-functions-policy。 - 说明:输入
Allow Service Connector Hub to invoke Functions。 - Compartment:选择隔离区。
- 名称:输入
- 在 Policy Builder 部分中,切换 Show manual editor。
输入以下政策声明:
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'}点击创建。
测试集成
- 登录 Oracle Cloud 控制台。
- 执行一些会生成审核日志的操作(例如,创建或修改资源)。
- 等待 2-5 分钟,让系统处理日志。
- 在 GCP Console 中,前往 Cloud Storage > 存储分区。
- 点击您的存储桶名称 (
oci-audit-logs-gcs)。 - 前往前缀文件夹 (
oci-audit-logs/)。 验证存储桶中是否显示新的
.ndjson文件。
检索 Google SecOps 服务账号
Google SecOps 使用唯一的服务账号从您的 GCS 存储桶中读取数据。您必须授予此服务账号对您的存储桶的访问权限。
获取服务账号电子邮件地址
- 依次前往 SIEM 设置 > Feed。
- 点击添加新 Feed。
- 点击配置单个 Feed。
- 在 Feed 名称字段中,输入 Feed 的名称(例如
Oracle Cloud Audit Logs)。 - 选择 Google Cloud Storage V2 作为来源类型。
- 选择 Oracle Cloud Infrastructure 审核日志作为日志类型。
点击获取服务账号。系统会显示一个唯一的服务账号电子邮件地址,例如:
chronicle-12345678@chronicle-gcp-prod.iam.gserviceaccount.com复制此电子邮件地址,以便在下一步中使用。
向 Google SecOps 服务账号授予 IAM 权限
Google SecOps 服务账号需要您的 GCS 存储桶的 Storage Object Viewer 角色。
- 前往 Cloud Storage > 存储分区。
- 点击您的存储桶名称 (
oci-audit-logs-gcs)。 - 前往权限标签页。
- 点击授予访问权限。
- 提供以下配置详细信息:
- 添加主账号:粘贴 Google SecOps 服务账号电子邮件地址。
- 分配角色:选择 Storage Object Viewer。
点击保存。
在 Google SecOps 中配置 Feed 以注入 Oracle Cloud Infrastructure 审核日志
- 依次前往 SIEM 设置 > Feed。
- 点击添加新 Feed。
- 点击配置单个 Feed。
- 在 Feed 名称字段中,输入 Feed 的名称(例如
Oracle Cloud Audit Logs)。 - 选择 Google Cloud Storage V2 作为来源类型。
- 选择 Oracle Cloud Infrastructure 审核日志作为日志类型。
- 点击下一步。
为以下输入参数指定值:
存储桶网址:输入带有前缀路径的 GCS 存储桶 URI:
gs://oci-audit-logs-gcs/oci-audit-logs/将
oci-audit-logs-gcs:您的 GCS 存储桶名称。oci-audit-logs:存储日志的可选前缀/文件夹路径(留空表示根目录)。
示例:
- 根存储桶:
gs://company-logs/ - 带前缀:
gs://company-logs/oci-audit-logs/ - 使用子文件夹:
gs://company-logs/oracle/audit/
- 根存储桶:
- 来源删除选项:根据您的偏好选择删除选项:
- 永不删除文件:转移后永不删除任何文件(建议用于测试)。
- 删除已转移的文件和空目录:成功转移后删除文件和空目录。
- 文件存在时间上限(天):包含在过去指定天数内修改的文件。默认值为 180 天。
- 资产命名空间:资产命名空间。
- 提取标签:要应用于相应 Feed 中事件的标签。
点击下一步。
在最终确定界面中查看新的 Feed 配置,然后点击提交。
UDM 映射表
| 日志字段 | UDM 映射 | 逻辑 |
|---|---|---|
authorization_field |
additional.fields |
已合并 |
compartment_id_field |
additional.fields |
已合并 |
compartment_name_field |
additional.fields |
已合并 |
content_length_field |
additional.fields |
已合并 |
content_type_field |
additional.fields |
已合并 |
event_grouping_id_field |
additional.fields |
已合并 |
tenant_id_label |
additional.fields |
已合并 |
data.message |
metadata.description |
直接映射 |
time |
metadata.event_timestamp |
解析为 ISO8601 |
has_principal_hostname |
metadata.event_type |
已映射:true → STATUS_UPDATE |
oracle.tenantid |
metadata.product_deployment_id |
直接映射 |
type |
metadata.product_event_type |
直接映射 |
oracle.logid |
metadata.product_log_id |
直接映射 |
specversion |
metadata.product_version |
直接映射 |
data.request.action |
network.http.method |
直接映射 |
data.identity.userAgent |
network.http.parsed_user_agent |
已重命名/已映射 |
data.response.status |
network.http.response_code |
已重命名/已映射 |
ip_protocol_out |
network.ip_protocol |
直接映射 |
data.bytesOut |
network.sent_bytes |
已重命名/已映射 |
data.packets |
network.sent_packets |
已重命名/已映射 |
data.identity.consoleSessionId |
network.session_id |
已重命名/已映射 |
id |
principal.asset.product_object_id |
直接映射 |
source |
principal.hostname |
直接映射 |
data.identity.ipAddress |
principal.ip |
已合并 |
data.sourceAddress |
principal.ip |
已合并 |
data.sourcePort |
principal.port |
已重命名/已映射 |
compartmentid_label |
principal.resource.attribute.labels |
已合并 |
forward_label |
principal.resource.attribute.labels |
已合并 |
loggroupid_label |
principal.resource.attribute.labels |
已合并 |
vniccompartmentocid_label |
principal.resource.attribute.labels |
已合并 |
vnicocid_label |
principal.resource.attribute.labels |
已合并 |
vnicsubnetocid_label |
principal.resource.attribute.labels |
已合并 |
data.flowid |
principal.resource.product_object_id |
直接映射 |
credentials_label |
principal.user.attribute.labels |
已合并 |
data.identity.principalName |
principal.user.user_display_name |
直接映射 |
data.identity.principalId |
principal.user.userid |
直接映射 |
action |
security_result.action |
已合并 |
endTime_label |
security_result.detection_fields |
已合并 |
startTime_label |
security_result.detection_fields |
已合并 |
status_label |
security_result.detection_fields |
已合并 |
version_label |
security_result.detection_fields |
已合并 |
data.destinationAddress |
target.ip |
已合并 |
data.destinationPort |
target.port |
已重命名/已映射 |
data.request.path |
target.url |
直接映射 |
| 不适用 | metadata.event_type |
常量:GENERIC_EVENT |
| 不适用 | metadata.product_name |
常量:ORACLE CLOUD AUDIT |
| 不适用 | metadata.vendor_name |
常量:ORACLE |