收集 Oracle Cloud Infrastructure 稽核記錄

支援的國家/地區:

本文說明如何使用 Amazon S3,將 Oracle Cloud Infrastructure 稽核記錄檔擷取至 Google Security Operations。

事前準備

請確認您已完成下列事前準備事項:

  • Google SecOps 執行個體。
  • 具備建立及管理下列項目的權限的 Oracle Cloud Infrastructure 帳戶:
    • 服務連接器中樞
    • Oracle Functions
    • 保管箱和密鑰
    • 動態群組和 IAM 政策
    • 記錄
  • 具有建立及管理權限的 AWS 帳戶:
    • S3 儲存貯體
    • IAM 使用者和政策

建立 Amazon S3 儲存貯體

  1. 登入 AWS 管理主控台
  2. 依序前往「S3」>「建立 bucket」
  3. 請提供下列設定詳細資料:
    • Bucket name:輸入不重複的名稱 (例如 oci-audit-logs-bucket)。
    • AWS 區域:選取區域 (例如 us-east-1)。
    • 其他選項保留預設設定。
  4. 按一下「建立值區」
  5. 儲存 bucket 的「名稱」和「區域」,稍後會用到。

在 AWS 中為 OCI Functions 建立 IAM 使用者

  1. 登入 AWS 管理主控台
  2. 依序前往「IAM」>「Users」>「Add users」
  3. 請提供下列設定詳細資料:
    • 使用者名稱:輸入使用者名稱 (例如 oci-functions-s3-user)。
    • 存取權類型:選取「存取金鑰 - 程式輔助存取」
  4. 點選 [Next: Permissions] (下一步:權限)。
  5. 按一下「Attach existing policies directly」(直接附加現有政策)
  6. 搜尋並選取 AmazonS3FullAccess 政策。
  7. 按一下「下一步:代碼」
  8. 按一下 [下一步:檢閱]
  9. 按一下「建立使用者」
  10. 重要事項:在成功頁面中,複製並儲存下列憑證:
    • 存取金鑰 ID
    • 存取密鑰

在 OCI Vault 中儲存 AWS 憑證

如要安全地儲存 AWS 憑證,請務必使用 Oracle Cloud Infrastructure Vault,而不是在函式程式碼中硬式編碼。

建立 Vault 和主加密金鑰

  1. 登入 Oracle Cloud Console
  2. 依序前往「身分與安全性」>「Vault」
  3. 如果沒有 Vault,請按一下「建立 Vault」
  4. 請提供下列設定詳細資料:
    • 在區間中建立:選取區間。
    • 「Name」(名稱):輸入名稱 (例如 oci-functions-vault)。
  5. 按一下「建立 Vault」
  6. 建立保管箱後,按一下保管箱名稱即可開啟。
  7. 在「主加密金鑰」下方,按一下「建立金鑰」
  8. 請提供下列設定詳細資料:
    • 保護模式:軟體
    • 「Name」(名稱):輸入名稱 (例如 oci-functions-key)。
    • 金鑰形狀:演算法:AES
    • 金鑰形狀:長度:256 位元
  9. 按一下 [Create Key] (建立金鑰)

建立 AWS 憑證的密鑰

  1. 在 Vault 中,按一下「Secrets」下方的「Create Secret」
  2. 請提供 AWS 存取金鑰的下列設定詳細資料:
    • 在區間中建立:選取區間。
    • Name (名稱):aws-access-key
    • 說明:S3 的 AWS 存取金鑰
    • 加密金鑰:選取您建立的主加密金鑰。
    • 密鑰類型內容:純文字
    • 私密內容:貼上 AWS 存取金鑰 ID。
  3. 按一下「建立密鑰」
  4. 複製並儲存這項密鑰的 OCID (看起來像 ocid1.vaultsecret.oc1...)。
  5. 再次按一下「建立密鑰」,建立第二個密鑰。
  6. 請提供 AWS 密鑰的下列設定詳細資料:
    • 在區間中建立:選取區間。
    • Name (名稱):aws-secret-key
    • 說明:S3 的 AWS 密鑰
    • 加密金鑰:選取相同的主加密金鑰。
    • 密鑰類型內容:純文字
    • 私密內容:貼上 AWS 私密存取金鑰。
  7. 按一下「建立密鑰」
  8. 複製並儲存這個密鑰的 OCID

為 OCI 函式建立動態群組

  1. 登入 Oracle Cloud Console
  2. 依序前往「身分與安全性」>「身分」>「動態群組」
  3. 按一下「建立動態群組」
  4. 請提供下列設定詳細資料:

    • Name (名稱):oci-functions-dynamic-group
    • 說明:OCI Functions 存取 Vault 密鑰的動態群組
    • 比對規則:輸入下列規則 (將 <your_compartment_ocid> 替換成分區 OCID):

      ALL {resource.type = 'fnfunc', resource.compartment.id = '<your_compartment_ocid>'}
      
  5. 點選「建立」

建立保管箱存取權的身分與存取權管理政策

  1. 登入 Oracle Cloud Console
  2. 依序前往「身分與安全性」>「身分」>「政策」
  3. 選取要建立政策的區間。
  4. 點選「建立政策」
  5. 請提供下列設定詳細資料:

    • Name (名稱):oci-functions-vault-access-policy
    • 說明:允許 OCI Functions 從 Vault 讀取密碼
    • 政策建立工具:切換「顯示手動編輯器」
    • 政策陳述式:輸入下列內容 (將 <compartment_name> 替換為區間名稱):

      allow dynamic-group oci-functions-dynamic-group to manage secret-family in compartment <compartment_name>
      
  6. 點選「建立」

建立 OCI 函式應用程式

  1. 登入 Oracle Cloud Console
  2. 依序前往「開發人員服務」>「應用程式」(位於「功能」下方)
  3. 點選「Create Application」(建立應用程式)
  4. 請提供下列設定詳細資料:
    • 「Name」(名稱):輸入名稱 (例如 oci-logs-to-s3-app)。
    • VCN:選取區間中的 VCN。
    • 子網路:選取一或多個子網路。
  5. 點選「建立」

建立及部署 OCI 函式

  1. Oracle Cloud 控制台中,按一下右上角的「Cloud Shell」圖示。
  2. 等待 Cloud Shell 初始化。

建立函式

  1. 在 Cloud Shell 中,為函式建立新目錄:

    mkdir pushlogs
    cd pushlogs
    
  2. 初始化新的 Python 函式:

    fn init --runtime python
    
  3. 這會建立三個檔案:func.pyfunc.yamlrequirements.txt

更新 func.py

  • func.py 的內容替換為下列程式碼:

    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
            )
    
    • secret_key_id 替換為 AWS 密鑰的實際保存庫密鑰 OCID
    • access_key_id 換成 AWS 存取金鑰的實際保存庫密鑰 OCID
    • 請將 s3_bucket_name 替換成實際的 S3 值區名稱

更新 func.yaml

func.yaml 改成以下內容:

  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

更新 requirements.txt

  • requirements.txt 改成以下內容:

    fdk>=0.1.56
    boto3
    oci
    

部署函式

  1. 設定 Fn 內容,以使用您的應用程式:

    fn use context <region-context>
    fn update context oracle.compartment-id <compartment-ocid>
    
  2. 部署函式:

    fn -v deploy --app oci-logs-to-s3-app
    
  3. 等待部署作業完成。輸出內容應該會指出函式已部署成功。

  4. 確認函式是否已建立:

    fn list functions oci-logs-to-s3-app
    

建立服務連接器,將 OCI 稽核記錄傳送至函式

  1. 登入 Oracle Cloud Console
  2. 依序前往「Analytics & AI」>「Messaging」>「Service Connector Hub」
  3. 選取要建立服務連接器的區間。
  4. 按一下「建立服務連接器」

設定服務連接器詳細資料

  1. 請提供下列設定詳細資料:

服務連接器資訊: * 連接器名稱:輸入描述性名稱 (例如 audit-logs-to-s3-connector)。 * 說明:選用說明 (例如「將 OCI 稽核記錄轉送至 AWS S3」)。 * 資源區間:選取區間。

設定來源

  1. 在「設定來源」下方:
    • 來源:選取「記錄」
    • 區間:選取包含稽核記錄的區間。
    • 記錄群組:選取 _Audit (這是稽核記錄的預設記錄群組)。
    • 記錄:按一下「+ 另一個記錄」
    • 選取區間的稽核記錄 (例如 _Audit_Include_Subcompartment)。

設定目標

  1. 在「設定目標」下方:
    • 目標:選取「函式」
    • 區間:選取包含函式應用程式的區間。
    • 「Function Application」(函式應用程式):選取 oci-logs-to-s3-app (您先前建立的應用程式)。
    • 函式:選取 pushlogs (您部署的函式)。

設定政策

  1. 在「設定政策」下方:

    • 查看顯示的必要 IAM 政策陳述式。
    • 按一下「建立」,自動建立必要政策。
  2. 按一下「建立」,建立服務連接器。

  3. 等待服務連結器建立並啟用。狀態應變更為「有效」

確認記錄是否已推送至 AWS S3

  1. 登入 Oracle Cloud Console
  2. 執行一些會產生稽核記錄的動作 (例如建立或修改資源)。
  3. 等待 2 到 5 分鐘,讓系統處理記錄。
  4. 登入 AWS 管理主控台
  5. 依序前往「S3」>「Buckets」
  6. 按一下 bucket (例如 oci-audit-logs-bucket)。
  7. 確認 JSON 記錄檔是否顯示在 bucket 中。

為 Google SecOps 設定 AWS S3 值區和 IAM

為 Chronicle 建立 IAM 使用者

  1. 登入 AWS 管理主控台
  2. 依序前往「IAM」>「Users」>「Add users」
  3. 請提供下列設定詳細資料:
    • 使用者名稱:輸入 chronicle-s3-reader
    • 存取權類型:選取「存取金鑰 - 程式輔助存取」
  4. 點選 [Next: Permissions] (下一步:權限)。
  5. 按一下「Attach existing policies directly」(直接附加現有政策)
  6. 搜尋並選取 AmazonS3ReadOnlyAccess 政策。
  7. 按一下「下一步:代碼」
  8. 按一下 [下一步:檢閱]
  9. 按一下「建立使用者」
  10. 按一下「下載 CSV 檔案」,即可儲存「存取金鑰 ID」和「私密存取金鑰」
  11. 按一下 [關閉]

選用:建立自訂 IAM 政策,提供最低權限存取權

如要限制只能存取特定 bucket,請按照下列步驟操作:

  1. 依序前往「IAM」>「Policies」>「Create policy」
  2. 按一下「JSON」分頁標籤。
  3. 輸入下列政策:

    {
      "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/*"
          ]
        }
      ]
    }
    
    • 請將 oci-audit-logs-bucket 替換成您的值區名稱。
  4. 按一下「下一步:代碼」

  5. 按一下 [下一步:檢閱]

  6. 請提供下列設定詳細資料:

    • Name (名稱):chronicle-s3-read-policy
    • 說明:OCI 稽核記錄 bucket 的唯讀存取權
  7. 點選「建立政策」

  8. 返回「IAM」>「Users」,然後選取 chronicle-s3-reader 使用者。

  9. 依序點選「新增權限」>「直接附加政策」

  10. 搜尋並選取 chronicle-s3-read-policy

  11. 如果先前新增了 AmazonS3ReadOnlyAccess 政策,請移除該政策。

  12. 按一下「Add permissions」。

在 Google SecOps 中設定資訊提供,以便擷取 Oracle Cloud 稽核記錄

  1. 依序前往「SIEM 設定」>「動態饋給」
  2. 按一下「新增動態消息」
  3. 在下一個頁面中,按一下「設定單一動態饋給」
  4. 在「動態饋給名稱」欄位中輸入動態饋給名稱 (例如 Oracle Cloud Audit Logs)。
  5. 選取「Amazon S3 V2」做為「來源類型」
  6. 選取「Oracle Cloud Infrastructure」做為「記錄類型」
  7. 點選「下一步」
  8. 指定下列輸入參數的值:
    • S3 URI:輸入 S3 bucket URI (例如 s3://oci-audit-logs-bucket/)。
    • 來源刪除選項:根據偏好選取刪除選項:
      • 永不:建議用於測試和初始設定。
      • 刪除已轉移的檔案:成功擷取檔案後刪除檔案 (適用於正式版,可管理儲存空間費用)。
    • 檔案存在時間上限:包含在過去天數內修改的檔案。預設值為 180 天。
    • 存取金鑰 ID:輸入您建立的 Chronicle IAM 使用者存取金鑰 ID。
    • 存取密鑰:輸入您建立的 Chronicle IAM 使用者存取密鑰。
    • 資產命名空間資產命名空間
    • 擷取標籤:要套用至這個動態饋給事件的標籤。
  9. 點選「下一步」
  10. 在「Finalize」(完成) 畫面中檢查新的動態饋給設定,然後按一下「Submit」(提交)

UDM 對應表

記錄欄位 UDM 對應 邏輯
data.request.headers.authorization.0 event.idm.read_only_udm.additional.fields data.request.headers.authorization.0 取得值,並以鍵/值組合的形式加入,其中鍵為「Request Headers Authorization」。
data.compartmentId event.idm.read_only_udm.additional.fields data.compartmentId 取得的值,並以鍵/值組合的形式新增,其中鍵為「compartmentId」。
data.compartmentName event.idm.read_only_udm.additional.fields data.compartmentName 取得值,並新增為鍵/值組合,其中鍵為「compartmentName」。
data.response.headers.Content-Length.0 event.idm.read_only_udm.additional.fields data.response.headers.Content-Length.0 取得值,並以鍵/值組合形式新增,其中鍵為「Response Headers Content-Length」。
data.response.headers.Content-Type.0 event.idm.read_only_udm.additional.fields data.response.headers.Content-Type.0 取得值,並以鍵/值組合形式新增,其中鍵為「Response Headers Content-Type」。
data.eventGroupingId event.idm.read_only_udm.additional.fields data.eventGroupingId 取得的值,並以鍵/值組合的形式加入,其中鍵為「eventGroupingId」。
oracle.tenantiddata.identity.tenantId event.idm.read_only_udm.additional.fields 如有 oracle.tenantid,則會從該處取值,否則會從 data.identity.tenantId 取值。系統會將其新增為鍵/值組合,其中鍵為「tenantId」。
data.message event.idm.read_only_udm.metadata.description 取自 data.message 的值。
time event.idm.read_only_udm.metadata.event_timestamp time 取得的值,並剖析為 ISO8601 時間戳記。
event.idm.read_only_udm.metadata.event_type 預設為 GENERIC_EVENT。如果主體 (IP 或主機名稱) 和目標 IP 都存在,請設為 NETWORK_CONNECTION。如果只有主體,請設為 STATUS_UPDATE
time event.idm.read_only_udm.metadata.ingested_timestamp 如果 oracle.ingestedtime 不為空白,系統會從 time 欄位取得值,並剖析為 ISO8601 時間戳記。
oracle.tenantid event.idm.read_only_udm.metadata.product_deployment_id 取自 oracle.tenantid 的值。
type event.idm.read_only_udm.metadata.product_event_type 取自 type 的值。
oracle.logid event.idm.read_only_udm.metadata.product_log_id 取自 oracle.logid 的值。
specversion event.idm.read_only_udm.metadata.product_version 取自 specversion 的值。
data.request.action event.idm.read_only_udm.network.http.method 取自 data.request.action 的值。
data.identity.userAgent event.idm.read_only_udm.network.http.parsed_user_agent data.identity.userAgent 擷取並剖析的值。
data.response.status event.idm.read_only_udm.network.http.response_code data.response.status 取得值並轉換為整數。
data.protocol event.idm.read_only_udm.network.ip_protocol data.protocol 中的數值會轉換為字串表示法 (例如 6 會變成「TCP」,17 會變成「UDP」)。
data.bytesOut event.idm.read_only_udm.network.sent_bytes data.bytesOut 取得的值,並轉換為無正負號整數。
data.packets event.idm.read_only_udm.network.sent_packets data.packets 取得值並轉換為整數。
data.identity.consoleSessionId event.idm.read_only_udm.network.session_id 取自 data.identity.consoleSessionId 的值。
id event.idm.read_only_udm.principal.asset.product_object_id 取自 id 的值。
source event.idm.read_only_udm.principal.hostname 取自 source 的值。
data.sourceAddressdata.identity.ipAddress event.idm.read_only_udm.principal.ip data.sourceAddressdata.identity.ipAddress 的值會合併到這個欄位。
data.sourcePort event.idm.read_only_udm.principal.port data.sourcePort 取得值並轉換為整數。
data.request.headers.X-Forwarded-For.0 event.idm.read_only_udm.principal.resource.attribute.labels data.request.headers.X-Forwarded-For.0 取得值,並新增為鍵/值組合,其中鍵為「x forward」。
oracle.compartmentid event.idm.read_only_udm.principal.resource.attribute.labels oracle.compartmentid 取得的值,並以鍵/值組合形式新增,其中鍵為「compartmentid」。
oracle.loggroupid event.idm.read_only_udm.principal.resource.attribute.labels oracle.loggroupid 取得值,並以鍵/值組合形式加入,其中鍵為「loggroupid」。
oracle.vniccompartmentocid event.idm.read_only_udm.principal.resource.attribute.labels oracle.vniccompartmentocid 取得值,並新增為鍵/值組合,其中鍵為「vniccompartmentocid」。
oracle.vnicocid event.idm.read_only_udm.principal.resource.attribute.labels oracle.vnicocid 取得值,並新增為鍵/值組合,其中鍵為「vnicocid」。
oracle.vnicsubnetocid event.idm.read_only_udm.principal.resource.attribute.labels oracle.vnicsubnetocid 取得值,並新增為鍵/值組合,其中鍵為「vnicsubnetocid」。
data.flowid event.idm.read_only_udm.principal.resource.product_object_id 取自 data.flowid 的值。
data.identity.credentials event.idm.read_only_udm.principal.user.attribute.labels data.identity.credentials 取得值,並新增為鍵/值組合,其中鍵為「credentials」。
data.identity.principalName event.idm.read_only_udm.principal.user.user_display_name 取自 data.identity.principalName 的值。
data.identity.principalId event.idm.read_only_udm.principal.user.userid 取自 data.identity.principalId 的值。
data.action event.idm.read_only_udm.security_result.action 預設為 UNKNOWN_ACTION。如果 data.action 為「REJECT」,則會設為 BLOCK。如果 data.action 為「ACCEPT」,則此值會設為 ALLOW
data.endTime event.idm.read_only_udm.security_result.detection_fields data.endTime 取得的值,並以鍵/值組合形式新增,其中鍵為「endTime」。
data.startTime event.idm.read_only_udm.security_result.detection_fields data.startTime 取得值,並新增為鍵/值組合,其中鍵為「startTime」。
data.status event.idm.read_only_udm.security_result.detection_fields data.status 取得值,並新增為鍵/值組合,其中鍵為「status」。
data.version event.idm.read_only_udm.security_result.detection_fields data.version 取得值,並新增為鍵/值組合,其中鍵為「version」。
data.destinationAddress event.idm.read_only_udm.target.ip 取自 data.destinationAddress 的值。
data.destinationPort event.idm.read_only_udm.target.port data.destinationPort 取得值並轉換為整數。
data.request.path event.idm.read_only_udm.target.url 取自 data.request.path 的值。
event.idm.read_only_udm.metadata.product_name 設為「ORACLE CLOUD AUDIT」。
event.idm.read_only_udm.metadata.vendor_name 設為「ORACLE」。

還有其他問題嗎?向社群成員和 Google SecOps 專業人員尋求答案。