Collect 1Password logs

Supported in:

This document explains how to ingest 1Password logs to Google Security Operations using Bindplane. The parser transforms raw JSON formatted log data into a structured format compliant with the Google SecOps Unified Data Model (UDM). It specifically focuses on normalizing and enriching events related to user sign-in attempts, extracting details about the user, their location, client information, and the outcome of the attempt.

Before you begin

Ensure that you have the following prerequisites:

  • Google SecOps instance
  • Windows 2016 or later or Linux host with systemd
  • If running behind a proxy, firewall ports are open
  • Privileged access to 1Password

Get Google SecOps ingestion authentication file

  1. Sign in to the Google SecOps console.
  2. Go to SIEM Settings > Collection Agents.
  3. Download the Ingestion Authentication File. Save the file securely on the system where Bindplane will be installed.

Get Google SecOps customer ID

  1. Sign in to the Google SecOps console.
  2. Go to SIEM Settings > Profile.
  3. Copy and save the Customer IDfrom the Organization Detailssection.

Install the Bindplane agent

Windows installation

  1. Open the Command Promptor PowerShellas an administrator.
  2. Run the following command:

      msiexec 
      
     / 
     i 
      
     "https://github.com/observIQ/bindplane-agent/releases/latest/download/observiq-otel-collector.msi" 
      
     / 
     quiet 
     
    

Linux installation

  1. Open a terminal with root or sudo privileges.
  2. 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 the installation guide .

Configure the Bindplane agent to ingest Syslog and send to Google SecOps

  1. 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).
  2. 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 
     : 
      
     'ONEPASSWORD' 
      
     raw_log_field 
     : 
      
     body 
     service 
     : 
      
     pipelines 
     : 
      
     logs/source0__chronicle_w_labels-0 
     : 
      
     receivers 
     : 
      
     - 
      
     udplog 
      
     exporters 
     : 
      
     - 
      
     chronicle/chronicle_w_labels 
     
    
  3. Replace the port and IP address as required in your infrastructure.

  4. Replace <customer_id> with the actual customer ID.

  5. 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 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 Servicesconsole or enter the following command:

     net stop BindPlaneAgent && net start BindPlaneAgent 
    

Get the 1Password API token

  1. Sign in to the 1Passwordweb UI.
  2. Go to Integrations.
  3. Click Directoryat the top of the page.
  4. Enter a name for the tokenand set the token expiration.
  5. In Events Reporting, click Other.
  6. Select the corresponding Event Types.
  7. Click Issue Tokento generate the access token key.
  8. Click Save in 1Passwordand select which vault to save your token to.
  9. Click View Integration Detailsto view the token.

Configure a Linux host to run the following

  • Run the following command:

     import datetime
      import requests
      import os
      import socket
      import json
    
    # For more information, check out the support page: https://support.1password.com/events-reporting
    
      api_token = os.environ.get('EVENTS_API_TOKEN')
      url = "https://events.1password.com"
      if not api_token:
          print("Please set the EVENTS_API_TOKEN environment variable.")
          exit(1)
      start_time = datetime.datetime.now() - datetime.timedelta(hours=24)
    
    # Define the bindplane agent details
    
      syslog_server_ip = <ip-address> # Replace with your Bindplane IP
      syslog_server_port = <port-number> # Replace with your Bindplane port
      headers = {
          "Content-Type": "application/json",
          "Authorization": f"Bearer {api_token}"
      payload = {
          "limit": 20,
          "start_time": start_time.astimezone().replace(microsecond=0).isoformat()
    
    # Alternatively, use the cursor returned from previous responses to get any new events
      # payload = { "cursor": cursor }
      try:
          r = requests.post(f"{url}/api/v1/signinattempts", headers=headers, json=payload)
          r.raise_for_status()  # Raise an exception if the request fails
          if r.status_code == requests.codes.ok:
    
    # Send the response to the bindplane server
              syslog_message = f"{json.dumps(r.json())}"
              with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
                  sock.connect((syslog_server_ip, syslog_server_port))
                  sock.sendall(f"{syslog_message}\n".encode())
          else:
              print(f"Error getting sign-in attempts: status code {r.status_code}")
      except requests.exceptions.RequestException as e:
          print(f"Request error: {e}")
      except Exception as e:
          print(f"Error during syslog logging: {e}") 
    

UDM mapping table

Log field UDM mapping Logic
category
security_result.category_details The value is taken from the category field in the raw log.
client.app_name
principal.application The value is taken from the client.app_name field in the raw log.
client.app_version
metadata.product_version The value is taken from the client.app_version field in the raw log.
client.ip_address
principal.ip The value is taken from the client.ip_address field in the raw log.
client.os_name
principal.platform The value is taken from the client.os_name field in the raw log and mapped to the corresponding UDM platform value (LINUX, WINDOWS, MAC).
client.os_version
principal.platform_version The value is taken from the client.os_version field in the raw log.
client.platform_name
principal.resource.attribute.labels.key: platform_name , principal.resource.attribute.labels.value: Chrome The value is taken from the client.platform_name field in the raw log.
client.platform_version
principal.asset.platform_software.platform_version The value is taken from the client.platform_version field in the raw log.
country
principal.location.country_or_region The value is taken from the country field in the raw log if location.country is not present.
item_uuid
security_result.about.resource.attribute.labels.key: item_uuid , security_result.about.resource.attribute.labels.value: nx4f2lhmafhhfkvgid6ff2fyh4 The value is taken from the item_uuid field in the raw log.
location.city
principal.location.city The value is taken from the location.city field in the raw log.
location.country
principal.location.country_or_region The value is taken from the location.country field in the raw log.
location.latitude
principal.location.region_latitude The value is taken from the location.latitude field in the raw log.
location.longitude
principal.location.region_longitude The value is taken from the location.longitude field in the raw log.
location.region
principal.location.name The value is taken from the location.region field in the raw log.
session.ip
principal.ip The value is taken from the session.ip field in the raw log.
session_uuid
network.session_id The value is taken from the session_uuid field in the raw log.
target_user.email
target.user.email_addresses The value is taken from the target_user.email field in the raw log.
target_user.uuid
target.user.userid The value is taken from the target_user.uuid field in the raw log.
timestamp
metadata.event_timestamp.seconds, metadata.event_timestamp.nanos The value is taken from the timestamp field in the raw log and converted to seconds and nanoseconds.
type
additional.fields.key: type , additional.fields.value.string_value: mfa_ok The value is taken from the type field in the raw log.
user.email
principal.user.email_addresses The value is taken from the user.email field in the raw log.
user.name
principal.user.user_display_name The value is taken from the user.name field in the raw log.
used_version
additional.fields.key: used_version , additional.fields.value.string_value: 1 The value is taken from the used_version field in the raw log.
uuid
principal.resource.attribute.labels.key: uuid , principal.resource.attribute.labels.value: EPNGUJLHFVHCXMJL5LJQGXTENA The value is taken from the uuid field in the raw log.
vault_uuid
security_result.about.resource.attribute.labels.key: vault_uuid , security_result.about.resource.attribute.labels.value: lddjidoxtrxteclqhubbo3pkyq The value is taken from the vault_uuid field in the raw log.
N/A
extensions.auth An empty object is created for this field.
N/A
metadata.event_type The value is set to USER_LOGIN if category is success or firewall_reported_success , STATUS_UPDATE if no user information is present, and USER_UNCATEGORIZED otherwise.
N/A
metadata.log_type The value is set to ONEPASSWORD .
N/A
metadata.product_name The value is set to ONEPASSWORD .
N/A
metadata.vendor_name The value is set to ONEPASSWORD .
N/A
security_result.action The value is set to ALLOW if category is success or firewall_reported_success , BLOCK if category is credentials_failed , mfa_failed , modern_version_failed , or firewall_failed , and is left empty otherwise.

Need more help? Get answers from Community members and Google SecOps professionals.

Design a Mobile Site
View Site in Mobile | Classic
Share by: