Note:

Ingest Oracle Cloud Infrastructure logs into Microsoft Azure Sentinel using OCI Functions

Introduction

Oracle Cloud Infrastructure (OCI) Functions is a fully managed, multi-tenant, highly scalable, on-demand, Functions-as-a-Service platform. It is built on enterprise grade Oracle Cloud Infrastructure and powered by the Fn Project open source engine.

Service Connector Hub is a cloud message bus platform that offers a single pane of glass for describing, executing, and monitoring interactions when moving data between Oracle Cloud Infrastructure services. Use the Service Connector Hub service to transfer data between services in Oracle Cloud Infrastructure.

By using the Service Connector and Functions services, you can connect the generation of logs from your OCI cloud environment with the automatic and scalable sending of all information security records from your environment to your instance of Security information and event management (SIEM) Microsoft Azure Sentinel.

Objective

Ingest OCI logs into Microsoft Azure Sentinel using OCI Functions.

Prerequisites

Task 1: Start the OCI Instance

  1. Create a new OCI instance via the Web Console and activate any of its plugins by default, go to the Instances page and click Create Instance.

    Create OCI Instance

  2. Fill in all the information required for instance creation.

    Fill required information for Instance setup

  3. Go to the end of the page and click Show advanced options.

    Show instance advanced options

  4. Some tabs will appear on the screen. Click Oracle Cloud Agent and select the plugins you want to be active after instance creation is complete.

    Oracle Cloud Agent option

  5. All plugins selected on this tab will be automatically activated once the instance is ready for use.

    Oracle Cloud Agent Plugins setup

  6. After selecting the plugins, click Create at the end of the page.

    Create the OCI instance

Task 2: Configure the OCI Logging settings

Task 2.1: Configure Windows Instance custom logs

After creating the Windows instance, you must configure your OCI environment to capture Event Viewer logs via Oracle Agent installed on the server.

  1. Before you start, make sure the “Custom Logs” plugin is active on the server you want to collect logs from. In your OCI console, go to Compute, Instances.

    Make sure Custom Logs plugin is active

  2. Select the instance to be monitored.

    Select your newly created instance

  3. Click on the Oracle Cloud Agent tab, and make sure the plugin named Custom Logs Monitoring is enabled.

    Activate the Custom Logs Monitoring plugin

    • If the plugin is not enabled in your instance, enable it. After that, let’s configure the OCI logging so that Windows Event Viewer events can be captured by this agent.

Task 2.2: Configure the Dynamic Group of servers

In order to capture Event Viewer logs from one or more Windows servers, a Dynamic Group must be created. This group will contain all Windows instances that should have their logs captured.

  1. To create the Dynamic Group, click on the main menu of your OCI console and go to Identity & Security, Identity.

    Access the Identity menu

  2. From the Identity menu, access the *Domains” submenu.

    Access the Domain menu

  3. Click on your Identity Domain (in this tutorial example, we use Default).

    Access the default domain configuration

  4. Now, inside the identity domain, click on the Dynamic groups menu so that we can create the Dynamic Group that will contain all the Windows servers to be monitored. Once this is done, click Create dynamic group.

    Create a dynamic group of servers

  5. A new page will open. Fill in the information regarding the creation of the Dynamic Group (name and description) and, in Matching rules, click on the Rule builder link to be able to create your rule for selecting instances that will be grouped in this Dynamic Group.

    Build the dynamic group rule

  6. The example rule that we will create will group all existing servers in our Compartment. To do this, just capture the Compartment ID and insert it in the Value field as shown in the image below.

    Fill with the required values

Note: You can use advanced filters and create Dynamic Groups to only capture instances with certain Tags. For this, we recommend reading the official OCI documentation at: Writing Matching Rules to Define Dynamic Groups.

Task 2.3: Create a Logging Group

You will also need to create a logging group to be able to concentrate all the logs sent by the agents installed on the Windows servers in your environment.

  1. Click on the main menu of your OCI console and go to Observability & Management, Log Groups.

    Create your log group

  2. When accessing the service page, click Create Log Group.

    Create your log group

  3. Inside the log group creation page, fill in the requested information and click Create.

    Fill the required information

Once this step is finished, let’s start creating the Event Viewer log capture by Oracle Cloud Agent installed in the OCI instance.

Task 2.4: Configure OCI Logging

  1. Once the instance, the Dynamic Group and the Log Group are configured, go to Observability & Management, and click Logging.

    Access the Logging service

  2. Within the OCI Logging page, click Agent Configurations, so that we can create the configuration that will allow the sending of Windows Event Viewer logs to OCI Logging. Once inside the agent configuration page, click Create agent config.

    Create agent config

  3. Fill in all the necessary fields on the page and select the Dynamic Group you created in the previous step.

    Fill required information

    • When filling out these initial items, scroll down the page and fill in the Agent Configuration fields, informing that you want to capture the “Windows event log” of each of the available channels (Application, Security and System). Here you will need to repeat the process of creating log inputs for each of the channels.

    • Once the configuration is finished, your agent config page will be available and will look like this.

      Agent config detailed informations

      Note: The agent config above was created to capture both Event Viewer logs and logs generated in the /var/log/messages file on Linux servers.

    • Once your Agent Config is in Active status, wait approximately 5 minutes until the first log collection can be done. To view the logs of the monitored instances being collected, click on the Explore log menu as shown in the image below.

      View logs

Task 3: Note the Microsoft Azure Sentinel details

Important: It is not the scope of this documentation to provide guidance on creating and configuring Microsoft Azure Sentinel within your Microsoft Azure subscription. To do so, access the official product documentation on the Microsoft website.

Task 4: Create your OCI Vault

Now that we already have the Microsoft Azure Log Analytics Workspace data belonging to SIEM Sentinel, let’s create an OCI Vault to store the secret value copied in the previous task. This secret must be stored in the OCI Vault so you don’t need to insert it inside the OCI Functions code that we will create in the next step.

  1. To create your OCI Vault, go to the main menu of your OCI console and go to Identity & Security, Vault.

    Create your OCI Vault

  2. Once the Vault page is loaded, click Create Vault, select the desired compartment and name your Vault.

    Fill the required information

  3. After creating the Vault, you will need to create your Master Encryption Key. This key will be used to encrypt all secrets in your Vault. To do this, click Create Key as shown in the image below.

    Create your Master Encryption Key (MEK)

  4. When you finish creating your Master Key, click on the Secrets menu and create the Microsoft Azure secret that you noted in the previous step.

    Create your secret

  5. Fill the necessary fields to create your Secret in the Vault with the primary or secondary key data from your Microsoft Azure Sentinel Log Analytics Workspace as shown in Task 3.

  6. The other items (Sentinel Workspace ID and the name of the table where the logs will be stored in Sentinel) may or may not be inserted in the Vault. Here, let’s insert them inside the code of our Function.

Important: Take note of the OCID of the Secret you create within the Vault.

Task 5: Create and configure OCI Functions

After setting up the centralized logging environment in your OCI region, the Vault and your Azure environment are ready, it’s time to create the OCI Function that will send the Custom Logs and Audit Logs from your OCI region to Microsoft Azure Sentinel.

Task 5.1: Create the OCI Function

  1. Go to the main menu of your OCI console and go to Developer Services, Functions.

    Acess OCI Functions service

  2. Once the Functions page is loaded, click Create application.

    Create your application

  3. Fill in the required fields and click the Create.

    Fill the required information

  4. After creation, note that your Function will not be protected by any network security group. You must add it to a network security group.

    NSG configuration

    Important Points:

    1. As your Function will access the public Microsoft Azure endpoint for sending logs to Microsoft Azure Sentinel, this Function must be created in a subnet that has access to the Internet.

    2. Also validate your VNET Security Lists to ensure that none of them prevent your OCI Function from accessing the Internet.

Task 5.2: Configure OCI Functions and Startup

Once the OCI Function has been created, you will see on the screen the commands necessary for configuring the function in the environment. Here, as an example, we will follow the step by step via Cloud Shell, but it is also possible to carry out these settings directly on your equipment.

  1. Open Cloud Shell directly in the web console of the OCI region to be configured (in this tutorial, the region is Brazil East).

    Region for Function configuration

  2. Follow the steps indicated on your Function page and execute the requested commands inside your Cloud Shell terminal.

    Execute commands in cloud-shell terminal

  3. The first 3 commands to be executed do not require changes, however, in the fourth command you will need to provide the name of the repository where the application image will be stored. In our example, the name entered was repo-ocilog-to-azuresiem.

    $ fn update context registry gru.ocir.io/xxxxxxxxxa/repo-ocilog-to-azuresiem

    Command execution

  4. Generate an Auth Token within your Oracle Cloud Infrastructure Identity and Access Management (OCI IAM) profile. The Auth Token is the access credential that will allow you to interact with the OCI repository where your Function’s Docker image will be stored. Click on your user icon in the OCI Web console and then click My profile.

    Creating an Auth Token

  5. Once inside your user page, scroll down and click Auth tokens.

    Auth Token menu

  6. Within the Auth Tokens section, click Generate Token.

    Generate Token

  7. Fill in the name for your Auth Token and click Generate token.

    Fill the required information

    Important: Write down this token and store it in a safe place. This token is your access password to the OCI Registry where your Function images will be stored.

  8. Return to the Functions page by accessing the main menu of the OCI web console and accessing Developer Services, Functions.

    Return to Functions page

  9. On the Functions page, access your Function created in the previous steps.

    Access your function

  10. Click on the Getting started menu and continue step by step after the Auth Token creation step.

    Get Started function menu

  11. Run the command docker login and as password use the string you just copied from the creation of the Auth Token in the last step executed.

    Follow the Get Started instructions

  12. Now in the next steps we will create, deploy and invoke the Function. To initialize the function in your Cloud Shell, change the command suggested in the example shown on the screen. This change is necessary because the Runtime Environment we are going to use is in Python (and not in Java as shown in the hello-world example suggested by creating the Function).

    $ fn init --runtime python func-ocilog-to-azuresiem

    Invoke your function

Task 5.2.1: Writing the source code of your OCI Function

  1. Once the init command is executed, access the newly created Function directory.

    $ cd func-ocilog-to-azuresiem/

    • Note that inside the directory you just accessed there is a Python file (func.py), a YAML file (func.yaml) and a requirements file (requirements.txt). We will need to edit two of these files.
  2. Edit the func.py file, delete all content and insert the below content into it.

    import io
    import json
    import requests
    import datetime
    import hashlib
    import hmac
    import base64
    import logging
    import oci
    import base64
    import sys
    from fdk import response
    
    # Global variable
    logger = logging.getLogger()
    
    # Get Resource Principal Credentials
    # OCI Functions get permission to read vault from OCI IAM
    signer = oci.auth.signers.get_resource_principals_signer()
    
    # Retrieve secret from OCI Vault
    def get_binary_secret(secret_ocid):
        try:
            client = oci.secrets.SecretsClient({}, signer=signer)
            secret_content = client.get_secret_bundle(secret_ocid).data.secret_bundle_content.content.encode('utf-8')
            secret_content_decoded = base64.b64decode(secret_content).decode('UTF-8')
        except Exception as ex:
            logger.critical("ERROR: failed to retrieve the secret content from OCI Vault. ", ex)
            raise
        return secret_content_decoded
    
    # Build the API signature
    def  build_signature(customer_id, shared_key, date, content_length, method, content_type, resource):
        x_headers =  'x-ms-date:'  + date
        string_to_hash = method +  "\n"  + str(content_length) +  "\n"  + content_type +  "\n"  + x_headers +  "\n"  + resource
        bytes_to_hash = bytes(string_to_hash, encoding= "utf-8" )
        decoded_key = base64.b64decode(shared_key)
        encoded_hash = base64.b64encode(hmac.new(decoded_key, bytes_to_hash, digestmod=hashlib.sha256).digest()).decode()
        authorization =  "SharedKey {}:{}" .format(customer_id,encoded_hash)
        return  authorization
    
    # Build and send a request to the POST API (Microsoft Azure Sentinel public endpoint)
    def  post_data(customer_id, shared_key, body, log_type, logger):
        method =  'POST'
        content_type =  'application/json'
        resource =  '/api/logs'
        rfc1123date = datetime.datetime.utcnow().strftime( '%a, %d %b %Y %H:%M:%S GMT' )
        content_length = len(body)
        signature = build_signature(customer_id, shared_key, rfc1123date, content_length, method, content_type, resource)
        uri =  'https://'  + customer_id +  '.ods.opinsights.azure.com'  + resource +  '?api-version=2016-04-01'
    
        headers = {
            'content-type' : content_type,
            'Authorization' : signature,
            'Log-Type' : log_type,
            'x-ms-date' : rfc1123date
        }
    
        response = requests.post(uri,data=body, headers=headers)
        if (response.status_code >= 200 and  response.status_code <=  299 ):
            logger.critical( '===> Upload to Microsoft Azure Sentinel was accepted %s', content_length )
        else:
            logger.critical( "Error during upload.  Response code: {}" .format(response.status_code))
    
    ####
    ## PART 3
    ####
    
    #
    # Entrypoint and initialization
    #
    def handler(ctx, data: io.BytesIO=None):
        logger.info("OCI Function - Handler function init fired.")
    
        # Update the customer ID to your Log Analytics workspace ID
        customer_id =  ‘<PUT_HERE_YOUR_AZURE_LOG_ANALYTICS_WORKSPACE_ID>'
    
        # For the shared key, use either the primary or the secondary Connected Sources client authentication key
        shared_key_OCID = "<PUT_HERE_THE_OCID_OF_YOUR_OCI_VAULT_SHARED_KEY_SECRET>"
        shared_key = get_binary_secret(shared_key_OCID)
    
        # The log type is the name of the event that is being submitted
        log_type =  '<SENTINEL_TABLE_NAME>'
    
        try:
            log_body = data.getvalue()
            post_data(customer_id, shared_key, log_body, log_type, logger)
        except  Exception  as  err:
            logger.error( "Error in main process: {}" .format(str(err)))
        return  response.Response(
            ctx,
            response_data=json.dumps({ "status" :  "Success" }),
            headers={ "Content-Type" :  "application/json" }
        )
    
    
    • This is the Python script that will connect to the Azure SIEM and send the OCI logs to the remote endpoint.

    • In addition to copying and pasting this script, you will need to change 3 fields within it

      1. _customer_id: Log Analytics Workspace ID within your Azure subscription, in the Agents Management menu.

      2. _shared_key: Primary or Secondary key that can also be obtained from the Agents Management menu.

      3. _log_type: Name of the Log Analytics Workspace that SIEM Sentinel uses. All logs coming into this Workspace are analyzed by Sentinel. Here in our example, we´ve used OCILogging.

    • Below is an example print of the screen where you can get the information above.

      Azure values from Log Analytics Workspace

    Note: It is outside the scope of this document to configure Log Analytics Workspace within your Azure Subscription. For this, look for more information in the official Microsoft documentation.

  3. After changing the func.py file, it’s time to edit the requirements.txt file. We will insert a requirement where the OCI Functions package manager will install the necessary Python dependencies for our script to work correctly. For this case, insert the word requests in the last line of the file:

    Required Python modules

  4. Once that’s done, run your Function’s deploy step.

    $ fn -v deploy --app app-ocilog-to-azuresiem

After a few minutes, the configuration of both the Function and the creation of the Docker image will be successfully completed.

Required Python modules

Task 5.2.2: Provide the required permissions for the OCI Function

For the OCI Function to run smoothly, it will need permissions to read the Azure secret inside the Vault. For this, we will need to create a Dynamic Group for the Function we created and, for this Dynamic Group, we will give the necessary permission (least-privilege) so that our code can read the Vault and capture the shared key from Azure in a secure way.

So, in the same way we did in item 2.2 above, where we created a Dynamic Group to aggregate the servers that will collect the logs, retrace the steps and create a Dynamic Group to include our Function.

During the creation of the Dynamic Group, you will need a Matching Rule that will be used to capture your Function. Here, in our example, we will create a Matching Rule that will list all the Functions of the Compartment that we are using exclusively for this tutorial.

ALL {resource.type = 'fnfunc', resource.compartment.id = 'ocid1.compartment.oc1..aaaaaxxxxgjxxxxglxxxxiqxxxxjdxxxxnxxxxmxxxxm3xxxxmoxxxxsxxx'}

  1. Capture your Compartment’s OCID and insert it into your Matching Rule and create your Dynamic Group.

    Configure your dynamic group for Functions

  2. After creating your Dynamic Group, go to Identity & Security, Policies to create the policy that will allow the Function to access the Vault in read mode.

    Create the policy to allow Functions to access Vault

    • Once the Dynamic Group is created, create the policy that will allow the Function to access the Vault.
  3. Use the policy below to grant the minimum required access to the Function to run your Vault credential reading activity.

    Allow dynamic-group <FUNCTION\_DYNAMIC\_GROUP\_NAME> to read secret-bundles in compartment <COMPARTMENT\_NAME>

    OCI Policy details

Task 5.2.3: Run your OCI Function

  1. Run your function to validate that it is working correctly.

    $ fn -v deploy --app app-ocilog-to-azuresiem

    Running your function

Now, to finalize, we need to configure the OCI Service Connectors to capture all OCI logs from your region and send them to Azure SIEM using the Function we just created.

Task 6: Configure the Service Connectors

In order to be able to send the logs of the regions of your OCI tenant for the analysis of the Microsoft Azure Sentinel, it is necessary to configure the Service Connectors.

Basically this service will capture the OCI logs that we have already configured and send it to our Function which, in turn, will forward all the logs to the Azure subscription.

  1. Go to the main menu of your OCI Console and then go to Observability & Management, **Service Connectors.

    Service Connectors menu

  2. Once inside the Service Connectors, click Create Service Connector.

    Create the Service Connector

  3. Fill in the required name and description fields, select the compartment where you want to create your Service Connector.

    Fill the required information

  4. Now, select the source of data that will be transmitted via the Service Connector. Here, use Logging. And, as target, that is, where the data will be transitioned, use Functions.

    Define source and target for your service connector

  5. To finalize the configuration, select in Configure source, which logs will be sent to OCI Functions. In this step we must select the \_Audit log and, adding one more log, we will select the log group that we created in the initial steps of this procedure.

    Finalize your configuration

    • If you want to add another log group, click + Another log.
  6. Having finished this step, we now need to define the Target parameters, that is, our OCI Function that will send the data to the Azure subscription. To do this, select your compartment where the function is, select the App and, after that, the name of your function. Then, just click Create as shown in the image below.

    Click create button

The process is finished. At this point, just wait until the logs start to be sent to Microsoft Azure automatically.

You can monitor the operation of the service Connector created by the “Metrics” menu.

Monitor your Service Connector metrics

Task 7: Read the logs at Microsoft Azure Sentinel

  1. After a few moments, logs from all servers will be sent to the Microsoft Azure subscription as shown in the image below.

    Logs in Microsoft Azure Sentinel

  2. According to your Microsoft Azure Sentinel configuration, incidents will start showing up in the interface as the SIEM rules are triggered.

    SIEM incidents being created

    • Incident opened for Brazil East region server (we’ve created some custom rule called “[Lab] Regex Incident” to generate our example incidents).

      SIEM incidents being created

    • Open incident for Us-Phoenix region server.

      Open incidents

Acknowledgments

Author - Rodrigo Pace de Barros (Oracle LAD A-Team Cloud Security Solution Engineer)

More Learning Resources

Explore other labs on docs.oracle.com/learn or access more free learning content on the Oracle Learning YouTube channel. Additionally, visit education.oracle.com/learning-explorer to become an Oracle Learning Explorer.

For product documentation, visit Oracle Help Center.