LogPoint SIEM Integration

Use this Content Pack to search logs, fetch incident logs from LogPoint, analyze them for underlying threats, and respond to these threats in real-time.

Utilities · LogPoint SIEM Integration

Details

IDLogPoint SIEM Integration
ProviderLogpoint
CategoryUtilities
From Version6.0.0
Docker Imagedemisto/python3:3.12.13.10116658
Supported ModulesAgentix XSIAM

README

Use this Content Pack to search logs, fetch incident logs from LogPoint, analyze them for underlying threats, and respond to these threats in real-time.
This integration was integrated and tested with version 6.7.4 of LogPoint.

Use Cases

  • Retrieve incidents using available filters.
  • Get data of particular incidents, their state, user, and user groups.
  • Resolve, Close, Re-open, Re-assign, and add comments to the incidents.
  • Act accordingly to the incidents using LogPoint provided or custom playbooks.
  • Use commands to get logs from LogPoint’s devices and repos

Configure LogPoint on Cortex XSOAR

  1. Navigate to Settings > Integrations > Servers & Services.
  2. Search for LogPoint SIEM Integration.
  3. Click Add instance to create and configure a new integration instance.

    Parameter Description Required
    LogPoint URL   True
    LogPoint Username   True
    API Key User’s secret key True
    Trust any certificate (not secure) Whether to allow connections without verifying SSL certificates validity. False
    Use system proxy settings Whether to use XSOAR’s system proxy settings to connect to the API False
    First fetch timestamp (<number> <time unit>, e.g., 6 hours, 1 day) If it is not provided, incidents from past 24 hours will be fetched by default. False
    Incident type   False
    Fetch incidents   False
    Fetch limit (Max value is 200, Recommended value is 50 or less) If this is left blank, maximum 50 incidents will be fetched at a time. False
    Incidents Fetch Interval   False
  4. Click Test to validate the URLs, token, and connection.

Commands

You can execute these commands from the Cortex XSOAR CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.

lp-get-incidents


Displays incidents between the provided two Timestamps ts_from and ts_to. By default, this command will display first 50 incidents of the past 24 hours but limit can be set to get desired number of incidents.

Base Command

lp-get-incidents

Input

Argument Name Description Required
ts_from From Timestamp. Optional
ts_to To Timestamp. Optional
limit Number of incidents to fetch. Accepts integer value. Optional

Context Output

Path Type Description
LogPoint.Incidents.name String LogPoint Incident Name
LogPoint.Incidents.type String LogPoint Incident Type
LogPoint.Incidents.incident_id String LogPoint Incident ID
LogPoint.Incidents.assigned_to String LogPoint Incidents Assigned To
LogPoint.Incidents.status String LogPoint Incidents Status
LogPoint.Incidents.id String LogPoint Incident Object ID
LogPoint.Incidents.detection_timestamp Number LogPoint Incidents Detection Timestamp
LogPoint.Incidents.username String LogPoint Incident Username
LogPoint.Incidents.user_id String LogPoint Incidents User ID
LogPoint.Incidents.assigned_to String LogPoint Incidents Assigned To
LogPoint.Incidents.visible_to String LogPoint Incidents Visible To
LogPoint.Incidents.tid String LogPoint Incidents Tid
LogPoint.Incidents.rows_count String LogPoint Incidents Rows Count
LogPoint.Incidents.risk_level String LogPoint Incidents Risk Level
LogPoint.Incidents.detection_timestamp String LogPoint Incidents Detection Timestamp
LogPoint.Incidents.loginspect_ip_dns String LogPoint Incidents Loginspect IP DNS
LogPoint.Incidents.status String LogPoint Incidents Status
LogPoint.Incidents.comments String LogPoint Incidents Comments
LogPoint.Incidents.commentscount Number LogPoint Incidents Comments Count
LogPoint.Incidents.query String LogPoint Incidents Query
LogPoint.Incidents.repos String LogPoint Incidents Repos
LogPoint.Incidents.time_range String LogPoint Incidents Time Range
LogPoint.Incidents.alert_obj_id String LogPoint Incidents Alert Obj Id
LogPoint.Incidents.throttle_enabled Boolean LogPoint Incidents Throttle Enabled
LogPoint.Incidents.lastaction String LogPoint Incidents Last Action
LogPoint.Incidents.description String LogPoint Incidents Description

Command Example

!lp-get-incidents ts_from=1610700720 ts_to=1610700900 limit=5

Context Example

{
    "LogPoint": {
        "Incidents": [
            {
                "alert_obj_id": "5fc8b1743dee69827459bc70",
                "assigned_to": "5bebd9fdd8aaa42840edc853",
                "comments": [],
                "commentscount": 0,
                "description": "",
                "detection_timestamp": 1610700740.2248185,
                "id": "600157c44a2018070b627f6a",
                "incident_id": "8a676c39450e099b3512961d71ec4f7d",
                "loginspect_ip_dns": "127.0.0.1",
                "logpoint_name": "LogPoint",
                "name": "Memory usages is greater than 50 percent",
                "query": "\"col_type\"=\"filesystem\" use>=50",
                "repos": [
                    "127.0.0.1:5504"
                ],
                "risk_level": "medium",
                "rows_count": 5,
                "status": "unresolved",
                "throttle_enabled": false,
                "tid": "",
                "time_range": [
                    1610700000,
                    1610700600
                ],
                "type": "Alert",
                "user_id": null,
                "username": "5bebd9fdd8aaa42840edc853",
                "visible_to": []
            },
            {
                "alert_obj_id": "5fc8b1743dee69827459bc70",
                "assigned_to": "5bebd9fdd8aaa42840edc853",
                "comments": [
                    {
                        "comment": "Example Incident",
                        "time": 1610700910,
                        "title": "admin"
                    }
                ],
                "commentscount": 0,
                "description": "",
                "detection_timestamp": 1610700860.245085,
                "id": "6001583c4a2018070b627f6b",
                "incident_id": "8a676c39450e099b3512961d71ec4f7d",
                "lastaction": {
                    "action": "Commented",
                    "time": 1610700910,
                    "title": "admin"
                },
                "loginspect_ip_dns": "127.0.0.1",
                "logpoint_name": "LogPoint",
                "name": "Memory usages is greater than 50 percent",
                "query": "\"col_type\"=\"filesystem\" use>=50",
                "repos": [
                    "127.0.0.1:5504"
                ],
                "risk_level": "medium",
                "rows_count": 5,
                "status": "unresolved",
                "throttle_enabled": false,
                "tid": "",
                "time_range": [
                    1610700120,
                    1610700720
                ],
                "type": "Alert",
                "user_id": null,
                "username": "5bebd9fdd8aaa42840edc853",
                "visible_to": []
            }
        ]
    }
}

Human Readable Output

Displaying all 2 incidents between 1610700720 and 1610700900

Type Incident Id Name Description Username User Id Assigned To Visible To Tid Rows Count Risk Level Detection Timestamp Loginspect Ip Dns Logpoint Name Status Comments Commentscount Query Repos Time Range Alert Obj Id Throttle Enabled Id
Alert 8a676c39450e099b3512961d71ec4f7d Memory usages is greater than 50 percent   5bebd9fdd8aaa42840edc853   5bebd9fdd8aaa42840edc853     5 medium 1610700740.2248185 127.0.0.1 LogPoint unresolved   0 “col_type”=”filesystem” use>=50 127.0.0.1:5504 1610700000,
1610700600
5fc8b1743dee69827459bc70 false 600157c44a2018070b627f6a
Alert 8a676c39450e099b3512961d71ec4f7d Memory usages is greater than 50 percent   5bebd9fdd8aaa42840edc853   5bebd9fdd8aaa42840edc853     5 medium 1610700860.245085 127.0.0.1 LogPoint unresolved {‘title’: ‘admin’, ‘comment’: ‘Example Incident’, ‘time’: 1610700910} 0 “col_type”=”filesystem” use>=50 127.0.0.1:5504 1610700120,
1610700720
5fc8b1743dee69827459bc70 false 6001583c4a2018070b627f6b

lp-get-incident-data


Retrieves a Particular Incident’s Data

Base Command

lp-get-incident-data

Input

Argument Name Description Required
incident_obj_id Object ID of a particular incident. It is the value contained in ‘id’ key of the incidents obtained from ‘lp-get-incidents’ command. Required
incident_id Incident Id of a particular incident. It is the value contained in ‘incident_id’ key of the incidents obtained from ‘lp-get-incidents’ command. Required
date Incident Detection TImestamp. It is the value contained in ‘detection_timestamp’ key of the incidents obtained from ‘lp-get-incidents’ command. Required

Context Output

Path Type Description
LogPoint.Incidents.data.use String LogPoint Incidents Data Use
LogPoint.Incidents.data.used String LogPoint Incidents Data Used
LogPoint.Incidents.data.log_ts Number LogPoint Incidents Data Log Ts
LogPoint.Incidents.data._type_str String LogPoint Incidents Data Type Str
LogPoint.Incidents.data.msg String LogPoint Incidents Data Msg
LogPoint.Incidents.data.total String LogPoint Incidents Data Total
LogPoint.Incidents.data.device_name String LogPoint Incidents Data Device Name
LogPoint.Incidents.data._offset String LogPoint Incidents Data Offset
LogPoint.Incidents.data.logpoint_name String LogPoint Incidents Data LogPoint Name
LogPoint.Incidents.data.repo_name String LogPoint Incidents Data Repo Name
LogPoint.Incidents.data.free String LogPoint Incidents Data Free
LogPoint.Incidents.data.source_name String LogPoint Incidents Data Source Name
LogPoint.Incidents.data.col_ts Number LogPoint Incidents Data Col Ts
LogPoint.Incidents.data._tz String LogPoint Incidents Data Tz
LogPoint.Incidents.data.norm_id String LogPoint Incidents Data Norm Id
LogPoint.Incidents.data._identifier String LogPoint Incidents Data Identifier
LogPoint.Incidents.data.collected_at String LogPoint Incidents Data Collected At
LogPoint.Incidents.data.device_ip String LogPoint Incidents Data Device IP
LogPoint.Incidents.data._fromV550 String LogPoint Incidents Data From V550
LogPoint.Incidents.data._enrich_policy String LogPoint Incidents Data Enrich Policy
LogPoint.Incidents.data._type_num String LogPoint Incidents Data Type Num
LogPoint.Incidents.data._type_ip String LogPoint Incidents Data Type IP
LogPoint.Incidents.data.sig_id String LogPoint Incidents Data Sig Id
LogPoint.Incidents.data.col_type String LogPoint Incidents Data Col Type
LogPoint.Incidents.data.object String LogPoint Incidents Data Object
LogPoint.Incidents.data._labels String LogPoint Incidents Data Labels
LogPoint.Incidents.data.source_address String Source Address
LogPoint.Incidents.data.destination_address String Destination Address
LogPoint.Incidents.data.workstation String Workstation
LogPoint.Incidents.data.domain String Domain
LogPoint.Incidents.data.user String User
LogPoint.Incidents.data.caller_user String Caller User
LogPoint.Incidents.data.target_user String Target User
LogPoint.Incidents.data.source_machine_id String Source Machie Id
LogPoint.Incidents.data.destination_machine_id String Destination Machine Id
LogPoint.Incidents.data.destination_port String Destination Port
LogPoint.Incidents.data.event_type String Event Type
LogPoint.Incidents.data.share_path String Share Path
LogPoint.Incidents.data.object_name String Object Name
LogPoint.Incidents.data.sub_status_code String Sub Status Code
LogPoint.Incidents.data.object_type String Object Type
LogPoint.Incidents.data.request_method String Request Method
LogPoint.Incidents.data.status_code String Status Code
LogPoint.Incidents.data.received_datasize String Received Datasize
LogPoint.Incidents.data.received_packet String Received Packet
LogPoint.Incidents.data.user_agent String User Agent
LogPoint.Incidents.data.sent_datasize String Sent Datasize
LogPoint.Incidents.data.sender String Sender
LogPoint.Incidents.data.receiver String Receiver
LogPoint.Incidents.data.datasize String Datasize
LogPoint.Incidents.data.file String File
LogPoint.Incidents.data.subject String Subject
LogPoint.Incidents.data.status String Status
LogPoint.Incidents.data.file_count String File Count
LogPoint.Incidents.data.protocol_id String Protocol Id
LogPoint.Incidents.data.sent_packet String Sent Packet
LogPoint.Incidents.data.service String Service
LogPoint.Incidents.data.printer String Printer
LogPoint.Incidents.data.print_count String Print Count
LogPoint.Incidents.data.event_id String Event Id
LogPoint.Incidents.data.country_name String Country Name
LogPoint.Incidents.data.host String Host
LogPoint.Incidents.data.hash String Hash
LogPoint.Incidents.data.hash_sha1 String Hash SHA1
LogPoint.Incidents.data.agent_address String Agent Address
LogPoint.Incidents.data.attacker_address String Attacker Address
LogPoint.Incidents.data.broadcast_address String Broadcast Address
LogPoint.Incidents.data.client_address String Client Address
LogPoint.Incidents.data.client_hardware_address String Client Hardware Address
LogPoint.Incidents.data.destination_hardware_address String Destination Hardware Address
LogPoint.Incidents.data.destination_nat_address String Destination NAT Address
LogPoint.Incidents.data.device_address String Device Address
LogPoint.Incidents.data.external_address String External Address
LogPoint.Incidents.data.gateway_address String Gateway Address
LogPoint.Incidents.data.hardware_address String Hardware Address
LogPoint.Incidents.data.host_address String Host Address
LogPoint.Incidents.data.interface_address String Interface Address
LogPoint.Incidents.data.lease_address String Lease Address
LogPoint.Incidents.data.local_address String Local Address
LogPoint.Incidents.data.nas_address String Nas ddress
LogPoint.Incidents.data.nas_ipv6_address String Nas_IPV6 Address
LogPoint.Incidents.data.nat_address String NAT Address
LogPoint.Incidents.data.nat_source_address String NAT Source Address
LogPoint.Incidents.data.network_address String Network Address
LogPoint.Incidents.data.new_hardware_address String New Hardware Address
LogPoint.Incidents.data.old_hardware_address String Old Hardware Address
LogPoint.Incidents.data.original_address String Original Address
LogPoint.Incidents.data.original_client_address String Original Client Address
LogPoint.Incidents.data.original_destination_address String Original Destination Address
LogPoint.Incidents.data.original_server_address String Original Server Address
LogPoint.Incidents.data.original_source_address String Original Source Address
LogPoint.Incidents.data.originating_address String Originating Address
LogPoint.Incidents.data.peer_address String Peer Address
LogPoint.Incidents.data.private_address String Private Address
LogPoint.Incidents.data.proxy_address String Proxy Address
LogPoint.Incidents.data.proxy_source_address String Proxy Source Address
LogPoint.Incidents.data.relay_address String Relay Address
LogPoint.Incidents.data.remote_address String Remote Address
LogPoint.Incidents.data.resolved_address String Resolved Address
LogPoint.Incidents.data.route_address String Route Address
LogPoint.Incidents.data.scanner_address String Scanner Address
LogPoint.Incidents.data.server_address String Server Address
LogPoint.Incidents.data.server_hardware_address String Server Hardware Address
LogPoint.Incidents.data.source_hardware_address String Source Hardware Address
LogPoint.Incidents.data.start_address String Start Address
LogPoint.Incidents.data.supplier_address String Supplier Address
LogPoint.Incidents.data.switch_address String Switch Address
LogPoint.Incidents.data.translated_address String Translated Address
LogPoint.Incidents.data.virtual_address String Virtual Address
LogPoint.Incidents.data.virtual_server_address String Virtual Server Address
LogPoint.Incidents.data.vpn_address String VPN Address
LogPoint.Incidents.data.hash_length String Hash Length
LogPoint.Incidents.data.hash_sha256 String Hash SHA256
LogPoint.Incidents.data.alternate_user String Alternate User
LogPoint.Incidents.data.authenticated_user String Authenticated User
LogPoint.Incidents.data.authorized_user String Authorized User
LogPoint.Incidents.data.certificate_user String Certificate User
LogPoint.Incidents.data.current_user String Current User
LogPoint.Incidents.data.database_user String Database User
LogPoint.Incidents.data.destination_user String Destination User
LogPoint.Incidents.data.logon_user String Logon User
LogPoint.Incidents.data.new_max_user String New Max User
LogPoint.Incidents.data.new_user String New User
LogPoint.Incidents.data.old_max_user String Old Max User
LogPoint.Incidents.data.os_user String OS User
LogPoint.Incidents.data.remote_user String Remote User
LogPoint.Incidents.data.source_user String Source User
LogPoint.Incidents.data.system_user String System User
LogPoint.Incidents.data.target_logon_user String Target Logon User
LogPoint.Incidents.data.zone_user String Zone User

Command Example

!lp-get-incident-data date=1610700740.2248185 incident_id=8a676c39450e099b3512961d71ec4f7d incident_obj_id=600157c44a2018070b627f6a

Context Example

{
    "LogPoint": {
        "Incidents": {
            "data": [
                {
                    "_enrich_policy": "None",
                    "_fromV550": "t",
                    "_identifier": "0",
                    "_labels": [
                        "Metrics",
                        "Usage",
                        "Memory",
                        "LogPoint"
                    ],
                    "_offset": 195673,
                    "_type_ip": "device_ip",
                    "_type_num": "log_ts col_ts free total use used sig_id _offset _identifier",
                    "_type_str": "msg col_type device_name collected_at device_ip source_name _tz _enrich_policy label norm_id object _fromV550 repo_name logpoint_name",
                    "_tz": "UTC",
                    "col_ts": 1610700549,
                    "col_type": "filesystem",
                    "collected_at": "LogPoint",
                    "device_ip": "127.0.0.1",
                    "device_name": "localhost",
                    "free": "1963",
                    "log_ts": 1610700541,
                    "logpoint_name": "LogPoint",
                    "msg": "2021-01-15_08:49:01 Metrics; Physical Memory; total=7977 MB; use=71.0%; used=5664 MB; free=1963 MB",
                    "norm_id": "LogPoint",
                    "object": "Physical Memory",
                    "repo_name": "_logpoint",
                    "sig_id": "10507",
                    "source_name": "/opt/immune/var/log/system_metrics/system_metrics.log",
                    "total": "7977",
                    "use": "71.0",
                    "used": "5664"
                },
                {
                    "_enrich_policy": "None",
                    "_fromV550": "t",
                    "_identifier": "0",
                    "_labels": [
                        "Metrics",
                        "Usage",
                        "Memory",
                        "LogPoint"
                    ],
                    "_offset": 101372,
                    "_type_ip": "device_ip",
                    "_type_num": "log_ts col_ts free total use used sig_id _offset _identifier",
                    "_type_str": "msg col_type device_name collected_at device_ip source_name _tz _enrich_policy label norm_id object _fromV550 repo_name logpoint_name",
                    "_tz": "UTC",
                    "col_ts": 1610700428,
                    "col_type": "filesystem",
                    "collected_at": "LogPoint",
                    "device_ip": "127.0.0.1",
                    "device_name": "localhost",
                    "free": "1965",
                    "log_ts": 1610700421,
                    "logpoint_name": "LogPoint",
                    "msg": "2021-01-15_08:47:01 Metrics; Physical Memory; total=7977 MB; use=71.0%; used=5662 MB; free=1965 MB",
                    "norm_id": "LogPoint",
                    "object": "Physical Memory",
                    "repo_name": "_logpoint",
                    "sig_id": "10507",
                    "source_name": "/opt/immune/var/log/system_metrics/system_metrics.log",
                    "total": "7977",
                    "use": "71.0",
                    "used": "5662"
                }
            ]
        }
    }
}

Human Readable Output

Incident Data

Msg Use Used Log Ts Type Str Total Device Name Offset Logpoint Name Repo Name Free source Name col Ts Tz Norm Id Identifier Collected At Device Ip FromV550 Enrich Policy Type Num Type Ip Sig Id Col Type Object Labels
2021-01-15_08:49:01 Metrics; Physical Memory; total=7977 MB; use=71.0%; used=5664 MB; free=1963 MB 71.0 5664 1610700541 msg col_type device_name collected_at device_ip source_name_tz _enrich_policy label norm_id object_fromV550 repo_name logpoint_name 7977 localhost 195673 LogPoint _logpoint 1963 /opt/immune/var/log/system_metrics/system_metrics.log 1610700549 UTC LogPoint 0 LogPoint 127.0.0.1 t None log_ts col_ts free total use used sig_id_offset _identifier device_ip 10507 filesystem Physical Memory Metrics,
Usage,
Memory,
LogPoint
2021-01-15_08:47:01 Metrics; Physical Memory; total=7977 MB; use=71.0%; used=5662 MB; free=1965 MB 71.0 5662 1610700421 msg col_type device_name collected_at device_ip source_name_tz _enrich_policy label norm_id object_fromV550 repo_name logpoint_name 7977 localhost 101372 LogPoint _logpoint 1965 /opt/immune/var/log/system_metrics/system_metrics.log 1610700428 UTC LogPoint 0 LogPoint 127.0.0.1 t None log_ts col_ts free total use used sig_id_offset _identifier device_ip 10507 filesystem Physical Memory Metrics,
Usage,
Memory,
LogPoint

lp-get-incident-states


Displays incident states data between the provided two Timestamps ts_from and ts_to. By default, this command will display first 50 data of the past 24 hours but limit can be set to get desired number of incident states data.

Base Command

lp-get-incident-states

Input

Argument Name Description Required
ts_from From Timestamp. Optional
ts_to To Timestamp. Optional
limit Number of incident states data to fetch. Accepts integer value. Optional

Context Output

Path Type Description
LogPoint.Incidents.states.id String LogPoint Incidents States Id
LogPoint.Incidents.states.status String LogPoint Incidents States Status
LogPoint.Incidents.states.assigned_to String LogPoint Incidents States Assigned To
LogPoint.Incidents.states.comments String LogPoint Incidents States Comments

Command Example

!lp-get-incident-states ts_from="1610700720" ts_to="1610700900" limit=5

Context Example

{
    "LogPoint": {
        "Incidents": {
            "states": [
                {
                    "assigned_to": "5fd9d95769d3a4ea5684fccf",
                    "comments": [
                        {
                            "comment": "Example comment",
                            "time": 1610700740,
                            "title": "admin"
                        },
                        {
                            "comment": "Reassigned",
                            "time": 1610700745,
                            "title": "admin"
                        }
                    ],
                    "id": "5fdc788ecf35d7ae0f6b791b",
                    "name": "Greater than 60",
                    "status": "unresolved"
                },
                {
                    "assigned_to": "5fd9d95769d3a4ea5684fccf",
                    "comments": [
                        {
                            "comment": "Reassigned",
                            "time": 1610700745,
                            "title": "admin"
                        }
                    ],
                    "id": "5fdc788ecf35d7ae0f6b791c",
                    "name": "Memory use greater than 50",
                    "status": "unresolved"
                }
            ]
        }
    }
}

Human Readable Output

Displaying all 2 incident states data

Id Name Assigned To Status Comments
5fdc788ecf35d7ae0f6b791b Greater than 60 5fd9d95769d3a4ea5684fccf unresolved {‘title’: ‘admin’, ‘comment’: ‘Example comment’, ‘time’: 1610700740},
{‘title’: ‘admin’, ‘comment’: ‘Reassigned’, ‘time’: 1610700745}
5fdc788ecf35d7ae0f6b791c Memory use greater than 50 5fd9d95769d3a4ea5684fccf unresolved {‘title’: ‘admin’, ‘comment’: ‘Reassigned’, ‘time’: 1610700745}

lp-add-incident-comment


Add comments to the incidents

Base Command

lp-add-incident-comment

Input

Argument Name Description Required
incident_obj_id Object ID of a particular incident. It is the value contained in ‘id’ key of the incidents obtained from ‘lp-get-incidents’ command. Required
comment Comment to be added to the incidents. Required

Context Output

Path Type Description
LogPoint.Incidents.comment String LogPoint Incidents Comment

Command Example

!lp-add-incident-comment comment="Example comment" incident_obj_id=600157c44a2018070b627f6a

Context Example

{
    "LogPoint": {
        "Incidents": {
            "comment": "Comments added"
        }
    }
}

Human Readable Output

Comments added

lp-assign-incidents


Assigning/Re-assigning Incidents

Base Command

lp-assign-incidents

Input

Argument Name Description Required
incident_obj_ids Object ID of a particular incident. It is the value contained in ‘id’ key of the incidents obtained from ‘lp-get-incidents’ command. Multiple id can be provided by separating them using comma. Required
new_assignee Id of the user whom the incidents are assigned. It can be displayed using ‘lp-get-users’ command. Required

Context Output

Path Type Description
LogPoint.Incidents.assign String LogPoint Incidents Assign

Command Example

!lp-assign-incidents incident_obj_ids="600157c44a2018070b627f6a,6001583c4a2018070b627f6b" new_assignee=5bebd9fdd8aaa42840edc853

Context Example

{
    "LogPoint": {
        "Incidents": {
            "assign": "Incidents re-assigned"
        }
    }
}

Human Readable Output

Incidents re-assigned

lp-resolve-incidents


Resolves the Incidents.

Base Command

lp-resolve-incidents

Input

Argument Name Description Required
incident_obj_ids Object ID of a particular incident. It is the value contained in ‘id’ key of the incidents obtained from ‘lp-get-incidents’ command. Multiple id can be provided by separating them using comma. Required

Context Output

Path Type Description
LogPoint.Incidents.resolve String LogPoint Incidents Resolve

Command Example

!lp-resolve-incidents incident_obj_ids="600157c44a2018070b627f6a,6001583c4a2018070b627f6b"

Context Example

{
    "LogPoint": {
        "Incidents": {
            "resolve": "Incidents resolved"
        }
    }
}

Human Readable Output

Incidents resolved

lp-close-incidents


Closes the Incidents.

Base Command

lp-close-incidents

Input

Argument Name Description Required
incident_obj_ids Object ID of a particular incident. It is the value contained in ‘id’ key of the incidents obtained from ‘lp-get-incidents’ command. Multiple id can be provided by separating them using comma. Required

Context Output

Path Type Description
LogPoint.Incidents.close String LogPoint Incidents Close

Command Example

!lp-close-incidents incident_obj_ids="600157c44a2018070b627f6a,6001583c4a2018070b627f6b"

Context Example

{
    "LogPoint": {
        "Incidents": {
            "close": "Incidents closed"
        }
    }
}

Human Readable Output

Incidents closed

lp-reopen-incidents


Re-opens the closed incidents

Base Command

lp-reopen-incidents

Input

Argument Name Description Required
incident_obj_ids Object ID of a particular incident. It is the value contained in ‘id’ key of the incidents obtained from ‘lp-get-incidents’ command. Multiple id can be provided by separating them using comma. Required

Context Output

Path Type Description
LogPoint.Incidents.reopen String LogPoint Incidents Reopen

Command Example

!lp-reopen-incidents incident_obj_ids="600157c44a2018070b627f6a,6001583c4a2018070b627f6b"

Context Example

{
    "LogPoint": {
        "Incidents": {
            "reopen": "Incidents reopened"
        }
    }
}

Human Readable Output

Incidents reopened

lp-get-users


Gets Incident users and user groups.

Base Command

lp-get-users

Input

There are no input arguments for this command.

Context Output

Path Type Description
LogPoint.Incidents.users.id String LogPoint Incidents Users Id
LogPoint.Incidents.users.name String LogPoint Incidents Users Name
LogPoint.Incidents.users.usergroups String LogPoint Incidents Users Usergroups

Command Example


#### Context Example

```json
{
    "LogPoint": {
        "Incidents": {
            "users": [
                {
                    "id": "5bebd9fdd8aaa42840edc853",
                    "name": "admin",
                    "usergroups": [
                        {
                            "id": "5bebd9fdd8aaa42840edc84f",
                            "name": "LogPoint Administrator"
                        }
                    ]
                },
                {
                    "id": "5fd9d95769d3a4ea5684fccf",
                    "name": "sbs",
                    "usergroups": [
                        {
                            "id": "5bebd9fdd8aaa42840edc850",
                            "name": "User Account Administrator"
                        },
                        {
                            "id": "5bebd9fdd8aaa42840edc84f",
                            "name": "LogPoint Administrator"
                        }
                    ]
                }
            ]
        }
    }
}

Human Readable Output

Incident Users

Id Name Usergroups
5bebd9fdd8aaa42840edc853 admin {‘id’: ‘5bebd9fdd8aaa42840edc84f’, ‘name’: ‘LogPoint Administrator’}
5fd9d95769d3a4ea5684fccf sbs {‘id’: ‘5bebd9fdd8aaa42840edc850’, ‘name’: ‘User Account Administrator’},
{‘id’: ‘5bebd9fdd8aaa42840edc84f’, ‘name’: ‘LogPoint Administrator’}

lp-get-users-preference


Gets LogPoint user’s preference such as timezone, date format, etc.

Base Command

lp-get-users-preference

Input

There are no input arguments for this command.

Context Output

Path Type Description
LogPoint.User.Preference.timezone String LogPoint user’s timezone.
LogPoint.User.Preference.date_format String LogPoint user’s date format.
LogPoint.User.Preference.hour_format String LogPoint user’s hour format.

Command Example


#### Context Example

```json
{
    "LogPoint": {
        "User": {
            "Preference": {
                "date_format": "%Y/%m/%d",
                "hour_format": "24 Hour",
                "timezone": "UTC"
            }
        }
    }
}

Human Readable Output

User’s Preference

Timezone Date Format Hour Format
UTC %Y/%m/%d 24 Hour

lp-get-logpoints


Gets user’s LogPoints.

Base Command

lp-get-logpoints

Input

There are no input arguments for this command.

Context Output

Path Type Description
LogPoint.LogPoints.name String LogPoint name.
LogPoint.LogPoints.ip String LogPoint’s IP address.

Command Example


#### Context Example

```json
{
    "LogPoint": {
        "LogPoints": {
            "ip": "127.0.0.1",
            "name": "LogPoint"
        }
    }
}

Human Readable Output

LogPoints

Name Ip
LogPoint 127.0.0.1

lp-get-repos


Gets the list of LogPoint repos that can be accessed by the user.

Base Command

lp-get-repos

Input

There are no input arguments for this command.

Context Output

Path Type Description
LogPoint.Repos.repo String LogPoint repo name.
LogPoint.Repos.address String LogPoint repo address.

Command Example


#### Context Example

```json
{
    "LogPoint": {
        "Repos": [
            {
                "address": "127.0.0.1:5504/default",
                "repo": "default"
            },
            {
                "address": "127.0.0.1:5504/_logpoint",
                "repo": "_logpoint"
            }
        ]
    }
}

Human Readable Output

LogPoint Repos

Repo Address
default 127.0.0.1:5504/default
_logpoint 127.0.0.1:5504/_logpoint

lp-get-devices


Gets devices associated with LogPoint.

Base Command

lp-get-devices

Input

There are no input arguments for this command.

Context Output

Path Type Description
LogPoint.Devices.name String Device name.
LogPoint.Devices.address String Device IP address.

Command Example


#### Context Example

```json
{
    "LogPoint": {
        "Devices": [
            {
                "address": "127.0.0.1/127.0.0.1",
                "name": "localhost"
            },
            {
                "address": "127.0.0.1/::1",
                "name": "localhost"
            },
            {
                "address": "127.0.0.1/192.168.1.20",
                "name": "Windows Server"
            }
        ]
    }
}

Human Readable Output

Devices

Name Address
localhost 127.0.0.1/127.0.0.1
localhost 127.0.0.1/::1
Windows Server 127.0.0.1/192.168.1.20

lp-get-livesearches


Gets live search results of the alerts and dashboards.

Base Command

lp-get-livesearches

Input

There are no input arguments for this command.

Context Output

Path Type Description
LogPoint.LiveSearches.generated_by String Who generated the live search.
LogPoint.LiveSearches.searchname String The name of the live search.
LogPoint.LiveSearches.description String A description of the live search.
LogPoint.LiveSearches.query String The live search query.

Command Example


#### Context Example

```json
{
    "LogPoint": {
        "LiveSearches": [
            {
                "description": "",
                "flush_on_trigger": false,
                "generated_by": "alert",
                "life_id": "c4e38a6fe8226ec0975ee5ed935a733003bd1f11",
                "limit": 25,
                "query": "\"use\"> 86 col_type=filesystem ",
                "query_info": {
                    "aliases": [],
                    "columns": [],
                    "fieldsToExtract": [
                        "use",
                        "col_type"
                    ],
                    "grouping": [],
                    "lucene_query": "(_num_use:{86 TO *} AND col_type:filesystem)",
                    "query_filter": "\"use\"> 86 col_type=filesystem",
                    "query_type": "simple",
                    "success": true
                },
                "searchname": "Memory greater than 86",
                "tid": "",
                "timerange_day": 0,
                "timerange_hour": 1,
                "timerange_minute": 0,
                "timerange_second": 0,
                "vid": ""
            }
        ]
    }
}

Human Readable Output

Live Searches

Description Flush On Trigger Generated By Life Id Limit Query Query Info Searchname Tid Timerange Day Timerange Hour Timerange Minute Timerange Second Vid
  false alert c4e38a6fe8226ec0975ee5ed935a733003bd1f11 25 “use”> 86 col_type=filesystem fieldsToExtract: use,
col_type
aliases:
success: true
query_filter: “use”> 86 col_type=filesystem
columns:
query_type: simple
lucene_query: (_num_use:{86 TO *} AND col_type:filesystem)
grouping:
Memory greater than 86   0 1 0 0  

lp-get-searchid


Gets the search ID based on the provided search parameters.

Base Command

lp-get-searchid

Input

Argument Name Description Required
query LogPoint search query. Required
time_range Time range. For example: Last 30 minutes, Last 7 days, etc. If not provided, it will use ‘Last 5 minutes’ as the time range by default. Default is “Last 5 minutes”. Optional
limit Number of logs to fetch. If not provided, the first 100 logs will be displayed. Default is 100. Optional
repos A comma-separated list of LogPoint repos from which logs are to be fetched. If not provided, it will display logs from all repos. Optional
timeout LogPoint search timeout in seconds. Default is 60. Optional

Context Output

Path Type Description
LogPoint.search_id String Search ID. Use this ID in the lp-search-logs command to get the search result.

Command Example

!lp-get-searchid query="| chart count() by col_type" limit=5 time_range="Last 30 minutes"

Context Example

{
    "LogPoint": {
        "search_id": "97df79d3-b2b8-4260-bd12-805b69434591"
    }
}

Human Readable Output

Search Id: 97df79d3-b2b8-4260-bd12-805b69434591

lp-search-logs


Gets LogPoint search result. Uses the value of search_id as an argument.

Base Command

lp-search-logs

Input

Argument Name Description Required
search_id Search ID obtained from the lp-get-searchid command. Required

Context Output

Path Type Description
LogPoint.SearchLogs String Search results

Command Example

!lp-search-logs search_id=29023c62-12f4-4771-b988-067284a0e0c5

Context Example

{
    "LogPoint": {
        "SearchLogs": [
            {
                "_group": [
                    "office365"
                ],
                "_type_ip": "",
                "_type_num": " count()",
                "_type_str": " col_type count()",
                "col_type": "office365",
                "count()": 312
            },
            {
                "_group": [
                    "filesystem"
                ],
                "_type_ip": "",
                "_type_num": " count()",
                "_type_str": " col_type count()",
                "col_type": "filesystem",
                "count()": 3658
            }
        ]
    }
}

Human Readable Output

Found 2 logs

Group Type Ip Type Num Type Str Col Type Count()
office365   count() col_type count() office365 312
filesystem   count() col_type count() filesystem 3658

Configuration parameters

  • url — LogPoint URL (required)
  • username — LogPoint Username (required)
  • apikey — API Key (required)
  • insecure — Trust any certificate (not secure)
  • proxy — Use system proxy settings
  • first_fetch — First fetch timestamp (<number> <time unit>, e.g., 6 hours, 1 day)
  • incidentType — Incident type
  • isFetch — Fetch incidents
  • max_fetch — Fetch limit (Max value is 200, Recommended value is 50 or less)
  • incidentFetchInterval — Incidents Fetch Interval

Commands (16)

  • lp-add-incident-comment

    Add comments to the incidents.

  • lp-assign-incidents

    Assigning/Re-assigning Incidents.

  • lp-close-incidents

    Closes the Incidents.

  • lp-get-devices

    Gets devices associated with LogPoint.

  • lp-get-incident-data

    Retrieves a Particular Incident's Data.

  • lp-get-incident-states

    Displays incident states data between the provided two Timestamps ts_from and ts_to. By default, this command will display first 50 data of the past 24 hours but limit can be set to get desired number of incident states data.

  • lp-get-incidents

    Displays incidents between the provided two Timestamps ts_from and ts_to. By default, this command will display first 50 incidents of the past 24 hours but limit can be set to get desired number of incidents.

  • lp-get-livesearches

    Gets live search results of the alerts and dashboards.

  • lp-get-logpoints

    Gets user's LogPoints.

  • lp-get-repos

    Gets the list of LogPoint repos that can be accessed by the user.

  • lp-get-searchid

    Gets the search ID based on the provided search parameters.

  • lp-get-users

    Gets Incident users and user groups.

  • lp-get-users-preference

    Gets LogPoint user's preference such as timezone, date format, etc.

  • lp-reopen-incidents

    Re-opens the closed incidents.

  • lp-resolve-incidents

    Resolves the Incidents.

  • lp-search-logs

    Gets LogPoint search results. Uses the value of search_id as an argument.

import demistomock as demisto  # noqa: F401
from CommonServerPython import *  # noqa: F401

""" IMPORTS """

import json
import traceback
from datetime import datetime, timedelta

import dateparser
import urllib3

# Disable insecure warnings
urllib3.disable_warnings()


""" CLIENT CLASS """


class Client(BaseClient):
    """
    This Client implements API calls, and does not contain any Demisto logic.
    Should only do requests and return data.
    It inherits from BaseClient defined in CommonServer Python.
    Most calls use _http_request() that handles proxy, SSL verification, etc.
    """

    def __init__(self, base_url, verify, proxy, headers, username, apikey):
        self.username = username
        self.apikey = apikey
        super().__init__(base_url, verify=verify, proxy=proxy, headers=headers)

    def get_incidents(self, ts_from=None, ts_to=None):
        """
        :param ts_from: From Timestamp
        :param ts_to:To Timestamp
        :return: dict containing response from API call
        """
        if not ts_to:
            ts_to = datetime.timestamp(datetime.utcnow())
        if not ts_from:
            ts_from = datetime.timestamp(datetime.utcnow() - timedelta(days=1))
        data = {
            "username": self.username,
            "secret_key": self.apikey,
            "requestData": {"ts_from": round(float(ts_from)), "ts_to": round(float(ts_to))},
        }
        data = json.dumps(data)
        return self._http_request(method="GET", url_suffix="/incidents", data=data)

    def get_incident_data(self, obj_id, incident_id, date):
        """
        :param obj_id: incident obj id
        :param incident_id: incident_id
        :param date: detection_timestamp
        :return: dict containing response from API call
        """
        data = {
            "username": self.username,
            "secret_key": self.apikey,
            "requestData": {"incident_obj_id": obj_id, "incident_id": incident_id, "date": float(date)},
        }
        data = json.dumps(data)
        return self._http_request(method="GET", url_suffix="/get_data_from_incident", data=data)

    def get_incident_states(self, ts_from=None, ts_to=None):
        """
        :param ts_from: From Timestamp
        :param ts_to: To Timestamp
        :return: dict containing response from API call
        """
        if not ts_to:
            ts_to = datetime.timestamp(datetime.utcnow())
        if not ts_from:
            ts_from = datetime.timestamp(datetime.utcnow() - timedelta(days=1))
        data = {
            "username": self.username,
            "secret_key": self.apikey,
            "requestData": {"ts_from": round(float(ts_from)), "ts_to": round(float(ts_to))},
        }
        data = json.dumps(data)
        return self._http_request(method="GET", url_suffix="/incident_states", data=data)

    def add_incident_comment(self, incident_obj_id, comment):
        """
        :param incident_obj_id: incident obj id
        :param comment: Comments to be added
        :return: dict containing response from API call
        """
        data = {
            "username": self.username,
            "secret_key": self.apikey,
            "requestData": {"version": "0.1", "states": [{"_id": incident_obj_id, "comments": [comment]}]},
        }
        data = json.dumps(data)
        return self._http_request(method="POST", url_suffix="/add_incident_comment", data=data)

    def assign_incidents(self, incident_obj_ids, new_assignee):
        """
        :param incident_obj_ids: incident obj ids in the list format
        :param new_assignee: id of the user
        :return: dict containing response from API call
        """
        data = {
            "username": self.username,
            "secret_key": self.apikey,
            "requestData": {"version": "0.1", "incident_ids": incident_obj_ids, "new_assignee": new_assignee},
        }
        data = json.dumps(data)
        return self._http_request(method="POST", url_suffix="/assign_incident", data=data)

    def resolve_incidents(self, incident_obj_ids):
        """
        :param incident_obj_ids: incident obj ids in the list format
        :return: dict containing response from API call
        """
        data = {
            "username": self.username,
            "secret_key": self.apikey,
            "requestData": {"version": "0.1", "incident_ids": incident_obj_ids},
        }
        data = json.dumps(data)
        return self._http_request(method="POST", url_suffix="/resolve_incident", data=data)

    def close_incidents(self, incident_obj_ids):
        """
        :param incident_obj_ids: incident ids in list format
        :return: dict containing response from API call
        """
        data = {
            "username": self.username,
            "secret_key": self.apikey,
            "requestData": {"version": "0.1", "incident_ids": incident_obj_ids},
        }
        data = json.dumps(data)
        return self._http_request(method="POST", url_suffix="/close_incident", data=data)

    def reopen_incidents(self, incident_obj_ids):
        """
        :param incident_obj_ids: incident obj ids in list format
        :return: dict containing response from API call
        """
        data = {
            "username": self.username,
            "secret_key": self.apikey,
            "requestData": {"version": "0.1", "incident_ids": incident_obj_ids},
        }
        data = json.dumps(data)
        return self._http_request(method="POST", url_suffix="/reopen_incident", data=data)

    def get_users(self):
        """
        :return: dict containing response from API call
        """
        data = {"username": self.username, "secret_key": self.apikey}
        data = json.dumps(data)
        return self._http_request(method="GET", url_suffix="/get_users", data=data)

    def get_users_preference(self):
        """
        :return: dict containing response from API call
        """
        data = {"username": self.username, "secret_key": self.apikey, "type": "user_preference"}
        return self._http_request(method="POST", url_suffix="/getalloweddata", data=data)

    def get_logpoints(self):
        """
        :return: dict containing response from API call
        """
        data = {"username": self.username, "secret_key": self.apikey, "type": "loginspects"}
        return self._http_request(method="POST", url_suffix="/getalloweddata", data=data)

    def get_repos(self):
        """
        :return: dict containing response from API call
        """
        data = {"username": self.username, "secret_key": self.apikey, "type": "logpoint_repos"}
        return self._http_request(method="POST", url_suffix="/getalloweddata", data=data)

    def get_devices(self):
        """
        :return: dict containing response from API call
        """
        data = {"username": self.username, "secret_key": self.apikey, "type": "devices"}
        return self._http_request(method="POST", url_suffix="/getalloweddata", data=data)

    def get_livesearches(self):
        """
        :return: dict containing response from API call
        """
        data = {"username": self.username, "secret_key": self.apikey, "type": "livesearches"}
        return self._http_request(method="POST", url_suffix="/getalloweddata", data=data)

    def get_search_id(self, query, time_range, limit=100, repos=[], timeout=60):
        """
        :param query: LogPoint search query

        :param time_range: Time range: Eg. Last 5 minutes, Last 1 day etc.

        :param limit: Number of search results to fetch

        :param repos: LogPoint repos from where logs should be fetched

        :param timeout: LogPoint search timeout

        :return: dict containing response from API call
        """
        data = {
            "username": self.username,
            "secret_key": self.apikey,
            "requestData": json.dumps(
                {"query": query, "time_range": time_range, "limit": limit, "repos": repos, "timeout": timeout}
            ),
        }
        return self._http_request(method="POST", url_suffix="/getsearchlogs", data=data)

    def get_search_results(self, search_id):
        """
        :param search_id: Search id obtained from get_search_id() method
        :return: dict containing response from API call
        """
        data = {"username": self.username, "secret_key": self.apikey, "requestData": json.dumps({"search_id": search_id})}
        return self._http_request(method="POST", url_suffix="/getsearchlogs", data=data)


""" HELPER FUNCTIONS """


def get_demisto_severity(severity):
    """
    Maps LogPoint risk_level into Demisto Severity
    :param severity: LogPoint risk_level
    :return: Demisto Severity level (0 to 4)
    """
    severity = severity.lower()
    if severity == "low":
        return 1
    elif severity == "medium":
        return 2
    elif severity == "high":
        return 3
    elif severity == "critical":
        return 4
    return 0


""" COMMAND FUNCTIONS """


def test_module(client, max_fetch):
    if max_fetch:
        try:
            max_fetch = int(max_fetch)
        except ValueError:
            return "Fetch limit does not seem to be valid integer. Suggested: 50 or less, max: 200"
        if max_fetch > 200:
            return "Fetch limit should not be greater than 200."
    ts_from = ts_to = round(datetime.timestamp(datetime.utcnow()))
    try:
        result = client.get_incidents(ts_from, ts_to)
        if not result.get("success"):
            msg = result.get("message")
            if msg == "Authentication Failed":
                return "LogPoint authentication failed. Please make sure that the API Key is correct."
            else:
                return msg
    except DemistoException as err:
        if "<requests.exceptions.ConnectionError>" in str(err):
            msg = (
                "Could not connect to the LogPoint server. "
                "Verify that the server URL parameter is correct "
                "and that you have access to the server from your host."
            )
            return msg
        else:
            raise err
    return "ok"


def get_incidents_command(client, args):
    ts_from = args.get("ts_from")
    ts_to = args.get("ts_to")
    limit = args.get("limit") if args.get("limit") else 50
    if limit:
        try:
            limit = int(limit)
        except ValueError:
            raise DemistoException(f"The provided argument '{limit}' for limit is not a valid integer.")
    result = client.get_incidents(ts_from, ts_to)
    if not result.get("success"):
        raise DemistoException(result.get("message"))
    incidents = result.get("incidents", [])
    table_header = []
    display_title = "Incidents"
    if incidents and len(incidents) > 0:
        table_header = list(incidents[0].keys())
        if not ts_from:
            ts_from = incidents[0].get("detection_timestamp")
    if len(incidents) > limit:
        incidents = incidents[:limit]
        last_detection_ts = incidents[-1].get("detection_timestamp")
        display_title = (
            f"Displaying first {limit} incidents between {ts_from} and {last_detection_ts} timestamps."
            f"\nPlease narrow down ts_from and ts_to arguments or increase the limit argument to "
            f"get more incidents."
        )
    elif len(incidents) <= limit and len(incidents) != 0:
        if not ts_to:
            ts_to = incidents[-1].get("detection_timestamp")
        display_title = f"Displaying all {len(incidents)} incidents between {ts_from} and {ts_to}"
    markdown = tableToMarkdown(display_title, incidents, headers=table_header, headerTransform=string_to_table_header)
    return CommandResults(
        readable_output=markdown, outputs_prefix="LogPoint.Incidents", outputs_key_field="id", outputs=incidents
    )


def get_incident_data_command(client, args):
    incident_obj_id = args.get("incident_obj_id")
    incident_id = args.get("incident_id")
    date = args.get("date")
    result = client.get_incident_data(incident_obj_id, incident_id, date)
    if not result.get("success"):
        raise DemistoException(result.get("message"))
    incident_data = result.get("rows", [])
    table_header = []
    if incident_data and len(incident_data) > 0:
        table_header = list(incident_data[0].keys())
    markdown = tableToMarkdown("Incident Data", incident_data, headers=table_header, headerTransform=string_to_table_header)
    return CommandResults(
        readable_output=markdown, outputs_prefix="LogPoint.Incidents.data", outputs_key_field="", outputs=incident_data
    )


def get_incident_states_command(client, args):
    ts_from = args.get("ts_from")
    ts_to = args.get("ts_to")
    limit = args.get("limit") if args.get("limit") else 50
    if limit:
        try:
            limit = int(limit)
        except ValueError:
            raise DemistoException(f"The provided argument '{limit}' for limit is not a valid integer.")
    result = client.get_incident_states(ts_from, ts_to)
    if not result.get("success"):
        raise DemistoException(result.get("message"))
    incident_states = result.get("states", [])
    table_header = []
    display_title = "Incident States"
    if incident_states and len(incident_states) > 0:
        table_header = list(incident_states[0].keys())
    if len(incident_states) > limit:
        incident_states = incident_states[:limit]
        display_title = (
            f"Displaying first {limit} incident states data. "
            f"\nPlease narrow down ts_from and ts_to arguments or increase the limit argument to "
            f"get more."
        )
    elif len(incident_states) <= limit and len(incident_states) != 0:
        display_title = f"Displaying all {len(incident_states)} incident states data."
    markdown = tableToMarkdown(display_title, incident_states, headers=table_header, headerTransform=string_to_table_header)
    return CommandResults(
        readable_output=markdown, outputs_prefix="LogPoint.Incidents.states", outputs_key_field="id", outputs=incident_states
    )


def add_incident_comment_command(client, args):
    incident_obj_id = args.get("incident_obj_id")
    comment = args.get("comment")
    result = client.add_incident_comment(incident_obj_id, comment)
    if not result.get("success"):
        raise DemistoException(result.get("message"))
    msg = result.get("message", "Comment added!")
    markdown = "### " + msg
    results = CommandResults(
        readable_output=markdown, outputs_prefix="LogPoint.Incidents.comment", outputs_key_field="", outputs=msg
    )
    return results


def assign_incidents_command(client, args):
    incident_obj_ids = argToList(args.get("incident_obj_ids"))
    new_assignee = args.get("new_assignee")
    result = client.assign_incidents(incident_obj_ids, new_assignee)
    if not result.get("success"):
        raise DemistoException(result.get("message"))
    msg = result.get("message")
    markdown = "### " + msg
    results = CommandResults(
        readable_output=markdown, outputs_prefix="LogPoint.Incidents.assign", outputs_key_field="", outputs=msg
    )
    return results


def resolve_incidents_command(client, args):
    incident_obj_ids = argToList(args.get("incident_obj_ids"))
    result = client.resolve_incidents(incident_obj_ids)
    if not result.get("success"):
        raise DemistoException(result.get("message"))
    msg = result.get("message")
    markdown = "### " + msg
    return CommandResults(
        readable_output=markdown, outputs_prefix="LogPoint.Incidents.resolve", outputs_key_field="", outputs=msg
    )


def close_incidents_command(client, args):
    incident_obj_ids = argToList(args.get("incident_obj_ids"))
    result = client.close_incidents(incident_obj_ids)
    if not result.get("success"):
        raise DemistoException(result.get("message"))
    msg = result.get("message")
    markdown = "### " + msg
    return CommandResults(readable_output=markdown, outputs_prefix="LogPoint.Incidents.close", outputs_key_field="", outputs=msg)


def reopen_incidents_command(client, args):
    incident_obj_ids = argToList(args.get("incident_obj_ids"))
    result = client.reopen_incidents(incident_obj_ids)
    if not result.get("success"):
        raise DemistoException(result.get("message"))
    msg = result.get("message")
    markdown = "### " + msg
    return CommandResults(readable_output=markdown, outputs_prefix="LogPoint.Incidents.reopen", outputs_key_field="", outputs=msg)


def get_users_command(client):
    result = client.get_users()
    if not result.get("success"):
        raise DemistoException(result.get("message"))
    users = result.get("users")
    if users and len(users) > 0:
        table_header = list(users[0].keys())
        markdown = tableToMarkdown("Incident Users", users, headers=table_header, headerTransform=string_to_table_header)
    else:
        markdown = "No users record found."
    return CommandResults(
        readable_output=markdown, outputs_prefix="LogPoint.Incidents.users", outputs_key_field="id", outputs=users
    )


def get_users_preference_command(client):
    result = client.get_users_preference()
    if not result.get("success"):
        raise DemistoException(result.get("message"))
    del result["success"]
    if not result or len(result) == 0:
        markdown = "No users preference found."
    else:
        table_header = list(result.keys())
        display_title = "User's Preference"
        markdown = tableToMarkdown(display_title, result, headers=table_header, headerTransform=string_to_table_header)
    return CommandResults(readable_output=markdown, outputs_prefix="LogPoint.User.Preference", outputs=result)


def get_logpoints_command(client):
    result = client.get_logpoints()
    if not result.get("success"):
        raise DemistoException(result.get("message"))
    allowed_loginspects = result.get("allowed_loginspects")
    if allowed_loginspects and len(allowed_loginspects) > 0:
        table_header = list(allowed_loginspects[0].keys())
        display_title = "LogPoints"
        markdown = tableToMarkdown(
            display_title, allowed_loginspects, headers=table_header, headerTransform=string_to_table_header
        )
    else:
        markdown = "No LogPoints found."
    return CommandResults(
        readable_output=markdown, outputs_prefix="LogPoint.LogPoints", outputs_key_field="ip", outputs=allowed_loginspects
    )


def get_repos_command(client):
    result = client.get_repos()
    if not result.get("success"):
        raise DemistoException(result.get("message"))
    allowed_repos = result.get("allowed_repos")
    if allowed_repos and len(allowed_repos) > 0:
        table_header = list(allowed_repos[0].keys())
        display_title = "LogPoint Repos"
        markdown = tableToMarkdown(display_title, allowed_repos, headers=table_header, headerTransform=string_to_table_header)
    else:
        markdown = "No repos found."
    return CommandResults(
        readable_output=markdown, outputs_prefix="LogPoint.Repos", outputs_key_field="repo", outputs=allowed_repos
    )


def get_devices_command(client):
    result = client.get_devices()
    if not result.get("success"):
        raise DemistoException(result.get("message"))
    display_title = "Devices"
    allowed_devices = result.get("allowed_devices")
    if allowed_devices and len(allowed_devices) > 0:
        device_list = []
        for device in allowed_devices:
            for key, value in device.items():
                device_list.append(
                    {
                        "name": value,
                        "address": key,
                    }
                )
        table_header = ["name", "address"]
        markdown = tableToMarkdown(display_title, device_list, headers=table_header, headerTransform=string_to_table_header)
    else:
        markdown = "Devices not found."
    return CommandResults(readable_output=markdown, outputs_prefix="LogPoint.Devices", outputs=device_list)


def get_livesearches_command(client):
    result = client.get_livesearches()
    if not result.get("success"):
        raise DemistoException(result.get("message"))
    livesearches = result.get("livesearches")
    if livesearches and len(livesearches) > 0:
        display_title = "Live Searches"
        markdown = tableToMarkdown(display_title, livesearches, headers=None, headerTransform=string_to_table_header)
    else:
        markdown = "No Live Searches data found."
    return CommandResults(readable_output=markdown, outputs_prefix="LogPoint.LiveSearches", outputs=livesearches)


def get_searchid_command(client, args):
    query = args.get("query")
    time_range = args.get("time_range", "Last 5 minutes")
    limit = args.get("limit", "100")
    repos = argToList(args.get("repos"))
    timeout = args.get("timeout", "60")
    if limit:
        try:
            limit = int(limit)
        except ValueError:
            raise DemistoException(f"The provided argument '{limit}' for limit is not a valid integer.")
    result = client.get_search_id(query, time_range, limit, repos, timeout)
    if not result.get("success"):
        raise DemistoException(result.get("message"))
    search_id = result.get("search_id")
    if search_id:
        del result["success"]
        if result.get("searchId"):
            del result["searchId"]
        headers = result.keys()
        display_title = f"Search Id: {search_id}"
        markdown = tableToMarkdown(display_title, result, headers=headers, headerTransform=string_to_table_header)
    else:
        markdown = "Could not get Search Id."
    return CommandResults(readable_output=markdown, outputs_prefix="LogPoint.search_id", outputs=search_id)


def search_logs_command(client, args):
    search_id = args.get("search_id")
    rows = []
    while True:
        search_result = client.get_search_results(search_id)
        if not search_result.get("success"):
            raise DemistoException(search_result.get("message"))
        rows += search_result.get("rows", [])
        if search_result.get("final"):
            break
    if rows and len(rows) > 0:
        display_title = f"Found {len(rows)} logs"
        markdown = tableToMarkdown(display_title, rows, headers=None, headerTransform=string_to_table_header)
    else:
        markdown = "No results found for the given search parameters."
    return CommandResults(readable_output=markdown, outputs_prefix="LogPoint.SearchLogs", outputs=rows)


def fetch_incidents(client, first_fetch, max_fetch):
    """
    This function retrieves new incidents every interval (default is 1 minute).
    """
    now = datetime.timestamp(datetime.utcnow())
    last_run_object = demisto.getLastRun()
    last_run = last_run_object.get("time", None) if last_run_object else None
    if not last_run:
        if first_fetch:
            last_run = float(first_fetch)
        else:
            last_run = datetime.timestamp(datetime.utcnow() - timedelta(days=1))
    result = client.get_incidents(last_run, now)
    if not result.get("success"):
        raise DemistoException(f"ERROR: {result.get('message')}; last_run: {last_run}; now: {now}")
    lp_incidents = result.get("incidents")
    incidents = []
    if len(lp_incidents) > max_fetch:
        next_fetch_time = lp_incidents[max_fetch]["detection_timestamp"]
        lp_incidents = lp_incidents[:max_fetch]
    else:
        next_fetch_time = now
    demisto.info(f"Executing LogPoint fetch_incidents between {last_run} and {next_fetch_time} Timestamp.")
    for inc in lp_incidents:
        detection_ts = inc["detection_timestamp"]
        dt = datetime.utcfromtimestamp(detection_ts)
        occurred = dt.strftime("%Y-%m-%dT%H:%M:%S.%fZ")
        incidents.append(
            {
                "name": inc.get("name", "LogPoint - No name"),
                "occurred": occurred,
                "severity": get_demisto_severity(inc.get("risk_level")),
                "rawJSON": json.dumps(inc),
            }
        )
    demisto.setLastRun({"time": next_fetch_time})
    return incidents


""" MAIN FUNCTION """


def main():
    """main function, parses params and runs command functions

    :return:
    :rtype:
    """
    handle_proxy()
    params = demisto.params()
    username = params.get("username")
    apikey = params.get("apikey")
    base_url = params.get("url").rstrip("/")
    proxy = params.get("proxy", False)
    verify_certificate = not params.get("insecure", False)
    first_fetch_param = params.get("first_fetch") if params.get("first_fetch") else "1 day"
    first_fetch_dt = dateparser.parse(first_fetch_param, settings={"TIMEZONE": "UTC"})
    if first_fetch_param and not first_fetch_dt:
        return_error(f"First fetch input '{first_fetch_param}' is invalid. Valid format eg.:1 day")
    assert first_fetch_dt is not None
    first_fetch = first_fetch_dt.timestamp()
    max_fetch = params.get("max_fetch")
    max_fetch = int(params.get("max_fetch")) if (max_fetch and max_fetch.isdigit()) else 50
    max_fetch = max(min(200, max_fetch), 1)
    command = demisto.command()
    demisto.debug(f"Command being called is {command}")
    incident_commands = [
        "test-module",
        "lp-get-incidents",
        "lp-get-incident-data",
        "lp-get-incident-states",
        "lp-add-incident-comment",
        "lp-assign-incidents",
        "lp-resolve-incidents",
        "lp-close-incidents",
        "lp-reopen-incidents",
        "lp-get-users",
        "fetch-incidents",
    ]
    if command in incident_commands:
        headers = {"Content-Type": "application/json"}
    else:
        headers = {"Content-Type": "application/x-www-form-urlencoded"}
    try:
        client = Client(
            base_url=base_url, verify=verify_certificate, headers=headers, proxy=proxy, username=username, apikey=apikey
        )
        args = demisto.args()
        if command == "test-module":
            return_results(test_module(client, params.get("max_fetch")))
        elif command == "lp-get-incidents":
            return_results(get_incidents_command(client, args))
        elif command == "lp-get-incident-data":
            return_results(get_incident_data_command(client, args))
        elif command == "lp-get-incident-states":
            return_results(get_incident_states_command(client, args))
        elif command == "lp-add-incident-comment":
            return_results(add_incident_comment_command(client, args))
        elif command == "lp-assign-incidents":
            return_results(assign_incidents_command(client, args))
        elif command == "lp-resolve-incidents":
            return_results(resolve_incidents_command(client, args))
        elif command == "lp-close-incidents":
            return_results(close_incidents_command(client, args))
        elif command == "lp-reopen-incidents":
            return_results(reopen_incidents_command(client, args))
        elif command == "lp-get-users":
            return_results(get_users_command(client))
        elif command == "lp-get-users-preference":
            return_results(get_users_preference_command(client))
        elif command == "lp-get-logpoints":
            return_results(get_logpoints_command(client))
        elif command == "lp-get-repos":
            return_results(get_repos_command(client))
        elif command == "lp-get-devices":
            return_results(get_devices_command(client))
        elif command == "lp-get-livesearches":
            return_results(get_livesearches_command(client))
        elif command == "lp-get-searchid":
            return_results(get_searchid_command(client, args))
        elif command == "lp-search-logs":
            return_results(search_logs_command(client, args))
        elif command == "fetch-incidents":
            demisto.incidents(fetch_incidents(client, first_fetch, max_fetch))
    except Exception as err:
        demisto.error(traceback.format_exc())  # print the traceback
        return_error(f"Failed to execute {command} command. Error: {err!s}")


""" ENTRY POINT """

if __name__ in ("__main__", "__builtin__", "builtins"):
    main()