收集 Oracle Fusion Cloud Applications 日志
本文档介绍了如何使用 Google Cloud Storage V2 将 Oracle Fusion Cloud Applications 日志注入到 Google Security Operations。
Oracle Fusion Cloud Applications 是 Oracle 的一套全面的基于云的企业资源规划 (ERP)、人力资源管理 (HCM)、供应链管理 (SCM) 和客户体验 (CX) 应用。该平台通过 REST API 提供广泛的审核日志记录功能,可捕获所有 Fusion 模块中的用户身份验证事件、交易更改、管理操作和安全相关活动。Cloud Run 函数会查询 Oracle Fusion Audit REST API 以检索此数据,并将其写入 GCS 存储桶,以便 Google SecOps 提取数据。
准备工作
请确保您满足以下前提条件:
- Google SecOps 实例
- 启用了 Cloud Storage、Cloud Run、Pub/Sub 和 Cloud Scheduler API 的 GCP 项目
- 创建和管理 GCS 存储分区的权限
- 管理 GCS 存储分区的 IAM 政策的权限
- 创建 Cloud Run 服务、Pub/Sub 主题和 Cloud Scheduler 作业的权限
- 对 Oracle Fusion Cloud Applications 的管理员访问权限
- 管理员对与 Fusion Applications 实例关联的 Oracle Cloud Infrastructure (OCI) Identity and Access Management (IAM) 身份网域的访问权限
- 具有 FND_VIEW_AUDIT_HISTORY_PRIV 权限或 Fusion Apps Administrator 角色的 Fusion Applications 用户账号
配置 Oracle Fusion Cloud Applications OAuth 2.0 API 访问权限
如需让 Google SecOps 检索审核日志,您需要使用“客户端凭据”授权类型创建 OAuth 2.0 机密应用,并将客户端 ID 配置为 Fusion Applications 中的用户。
创建 OAuth 2.0 保密应用
- 使用身份网域管理员凭据登录 Oracle Cloud Infrastructure 控制台。
- 在菜单栏中,依次点击身份和安全 > 网域。
- 选择您的隔离区。
- 点击与您的 Fusion Applications 实例关联的身份网域。
- 在菜单栏中,依次点击集成式应用 > 添加应用。
- 在添加应用对话框中,选择保密应用,然后点击启动工作流。
- 在添加保密应用页面上的名称字段中,输入一个描述性名称(例如
Chronicle SIEM Integration)。 - 点击下一步。
- 在 Configure OAuth(配置 OAuth)部分,选中 Configure this application as a client now(立即将此应用配置为客户端)复选框。
- 在授权部分中,选中客户端凭据复选框。
- 清除所有其他授权类型复选框。
- 向下滚动到令牌发放政策部分。
- 在授权资源部分,选择特定。
- 选中添加资源复选框。
- 在资源子部分中,点击添加范围。
- 在添加范围对话框中,找到并选择 Fusion Applications 资源应用。
为 Fusion Applications 实例选择合适的范围。
点击 Add(添加)。
点击下一步。
在 Web tier policy 页面上,接受默认设置,然后点击 Finish。
系统会显示一个确认对话框,其中显示自动生成的客户端 ID 和客户端密钥值。
立即复制并保存客户端 ID 和客户端密钥。
点击关闭。
在应用详情页面上,点击启用。
在确认对话框中,点击激活应用。
记录身份网域网址
- 在 Oracle 云基础设施控制台中,查看身份网域时,请记下页面顶部显示的网域网址。
- 网域网址的格式为
https://idcs-<idcs-id>.identity.oraclecloud.com。 保存此网址以备稍后使用。
为 OAuth 客户端创建用户账号
在客户端凭据流程中,API 调用是在应用本身(而非用户)的上下文中调用的。您必须在 Fusion Applications 中创建一个与 OAuth 客户端 ID 具有相同用户名的用户账号。
- 登录 Oracle Fusion Cloud Applications。
- 点击左上角的Navigator图标。
- 在工具下,选择安全控制台。
- 点击用户。
- 点击添加用户账号。
在用户信息部分的用户名字段中,输入 OAuth 应用中的客户端 ID 值。
填写剩余的必填字段:
- First Name(名字):输入
Google SecOps或描述性名称 - Last Name(姓氏):输入
Integration或描述性名称 - 电子邮件地址:输入有效的电子邮件地址(例如
chronicle-integration@yourcompany.com)
- First Name(名字):输入
点击添加角色。
搜索并添加以下角色:
- Fusion Apps 管理员
点击保存并关闭。
记录 Fusion Applications 基准网址
- 登录 Oracle Fusion Cloud Applications 后,记下浏览器地址栏中的网址。
- 基本网址的格式为
https://<instance>.<service>.<datacenter>.oraclecloud.com。 - 仅提取主机名部分(例如,
mycompany.fa.us2.oraclecloud.com)。 保存此主机名以备稍后使用。
验证权限
如需验证 OAuth 客户端是否拥有所需权限,请执行以下操作:
- 登录 Oracle Fusion Cloud Applications。
- 依次点击导航器图标 > 工具 > 安全控制台。
- 点击用户,然后搜索与客户端 ID 匹配的用户账号。
- 验证用户是否已获分配 Fusion Apps 管理员角色或 FND_VIEW_AUDIT_HISTORY_PRIV 权限。
- 如果您找不到相应用户或缺少相应权限,请与 Fusion Applications 管理员联系,以获取所需角色。
测试 API 访问权限
在继续进行集成之前,请先测试您的凭据:
# Replace with your actual values IDENTITY_DOMAIN_URL="https://idcs-xxxxxxxxxxxx.identity.oraclecloud.com" CLIENT_ID="your-client-id" CLIENT_SECRET="your-client-secret" FUSION_HOST="mycompany.fa.us2.oraclecloud.com" OAUTH_SCOPE="urn:opc:resource:fusion:podname:boss/" FUSION_USERNAME="svc_secops_audit" FUSION_PASSWORD="your-user-password" # Step 1: Obtain OAuth access token (only needed if you use bearer auth instead of Basic) TOKEN=$(curl -s -u "${CLIENT_ID}:${CLIENT_SECRET}" \ -H "Content-Type: application/x-www-form-urlencoded;charset=UTF-8" \ -X POST "${IDENTITY_DOMAIN_URL}/oauth2/v1/token" \ -d "grant_type=client_credentials&scope=${OAUTH_SCOPE}" \ | python3 -c "import sys,json; print(json.load(sys.stdin)['access_token'])") echo "Token obtained: ${TOKEN:0:20}..." # Step 2: Test the Sign In - Sign Out Audit REST API (last 7 days of data) # The API is documented with HTTP Basic auth (-u "<user>:<password>"). # If your tenant accepts the bearer token instead, replace -u with # -H "Authorization: Bearer ${TOKEN}". curl -s -X GET "https://${FUSION_HOST}/oam/services/rest/access/api/v1/audit/events/1?fromDate=$(date -u -v-7d '+%Y-%m-%dT%H:%M:%S.000Z')&toDate=$(date -u '+%Y-%m-%dT%H:%M:%S.000Z')&pageSize=5" \ -u "${FUSION_USERNAME}:${FUSION_PASSWORD}" \ -H "Accept: application/json" \ | python3 -m json.tool
如果请求成功,系统会返回一个 JSON 对象,其中包含一个 Events.eventData 数组,该数组包含登录和退出记录(每条记录都包含 eventID、userID、ipAddress、type、status 和 accessTime 等字段)。
创建 Google Cloud Storage 存储桶
- 前往 Google Cloud 控制台。
- 选择您的项目或创建新项目。
- 在导航菜单中,依次前往 Cloud Storage > 存储分区。
- 点击创建存储分区。
提供以下配置详细信息:
设置 值 为存储桶命名 输入一个全局唯一的名称(例如 oracle-fusion-audit-logs)位置类型 根据您的需求进行选择(区域级、双区域、多区域) 位置 选择营业地点(例如 us-central1)存储类别 标准(建议用于经常访问的日志) 访问权限控制 均匀(推荐) 保护工具 可选:启用对象版本控制或保留政策 点击创建。
为 Cloud Run 函数创建服务账号
Cloud Run 函数需要一个服务账号,该账号具有写入 GCS 存储桶的权限,并且可以由 Pub/Sub 调用。
创建服务账号
- 在 GCP 控制台中,依次前往 IAM 和管理 > 服务账号。
- 点击创建服务账号。
- 提供以下配置详细信息:
- 服务账号名称:输入
oracle-fusion-audit-collector-sa - 服务账号说明:输入
Service account for Cloud Run function to collect Oracle Fusion Cloud Applications audit logs
- 服务账号名称:输入
- 点击创建并继续。
- 在向此服务账号授予对项目的访问权限部分中,添加以下角色:
- 点击选择角色。
- 搜索并选择 Storage Object Admin。
- 点击 + 添加其他角色。
- 搜索并选择 Cloud Run Invoker。
- 点击 + 添加其他角色。
- 搜索并选择 Cloud Functions Invoker。
- 点击继续。
- 点击完成。
必须拥有这些角色,才能:
- Storage Object Admin:将日志写入 GCS 存储桶并管理状态文件
- Cloud Run Invoker:允许 Pub/Sub 调用函数
- Cloud Functions Invoker:允许调用函数
授予对 GCS 存储桶的 IAM 权限
- 前往 Cloud Storage > 存储分区。
- 点击您的存储桶名称 (
oracle-fusion-audit-logs)。 - 前往权限标签页。
- 点击授予访问权限。
- 提供以下配置详细信息:
- 添加主账号:输入服务账号电子邮件地址 (
oracle-fusion-audit-collector-sa@PROJECT_ID.iam.gserviceaccount.com) - 分配角色:选择 Storage Object Admin
- 添加主账号:输入服务账号电子邮件地址 (
- 点击保存。
创建 Pub/Sub 主题
- 在 GCP 控制台中,前往 Pub/Sub > 主题。
- 点击创建主题。
- 提供以下配置详细信息:
- 主题 ID:输入
oracle-fusion-audit-trigger - 将其他设置保留为默认值
- 主题 ID:输入
- 点击创建。
创建 Cloud Run 函数以收集日志
Cloud Run 函数将由来自 Cloud Scheduler 的 Pub/Sub 消息触发,以从 Oracle Fusion Cloud Applications Audit REST API 中提取审核数据并将其写入 GCS。
- 在 GCP 控制台中,前往 Cloud Run。
- 点击创建服务。
- 选择函数(使用内嵌编辑器创建函数)。
在配置部分中,提供以下配置详细信息:
设置 值 Service 名称 oracle-fusion-audit-collector区域 选择与您的 GCS 存储桶匹配的区域(例如 us-central1)运行时 选择 Python 3.12 或更高版本 在触发器(可选)部分中:
- 点击 + 添加触发器。
- 选择 Cloud Pub/Sub。
- 在选择 Cloud Pub/Sub 主题中,选择
oracle-fusion-audit-trigger。 - 点击保存。
在身份验证部分中:
- 选择需要进行身份验证。
- 检查 Identity and Access Management (IAM)。
向下滚动并展开容器、网络、安全性。
前往安全性标签页:
- 服务账号:选择
oracle-fusion-audit-collector-sa
- 服务账号:选择
前往容器标签页:
- 点击变量和密钥。
- 为每个环境变量点击+ 添加变量:
变量名称 示例值 说明 GCS_BUCKEToracle-fusion-audit-logsGCS 存储桶名称 GCS_PREFIXoracle-fusion-audit日志文件的前缀 STATE_KEYoracle-fusion-audit/state.json状态文件路径 FUSION_HOSTmycompany.fa.us2.oraclecloud.comFusion Applications 主机名 IDENTITY_DOMAIN_URLhttps://idcs-xxxx.identity.oraclecloud.com身份网域网址 CLIENT_IDyour-client-idOAuth 2.0 客户端 ID CLIENT_SECRETyour-client-secretOAuth 2.0 客户端密钥 OAUTH_SCOPEurn:opc:resource:fusion:podname:boss/Fusion Applications 的 OAuth 范围 LOOKBACK_HOURS24初始回溯期 PAGE_SIZE100每页记录数 FUSION_USERNAMEsvc_secops_audit可选。HTTP 基本身份验证的用户,用于登录/退出审核 API。如果为空,则使用 OAuth 2.0 不记名令牌 FUSION_PASSWORDyour-user-password可选。 FUSION_USERNAME的密码(存储为 Secret Manager Secret)在变量和 Secret 部分中,向下滚动到请求:
- 请求超时:输入
600秒(10 分钟)
- 请求超时:输入
前往设置标签页:
- 在资源部分中:
- 内存:选择 512 MiB 或更高值
- CPU:选择 1
- 在资源部分中:
在修订版本伸缩部分中:
- 实例数下限:输入
0 - 实例数上限:输入
100
- 实例数下限:输入
点击创建。
等待服务创建完成(1-2 分钟)。
创建服务后,系统会自动打开内嵌代码编辑器。
添加函数代码
- 在入口点字段中输入 main。
在内嵌代码编辑器中,创建两个文件:
- main.py:
import functions_framework from google.cloud import storage import json import os import urllib3 from datetime import datetime, timezone, timedelta import time import base64 import urllib.parse http = urllib3.PoolManager( timeout=urllib3.Timeout(connect=10.0, read=60.0), retries=False, ) storage_client = storage.Client() GCS_BUCKET = os.environ.get('GCS_BUCKET') GCS_PREFIX = os.environ.get('GCS_PREFIX', 'oracle-fusion-audit') STATE_KEY = os.environ.get('STATE_KEY', 'oracle-fusion-audit/state.json') FUSION_HOST = os.environ.get('FUSION_HOST', '').strip() IDENTITY_DOMAIN_URL = os.environ.get('IDENTITY_DOMAIN_URL', '').rstrip('/') CLIENT_ID = os.environ.get('CLIENT_ID') CLIENT_SECRET = os.environ.get('CLIENT_SECRET') OAUTH_SCOPE = os.environ.get('OAUTH_SCOPE', '') # The Sign In - Sign Out Audit REST API is documented with HTTP Basic auth. # Set FUSION_USERNAME / FUSION_PASSWORD to use it; otherwise the function falls # back to the OAuth 2.0 bearer token configured above. FUSION_USERNAME = os.environ.get('FUSION_USERNAME', '') FUSION_PASSWORD = os.environ.get('FUSION_PASSWORD', '') LOOKBACK_HOURS = int(os.environ.get('LOOKBACK_HOURS', '24')) PAGE_SIZE = int(os.environ.get('PAGE_SIZE', '100')) # Sign In - Sign Out Audit REST API. Returns {"Events": {"eventData": [...]}}, # which the ORACLE_FUSION parser reads directly. Data is retained for 7 days. AUDIT_PATH = '/oam/services/rest/access/api/v1/audit/events' def get_oauth_token(): token_url = f"{IDENTITY_DOMAIN_URL}/oauth2/v1/token" auth_b64 = base64.b64encode(f"{CLIENT_ID}:{CLIENT_SECRET}".encode('utf-8')).decode('utf-8') body = f"grant_type=client_credentials&scope={urllib.parse.quote(OAUTH_SCOPE, safe='')}" try: response = http.request( 'POST', token_url, body=body.encode('utf-8'), headers={ 'Authorization': f'Basic {auth_b64}', 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8', } ) if response.status != 200: print(f"OAuth token request failed: {response.status} {response.data.decode('utf-8')}") return None return json.loads(response.data.decode('utf-8')).get('access_token') except Exception as e: print(f"Error obtaining OAuth token: {e}") return None def get_auth_header(): """Use HTTP Basic auth when FUSION_USERNAME/PASSWORD are set, else OAuth bearer.""" if FUSION_USERNAME and FUSION_PASSWORD: creds_b64 = base64.b64encode(f"{FUSION_USERNAME}:{FUSION_PASSWORD}".encode('utf-8')).decode('utf-8') return f"Basic {creds_b64}" token = get_oauth_token() return f"Bearer {token}" if token else None def fetch_signin_audit(auth_header, start_time, end_time): """Page through the Sign In - Sign Out Audit REST API. Returns (pages, newest_time). Each item in pages is a raw {"Events": {"eventData": [...]}} object, written unchanged for the parser. """ base_url = f"https://{FUSION_HOST}{AUDIT_PATH}" from_date = start_time.strftime('%Y-%m-%dT%H:%M:%S.000Z') to_date = end_time.strftime('%Y-%m-%dT%H:%M:%S.000Z') headers = {'Authorization': auth_header, 'Accept': 'application/json'} pages = [] newest_time = None page_num = 1 backoff = 1.0 while True: query_string = urllib.parse.urlencode({ 'fromDate': from_date, 'toDate': to_date, 'pageSize': str(PAGE_SIZE), }) # The page number is a path segment: /audit/events/{page} request_url = f"{base_url}/{page_num}?{query_string}" try: response = http.request('GET', request_url, headers=headers) if response.status == 429: retry_after = int(response.headers.get('Retry-After', str(int(backoff)))) print(f"Rate limited (429). Retrying after {retry_after}s...") time.sleep(retry_after) backoff = min(backoff * 2, 60.0) continue backoff = 1.0 if response.status != 200: print(f"HTTP Error {response.status}: {response.data.decode('utf-8')}") break data = json.loads(response.data.decode('utf-8')) event_list = data.get('Events', {}).get('eventData', []) if isinstance(event_list, dict): event_list = [event_list] if not event_list: print(f"No more sign-in events (empty page {page_num})") break # Preserve the exact {"Events": {"eventData": [...]}} shape the parser # consumes; do not rename or flatten individual records. pages.append({'Events': {'eventData': event_list}}) print(f"Page {page_num}: retrieved {len(event_list)} sign-in events") for event in event_list: access_time = event.get('accessTime') if access_time and (newest_time is None or access_time > newest_time): newest_time = access_time if len(event_list) < PAGE_SIZE: break page_num += 1 except Exception as e: print(f"Error fetching sign-in audit: {e}") break print(f"Retrieved {len(pages)} page(s) of sign-in audit events") return pages, newest_time @functions_framework.cloud_event def main(cloud_event): if not all([GCS_BUCKET, FUSION_HOST]): print('Error: Missing required environment variables (GCS_BUCKET, FUSION_HOST)') return try: bucket = storage_client.bucket(GCS_BUCKET) state = load_state(bucket) now = datetime.now(timezone.utc) if isinstance(state, dict) and state.get('last_event_time'): try: last_val = state['last_event_time'] if last_val.endswith('Z'): last_val = last_val[:-1] + '+00:00' last_time = datetime.fromisoformat(last_val) - timedelta(minutes=2) except Exception as e: print(f"Warning: could not parse last_event_time: {e}") last_time = now - timedelta(hours=LOOKBACK_HOURS) else: last_time = now - timedelta(hours=LOOKBACK_HOURS) # The API retains only 7 days of data; never look back further. earliest = now - timedelta(days=7) if last_time < earliest: last_time = earliest print(f"Fetching sign-in audit from {last_time.isoformat()} to {now.isoformat()}") auth_header = get_auth_header() if not auth_header: print("Error: could not build authorization header") return pages, newest_time = fetch_signin_audit(auth_header, last_time, now) if not pages: print("No new sign-in audit events found.") save_state(bucket, now.isoformat()) return timestamp = now.strftime('%Y%m%d_%H%M%S') object_key = f"{GCS_PREFIX}/oracle_fusion_audit_{timestamp}.ndjson" blob = bucket.blob(object_key) ndjson = '\n'.join([json.dumps(p, ensure_ascii=False, default=str) for p in pages]) + '\n' blob.upload_from_string(ndjson, content_type='application/x-ndjson') print(f"Wrote {len(pages)} page(s) to gs://{GCS_BUCKET}/{object_key}") save_state(bucket, newest_time if newest_time else now.isoformat()) print("Successfully processed sign-in audit events") except Exception as e: print(f'Error processing logs: {str(e)}') raise def load_state(bucket): try: blob = bucket.blob(STATE_KEY) if blob.exists(): return json.loads(blob.download_as_text()) except Exception as e: print(f"Warning: Could not load state: {e}") return {} def save_state(bucket, last_event_time_iso): try: state = { 'last_event_time': last_event_time_iso, 'last_run': datetime.now(timezone.utc).isoformat() } blob = bucket.blob(STATE_KEY) blob.upload_from_string(json.dumps(state, indent=2), content_type='application/json') print(f"Saved state: last_event_time={last_event_time_iso}") except Exception as e: print(f"Warning: Could not save state: {e}")requirements.txt:
functions-framework==3.* google-cloud-storage==2.* urllib3>=2.0.0
点击部署以保存并部署该函数。
等待部署完成(2-3 分钟)。
创建 Cloud Scheduler 作业
- 在 GCP Console 中,前往 Cloud Scheduler。
- 点击创建作业。
提供以下配置详细信息:
设置 值 名称 oracle-fusion-audit-collector-hourly区域 选择与 Cloud Run 函数相同的区域 频率 0 * * * *(每小时一次,整点时)时区 选择时区(建议选择 UTC) 目标类型 Pub/Sub 主题 选择 oracle-fusion-audit-trigger消息正文 {}(空 JSON 对象)点击创建。
时间表频率选项
根据日志量和延迟时间要求选择频次:
| 频率 | Cron 表达式 | 使用场景 |
|---|---|---|
| 每隔 5 分钟 | */5 * * * * |
大批量、低延迟 |
| 每隔 15 分钟 | */15 * * * * |
搜索量中等 |
| 每小时 | 0 * * * * |
标准(推荐) |
| 每 6 小时 | 0 */6 * * * |
低成交量、批处理 |
| 每天 | 0 0 * * * |
历史数据收集 |
测试集成
- 在 Cloud Scheduler 控制台中,找到您的作业 (
oracle-fusion-audit-collector-hourly)。 - 点击强制运行以手动触发作业。
- 等待几秒钟。
- 前往 Cloud Run > 服务。
- 点击
oracle-fusion-audit-collector。 - 点击日志标签页。
验证函数是否已成功执行。查找:
Fetching logs from YYYY-MM-DDTHH:MM:SS+00:00 to YYYY-MM-DDTHH:MM:SS+00:00 Successfully obtained OAuth access token Page 1: Retrieved X audit events Wrote X records to gs://oracle-fusion-audit-logs/oracle-fusion-audit/oracle_fusion_audit_YYYYMMDD_HHMMSS.ndjson Successfully processed X records前往 Cloud Storage > 存储分区。
点击
oracle-fusion-audit-logs。转到
oracle-fusion-audit/文件夹。验证是否已创建具有当前时间戳的新
.ndjson文件。
如果您在日志中看到错误,请执行以下操作:
- HTTP 401:验证
CLIENT_ID和CLIENT_SECRET环境变量是否正确,以及 OAuth 应用是否已激活 - HTTP 403:验证 Fusion Applications 用户(与客户端 ID 匹配)是否具有 FND_VIEW_AUDIT_HISTORY_PRIV 权限或 Fusion Apps 管理员角色
- HTTP 429:速率限制 - 函数将自动重试,并采用指数退避算法
- API 状态为“失败”:验证
FUSION_HOST环境变量是否正确,以及 Fusion Applications 实例是否可访问 - OAuth 令牌错误:验证
IDENTITY_DOMAIN_URL和OAUTH_SCOPE环境变量是否正确
所需 API 权限
OAuth 客户端需要以下权限:
权限/范围 访问权限级别 用途 FND_VIEW_AUDIT_HISTORY_PRIV 读取 从 Fusion Applications 检索审核历史记录数据 Fusion 应用范围 应用 访问 Fusion Applications REST API 资源
区域端点
Oracle Fusion Cloud Applications 使用不同的数据中心区域。基本网址格式因区域而异:
| 区域 | 数据中心代码 | 主机名示例 |
|---|---|---|
| 美国西部(凤凰城) | us-phoenix-1 | instance.fa.us-phoenix-1.oraclecloud.com |
| 美国东部(阿什本) | us-ashburn-1 | instance.fa.us-ashburn-1.oraclecloud.com |
| 美国商业广告 2 | us2 | instance.fa.us2.oraclecloud.com |
| 欧盟西部(法兰克福) | eu-frankfurt-1 | instance.fa.eu-frankfurt-1.oraclecloud.com |
| 欧盟西部(阿姆斯特丹) | eu-amsterdam-1 | instance.fa.eu-amsterdam-1.oraclecloud.com |
| 英国南部(伦敦) | uk-london-1 | instance.fa.uk-london-1.oraclecloud.com |
| 加拿大东南部(多伦多) | ca-toronto-1 | instance.fa.ca-toronto-1.oraclecloud.com |
| 亚太地区东南(悉尼) | ap-sydney-1 | instance.fa.ap-sydney-1.oraclecloud.com |
| 亚太东北地区(东京) | ap-tokyo-1 | instance.fa.ap-tokyo-1.oraclecloud.com |
使用与您的 Oracle Fusion Cloud Applications 实例区域对应的主机名。您可以通过访问 Fusion Applications 环境时显示的网址来确定您的区域。
API 速率限制
Oracle Fusion Cloud Applications Audit REST API 具有以下特征:
| 限制类型 | 值 |
|---|---|
| 令牌有效期 | 3600 秒(1 小时) |
| 审核历史记录查询范围 | 每次请求最多可查询 1 个月的数据 |
| 登录/退出审核日志保留 | 7 天 |
| 交易审核日志保留 | 30-365 天(因产品而异) |
Cloud Run 函数会自动处理 OAuth 令牌刷新、分页和查询范围分块。该函数会将超过一个月的时间范围拆分为按月分块,并通过自动重新身份验证来处理令牌过期问题。
Note: For sign-in and sign-out audit events, the retention period is limited to 7 days. Configure the scheduler to poll frequently to avoid data loss. Transaction audit retention varies by Fusion Applications product and configuration.
检索 Google SecOps 服务账号
- 依次前往 SIEM 设置 > Feed。
- 点击添加新 Feed。
- 点击配置单个 Feed。
- 在 Feed 名称字段中,输入 Feed 的名称(例如
Oracle Fusion Audit Logs)。 - 选择 Google Cloud Storage V2 作为来源类型。
- 选择 Oracle Fusion Cloud Applications 作为日志类型。
- 点击获取服务账号。
系统会显示一个唯一的服务账号电子邮件地址,例如:
chronicle-12345678@chronicle-gcp-prod.iam.gserviceaccount.com复制此电子邮件地址,以便在下一步中使用。
点击下一步。
为以下输入参数指定值:
存储桶网址:输入带有前缀路径的 GCS 存储桶 URI:
gs://oracle-fusion-audit-logs/oracle-fusion-audit/
来源删除选项:根据您的偏好选择删除选项:
- 永不:转移后永不删除任何文件(建议用于测试)。
- 删除已转移的文件:在成功转移后删除文件。
删除已转移的文件和空目录:成功转移后删除文件和空目录。
文件存在时间上限:包含在过去指定天数内修改过的文件(默认值为 180 天)
资产命名空间:资产命名空间
注入标签:要应用于此 Feed 中事件的标签
点击下一步。
在最终确定界面中查看新的 Feed 配置,然后点击提交。
向 Google SecOps 服务账号授予 IAM 权限
Google SecOps 服务账号需要您的 GCS 存储桶的 Storage Object Viewer 角色。
- 前往 Cloud Storage > 存储分区。
- 点击
oracle-fusion-audit-logs。 - 前往权限标签页。
- 点击授予访问权限。
- 提供以下配置详细信息:
- 添加主账号:粘贴 Google SecOps 服务账号电子邮件地址
- 分配角色:选择 Storage Object Viewer
点击保存。
UDM 映射表
| 日志字段 | UDM 映射 | 逻辑 |
|---|---|---|
| 类型 | extensions.auth.type | 身份验证类型 |
| 类型 | metadata.event_type | 事件类型 |
| ipAddress | metadata.event_type | |
| eventID | metadata.product_log_id | 产品日志 ID |
| attributeMap.attribute.value | network.http.user_agent | HTTP 用户代理 |
| ipAddress | principal.asset.ip | 与正文相关联的资产的 IP 地址 |
| ipAddress | principal.ip | 主账号的 IP 地址 |
| userID.userDN | principal.user.attribute.labels | 用户属性的标签 |
| userID.userDN | principal.user.email_addresses | 用户的电子邮件地址 |
| userID.loginID | principal.user.userid | 用户 ID |
| 状态 | security_result.action | 安全操作 |
| oracleECID | target.user.userid | 目标的相应用户 ID |
更新日志
需要更多帮助?获得社区成员和 Google SecOps 专业人士的解答。