Collect Forcepoint Proxy logs
This document explains how to ingest Forcepoint Proxy logs to Google Security Operations by using Bindplane. The parser first cleans up the input log message and extracts key-value pairs using grok patterns and regular expressions. Then, it maps the extracted fields to the Unified Data Model (UDM) based on specific conditions and field values, handling various log formats and edge cases to ensure consistent data representation.
Before you begin
- Ensure that you have a Google Security Operations instance.
- Ensure that you are using Windows 2016 or later, or a Linux host with
systemd
. - If running behind a proxy, ensure firewall ports are open.
- Ensure that you have privileged access to Forcepoint Proxy.
Get Google SecOps ingestion authentication file
- Sign in to the Google SecOps console.
- Go to SIEM Settings > Collection Agents.
- Download the Ingestion Authentication File. Save the file securely on the system where Bindplane will be installed.
Get Google SecOps customer ID
- Sign in to the Google SecOps console.
- Go to SIEM Settings > Profile.
- Copy and save the Customer ID from the Organization Details section.
Install the Bindplane agent
Windows installation
- Open the Command Prompt or PowerShell as an administrator.
Run the following command:
msiexec /i "https://github.com/observIQ/bindplane-agent/releases/latest/download/observiq-otel-collector.msi" /quiet
Linux installation
- Open a terminal with root or sudo privileges.
Run the following command:
sudo sh -c "$(curl -fsSlL https://github.com/observiq/bindplane-agent/releases/latest/download/install_unix.sh)" install_unix.sh
Additional installation resources
- For additional installation options, consult this installation guide.
Configure the Bindplane agent to ingest Syslog and send to Google SecOps
Access the configuration file:
- Locate the
config.yaml
file. Typically, it's in the/etc/bindplane-agent/
directory on Linux or in the installation directory on Windows. - Open the file using a text editor (for example,
nano
,vi
, or Notepad).
- Locate the
Edit the
config.yaml
file as follows:receivers: udplog: # Replace the port and IP address as required listen_address: "0.0.0.0:514" exporters: chronicle/chronicle_w_labels: compression: gzip # Adjust the path to the credentials file you downloaded in Step 1 creds: '/path/to/ingestion-authentication-file.json' # Replace with your actual customer ID from Step 2 customer_id: <customer_id> endpoint: malachiteingestion-pa.googleapis.com # Add optional ingestion labels for better organization ingestion_labels: log_type: FORCEPOINT_WEBPROXY raw_log_field: body service: pipelines: logs/source0__chronicle_w_labels-0: receivers: - udplog exporters: - chronicle/chronicle_w_labels
Replace the port and IP address as required in your infrastructure.
Replace
<customer_id>
with the actual customer ID.Update
/path/to/ingestion-authentication-file.json
to the path where the authentication file was saved in the Get Google SecOps ingestion authentication file section.
Restart the Bindplane agent to apply the changes
To restart the Bindplane agent in Linux, run the following command:
sudo systemctl restart bindplane-agent
To restart the Bindplane agent in Windows, you can either use the Services console or enter the following command:
net stop BindPlaneAgent && net start BindPlaneAgent
Configure Forcepoint Web Security Suite
- Sign in to the Forcepoint console.
- Go to Web > Settings > General.
- Click SIEM integration.
- Select the Enable SIEM integration for this policy server checkbox.
- Provide the following configuration details:
- IP address or hostname: enter the IP address of the Bindplane agent.
- Port number: enter the port number configured on the Bindplane agent; for example,
514
. - Transport protocol: select the UDP protocol.
- SIEM format: select Syslog/CEF (Arcsight).
- Click Ok.
- Click Save and deploy.
UDM Mapping Table
Log Field | UDM Mapping | Logic |
---|---|---|
action | security_result.summary | If action_msg is not empty, it is mapped to security_result.summary. Otherwise, if action is not empty, it is mapped to security_result.summary. Otherwise, if act is not empty, it is mapped to security_result.summary. |
action_msg | security_result.summary | If action_msg is not empty, it is mapped to security_result.summary. Otherwise, if action is not empty, it is mapped to security_result.summary. Otherwise, if act is not empty, it is mapped to security_result.summary. |
app | target.application | If destinationServiceName is not empty, it is mapped to app_name. Otherwise, if app is not empty and does not contain http or HTTP , it is mapped to app_name. Finally, app_name is mapped to target.application. |
bytes_in | network.received_bytes | If in is not empty, it is mapped to bytes_in. Finally, bytes_in is mapped to network.received_bytes. |
bytes_out | network.sent_bytes | If out is not empty, it is mapped to bytes_out. Finally, bytes_out is mapped to network.sent_bytes. |
cat | security_result.category_details | If cat is not empty, it is mapped to category. Finally, category is mapped to security_result.category_details. |
cn1 | security_result.detection_fields.value | If cn1 is not empty, it is mapped to security_result.detection_fields.value with key Disposition Number . |
ContentType | target.file.mime_type | If contentType is not empty, it is mapped to ContentType. Finally, ContentType is mapped to target.file.mime_type. |
cs1 | target_role.description | cs1 is mapped to target_role.description. |
cs2 | security_result.category_details | If cs2 is not empty and not 0 , it is mapped to security_result.category_details with the prefix Dynamic Category: . |
cs3 | target.file.mime_type | cs3 is mapped to target.file.mime_type. |
description | metadata.description | If description is not empty, it is mapped to metadata.description. |
destinationServiceName | target.application | If destinationServiceName is not empty, it is mapped to app_name. Finally, app_name is mapped to target.application. |
deviceFacility | metadata.product_event_type | If product_event and deviceFacility are not empty, they are concatenated with - and mapped to metadata.product_event_type. Otherwise, product_event is mapped to metadata.product_event_type. |
disposition | security_result.detection_fields.value | If disposition is not empty, it is mapped to security_result.detection_fields.value with key Disposition Number . |
dst | target.ip | If dst is not empty and dvchost is empty, it is mapped to dst_ip. Finally, dst_ip is mapped to target.ip. |
dst_host | target.hostname | If dst is not empty and dvchost is empty, it is mapped to dst_host. Finally, dst_host is mapped to target.hostname. |
dst_ip | target.ip | If dst is not empty and dvchost is empty, it is mapped to dst_ip. Finally, dst_ip is mapped to target.ip. |
dst_port | target.port | If dst is not empty and dvchost is empty, it is mapped to dst_port. Finally, dst_port is mapped to target.port. |
duration | network.session_duration.seconds | If duration is not empty and not 0 , it is mapped to network.session_duration.seconds. |
dvchost | intermediary.ip | If dvchost is not empty, it is mapped to int_ip. Finally, int_ip is mapped to intermediary.ip if it is a valid IP address, otherwise it is mapped to intermediary.hostname. |
file_path | target.file.full_path | If file_path is not empty, it is mapped to target.file.full_path. |
host | principal.ip | If host is not empty, it is mapped to src. Finally, src is mapped to principal.ip. |
http_method | network.http.method | If requestMethod is not empty, it is mapped to http_method. Otherwise, if method is not empty, it is mapped to http_method. Finally, http_method is mapped to network.http.method. |
http_proxy_status_code | network.http.response_code | If http_response is empty or 0 or - , and http_proxy_status_code is not empty, it is mapped to network.http.response_code. |
http_response | network.http.response_code | If http_response is not empty and not 0 and not - , it is mapped to network.http.response_code. |
http_user_agent | network.http.user_agent | If http_user_agent is not empty and not - it is mapped to network.http.user_agent. |
in | network.received_bytes | If in is not empty, it is mapped to bytes_in. Finally, bytes_in is mapped to network.received_bytes. |
int_host | intermediary.hostname | If int_ip is not empty and int_host is not empty and different from int_ip, it is mapped to intermediary.hostname. |
int_ip | intermediary.ip | If dvchost is not empty, it is mapped to int_ip. Finally, int_ip is mapped to intermediary.ip if it is a valid IP address, otherwise it is mapped to intermediary.hostname. |
level | target_role.name | If level is not empty and role is empty, it is mapped to role. Finally, role is mapped to target_role.name. |
log_level | security_result.severity | If severity is 1 or log_level contains info or message contains notice , security_result.severity is set to INFORMATIONAL . If severity is 7 , security_result.severity is set to HIGH . |
loginID | principal.user.userid | If loginID is not empty, it is mapped to user. Finally, if user is not empty and not - , and does not contain LDAP , it is mapped to principal.user.userid. |
method | network.http.method | If requestMethod is not empty, it is mapped to http_method. Otherwise, if method is not empty, it is mapped to http_method. Finally, http_method is mapped to network.http.method. |
NatRuleId | security_result.detection_fields.value | If NatRuleId is not empty, it is mapped to security_result.detection_fields.value with key NatRuleId . |
out | network.sent_bytes | If out is not empty, it is mapped to bytes_out. Finally, bytes_out is mapped to network.sent_bytes. |
pid | target.process.pid | If pid is not empty, it is mapped to target.process.pid. |
policy | target_role.description | If Policy is not empty, it is mapped to policy. If policy is not empty and not - , it is mapped to target_role.description. |
Policy | target_role.description | If Policy is not empty, it is mapped to policy. If policy is not empty and not - , it is mapped to target_role.description. |
product_event | metadata.product_event_type | If product is not empty, it is mapped to product_event. If product_event and deviceFacility are not empty, they are concatenated with - and mapped to metadata.product_event_type. Otherwise, product_event is mapped to metadata.product_event_type. |
proxyStatus-code | network.http.response_code | If http_response is empty or 0 or - , and http_proxy_status_code is empty and proxyStatus-code is not empty, it is mapped to network.http.response_code. |
refererUrl | network.http.referral_url | If refererUrl is not empty and not - , it is mapped to network.http.referral_url. |
requestClientApplication | network.http.user_agent | If requestMethod is not empty, it is mapped to http_user_agent. Finally, http_user_agent is mapped to network.http.user_agent. |
requestMethod | network.http.method | If requestMethod is not empty, it is mapped to http_method. Finally, http_method is mapped to network.http.method. |
role | target_role.name | If level is not empty and role is empty, it is mapped to role. Finally, role is mapped to target_role.name. |
RuleID | security_result.rule_id | If RuleID is not empty, it is mapped to security_result.rule_id. |
serverStatus-code | network.http.response_code | If http_response is empty or 0 or - , and http_proxy_status_code is empty and proxyStatus-code is not empty, it is mapped to network.http.response_code. |
severity | security_result.severity | If severity is 1 or log_level contains info or message contains notice , security_result.severity is set to INFORMATIONAL . If severity is 7 , security_result.severity is set to HIGH . |
spt | principal.port | If spt is not empty, it is mapped to src_port. Finally, src_port is mapped to principal.port. |
src | principal.ip | If src_host is not empty, it is mapped to source_ip_temp. If source_ip_temp is a valid IP address and src is empty, it is mapped to src. If host is not empty, it is mapped to src. Finally, src is mapped to principal.ip. |
src_host | principal.hostname | If src_host is not empty, it is mapped to source_ip_temp. If source_ip_temp is not a valid IP address, it is mapped to principal.hostname. If source_ip_temp is a valid IP address and src is empty, it is mapped to src. Finally, src is mapped to principal.ip. |
src_port | principal.port | If src_port is not empty, it is mapped to principal.port. |
suser | principal.user.userid | If loginID is not empty, it is mapped to user. If suser is not empty, it is mapped to user. Finally, if user is not empty and not - , and does not contain LDAP , it is mapped to principal.user.userid. |
url | target.url | If url is not empty, it is mapped to target.url. |
user | principal.user.userid | If loginID is not empty, it is mapped to user. If suser is not empty, it is mapped to user. Otherwise, if usrName is not empty, it is mapped to user. Finally, if user is not empty and not - , and does not contain LDAP , it is mapped to principal.user.userid. |
usrName | principal.user.userid | If loginID is not empty, it is mapped to user. If suser is not empty, it is mapped to user. Otherwise, if usrName is not empty, it is mapped to user. Finally, if user is not empty and not - , and does not contain LDAP , it is mapped to principal.user.userid. |
when | metadata.event_timestamp | If when is not empty, it is parsed and mapped to metadata.event_timestamp. |
metadata.log_type | The value FORCEPOINT_WEBPROXY is hardcoded into metadata.log_type. |
|
metadata.product_name | The value Forcepoint Webproxy is hardcoded into metadata.product_name. |
|
metadata.vendor_name | The value Forcepoint is hardcoded into metadata.vendor_name. |
|
network.application_protocol | If dst_port is 80 , network.application_protocol is set to HTTP . If dst_port is 443 , network.application_protocol is set to HTTPS . |
|
principal.user.group_identifiers | If user is not empty and not - and contains LDAP , the OU part of the user string is extracted and mapped to principal.user.group_identifiers. |
|
principal.user.user_display_name | If user is not empty and not - and contains LDAP , the username part of the user string is extracted and mapped to principal.user.user_display_name. |
|
security_result.action | If action_msg, action, or act are not empty, sec_action is set to ALLOW or BLOCK based on their values. Finally, sec_action is mapped to security_result.action. |
|
security_result.category_details | If cat is not empty, it is mapped to category. Finally, category is mapped to security_result.category_details. If cs2 is not empty and not 0 , it is mapped to security_result.category_details with the prefix Dynamic Category: . |
|
security_result.detection_fields.key | The value Disposition Number is hardcoded into security_result.detection_fields.key when mapping disposition or cn1. The value NatRuleId is hardcoded into security_result.detection_fields.key when mapping NatRuleId. The value Category Number is hardcoded into security_result.detection_fields.key when mapping category_no. |
|
security_result.severity | If severity is 1 or log_level contains info or message contains notice , security_result.severity is set to INFORMATIONAL . If severity is 7 , security_result.severity is set to HIGH . |
|
target_role.description | If Policy is not empty, it is mapped to policy. If policy is not empty and not - , it is mapped to target_role.description. |
|
target_role.name | If level is not empty and role is empty, it is mapped to role. Finally, role is mapped to target_role.name. | |
category_no | security_result.detection_fields.value | If category_no is not empty, it is mapped to security_result.detection_fields.value with key Category Number . |
Changes
2025-01-16
Enhancement:
- Mapped
security_result.action
toBLOCK
whens-action
isTCP_DENIED
.
2024-10-18
Enhancement:
- Added support to parse the unparsed CSV logs.
- Added support to drop invalid CSV logs.
- Mapped
host-url
toprincipal.url
.
2024-07-10
Enhancement:
- Added the Grok patterns for new KV format logs.
- Mapped
username
toprincipal.user.userid
. - Mapped
cs-uri
totarget.url
. - Mapped
cs-uri-query
,time-taken
,filter-category
,cs-uri-path
,cs-uri-extension
andrs_content_type
toadditional.fields
. - If
sc-filter-result
isOBSERVED
then setsecurity_result.action
toALLOW
, else ifsc-filter-result
isDENIED
then setsecurity_result.action
toBLOCK
, else setsecurity_result.action
toALLOW
. - Mapped
cs-auth-group
toprincipal.user_group_identifiers
. - Mapped
cs-method
tonetwork.http.method
. - Mapped
sc-status
toresponse_code
. - Mapped
s-action
tosecurity_result.detection_fields
. - Mapped
srcport
toprincipal.port
. - Mapped
dstport
totarget.port
. - Mapped
sc-bytes
tonetwork.received_bytes
. - Mapped
cs-bytes
tonetwork.sent_bytes
. - Mapped
cs
tosecurity_result.summary
. - Mapped
cs_referer
tonetwork.http.referral_url
. - Mapped
cs-host
totarget.hostname
.
2024-06-10
Enhancement:
- Added support for CSV format logs.
2023-06-12
Enhancement:
- Modified Grok pattern to parse failing logs in which some of the values are present as '-'.
- Added condition check for field 'http_response' before mapping.
2022-08-11
Enhancement:
- Modified grok to parse CEF type logs with no syslog header.
2022-05-16
Enhancement:
- Mapped category number to security_result.detection_fields.
2022-05-05
Enhancement:
- Added mapping for fields:
requestClientApplication
to http.user_agent,proxyStatus-code
to http.response_code,disposition
andcn1
to security_result.detection_fields. - Mapped 'cs2' field to 'security_result.category_details' if the value of 'cs2Label' is 'DynCat'.
- Mapped 'cs2' field to 'security_result.detection_fields' if the value of 'cs2Label' is 'NatRuleId'.
Need more help? Get answers from Community members and Google SecOps professionals.