Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.11
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from __future__ import annotations
from soar_sdk.SiemplifyUtils import output_handler
from ..core.ElasticsearchManager import ElasticsearchManager
from soar_sdk.SiemplifyAction import SiemplifyAction
from TIPCommon import dict_to_flat, construct_csv, extract_configuration_param
import json

INTEGRATION_NAME = "ElasticSearchV7"
SCRIPT_NAME = "ElasticSearchV7-AdvancedESSearch"


@output_handler
def main():
siemplify = SiemplifyAction()
siemplify.script_name = SCRIPT_NAME
# Integration Parameters
server_address = extract_configuration_param(
siemplify,
provider_name=INTEGRATION_NAME,
param_name="Server Address",
is_mandatory=True,
)
username = extract_configuration_param(
siemplify,
provider_name=INTEGRATION_NAME,
param_name="Username",
is_mandatory=False,
)
password = extract_configuration_param(
siemplify,
provider_name=INTEGRATION_NAME,
param_name="Password",
is_mandatory=False,
)
api_token = extract_configuration_param(
siemplify,
provider_name=INTEGRATION_NAME,
param_name="API Token",
is_mandatory=False,
)
authenticate = extract_configuration_param(
siemplify,
provider_name=INTEGRATION_NAME,
param_name="Authenticate",
is_mandatory=True,
default_value=False,
input_type=bool,
)
verify_ssl = extract_configuration_param(
siemplify,
provider_name=INTEGRATION_NAME,
param_name="Verify SSL",
is_mandatory=True,
default_value=False,
input_type=bool,
)
ca_certificate_file = extract_configuration_param(
siemplify,
provider_name=INTEGRATION_NAME,
param_name="CA Certificate File",
is_mandatory=False,
input_type=str,
)

if authenticate:
elasticsearch_wrapper = ElasticsearchManager(
server_address,
username=username,
password=password,
api_token=api_token,
verify_ssl=verify_ssl,
authenticate=True,
ca_certificate_file=ca_certificate_file,
)
else:
elasticsearch_wrapper = ElasticsearchManager(
server_address,
verify_ssl=verify_ssl,
ca_certificate_file=ca_certificate_file,
)

kwargs = {}

kwargs["Index"] = siemplify.parameters.get("Index")
kwargs["Query"] = siemplify.parameters.get("Query")
kwargs["Display Field"] = siemplify.parameters.get("Display Field")
kwargs["Search Field"] = siemplify.parameters.get("Search Field")
kwargs["Timestamp Field"] = siemplify.parameters.get("Timestamp Field")
kwargs["Oldest Date"] = siemplify.parameters.get("Oldest Date")
kwargs["Earliest Date"] = siemplify.parameters.get("Earliest Date")
kwargs["Limit"] = siemplify.parameters.get("Limit")
kwargs["Oldest Date Compare Type"] = "gte"
kwargs["Earliest Date Compare Type"] = "lte"

results, status, total_hits = elasticsearch_wrapper.advanced_es_search(**kwargs)

if status or results:
output_message = (
f"Query ran successfully {len(results)} hits found"
if results
else "No results found for the provided query."
)
else:
output_message = "ERROR: Query failed to run"

if results:
flat_results = []
for result in results:
flat_result = dict_to_flat(result)
flat_results.append(flat_result)

csv_output = construct_csv(flat_results)
siemplify.result.add_data_table(f"Results - Total {len(results)}", csv_output)

siemplify.result.add_result_json(json.dumps(results))
siemplify.end(output_message, json.dumps(results))


if __name__ == "__main__":
main()
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
name: Advanced ES Search
description: Premade structured Elastic search query, returns a dict of dictionaries.
This action should be used when you want to use time range in the query. If you
don’t want to use the time range, use Simple ES Search action.
integration_identifier: ElasticSearchV7
parameters:
- name: Index
default_value: '*'
type: string
description: "Search pattern for a elastic index.\r\nIn elastic, index is like\
\ a DatabaseName, and data is stored across various indexes.\r\nThis param\
\ defines in what index(es) to search. It can be an exact name ie: \"smp_playbooks-2019.06.13\"\
\r\nor you can use a (*) wildcard to search by a pattern. e: \"smp_playbooks-2019.06*\"\
\ or \"smp*\".\r\nTo learn more about elastic indexes visit https://www.elastic.co/blog/what-is-an-elasticsearch-index"
is_mandatory: false
- name: Query
default_value: '*'
type: string
description: "The search query to perform. It is in Lucene syntax.\r\nIE1: \"\
*\" (this is a wildcard that will return all record)\r\nIE1: \"level:error\"\
\r\nIE2: \"level:information\"\r\nIE3: \"level:error OR level:warning\"\r\n\
To learn more about lucene syntax, visit\r\nhttps://www.elastic.co/guide/en/kibana/current/lucene-query.html#lucene-query\r\
\nhttps://www.elastic.co/guide/en/elasticsearch/reference/7.1/query-dsl-query-string-query.html#query-string-syntax"
is_mandatory: false
- name: Limit
default_value: '100'
type: string
description: "Limits the document return count, ie: 10.\r\n0 = No limit"
is_mandatory: false
- name: Display Field
default_value: '*'
type: string
description: "Limits the returned fields. Default \"*\" = Return all fields.\r\
\nYou can state a single field. ie: \"level\""
is_mandatory: false
- name: Search Field
default_value: _all
type: string
description: "Search field for free text queries (When query doesn't specify a\
\ field name).\r\nDefault is \"_all\", which means all fields are searched.\
\ It is best to use proper lucene syntanx on \"_all\" fields, or textual search\
\ on a specific field.\r\nie1: Search Field = \"_all\". Query = \"level:error\"\
\ Query will return all records where \"level\" field, equals \"error\".\r\
\nie2: Search Field = \"Message\", query = \"*Login Alarm*\". Query will return\
\ all records, which their \"Message\" field, contains the text \"Login Alarm\""
is_mandatory: false
- name: Timestamp Field
default_value: '@timestamp'
type: string
description: The name of the field to run time-based filtering against. Default
is @timestamp. If both Earliest Date and Oldest Date are empty, no time-based
filtering will occur.
is_mandatory: false
- name: Oldest Date
default_value: now-1d
type: string
description: "Start date of the search. Search will return only records equal\
\ or after this point in time.\r\nInput may be in exact UTC:\r\n\tFormat:\
\ YYYY-MM-DDTHH:MM:SSZ\r\n\tie: 2019-06-04T10:00:00Z\r\nInput may also be\
\ in relative form (using date-math):\r\n\tie: \"now\", \"now-1d\", \"now-1d/d\"\
, \"now-2h/h\"\r\n\tto learn more about date-math visit https://www.elastic.co/guide/en/elasticsearch/reference/7.1/common-options.html#date-math"
is_mandatory: false
- name: Earliest Date
default_value: now
type: string
description: "End date of the search. Search will return only records equal or\
\ before this point in time.\r\nInput may be in exact UTC:\r\n\tFormat: YYYY-MM-DDTHH:MM:SSZ\r\
\n\tie: 2019-06-04T10:00:00Z\r\nInput may also be in relative form (using\
\ date-math):\r\n\tie: \"now\", \"now-1d\", \"now-1d/d\", \"now-2h/h\"\r\n\
\tto learn more about date-math visit https://www.elastic.co/guide/en/elasticsearch/reference/7.1/common-options.html#date-math"
is_mandatory: false
dynamic_results_metadata:
- result_example_path: resources/advanced_es_search_JsonResult_example.json
result_name: JsonResult
show_result: true
creator: Siemplify System
script_result_name: results
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from __future__ import annotations
from soar_sdk.SiemplifyUtils import output_handler
from ..core.ElasticsearchManager import ElasticsearchManager
from soar_sdk.SiemplifyAction import SiemplifyAction
from TIPCommon import extract_configuration_param, extract_action_param, construct_csv
from soar_sdk.ScriptResult import EXECUTION_STATE_COMPLETED, EXECUTION_STATE_FAILED
import json

INTEGRATION_NAME = "ElasticSearchV7"
SCRIPT_NAME = "DSL Search"


@output_handler
def main():
siemplify = SiemplifyAction()
siemplify.script_name = f"{INTEGRATION_NAME} - {SCRIPT_NAME}"

server_address = extract_configuration_param(
siemplify,
provider_name=INTEGRATION_NAME,
param_name="Server Address",
is_mandatory=True,
input_type=str,
)
username = extract_configuration_param(
siemplify,
provider_name=INTEGRATION_NAME,
param_name="Username",
is_mandatory=False,
input_type=str,
)
password = extract_configuration_param(
siemplify,
provider_name=INTEGRATION_NAME,
param_name="Password",
is_mandatory=False,
input_type=str,
)
api_token = extract_configuration_param(
siemplify,
provider_name=INTEGRATION_NAME,
param_name="API Token",
is_mandatory=False,
)
authenticate = extract_configuration_param(
siemplify,
provider_name=INTEGRATION_NAME,
param_name="Authenticate",
default_value=False,
input_type=bool,
)
verify_ssl = extract_configuration_param(
siemplify,
provider_name=INTEGRATION_NAME,
param_name="Verify SSL",
default_value=False,
input_type=bool,
)
ca_certificate_file = extract_configuration_param(
siemplify,
provider_name=INTEGRATION_NAME,
param_name="CA Certificate File",
is_mandatory=False,
input_type=str,
)

index = extract_action_param(
siemplify,
param_name="Index",
is_mandatory=False,
print_value=True,
input_type=str,
)
query = extract_action_param(
siemplify,
param_name="Query",
is_mandatory=False,
print_value=True,
input_type=str,
)
limit = extract_action_param(
siemplify,
param_name="Limit",
is_mandatory=False,
print_value=True,
input_type=int,
)
status = EXECUTION_STATE_COMPLETED

try:
if authenticate:
elasticsearch_wrapper = ElasticsearchManager(
server_address,
username=username,
password=password,
api_token=api_token,
verify_ssl=verify_ssl,
authenticate=True,
ca_certificate_file=ca_certificate_file,
siemplify=siemplify,
)
else:
elasticsearch_wrapper = ElasticsearchManager(
server_address,
verify_ssl=verify_ssl,
ca_certificate_file=ca_certificate_file,
siemplify=siemplify,
)
dsl_search_results, total_hits = elasticsearch_wrapper.dsl_search(
index, query, limit
)
if dsl_search_results:
output_message = f"Successfully executed ElasticSearch DSL Query {len(dsl_search_results)} hits found"
else:
output_message = "Error executing ElasticSearch action 'Run DSL Query'."

if dsl_search_results:
flat_results = []
for dsl_result in dsl_search_results:
flat_result = dsl_result.to_flat()
flat_results.append(flat_result)

csv_output = construct_csv(flat_results)
siemplify.result.add_data_table(
f"Results - Total {len(dsl_search_results)}", csv_output
)

siemplify.result.add_result_json(
json.dumps([dsl_result.to_json() for dsl_result in dsl_search_results])
)
result = "true"

except Exception as e:
output_message = f"Failed to run DSL query. Error {e}"
result = "false"
status = EXECUTION_STATE_FAILED

siemplify.LOGGER.error(output_message)
siemplify.LOGGER.exception(e)

siemplify.end(output_message, result, status)


if __name__ == "__main__":
main()
Loading
Loading