Details
| ID | GraphQL |
|---|---|
| Provider | Open Source |
| Category | Utilities |
| From Version | 5.0.0 |
| Docker Image | demisto/graphql:1.0.0.10120494 |
| Supported Modules | Agentix XSIAM |
README
Generic GraphQL client to interact with any GraphQL server API.
Configure GraphQL in Cortex
| Parameter | Description | Required |
|---|---|---|
| url | GraphQL Server URL (e.g. https://api.github.com/graphql) | True |
| credentials | Username / Header Name | False |
| fetch_schema_from_transport | Fetch the schema from the transport | False |
| insecure | Trust any certificate (not secure) | False |
| proxy | Use system proxy settings | False |
Authentication
The Username and Password integration parameters can be used to access server that require basic authentication.
These fields also support the use of API key headers. To use API key headers, specify the header name and value in the following format:
_header:<header_name> in the Username field, and the header value in the Password field.
For example, in order to use
GitHub GraphQL API, the parameters
should be set as follows:
- Username :
_header:Authorization - Password :
bearer <PERSONAL-ACCESS-TOKEN>
Commands
You can execute these commands from the 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.
graphql-query
Execute a query request to the GraphQL server.
Base Command
graphql-query
Input
| Argument Name | Description | Required |
|---|---|---|
| query | The GraphQL query to execute. | Required |
| variables_names | A comma-separated list of names, for example: flag,num,alpha | Optional |
| variables_values | A comma-separated list of values, for example: true,4,3.5 | Optional |
| variables_types | An optional comma-separated list of types, for example: boolean,number,number. Optional values are: string, boolean and number. If not provided, integers and booleans will be detected automatically, and the rest of the variables will be handled as strings. | Optional |
| max_result_size | Max result size in KBs. Default is 10. | Optional |
| populate_context_data | Whether to populate the result to the context data. Possible values are: true, false. Default is true. | Optional |
| outputs_key_field | Primary key field in the response to unique the object in the context data. | Optional |
Command Example
!graphql-query query="query($number_of_repos:Int!) {viewer {name repositories(last: $number_of_repos) { nodes { name } } } }" variables_names="number_of_repos" variables_values="3" variables_types="Int" max_result_size="10" populate_context_data="true"`
Context Example
{
"GraphQL": {
"viewer": {
"repositories": {
"nodes": [
{
"name": "content"
},
{
"name": "demisto-sdk"
},
{
"name": "content-docs"
}
]
}
}
}
}
Human Readable Output
GraphQL Query Results
viewer repositories: {“nodes”: [{“name”: “content”}, {“name”: “demisto-sdk”}, {“name”: “content-docs”}]}
graphql-mutation
Execute a mutation request to the GraphQL server.
Base Command
graphql-mutation
Input
| Argument Name | Description | Required |
|---|---|---|
| query | The GraphQL mutation to execute. | Required |
| variables_names | A comma-separated list of names, for example: flag,num,alpha | Optional |
| variables_values | A comma-separated list of values, for example: true,4,3.5 | Optional |
| variables_types | An optional comma-separated list of types, for example: boolean,number,number. Optional values are: string, boolean and number. If not provided, integers and booleans will be detected automatically, and the rest of the variables will be handled as strings. | Optional |
| max_result_size | Max result size in KBs. Default is 10. | Optional |
| populate_context_data | Whether to populate the result to the context data. Possible values are: true, false. Default is true. | Optional |
| outputs_key_field | Primary key field in the response to unique the object in the context data. | Optional |
Command Example
!graphql-mutation query="mutation AddReactionToIssue {addReaction(input:{subjectId:"MDU6SXNzdWUyMzEzOTE1NTE=",content:HOORAY}) {reaction {content} subject { id } } }" max_result_size="10" populate_context_data="true"`
Context Example
{
"GraphQL": {
"addReaction": {
"reaction": {
"content": "HORRAY"
},
"subject": {
"id": "MDU6SXNzdWUyMzEzOTE1NTE="
}
}
}
}
Human Readable Output
GraphQL Query Results
addReaction reaction: {“content”: “HOORAY”}
subject: {“id”: “MDU6SXNzdWUyMzEzOTE1NTE=”}
Troubleshooting
- If you are encountering the error
GraphQLError: Cannot query field, you may be failing because of a schema validation error. Uncheck the Fetch the schema from the transport integration parameter to disable the schema validation.
Configuration parameters
url— GraphQL Server URL (e.g., https://api.github.com/graphql) (required)credentials— Username / Header Namefetch_schema_from_transport— Fetch the schema from the transportinsecure— Trust any certificate (not secure)proxy— Use system proxy settings
Commands (2)
-
graphql-mutationExecutes a mutation request to the GraphQL server.
-
graphql-queryExecutes a query request to the GraphQL server.
from collections.abc import Callable from itertools import zip_longest import demistomock as demisto # noqa: F401 import urllib3 from CommonServerPython import * # noqa: F401 from gql import Client, gql from gql.transport.requests import RequestsHTTPTransport from CommonServerUserPython import * # Disable insecure warnings urllib3.disable_warnings() CAST_MAPPING: dict[str, Callable] = { "string": str, "boolean": bool, "number": arg_to_number, } def execute_query(client: Client, args: dict) -> CommandResults: query = gql(args["query"]) variables_names = argToList(args.get("variables_names", "")) variables_values = argToList(args.get("variables_values", "")) variables_types = argToList(args.get("variables_types", "")) if len(variables_names) != len(variables_values) or (variables_types and len(variables_types) != len(variables_values)): raise ValueError("The variable lists are not in the same length") variables = {} for variable_name, variable_value, variable_type in zip_longest(variables_names, variables_values, variables_types): if variable_type: variable_value = CAST_MAPPING[variable_type](variable_value) elif variable_value.isdigit(): variable_value = int(variable_value) elif variable_value.lower() in {"true", "false"}: variable_value = bool(variable_value) variables[variable_name] = variable_value result = client.execute(query, variable_values=variables) if (result_size := sys.getsizeof(result)) > (max_result_size := float(args.get("max_result_size", 10))) * 10000: raise ValueError(f"Result size {result_size / 10000} KBs is larger then max result size {max_result_size} KBs") command_results_args = { "readable_output": tableToMarkdown("GraphQL Query Results", result), "raw_response": result, "outputs": result if argToBoolean(args.get("populate_context_data")) else None, "outputs_prefix": "GraphQL", } if args.get("outputs_key_field"): command_results_args["outputs_key_field"] = args.get("outputs_key_field") return CommandResults(**command_results_args) def main() -> None: command = demisto.command() try: params = demisto.params() request_params = { "url": params.get("url"), "verify": not params.get("insecure", False), "retries": 3, } if credentials := params.get("credentials"): if (identifier := credentials.get("identifier", "")).startswith("_header:"): header_name = identifier.split("_header:")[1] header_value = credentials.get("password", "") request_params["headers"] = {header_name: header_value} else: request_params["auth"] = (identifier, credentials.get("password")) transport = RequestsHTTPTransport(**request_params) handle_proxy() fetch_schema_from_transport = params.get("fetch_schema_from_transport", True) if fetch_schema_from_transport is None: fetch_schema_from_transport = True client = Client( transport=transport, fetch_schema_from_transport=fetch_schema_from_transport, ) demisto.debug(f"Command being called is {command}") if command == "test-module": with client as session: if not fetch_schema_from_transport: # When schema fetching is disabled, the connection alone doesn't verify # the GraphQL endpoint. Execute an introspection query to confirm connectivity. session.execute(gql("{__typename}")) return_results("ok") elif command == "graphql-query": return_results(execute_query(client, demisto.args())) elif command == "graphql-mutation": return_results(execute_query(client, demisto.args())) else: raise NotImplementedError(f"Received an un-supported command: {command}") except Exception as e: return_error(f"Failed to execute {command} command. Error: {e!s}") if __name__ in ("__main__", "__builtin__", "builtins"): main()