Tanium Deprecated

Deprecated. Use Tanium v2 instead.

Endpoint · Tanium

Details

IDTanium
ProviderTanium
CategoryEndpoint
From Version5.0.0
Docker Imagedemisto/pytan:1.0.0.38590
Supported ModulesAgentix XSIAM

README

Use the Tanium integration to manage questions, packages, and actions.

This integration was integrated and tested with version 7.0.314 of Tanium v7.0.314 and Pytan v2.2.2.

Configure Tanium on Cortex XSOAR

  1. Navigate to Settings > Integrations > Servers & Services.
  2. Search for Tanium.
  3. Click Add instance to create and configure a new integration instance.
    • Name: a textual name for the integration instance.
    • Host URL (e.g. 1.2.3.4)
    • Port
    • Credentials
    • Use system proxy settings
    • 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.

Action Commands

  1. Parse question text: tn-ask-question
  2. Ask a question about an endpoint: tn-ask-system
  3. Create and ask a manual question: tn-ask-manual-question
  4. Deploy a package: tn-deploy-package
  5. Approve pending (saved) actions: tn-approve-pending-action
  6. Create a package object: tn-create-package

Information Commands

  1. Get sensor information: tn-get-sensor
  2. Get a package object: tn-get-package
  3. Get a saved question: tn-get-saved-question
  4. Get an object: tn-get-object
  5. Get all packages: tn-get-all-packages
  6. Get all saved questions: tn-get-all-saved-questions
  7. Get all saved actions: tn-get-all-saved-actions
  8. Get all pending actions: tn-get-all-pending-actions
  9. Get all objects: tn-get-all-objects

 Debug Commands

  1. Request the server to parse question text: tn-parse-query

Action Commands

1. Parse question text


Ask the server to parse the question text and select one of the parsed results as the question to run.

Base Command

tn-ask-question

Input
Argument Name Description Required
question The question text Required
index The index of the parsed question to be asked (as returned by the tn-parse-query command) Optional

 

Context Output
Path Type Description
Tanium.QuestionResults object Results of the requested question. Can be a complex object.
 
Command Example
  !tn-ask-question question="Get Computer Name from all machines"
Context Example
{
 Tanium: {
     QuestionResults:[{
        Computer Name: Demisto-Computer,
        Count:1
     }]
 }
}
Human Readable Output

Result for parsed query - Get Computer Name from all machines

Count Computer Name
1 Demisto-Computer

 

2. Ask a question about an endpoint


Ask a question about a specific endpoint.

Base Command

tn-ask-system

Input
Argument Name Description Required
hostname Name of host Required

 

Context Output
Path Type Description
Tanium.QuestionResults object Results of requested computer name. Can be a complex object.

 

Command Example
!tn-ask-system hostname="Demisto-Computer"
Context Example
{
 Tanium: {
     QuestionResults:[{
        Computer Name: Demisto-Computer,
        Count:1
     }]
 }
}
Human Readable Output

Result for parsed query - Get Computer Name from all machines

Count Computer Name
1 Demisto-Computer

 

3. Create and ask a manual question


Ask a manual question using human strings, and get the question results. Use the help argument for full details.

Base Command

tn-ask-manual-question

Input
Argument Name Description Required
sensors A semicolon-separated list of sensors (columns) to include in a question. For detailed information use  the tn-get-sensor command. Optional
question_filters A semicolon-separated list of filters that apply to the entire question Optional
question_options

A semicolon-separated list of options that apply to the entire question. Options are

  • ignore_case
  • match_case
  • match_any_value
  • match_all_values
  • max_data_age
  • value_type
  • and
  • or
Optional
filters_help Print the help string for filters and exit Optional
sensors_help Print the help string for sensors and exit Optional
options_help Print the help string for options and exit Optional
polling_secs Number of seconds to wait between result fetching attempts Optional
complete_pct Percentage of mr_tested out of estimated_total to consider the question Optional

 

Context Output
Path Type Description
Tanium.QuestionResults object Results of requested question. May be a complex object

 

Command Example
!tn-ask-manual-question sensors="Computer Name, opt:max_data_age:60" question_filters="Index Query File Exists{fileMagicNumber=10}, that contains:No;Computer Name, that contains:WIN"
Context Example
{
 Tanium: {
     QuestionResults:[{
        Computer Name: Demisto-Computer,
        Count:1
     }]
 }
}
Human Readable Output

Result for parsed query - Get Computer Name from all machines

Count Computer Name
1 Demisto-Computer

 

4. Deploy a package


Deploy a package and get the results.

Base Command

tn-deploy-package

Input
Argument Name Description Required
package Name of package to deploy with this action Required
action_filters A semicolon-separated list of strings. Each string must describe a sensor and a filter, which limits which computers the action will deploy package to, (e.g., Operating System, that contains:Windows; Computer Name, that contains:WIN) Optional
action_options A comma-separated list of options to apply to action_filters (e.g. "max_data_age:3600,and"). Default is or. Optional
get_results Specifies whether to wait for result completion after deploying action Optional
package_args A comma-separated list of arguments needed to execute the package command. Run the tn-get-package command to view a detailed list of arguments. Optional
action_filters_groups A comma-separated list of computer group names to filter by Optional
action_group Name of action group Optional

 

Context Output
Path Type Description
Tanium.SavedActions.Id string Saved action ID
Tanium.SavedActions.Name string Saved action name

 

Command Example
!tn-deploy-package package="Comply - Remove Selected Hashes - Unix" package_args=hash1
Context Example
Tanium:{
 SavedActions:[{
  Id:1050
  Name:API Deploy Comply - Remove Selected Hashes - Unix
 }]
}
Human Readable Output

Id of saved action is 1050

 

5. Approve pending (saved) actions


Approve saved actions.

Base Command

tn-approve-pending-action

Input
Argument Name Description Required
action_id ID of the saved action to approve Required

 

Context Output
Path Type Description
Tanium.ActionApproval.ApprovedFlag boolean Approval status
Tanium.ActionApproval.Id string Saved action ID
Tanium.ActionApproval.Name string Saved action name

 

Command Example
!tn-approve-pending-action id=1050
Context Example
Tanium:{
 ActionApproval:[{
  ApprovedFlag:1
  Id:1050
  Name:API Deploy Comply - Remove Selected Hashes - Unix
 }]
}
Human Readable Output

Action Approval

ApprovedFlag Id Name
1 1050 API Deploy Comply - Remove Selected Hashes - Unix

 

6. Create a package object


Create a package object.

Base Command

tn-create-package

Input
Argument Name Description Required
name Name of package to create Required
command Command to execute Required
display_name Display name of package Optional
file_urls A comma-separated list of URLs of files to add to the package Optional
command_timeout_seconds Timeout for command execution (in seconds) Optional
expire_seconds Timeout for action expiry (in seconds) Optional

 

Context Output
Path Type Description
Tanium.Packages.verify_expire_seconds string Timeout for verifying the action expiry (in seconds)
Tanium.Packages.display_name string Display name of package
Tanium.Packages.name string Name of created package
Tanium.Packages.command string Command to execute
Tanium.Packages.creation_time date Package creation time
Tanium.Packages.command_timeout number Timeout for command execution (in seconds)
Tanium.Packages.modification_time date Package modification time
Tanium.Packages.last_update date Time when package was last updated
Tanium.Packages.deleted_flag boolean Was the package deleted
Tanium.Packages.id string Tanium unique package ID
Tanium.Packages.expire_seconds number Timeout for action expiry (in seconds)

 

Command Example
!tn-create-package command="cmd /c echo $1" name=ExamplePackage display_name="Example Package"
Context Example
Tanium:{
 Packages:[{
  skip_lock_flag:0
  hidden_flag:0
  verify_group_id:0
  available_time:2001-01-01T00:00:00
  last_modified_by:Shani
  verify_expire_seconds:3600
  display_name:Echo
  name:EchoPackage
  command:cmd /c echo $1
  creation_time:2018-08-23T15:22:54
  command_timeout:600
  modification_time:2018-08-23T15:22:54
  last_update:2018-08-23T15:22:54
  deleted_flag:0
  _type:package_spec
  verify_group:{}
  _type:group
  id:0
  id:771
  expire_seconds:600
  source_id:0
 }]
}
Human Readable Output

Tanium Package

id name creation_time command
772 EchoPackage 2018-08-23T15:22:54 cmd /c echo $1

 

Information Commands

1. Get sensor information


Get detailed information about a specified sensor.

Base Command

tn-get-sensor

Input
Argument Name Description Required
name Name of the sensor Required

 

Context Output
Path Type Description
Tanium.Sensors.max_age_seconds number Sensor maximum age (in seconds)
Tanium.Sensors.description string Description of the sensor
Tanium.Sensors.name string Name of the sensor
Tanium.Sensors.id string ID of the sensor

 

Command Example
!tn-get-sensor name="Index Query File Exists"
Context Example
Tanium:{
 Sensors:[{
  hidden_flag:0
  string_count:6
  max_age_seconds:86400
  queries:{
   _type:queries
   query:[{
    _type:query
    platform:Windows
    script:select CSName from win32_operatingsystem
    script_type:WMIQuery
   }]
  }
  exclude_from_parse_flag:0
  value_type:String
  name:Computer Name
  ignore_case_flag:1
  _type:sensor
  id:3
  description:The assigned name of the client machine. Example: workstation-1.company.com
  category:Reserved
  source_id:0
 }]
}
Human Readable Output

Tanium Sensor - Index Query File Exists

id name category description max_age_seconds
706 Index Query File Exists Index Returns Yes or No, using Index to determine whether specified file exists based on the supplied input 900

 

Sensor Parameters Details

Key Name Values Description Type
directoryPath Directory Path Any value Glob of directory name used for searching,e.g. Windows TextInputParameter
fileName File Name Any value Glob of file name used for searching, e.g. *exe TextInputParameter

 

2. Get a package object


Get a package object by name or ID.

Base Command

tn-get-package

Input
Argument Name Description Required
name Name of package Optional
id Tanium ID of package (use instead of name) Optional

 

Context Output
Path Type Description
Tanium.Packages.verify_expire_seconds number Timeout for verifying action (in seconds)
Tanium.Packages.display_name string Display name of package
Tanium.Packages.name string Name of created package
Tanium.Packages.command string Command to execute
Tanium.Packages.creation_time date Package creation time
Tanium.Packages.command_timeout number Timeout for command execution (in seconds)
Tanium.Packages.modification_time date Package modification time
Tanium.Packages.last_modified_by string User who last modified packge
Tanium.Packages.last_update date Time when package was last updated
Tanium.Packages.deleted_flag boolean Was the package deleted
Tanium.Packages.id string Tanium unique package ID
Tanium.Packages.expire_seconds number Timeout for action (in seconds)
Tanium.Packages.files object Package files

 

Command Example
!tn-get-package name="Set Mac Tanium Client Logging Level"
Context Example
Tanium:{
 Packages:[{
  skip_lock_flag:0
  hidden_flag:0
  verify_group_id:0
  available_time:2016-04-06T13:03:12
  last_modified_by:Administrator
  verify_expire_seconds:600
  display_name:Set Mac Tanium Client Logging Level
  parameter_definition:{"parameters":[{"maximum":99,"key":"$1","stepSize":1,"label":"Log Level (0-99)","helpString":"Enter a logging level, 0=no logging, 99=verbose logging","snapInterval":1,"defaultValue":"1","minimum":0,"value":"1","parameterType":"com.tanium.components.parameters::NumericParameter","model":"com.tanium.components.parameters::NumericParameter"}],"parameterType":"com.tanium.components.parameters::ParametersArray","model":"com.tanium.components.parameters::ParametersArray"}
  name:Set Mac Tanium Client Logging Level
  command:/bin/sh set-log-level-parameterized.sh $1
  creation_time:2018-01-10T18:37:56
  command_timeout:900
  modification_time:2018-01-10T18:37:56
  last_update:2018-01-10T18:37:56
  deleted_flag:0
  files:{}
  _type:package_spec
  verify_group:{}
  _type:group
  id:0
  id:50
  expire_seconds:1500
  source_id:0
 }]
}
Human Readable Output

Tanium Package

id name creation_time command last_modified_by
50 Set Mac Tanium Client Logging Level 2018-01-10T18:37:56 /bin/sh set-log-level-parameterized.sh $1 Administrator

 

Package Arguments Details

Key Name Values Description Type
$1 Log Level (0-99) Any value Enter a logging level, 0=no logging, 99=verbose logging NumericParameter

 

3. Get a saved question


Get a saved question by name or ID.

Base Command

tn-get-saved-question

Input
Argument Name Description Required
name Name of saved question Optional
id Tanium unique id of saved question to be used instead of name Optional

 

Context Output
Path Type Description
Tanium.SavedQuestions.query_text string Question query text
Tanium.SavedQuestions.mod_time date Question modification time
Tanium.SavedQuestions.user.id string Unique ID of user who saved question
Tanium.SavedQuestions.user.name string Name of user who saved question
Tanium.SavedQuestions.name string Name of saved question
Tanium.SavedQuestions.expire_seconds number Question expiration time (in seconds)
Tanium.SavedQuestions.id string Unique ID of the saved question
Tanium.SavedQuestions.issue_seconds number Issue time (in seconds)

 

Command Example
!tn-get-saved-question id=132
Context Example
Tanium:{
 SavedQuestions:[{
  row_count_flag:0
  hidden_flag:0
  public_flag:1
  query_text:Get Is Virtual and Chassis Type from all machines
  issue_seconds_never_flag:0
  keep_seconds:0
  question:{}
  archive_enabled_flag:0
  mod_user:{}
  mod_time:2018-01-10T18:38:00
  action_tracking_flag:0
  name:Virtualized / Physical Chassis
  user: {}
  most_recent_question_id:519303
  packages:{}
  archive_owner:{}
  sort_column:0
  _type:saved_question
  issue_seconds:120
  id:182
  cache_row_id:68
  expire_seconds:600
 }]
}
Human Readable Output

Tanium Saved Question

query_text name id
Get Computer Name and Operating System from all machines with Action Lock Status containing "Action Lock On" Clients That Cannot Take Actions - Action Lock On 132

 

4. Get an object


Send a generic get object request.

Base Command

tn-get-object

Input
Argument Name Description Required
name Name of object Optional
id Tanium ID of the object (use instead of name) Optional
object_type Type of object to get Required

 

Context Output

There is no context output for this command.

Command Example
!tn-get-object object_type=sensor name="Computer Name"
Human Readable Output
{
    "_type": "sensors",
    "sensor": [
        {
            "_type": "sensor",
            "category": "Reserved",
            "description": "The assigned name of the client machine.\nExample: workstation-1.company.com",
            "exclude_from_parse_flag": 0,
            "hash": 3409330187,
            "hidden_flag": 0,
            "id": 3,
            "ignore_case_flag": 1,
            "max_age_seconds": 86400,
            "name": "Computer Name",
            "queries": {},
            "source_id": 0,
            "string_count": 6,
            "value_type": "String"
        }
    ]
}

 

5. Get all packages


Get all Tanium package objects

Base Command

tn-get-all-packages

Input

There is no input for this command.

Context Output
Path Type Description
Tanium.Packages.verify_expire_seconds number Timeout for verifying the action (in seconds)
Tanium.Packages.display_name string Display name of package
Tanium.Packages.name string Name of created package
Tanium.Packages.command string Command to execute
Tanium.Packages.creation_time date Package creation time
Tanium.Packages.command_timeout number Timeout for command execution (in seconds)
Tanium.Packages.modification_time date Package modification time
Tanium.Packages.last_modified_by string User who last modified packge
Tanium.Packages.last_update date Time when package was last updated
Tanium.Packages.deleted_flag boolean Is the package deleted
Tanium.Packages.id string Tanium unique package ID
Tanium.Packages.expire_seconds number Timeout for the action (in seconds)
Tanium.Packages.files unknown Package files

 

Command Example
!tn-get-all-packages
Context Example
Tanium:{
 Packages:[{
  skip_lock_flag:0
  hidden_flag:0
  verify_group_id:0
  available_time:2016-04-06T13:03:12
  last_modified_by:Administrator
  verify_expire_seconds:600
  display_name:Set Mac Tanium Client Logging Level
  parameter_definition:{"parameters":[{"maximum":99,"key":"$1","stepSize":1,"label":"Log Level (0-99)","helpString":"Enter a logging level, 0=no logging, 99=verbose logging","snapInterval":1,"defaultValue":"1","minimum":0,"value":"1","parameterType":"com.tanium.components.parameters::NumericParameter","model":"com.tanium.components.parameters::NumericParameter"}],"parameterType":"com.tanium.components.parameters::ParametersArray","model":"com.tanium.components.parameters::ParametersArray"}
  name:Set Mac Tanium Client Logging Level
  command:/bin/sh set-log-level-parameterized.sh $1
  creation_time:2018-01-10T18:37:56
  command_timeout:900
  modification_time:2018-01-10T18:37:56
  last_update:2018-01-10T18:37:56
  deleted_flag:0
  files:{}
  _type:package_spec
  verify_group:{}
  _type:group
  id:0
  id:50
  expire_seconds:1500
  source_id:0
 }]
}
Human Readable Output

Tanium Packages

id name creation_time command last_modified_by
734 Detect Intel for Windows 2001-01-01T00:00:00 cmd /c cscript /nologo run-add-intel-package.vbs 2>&1  
672 Remove Tanium Trace Tools [Mac-Linux] 2018-08-21T10:57:13 /bin/bash remove_tanium_trace_tools.sh Administrator

 

6. Get all saved questions


Gets all saved questions.

Base Command

tn-get-all-saved-questions

Input

There are no inputs for this command.

Context Output
Path Type Description
Tanium.SavedQuestions.query_text string Question query text
Tanium.SavedQuestions.mod_time date Question modification time
Tanium.SavedQuestions.user.id string Unique ID of the user who saved question
Tanium.SavedQuestions.user.name string Name of the user who saved question
Tanium.SavedQuestions.name string Name of saved question
Tanium.SavedQuestions.expire_seconds number Question expiration time (in seconds)
Tanium.SavedQuestions.id string Unique ID of the saved question
Tanium.SavedQuestions.issue_seconds number Issue time (in seconds)

 

Command Example
!tn-get-all-saved-questions
Context Example
Tanium:{
 SavedQuestions:[{
  row_count_flag:0
  hidden_flag:0
  public_flag:1
  query_text:Get Is Virtual and Chassis Type from all machines
  issue_seconds_never_flag:0
  keep_seconds:0
  question:{}
  archive_enabled_flag:0
  mod_user:{}
  mod_time:2018-01-10T18:38:00
  action_tracking_flag:0
  name:Virtualized / Physical Chassis
  user: {}
  most_recent_question_id:519303
  packages:{}
  archive_owner:{}
  sort_column:0
  _type:saved_question
  issue_seconds:120
  id:182
  cache_row_id:68
  expire_seconds:600
 }]
}
Human Readable Output

Tanium Saved Questions

query_text name id
Get Is Virtual and Chassis Type from all machines Virtualized / Physical Chassis 182
Get Installed Applications starting with "adobe reader" from all machines Adobe Reader Versions 197

 

7. Get all saved actions


Gets all saved actions.

Base Command

tn-get-all-saved-actions

Input

There is no input for this command.

Context Output
Path Type Description
Tanium.SavedActions.distribute_seconds number Distribute seconds of action
Tanium.SavedActions.public_flag boolean Whether action is public or not
Tanium.SavedActions.action_group_id string Group ID of action
Tanium.SavedActions.approver.id string ID of the user who approved the action
Tanium.SavedActions.start_time date Action start time
Tanium.SavedActions.name string Action name
Tanium.SavedActions.user.id string ID of the user who created the action
Tanium.SavedActions.creation_time date Time the action was created
Tanium.SavedActions.end_time date Time the action ended
Tanium.SavedActions.status string Action status
Tanium.SavedActions.last_start_time date Last time action started
Tanium.SavedActions.id string ID of action
Tanium.SavedActions.package_spec.id string The package associated with the action
Tanium.SavedActions.approved_flag boolean Whether action was approved or not

 

Command Example
!tn-get-all-saved-actions
Context Example
Tanium:{
 SavedActions:[{
  distribute_seconds:0
  public_flag:0
  action_group_id:0
  approver:{}
  issue_count:0
  start_time:2001-01-01T00:00:00
  name:Unscheduled - Clean Stale Tanium Client Data
  user:{}
  creation_time:2016-08-10T07:12:58
  metadata:{}
  target_group:{}
  end_time:Never
  status:1
  last_start_time:Never
  package_spec:{}
  approved_flag:1
  next_start_time:Never
  _type:saved_action
  issue_seconds:0
  policy_flag:0
  id:94
  cache_row_id:1
  user_start_time:2016-08-10T07:13:00
  expire_seconds:1800
  last_action:{}
 }]
}
Human Readable Output

Tanium Saved Actions

id name creation_time action_group_id approved_flag
914 API Deploy USB Write Protect - Set to On 2018-08-17T01:59:31 0 0
939 Start Tanium Trace Session 2018-08-21T07:00:52 2334 0

 

8. Get all pending actions


Gets all pending actions.

Base Command

tn-get-all-pending-actions

Input

There is no input for this command.

Context Output
Path Type Description
Tanium.PendingActions.distribute_seconds number Distribute seconds of action
Tanium.PendingActions.public_flag boolean Whether action is public or not
Tanium.PendingActions.action_group_id string Group ID of action
Tanium.PendingActions.approver.id string ID of the user who approved the action
Tanium.PendingActions.start_time date Action start time
Tanium.PendingActions.name string Action name
Tanium.PendingActions.user.id string

ID of the user who created the action

Tanium.PendingActions.creation_time date Time the action was created
Tanium.PendingActions.end_time date Time the action ended
Tanium.PendingActions.status string Action status
Tanium.PendingActions.last_start_time date Last time action started
Tanium.PendingActions.id string ID of the action
Tanium.PendingActions.package_spec.id string The package associated with the action
Tanium.PendingActions.approved_flag boolean Whether the action was approved

 

Command Example
!tn-get-all-pending-actions
Context Example
Tanium:{
 PendingActions:[{
  distribute_seconds:0
  public_flag:0
  action_group_id:0
  approver:{}
  issue_count:0
  start_time:2001-01-01T00:00:00
  name:Unscheduled - Clean Stale Tanium Client Data
  user:{}
  creation_time:2016-08-10T07:12:58
  metadata:{}
  target_group:{}
  end_time:Never
  status:1
  last_start_time:Never
  package_spec:{}
  approved_flag:1
  next_start_time:Never
  _type:saved_action
  issue_seconds:0
  policy_flag:0
  id:94
  cache_row_id:1
  user_start_time:2016-08-10T07:13:00
  expire_seconds:1800
  last_action:{}
 }]
}
Human Readable Output

Tanium Pending Actions

id name creation_time action_group_id approved_flag
914 API Deploy USB Write Protect - Set to On 2018-08-17T01:59:31 0 0
939 Start Tanium Trace Session 2018-08-21T07:00:52 2334 0

 

9. Get all objects


Gets all objects of the specified type.

Base Command

tn-get-all-objects

Input
Argument Name Description Required
object_type Type of object to get Required

 

Context Output

There is no context output for this command.

Command Example
!tn-get-all-objects object_type=package
Human Readable Output
{
    "_type": "sensors",
    "sensor": [
        {
            "_type": "sensor",
            "category": "Reserved",
            "description": "The assigned name of the client machine.\nExample: workstation-1.company.com",
            "exclude_from_parse_flag": 0,
            "hash": 3409330187,
            "hidden_flag": 0,
            "id": 3,
            "ignore_case_flag": 1,
            "max_age_seconds": 86400,
            "name": "Computer Name",
            "queries": {},
            "source_id": 0,
            "string_count": 6,
            "value_type": "String"
        }
    ]
}

 

tn-get-all-sensors


Gets all sensors

Base Command

tn-get-all-sensors

Input

There are no input arguments for this command.

Context Output

There is no context output for this command.

tn-get-action


Get detailed information about a given action.

Base Command

tn-get-action

Input

Argument Name Description Required
id ID of action of retrieve. Optional

Context Output

Path Type Description
Tanium.Actions.name string Name of the actions
Tanium.Actions.id number ID of the action
Tanium.Actions.status string Status of the action - Closed, Pending, etc.
Tanium.Actions.start_time date Time when the action started running
Tanium.Actions.approver.name string Name of Tanium user who approved the action
Tanium.Actions.creation_time date Time when the action was created
Tanium.Actions.package_spec.command string The command that is issued by the action
Tanium.Actions.package_spec.name string Name of the package that was deployed

Debug Commands

1. Request the server to parse question text


Ask the server to parse the question text and return all parsing options.

Base Command

tn-parse-query

Input
Argument Name Description Required
question The question text to be parsed Optional

 

Context Output

There is no context output for this command.

Command Example
!tn-parse-query question="get computer name"
Human Readable Output

Tanium Questions

index question
1 Get Computer Name from all machines
2 Get Computer ID from all machines
3 Get Computer ID containing "name" from all machines

Configuration parameters

  • host — Host URL (e.g. 1.2.3.4) (required)
  • port — Port (required)
  • credentials — Credentials (required)
  • proxy — Use system proxy settings

Commands (18)

  • tn-approve-pending-action

    Approve saved actions

  • tn-ask-manual-question

    Ask a manual question using human strings and get the results back

  • tn-ask-question

    Ask the server to parse the question text and choose the first parsed result as the question to run

  • tn-ask-system

    Ask a question about a specific endpoint

  • tn-create-package

    Create a package object

  • tn-deploy-package

    Deploy a package and get the results back

  • tn-get-action

    Get detailed information about a given action.

  • tn-get-all-objects

    Gets all objects of the specified type

  • tn-get-all-packages

    Get all Tanium package objects

  • tn-get-all-pending-actions

    Gets all pending actions

  • tn-get-all-saved-actions

    Gets all saved actions

  • tn-get-all-saved-questions

    Gets all saved questions

  • tn-get-all-sensors

    Gets all sensors

  • tn-get-object

    Send a generic Get Object request

  • tn-get-package

    Get a package object based on name or ID.

  • tn-get-saved-question

    Get a saved question by name or id

  • tn-get-sensor

    Get detailed information about a given sensor.

  • tn-parse-query

    Ask the server to parse the question text and return all parsing options

from CommonServerPython import *
from CommonServerUserPython import *
import json
import os
import sys

from cStringIO import StringIO

handle_proxy(demisto.params().get('proxy'))

response = ''

# disable python from generating a .pyc file
sys.dont_write_bytecode = True

# change me to the path of pytan
pytan_loc = "/pytan-2.2.2"
pytan_static_path = os.path.join(os.path.expanduser(pytan_loc), 'lib')

# Determine our script name, script dir
my_file = os.path.abspath(sys.argv[0])
my_dir = os.path.dirname(my_file)

# try to automatically determine the pytan lib directory by assuming it is in '../../lib/'
parent_dir = os.path.dirname(my_dir)
pytan_root_dir = os.path.dirname(parent_dir)
lib_dir = os.path.join(pytan_root_dir, 'lib')

# add pytan_loc and lib_dir to the PYTHONPATH variable
path_adds = [lib_dir, pytan_static_path]
[sys.path.append(aa) for aa in path_adds if aa not in sys.path]  # type: ignore

try:
    import pytan
    import pytan.binsupport
    import taniumpy
except Exception:
    raise


def raw_response_to_json(raw_json):
    result = []
    for row_dict in raw_json:
        row_key = row_dict.keys()[0]
        parsed_row_dict = {}
        for cell in row_dict[row_key]:
            column_name = cell.get('column.display_name')
            cell_value = cell.get('column.values')
            cell_value_without_none = []

            for value in cell_value:
                if value is not None:
                    cell_value_without_none.append(value)

            if len(cell_value_without_none) > 0:
                cell_value = '\n'.join(cell_value_without_none)

            else:
                cell_value = None

            parsed_row_dict[column_name] = cell_value

        result.append(parsed_row_dict)

    return result


def parseToJson(handler, response):
    LOG("exporting tanium response")
    export_kwargs = {}
    export_kwargs['obj'] = response
    export_kwargs['export_format'] = 'json'
    out = handler.export_obj(**export_kwargs)
    return json.loads(out)


def create_error_entry(contents):
    return {
        'ContentsFormat': formats['text'],
        'Type': entryTypes['error'],
        'Contents': "Error - " + contents
    }


def create_entry(header, table, context={}, headers=None):
    return {
        'ContentsFormat': formats['json'],
        'Type': entryTypes['note'],
        'Contents': table,
        'ReadableContentsFormat': formats['markdown'],
        'HumanReadable': tableToMarkdown(header, table,
                                         headers) if table else '### ' + header + '\nNo results were found',
        'EntryContext': context
    }


def filter_list(lst, keys):
    res = []
    for i in range(len(lst)):
        tmp = {}
        for key in keys:
            tmp[key] = lst[i].get(key)
        res.append(tmp)
    return res


def get_handler():
    handler_args = {}

    handler_args['username'] = demisto.params().get('credentials', {}).get('identifier')
    handler_args['password'] = demisto.params().get('credentials', {}).get('password')
    handler_args['host'] = demisto.params().get('host')
    handler_args['port'] = demisto.params().get('port')

    handler_args['loglevel'] = 1
    handler_args['debugformat'] = False
    handler_args['record_all_requests'] = True

    return pytan.Handler(**handler_args)


def get_all_objects(handler, objtype):
    LOG("getting all tanium objects of type %s" % objtype)
    kwargs = {}
    kwargs["objtype"] = objtype
    response = handler.get_all(**kwargs)
    return parseToJson(handler, response)


def get_all_objects_with_entry(handler, objtype):
    response = get_all_objects(handler, unicode(objtype))
    parsed = response[objtype]
    return create_entry('Tanium ' + objtype + 's', parsed)


def get_all_sensors(handler):
    response = get_all_objects(handler, u'sensor')
    parsed = response.get('sensor')
    return create_entry('Tanium Sensors', parsed, {'Tanium.Sensors': parsed})


def get_all_saved_actions(handler):
    response = get_all_objects(handler, u'saved_action')
    parsed = response.get('saved_action')
    return create_entry('Tanium Saved Actions', parsed, {'Tanium.SavedActions': parsed},
                        ['id', 'name', 'creation_time', 'action_group_id', 'approved_flag'])


def getAllPendingActions(handler):
    response = get_all_objects(handler, u'saved_action')
    parsed = response.get('saved_action')
    filterNonPending = filter(lambda x: x['approved_flag'] == 0, parsed)
    return create_entry('Tanium Pending Actions', filterNonPending, {'Tanium.PendingActions': filterNonPending},
                        ['id', 'name', 'creation_time', 'action_group_id', 'approved_flag'])


def getAllPackages(handler):
    response = get_all_objects(handler, u'package')
    parsed = response.get('package_spec')
    return create_entry('Tanium Packages', parsed, {'Tanium.Packages': parsed},
                        ['id', 'name', 'creation_time', 'command', 'last_modified_by'])


def get_all_saved_questions(handler):
    response = get_all_objects(handler, u'saved_question')
    parsed = response.get('saved_question')
    return create_entry('Tanium Saved Questions', parsed, {'Tanium.SavedQuestions': parsed},
                        ['query_text', 'name', 'id'])


def get_object(handler, objtype, name=None, id=None):
    LOG("getting Tanium %s - %s" % (objtype, name if name is not None else id))
    kwargs = {}
    kwargs["objtype"] = objtype
    kwargs["id"] = id
    kwargs["name"] = name

    response = handler.get(**kwargs)
    return parseToJson(handler, response)


def parameter_table_builder(data, header, object_type):
    if not data.get('parameter_definition'):
        return 'No arguments needed for this ' + object_type
    param_data = json.loads(data['parameter_definition']).get('parameters', [])
    parsed_params = []
    parsed_param = {}
    for param in param_data:
        parsed_param['Description'] = param.get('helpString', 'No description')
        parsed_param['Name'] = param.get('label', 'No argument name')
        parsed_param['Values'] = ','.join(param['values']) if param.get('values') else 'Any value'
        parsed_param['Key'] = param.get('key', 'No key')
        parsed_param['Type'] = param['parameterType'].split('::')[-1] if param.get(
            'parameterType') else 'Type not specified'
        parsed_params.append(parsed_param)
        parsed_param = {}
    data['parameters'] = parsed_params
    del data['parameter_definition']
    return tableToMarkdown(header, parsed_params, ['Key', 'Name', 'Values', 'Description', 'Type'])


def get_sensor_variable(parsed):
    if len(parsed) > 0 and parsed[0].get('command'):
        command = parsed[0].get('command')
        if command:
            idx1 = command.find("||")
            if idx1 > -1:
                idx2 = command.find("||", idx1 + 2)
                if idx2 > -1:
                    return command[idx1:idx2 + 2]
    return None


def get_package(handler):
    response = get_object(handler, u'package', demisto.args().get('name'), demisto.args().get('id'))
    parsed = response.get('package_spec')
    sensor_var = get_sensor_variable(parsed)
    res = parsed[0]
    res['sensor_variable'] = sensor_var
    parameters = parameter_table_builder(res, 'Package Arguments Details', 'package')
    final_result = create_entry(
        'Tanium Package',
        res,
        {'Tanium.Packages(val.id && val.id == obj.id)': filter_list([res], ['name', 'id', 'display_name', 'command',
                                                                            'command_timeout', 'deleted_flag', 'files',
                                                                            'parameters', 'sensor_variable'])},
        ['id', 'name', 'creation_time', 'command', 'last_modified_by']
    )
    final_result['HumanReadable'] += parameters
    if sensor_var is not None:
        final_result['HumanReadable'] += '\n### Sensor Variables Type\n' + sensor_var
    return final_result


def get_saved_question(handler):
    response = get_object(handler, u'saved_question', demisto.args().get('name'), demisto.args().get('id'))
    parsed = response.get('saved_question')
    return create_entry(
        'Tanium Saved Question',
        parsed,
        {'Tanium.SavedQuestions(val.id && val.id == obj.id)': filter_list(parsed,
                                                                          ['query_text', 'mod_time', 'user', 'name',
                                                                           'expire_seconds', 'id', 'issue_seconds'])},
        ['query_text', 'name', 'id']
    )


def get_sensor(handler):
    response = get_object(handler, u'sensor', demisto.args().get('name'), demisto.args().get('id'))
    parsed = response.get('sensor', None)
    parameters = parameter_table_builder(parsed[0], 'Sensor Parameters Details', 'sensor')
    final_result = create_entry(
        'Tanium Sensor - ' + demisto.args()['name'],
        parsed,
        {'Tanium.Sensors(val.id && val.id == obj.id)': filter_list(parsed,
                                                                   ['id', 'name', 'max_age_seconds', 'description',
                                                                    'parameters'])},
        ['id', 'name', 'category', 'description'])
    final_result['HumanReadable'] += '\n' + parameters
    return final_result


def get_action(handler):
    response = get_object(handler, u'action', demisto.args().get('name'), demisto.args().get('id'))
    parsed = response.get('action', None)
    if 'saved_action' in parsed[0]:
        parsed[0]['saved_action_id'] = parsed[0]['saved_action']['id']
        del parsed[0]['saved_action']

    return create_entry(
        'Tanium Action - ' + parsed[0]['name'],
        parsed,
        {'Tanium.Actions(val.id && val.id == obj.id)': filter_list(parsed,
                                                                   ['name', 'id', 'status', 'start_time', 'approver',
                                                                    'creation_time', 'package_spec'])},
        ['id', 'name', 'status', 'saved_action_id', 'stopped_flag'])


def handle_cgs(handler, obj, kwargs):
    """Example PreAddAction callback that modifies the target_group of an Action if computer group names are supplied.
    callbacks = {}
    callbacks["PreAddAction"] = handle_cgs
    deploy_action(package="blah", cg_names=["ip has 192.168", "has tanium app"], action_filters=["Computer Name, that
     contains:a"], callbacks=callbacks)
    """
    cgs = kwargs.get("cg_names", [])
    LOG("handling cgs %s" % cgs)
    cg_objs = [handler.get("group", name=x)[0] for x in cgs]
    cg_listobj = taniumpy.GroupList()
    [cg_listobj.append(x) for x in cg_objs]

    if cg_objs:
        tg_obj = taniumpy.Group()
        tg_obj.sub_groups = cg_listobj
        tg_obj.and_flag = 0
        if obj.target_group is not None:
            tg_obj.sub_groups.append(obj.target_group)
        obj.target_group = tg_obj
    return obj


def parse_deploy_action_raw_resp(handler, response):
    saved_action_object = response.get('saved_action_object')
    action_object = response.get('action_object')
    package_object = response.get('package_object')

    return {
        'saved_action_object': parseToJson(handler, saved_action_object),
        'action_object': parseToJson(handler, action_object),
        'package_object': parseToJson(handler, package_object)
    }


def deploy_action(handler):
    kwargs = {}
    kwargs["run"] = True

    for key, value in demisto.args().items():
        kwargs[key] = value

    kwargs["get_results"] = True if str(kwargs.get('get_results', '')).lower() == 'true' else False

    callbacks = {}
    callbacks['PreAddAction'] = handle_cgs
    kwargs['callbacks'] = callbacks  # type: ignore
    kwargs['action_options'] = ['or']  # type: ignore
    if demisto.get(demisto.args(), 'action_options'):
        kwargs['action_options'] = demisto.args()['action_options'].split(',')
    if demisto.get(demisto.args(), 'action_filters'):
        kwargs['action_filters'] = demisto.args()['action_filters'].split(';')
    if demisto.get(demisto.args(), 'action_filters_groups'):
        kwargs['cg_names'] = demisto.args()['action_filters_groups'].split(',')

    # Building the package query
    package = demisto.args()['package']
    package_with_args = [package]

    formatted_args = ''
    if demisto.args().get('package_args'):
        package_args = demisto.args().get('package_args', '').split(",")
        for i in range(0, len(package_args)):
            formatted_args = formatted_args + '$' + str(i + 1) + '=' + package_args[i] + ','
        formatted_args = formatted_args[:-1]

    replace_str = get_sensor_variable(get_object(handler, u'package', package).get('package_spec'))
    sensor_var = demisto.args().get('sensor_variables')

    if replace_str is None and sensor_var:
        return create_error_entry("Package \"" + package + "\" does not have a sensor variable.")
    if replace_str and sensor_var is None:
        return create_error_entry("Package \"" + package + "\" requires a sensor variable.")

    if sensor_var:
        sensor_vars = demisto.args().get('sensor_variables', '').split(";")
        package_with_args = []
        if formatted_args != '':
            formatted_args += ','
        for var in sensor_vars:
            package_with_args.append(package + '{' + formatted_args + replace_str + '=' + var + '}')

    elif formatted_args != '':
        package_with_args = [package + '{' + formatted_args + '}']

    response = []
    for pack in package_with_args:
        kwargs['package'] = pack
        LOG("deploying Tanium package %s" % pack)
        response.append(handler.deploy_action(**kwargs))

    ec = {  # type: ignore
        'Tanium.SavedActions(val.Id && val.Id == obj.Id)': [],
        'Tanium.Actions(val.id && val.id == obj.id)': []
    }
    contents = []
    tbl = []

    for res in response:
        ec['Tanium.SavedActions(val.Id && val.Id == obj.Id)'].append({
            'Name': res['saved_action_object'].name,
            'Id': res['saved_action_object'].id
        })
        parsed = parse_deploy_action_raw_resp(handler, res)
        ec['Tanium.Actions(val.id && val.id == obj.id)'] += filter_list([parsed['action_object']],
                                                                        ['name', 'id', 'status', 'start_time',
                                                                         'approver', 'creation_time', 'package_spec'])
        contents.append(parsed)
        tbl.append({
            'Action ID': parsed['action_object']['id'],
            'Saved Action ID': parsed['saved_action_object']['id'],
            'Name': parsed['action_object']['name'],
            'Package Name': parsed['package_object']['name'],
            'Command': parsed['package_object']['command']
        })

    return {
        'ContentsFormat': formats['json'],
        'Type': entryTypes['note'],
        'Contents': contents,
        'ReadableContentsFormat': formats['markdown'],
        'HumanReadable': tableToMarkdown('Tanium Deployed Actions', tbl) if tbl else 'No results were found',
        'EntryContext': ec
    }


def approveSavedAction(handler, action_id, saved_action_id):
    LOG("approving saved action with id %s %s" % (action_id, saved_action_id))
    kwargs = {}
    if not saved_action_id and not action_id:
        raise Exception('Missing action ID')
    if not saved_action_id:
        action = get_object(handler, u'action', id=action_id)
        parsed = action.get('action', None)
        saved_action_id = parsed[0]['saved_action']['id']
    kwargs['id'] = saved_action_id
    response = handler.approve_saved_action(**kwargs)
    parsed = {'Id': response.id, 'Name': response.name, 'ApprovedFlag': response.approved_flag}
    final_result = create_entry('Action Approval', [parsed], {'Tanium.ActionApproval': parsed})
    return final_result


def format_context(res):
    """Reformat the response's multi-lined cells to look better in the context

    Args:
        res (list): a list of dictionaries formatted from the Tanium answer

    Returns:
        list. A list of dictionaries where multi-lined cells have spaces instead of line drops.
    """
    context = []
    for element in res:
        context.append({key: value.split('\n') if value and '\n' in value else value
                        for (key, value) in element.items()})

    return context


def askQuestion(handler, kwargs):
    response = handler.ask(**kwargs)

    if isinstance(response, str):
        return response

    query_text = response['question_object'].query_text
    if response.get('question_results'):
        export_kwargs = {}
        export_kwargs['obj'] = response['question_results']
        export_kwargs['export_format'] = 'json'
        LOG("exporting tanium question response")
        out = handler.export_obj(**export_kwargs)
        if out:
            result = raw_response_to_json(json.loads(out))

        else:
            result = []

        ec = {'Tanium.QuestionResults': format_context(result)}
        return create_entry(
            'Result for parsed query - %s' % (query_text,),
            result,
            ec)
    else:
        return 'Parsed query - %s\nNo results were found' % (query_text,)


def get_parse_query_options(handler, question):
    LOG("parsing query options")
    parse_job_results = handler.parse_query(question)
    jsonable = parse_job_results.to_jsonable()

    ans = jsonable["parse_result_group"]
    res = []
    i = 0
    while i < len(ans):
        res.append({"index": i + 1, "question": ans[i]["question_text"]})
        i = i + 1
    return create_entry('Tanium Questions', res, {}, ['index', 'question'])


def get_ask_manual_help():
    desc = '# Tanium Ask Manual Question - Help\n' + \
           'The _tn-ask-manual-question_ command corresponds directly with the Tanium Question Builder.\n' + \
           'Each command argument can be mapped to a field in the Tanium Question Builder.\n' + \
           '## Sensors\n---\n' + \
           'The _sensors_ argument correlates with the **"Get all ____ from..."** part of a the Tanium Question.\n' + \
           'All sensor types share the same filters and sensor options, but each sensor has its own parameters.\n' + \
           '\n' + \
           '**Example** (simple sensor list):\n' + \
           '`!tn-ask-manual-question sensors="Computer Name;IP Address"`\n' + \
           '### Sensor filters\n' + \
           'You can only apply a single filter to a sensor, and should be passed using this format:\n' + \
           '_<sensor1>,that <filter type>:<filter value>;<sensor2>,that <filter type>:<filter value>_\n' + \
           '\n' + \
           '**Example #1** (2 sensors, 2 filters):\n`!tn-ask-manual-question sensors="Computer Name,that starts with:' \
           'D;IP Address,that does not contain:192"`\n**Example #2** (2 sensors, 1 filter):\n' + \
           '`!tn-ask-manual-question sensors="Computer Name,that starts with:D;IP Address"`\n' + \
           '### Sensor parameters\n' + \
           'Each sensor has its own unique parameters. ' \
           'To get a complete list of sensor parameters, run the _!tn-get-sensor_ command.\n' + \
           'Parameters are passed in curly brackets, after the sensor name, and before the filter.\n' + \
           '**Example** (1 sensor, 1 filter, 1 parameter):\n' + \
           '`!tn-ask-manual-question sensors=' \
           '"Index Query File Exists{fileMD5Hash=4F83C01E8F7507D23C67AB085BF79E97},that contains:yes"`\n' + \
           '### Sensor options\n' + \
           'All sensors have the same options: _ignore_case_, _match_case_, _match_any_value_, _match_all_values_, ' \
           '_max_data_age_, _value_type_\nOptions are passed directly after filters.\n\n' \
           '**Example** (1 sensor, 1 filter, 1 parameter):\n' + \
           '`!tn-ask-manual-question sensors="Index Query File Exists{fileMD5Hash=4F83C01E8F7507D23C67AB085BF79E97},' \
           'that contains:yes,opt:match_all_values, opt:ignore_case, opt:max_data_age:3600"`\n' + \
           '## Question Filters\n---\n' + \
           'The _question_filters_ argument is a semicolon-separated list of sensors, with filters and parameters, ' \
           'that correlates to the **"... from all computers with ___"** part of a the Tanium Question.\n' + \
           'Question filters can have an ***and*** or an ***or*** relation. ' \
           'You set the relation by using the _question_options_ argument.\n\n' + \
           '**Example** (2 question filters):\n`!tn-ask-manual-question sensors="Computer Name" question_filters=' \
           '"Index Query File Exists{fileMD5Hash=4F83C01E8F7507D23C67AB085BF79E97},that contains:yes;' \
           'Index Query File Exists{fileMD5Hash=4F83C01E8F7507D23C67AB085BF79E98},that contains:yes"`\n\n' + \
           '## Question Options\n---\n' + \
           'Question options are a semicolon-separated list of options that apply to the entire question. They are ' \
           'generally used to define the relation of the different filter statements.\n' + \
           '**Example** (1 question option):\n`!tn-ask-manual-question sensors="Computer Name" question_options="or" ' \
           'question_filters="Index Query File Exists{' \
           'fileMD5Hash=4F83C01E8F7507D23C67AB085BF79E97},that contains:yes"`\n'
    return {
        'ContentsFormat': formats['markdown'],
        'Type': entryTypes['note'],
        'Contents': desc,
        'ReadableContentsFormat': formats['markdown'],
        'HumanReadable': desc
    }


def ask_manual_question(handler, args):
    if args.get('help') == 'True':
        return get_ask_manual_help()

    kwargs = {}
    kwargs["qtype"] = u'manual'
    kwargs["sensors_help"] = True if args.get('sensors_help') == 'True' else False  # type: ignore
    kwargs["filters_help"] = True if args.get('filters_help') == 'True' else False  # type: ignore
    kwargs["options_help"] = True if args.get('options_help') == 'True' else False  # type: ignore

    if kwargs["filters_help"] or kwargs["sensors_help"] or kwargs["options_help"]:
        try:
            response = handler.ask(**kwargs)
            # should always throw an exception
            return response
        except Exception as ex:
            return str(ex)

    kwargs["question_options"] = args.get('question_options', '').split(';') if args.get('question_options',
                                                                                         '') != '' else None
    kwargs["question_filters"] = args.get('question_filters', '').split(';') if args.get('question_filters',
                                                                                         '') != '' else None
    kwargs["sensors"] = args.get('sensors', '').split(';') if args.get('sensors', '') != '' else None
    kwargs["polling_secs"] = int(args.get('polling_secs', '5'))  # type: ignore
    kwargs["complete_pct"] = int(args.get('complete_pct', '99'))  # type: ignore

    LOG("asking Tanium question")
    return askQuestion(handler, kwargs)


def ask_parsed_question(handler, question, index):
    kwargs = {
        'picker': int(index),
        'question_text': question,
        'qtype': u'parsed',
        'get_results': True
    }

    LOG("asking Tanium question %s" % (question))
    return askQuestion(handler, kwargs)


def create_package(handler):
    kwargs = {}
    dArgs = demisto.args()
    for key, value in dArgs.items():
        kwargs[key] = value
    if demisto.get(dArgs, 'file_urls'):
        kwargs['file_urls'] = dArgs['file_urls'].split(",")
    LOG("creating Tanium package")
    response = handler.create_package(**kwargs)
    parsed = parseToJson(handler, response)
    final_result = create_entry('Tanium Package', [parsed], {'Tanium.Packages': parsed},
                                ['id', 'name', 'creation_time', 'command'])
    return final_result


def restore_sout_and_exit(final_result):
    sys.stdout = sout
    LOG.print_log()
    demisto.results(final_result)
    # kill this thread and any additional thread in existence in the docker
    os._exit(0)


# Dealing with Broken Pipe issues raised by some commands
sout = sys.stdout
sys.stdout = StringIO()


def main():
    try:
        handler = get_handler()
        LOG("successfully logged into Tanium")
        d_args = demisto.args()

        if demisto.command() == 'test-module':
            test_question = 'get Computer Name from all machines with Computer Name contains "this is a test"'
            final_result = ask_parsed_question(handler, test_question, '1')
            restore_sout_and_exit('ok')
        if demisto.command() == 'tn-get-package':
            final_result = get_package(handler)
        if demisto.command() == 'tn-get-saved-question':
            final_result = get_saved_question(handler)
        if demisto.command() == 'tn-get-object':
            final_result = get_object(handler, unicode(d_args['object_type']), d_args.get('name'), d_args.get('id'))
        if demisto.command() == 'tn-get-all-objects':
            final_result = get_all_objects(handler, unicode(d_args['object_type']))
        if demisto.command() == 'tn-get-all-packages':
            final_result = getAllPackages(handler)
        if demisto.command() == 'tn-get-all-sensors':
            final_result = get_all_sensors(handler)
        if demisto.command() == 'tn-get-all-saved-questions':
            final_result = get_all_saved_questions(handler)
        if demisto.command() == 'tn-get-all-saved-actions':
            final_result = get_all_saved_actions(handler)
        if demisto.command() == 'tn-get-all-pending-actions':
            final_result = getAllPendingActions(handler)
        if demisto.command() == 'tn-deploy-package':
            final_result = deploy_action(handler)
        if demisto.command() == 'tn-ask-system':
            final_result = ask_parsed_question(handler, 'Get Computer Name from all machines with Computer Name matching \"'
                                               + demisto.args()['hostname'] + '\"', '1')
        if demisto.command() == 'tn-ask-question':
            final_result = ask_parsed_question(handler, d_args['question'], d_args.get('index', '1'))
        if demisto.command() == 'tn-create-package':
            final_result = create_package(handler)
        if demisto.command() == 'tn-approve-pending-action':
            final_result = approveSavedAction(handler, d_args.get('id'),
                                              d_args.get('saved_action_id', d_args.get('action_id')))
        if demisto.command() == 'tn-ask-manual-question':
            final_result = ask_manual_question(handler, d_args)
        if demisto.command() == 'tn-parse-query':
            final_result = get_parse_query_options(handler, d_args['question'])
        if demisto.command() == 'tn-get-sensor':
            final_result = get_sensor(handler)
        if demisto.command() == 'tn-get-action':
            final_result = get_action(handler)

    except Exception:
        sys.stdout = sout
        LOG.print_log()
        raise

    restore_sout_and_exit(final_result)


# python2 uses __builtin__ python3 uses builtins
if __name__ == "__builtin__" or __name__ == "builtins" or __name__ == "__main__":
    main()