Skip to content

5.0.0

Compare
Choose a tag to compare
@gluemaker gluemaker released this 02 May 15:10
· 120 commits to master since this release
37222a8

5.0.0

Massive back-end library changes

Transitioning to a modular approach and minimizing package dependencies as much as possible.

The axonshell interface remains unchanged and although the Python library interface has changed in several places, the actual usage remains consistent and will still work the same way for now.

For a comprehensive list of changes to the Python library, see below the axonshell changes.

Bugfix: Logging in with credentials KeyError access_token

In this release, the issue related to logging in with credentials resulting in a KeyError for 'access_token' has been fixed.

The response from the REST API has changed, and the access_token must now be accessed from the response headers instead of the response body of the login endpoint.

Bugfix: Signup object has no attribute auth

In this release, the issue with the Signup object not having the 'auth' attribute has been addressed and fixed.

Users should no longer encounter this error, and the Signup object should now function as expected.

Bugfix: Multiple with datascopes

A bugfix has been implemented to address issues related to datascopes when adding a saved query.

Previously, when datascopes were enabled, the default folder for saving a new query was /Shared Queries.

However, with datascopes enabled, saving to this folder is no longer allowed.

To resolve this issue, the API client logic has been updated to set the default folder for saving queries to /Global instead of /Shared Queries when datascopes are enabled.

Axonshell Changes

New command group in axonshell enforcements for tasks

A new command group has been added to the axonshell enforcements command group for tasks.

Usage: axonshell enforcements tasks [OPTIONS] COMMAND [ARGS]...

  Group: Work with tasks ran by the Enforcement Center.

Options:
  --help  Show this message and exit.

Commands:
  count        Get Count of Enforcement Center Tasks matching filters.
  get          Get Enforcement Center Tasks matching filters.
  get-filters  Get valid values for filtering count or get of Enforcement...

axonshell enforcements tasks count

Usage: axonshell enforcements tasks count [OPTIONS]

  Get Count of Enforcement Center Tasks matching filters.

Options:
  -u, --url URL                   URL of an Axonius instance  [env var:
                                  AX_URL; required]
  -k, --key KEY                   API Key (or username if credentials=True) of
                                  user in an Axonius instance  [env var:
                                  AX_KEY; required]
  -s, --secret SECRET             API Secret (or password if credentials=True)
                                  of user in an Axonius instance  [env var:
                                  AX_SECRET; required]
  -at, --action-types TEXT        Only get tasks that were ran by types of
                                  actions (use re_prefix for pattern matching)
                                  (multiple)  [env var: AX_ACTION_TYPES]
  -ate, --action-types-error / -nate, --no-action-types-error
                                  Error if any action_types provided are not
                                  valid  [env var: AX_ACTION_TYPES_ERROR;
                                  default: action-types-error]
  -atm, --action-types-minimum INTEGER
                                  Error if matches for action_types are < this
                                  number  [env var: AX_ACTION_TYPES_MINIMUM]
  -df, --date-from TEXT           Only get tasks with creation date >= this
                                  date  [env var: AX_DATE_FROM]
  -dfa, --date-from-add TEXT      seconds to add to date_from (or now if
                                  date_from not provided)  [env var:
                                  AX_DATE_FROM_ADD]
  -dfs, --date-from-subtract TEXT
                                  seconds to subtract from date_from (or now
                                  if date_from not provided)  [env var:
                                  AX_DATE_FROM_SUBTRACT]
  -dt, --date-to TEXT             Only get tasks with creation date <= this
                                  date  [env var: AX_DATE_TO]
  -dta, --date-to-add TEXT        seconds to add to date_to (or now if date_to
                                  not provided)  [env var: AX_DATE_TO_ADD]
  -dts, --date-to-subtract TEXT   seconds to subtract from date_to (or now if
                                  date_to not provided)  [env var:
                                  AX_DATE_TO_SUBTRACT]
  -du, --discovery-uuids TEXT     Only get tasks that were ran by discovery
                                  UUIDs (use re_prefix for pattern matching)
                                  (multiple)  [env var: AX_DISCOVERY_UUIDS]
  -due, --discovery-uuids-error / -ndue, --no-discovery-uuids-error
                                  Error if any discovery_uuids provided are
                                  not valid  [env var:
                                  AX_DISCOVERY_UUIDS_ERROR; default:
                                  discovery-uuids-error]
  -dum, --discovery-uuids-minimum INTEGER
                                  Error if matches for discovery_uuids are <
                                  this number  [env var:
                                  AX_DISCOVERY_UUIDS_MINIMUM]
  -do, --duration-operator [equal|greater|less]
                                  Operator to evaluate the duration_seconds
                                  value against task run durations  [env var:
                                  AX_DURATION_OPERATOR; default: less]
  -ds, --duration-seconds INTEGER
                                  Only get tasks where run duration matches
                                  duration_operator  [env var:
                                  AX_DURATION_SECONDS]
  -en, --enforcement-names TEXT   Only get tasks that were ran by enforcement
                                  names (use re_prefix for pattern matching)
                                  (multiple)  [env var: AX_ENFORCEMENT_NAMES]
  -ene, --enforcement-names-error / -nene, --no-enforcement-names-error
                                  Error if any enforcement_names provided are
                                  not valid  [env var:
                                  AX_ENFORCEMENT_NAMES_ERROR; default:
                                  enforcement-names-error]
  -enm, --enforcement-names-minimum INTEGER
                                  Error if matches for enforcement_names are <
                                  this number  [env var:
                                  AX_ENFORCEMENT_NAMES_MINIMUM]
  -re, --re-prefix TEXT           Any strings provided to action_type,
                                  discovery_uuids, enforcement_names,statuses,
                                  or statuses_result that start with this
                                  value will be treated as a regex pattern
                                  [env var: AX_RE_PREFIX; default: ~]
  -sp, --split / -nsp, --no-split
                                  Split strings provided to filters using
                                  split_sep  [env var: AX_SPLIT; default:
                                  split]
  -ss, --split-sep TEXT           Split strings provided to filters using this
                                  separator  [env var: AX_SPLIT_SEP; default:
                                  re.compile(',')]
  -st, --strip / -nst, --no-strip
                                  Strip strings provided to filters  [env var:
                                  AX_STRIP; default: strip]
  -so, --sort TEXT                Ask REST API to sort tasks on this attribute
                                  (prefix with '-' for descending)   [env var:
                                  AX_SORT]
  -st, --statuses TEXT            Only get tasks that have the provided
                                  statuses (use re_prefix for pattern
                                  matching) (multiple)  [env var: AX_STATUSES]
  -ste, --statuses-error / -note, --no-statuses-error
                                  Error if any statuses provided are not valid
                                  [env var: AX_STATUSES_ERROR; default:
                                  statuses-error]
  -stm, --statuses-minimum INTEGER
                                  Error if matches for statuses are < this
                                  number  [env var: AX_STATUSES_MINIMUM]
  -sr, --statuses-result TEXT     Only get tasks that have the provided result
                                  statuses (use re_prefix for pattern
                                  matching) (multiple)  [env var:
                                  AX_STATUSES_RESULT]
  -sre, --statuses-result-error / -nsre, --no-statuses-result-error
                                  Error if any result statuses provided are
                                  not valid  [env var:
                                  AX_STATUSES_RESULT_ERROR; default: statuses-
                                  result-error]
  -srm, --statuses-result-minimum INTEGER
                                  Error if matches for result statuses are <
                                  this number  [env var:
                                  AX_STATUSES_RESULT_MINIMUM]
  -id, --task-id INTEGER          Only get tasks associated with this 'pretty
                                  id'  [env var: AX_TASK_ID]
  --help                          Show this message and exit.

axonshell enforcements tasks get

Usage: axonshell enforcements tasks get [OPTIONS]

  Get Enforcement Center Tasks matching filters.

Options:
  -u, --url URL                   URL of an Axonius instance  [env var:
                                  AX_URL; required]
  -k, --key KEY                   API Key (or username if credentials=True) of
                                  user in an Axonius instance  [env var:
                                  AX_KEY; required]
  -s, --secret SECRET             API Secret (or password if credentials=True)
                                  of user in an Axonius instance  [env var:
                                  AX_SECRET; required]
  -at, --action-types TEXT        Only get tasks that were ran by types of
                                  actions (use re_prefix for pattern matching)
                                  (multiple)  [env var: AX_ACTION_TYPES]
  -ate, --action-types-error / -nate, --no-action-types-error
                                  Error if any action_types provided are not
                                  valid  [env var: AX_ACTION_TYPES_ERROR;
                                  default: action-types-error]
  -atm, --action-types-minimum INTEGER
                                  Error if matches for action_types are < this
                                  number  [env var: AX_ACTION_TYPES_MINIMUM]
  -df, --date-from TEXT           Only get tasks with creation date >= this
                                  date  [env var: AX_DATE_FROM]
  -dfa, --date-from-add TEXT      seconds to add to date_from (or now if
                                  date_from not provided)  [env var:
                                  AX_DATE_FROM_ADD]
  -dfs, --date-from-subtract TEXT
                                  seconds to subtract from date_from (or now
                                  if date_from not provided)  [env var:
                                  AX_DATE_FROM_SUBTRACT]
  -dt, --date-to TEXT             Only get tasks with creation date <= this
                                  date  [env var: AX_DATE_TO]
  -dta, --date-to-add TEXT        seconds to add to date_to (or now if date_to
                                  not provided)  [env var: AX_DATE_TO_ADD]
  -dts, --date-to-subtract TEXT   seconds to subtract from date_to (or now if
                                  date_to not provided)  [env var:
                                  AX_DATE_TO_SUBTRACT]
  -du, --discovery-uuids TEXT     Only get tasks that were ran by discovery
                                  UUIDs (use re_prefix for pattern matching)
                                  (multiple)  [env var: AX_DISCOVERY_UUIDS]
  -due, --discovery-uuids-error / -ndue, --no-discovery-uuids-error
                                  Error if any discovery_uuids provided are
                                  not valid  [env var:
                                  AX_DISCOVERY_UUIDS_ERROR; default:
                                  discovery-uuids-error]
  -dum, --discovery-uuids-minimum INTEGER
                                  Error if matches for discovery_uuids are <
                                  this number  [env var:
                                  AX_DISCOVERY_UUIDS_MINIMUM]
  -do, --duration-operator [equal|greater|less]
                                  Operator to evaluate the duration_seconds
                                  value against task run durations  [env var:
                                  AX_DURATION_OPERATOR; default: less]
  -ds, --duration-seconds INTEGER
                                  Only get tasks where run duration matches
                                  duration_operator  [env var:
                                  AX_DURATION_SECONDS]
  -en, --enforcement-names TEXT   Only get tasks that were ran by enforcement
                                  names (use re_prefix for pattern matching)
                                  (multiple)  [env var: AX_ENFORCEMENT_NAMES]
  -ene, --enforcement-names-error / -nene, --no-enforcement-names-error
                                  Error if any enforcement_names provided are
                                  not valid  [env var:
                                  AX_ENFORCEMENT_NAMES_ERROR; default:
                                  enforcement-names-error]
  -enm, --enforcement-names-minimum INTEGER
                                  Error if matches for enforcement_names are <
                                  this number  [env var:
                                  AX_ENFORCEMENT_NAMES_MINIMUM]
  -re, --re-prefix TEXT           Any strings provided to action_type,
                                  discovery_uuids, enforcement_names,statuses,
                                  or statuses_result that start with this
                                  value will be treated as a regex pattern
                                  [env var: AX_RE_PREFIX; default: ~]
  -sp, --split / -nsp, --no-split
                                  Split strings provided to filters using
                                  split_sep  [env var: AX_SPLIT; default:
                                  split]
  -ss, --split-sep TEXT           Split strings provided to filters using this
                                  separator  [env var: AX_SPLIT_SEP; default:
                                  re.compile(',')]
  -st, --strip / -nst, --no-strip
                                  Strip strings provided to filters  [env var:
                                  AX_STRIP; default: strip]
  -so, --sort TEXT                Ask REST API to sort tasks on this attribute
                                  (prefix with '-' for descending)   [env var:
                                  AX_SORT]
  -st, --statuses TEXT            Only get tasks that have the provided
                                  statuses (use re_prefix for pattern
                                  matching) (multiple)  [env var: AX_STATUSES]
  -ste, --statuses-error / -note, --no-statuses-error
                                  Error if any statuses provided are not valid
                                  [env var: AX_STATUSES_ERROR; default:
                                  statuses-error]
  -stm, --statuses-minimum INTEGER
                                  Error if matches for statuses are < this
                                  number  [env var: AX_STATUSES_MINIMUM]
  -sr, --statuses-result TEXT     Only get tasks that have the provided result
                                  statuses (use re_prefix for pattern
                                  matching) (multiple)  [env var:
                                  AX_STATUSES_RESULT]
  -sre, --statuses-result-error / -nsre, --no-statuses-result-error
                                  Error if any result statuses provided are
                                  not valid  [env var:
                                  AX_STATUSES_RESULT_ERROR; default: statuses-
                                  result-error]
  -srm, --statuses-result-minimum INTEGER
                                  Error if matches for result statuses are <
                                  this number  [env var:
                                  AX_STATUSES_RESULT_MINIMUM]
  -id, --task-id INTEGER          Only get tasks associated with this 'pretty
                                  id'  [env var: AX_TASK_ID]
  -ps, --page-size INTEGER        Number of rows to get per page  [env var:
                                  AX_PAGE_SIZE; default: 2000]
  -rt, --row-start INTEGER        Row to start on  [env var: AX_ROW_START;
                                  default: 0]
  -rs, --row-stop INTEGER         Row to stop on  [env var: AX_ROW_STOP]
  -ex, --explode / -nex, --no-explode
                                  Explode each result for each task into
                                  individual rows (defaults per --export-
                                  format json:False, jsonl:False, csv:True)
                                  [env var: AX_EXPLODE]
  -sc, --schemas / -nsc, --no-schemas
                                  Include schema definitions for each task and
                                  result attribute (defaults per --export-
                                  format json:False, jsonl:False, csv:True)
                                  [env var: AX_SCHEMAS]
  -xt, --export-format [str|json|jsonl|csv]
                                  Format to write data as to STDOUT or
                                  --export-file.  [env var: AX_EXPORT_FORMAT;
                                  default: str]
  -xf, --export-file PATH         File to send data to  [env var:
                                  AX_EXPORT_FILE]
  -xo, --export-overwrite / -nxo, --no-export-overwrite
                                  If --export-file supplied and it exists,
                                  overwrite it  [env var: AX_EXPORT_OVERWRITE;
                                  default: no-export-overwrite]
  -e, --echo / -ne, --no-echo     Echo fetch messages to console.  [env var:
                                  AX_ECHO; default: echo]
  --help                          Show this message and exit.

axonshell enforcements tasks get-filters


Usage: axonshell enforcements tasks get-filters [OPTIONS]

  Get valid values for filtering count or get of Enforcement Center Tasks.

Options:
  -u, --url URL                   URL of an Axonius instance  [env var:
                                  AX_URL; required]
  -k, --key KEY                   API Key (or username if credentials=True) of
                                  user in an Axonius instance  [env var:
                                  AX_KEY; required]
  -s, --secret SECRET             API Secret (or password if credentials=True)
                                  of user in an Axonius instance  [env var:
                                  AX_SECRET; required]
  -iat, --include-action-types / -niat, --no-include-action-types
                                  Include Action types in use by any
                                  Enforcement Set in output  [env var:
                                  AX_ACTION_TYPES; default: include-action-
                                  types]
  -idu, --include-discovery-uuids / -nidu, --no-include-discovery-uuids
                                  Include UUIDs of Discovery Cycles that have
                                  launched a task in output  [env var:
                                  AX_DISCOVERY_UUIDS; default: include-
                                  discovery-uuids]
  -ien, --include-enforcement-names / -nien, --no-include-enforcement-names
                                  Include Names of all Enforcement Sets that
                                  have launched a task in output  [env var:
                                  AX_ENFORCEMENT_NAMES; default: include-
                                  enforcement-names]
  -iti, --include-task-ids / -niti, --no-include-task-ids
                                  Include Pretty IDs of all tasks for all
                                  Enforcement Sets in output  [env var:
                                  AX_TASK_IDS; default: include-task-ids]
  -is, --include-statuses / -nis, --no-include-statuses
                                  Include Statuses of all tasks and task
                                  results for all Enforcement Sets in output
                                  [env var: AX_STATUSES; default: include-
                                  statuses]
  -xt, --export-format [str|json]
                                  Format to write data as to STDOUT or
                                  --export-file.  [env var: AX_EXPORT_FORMAT;
                                  default: str]
  -xf, --export-file PATH         File to send data to  [env var:
                                  AX_EXPORT_FILE]
  -xo, --export-overwrite / -nxo, --no-export-overwrite
                                  If --export-file supplied and it exists,
                                  overwrite it  [env var: AX_EXPORT_OVERWRITE;
                                  default: no-export-overwrite]
  --help                          Show this message and exit.

Added Cloudflared support

Cloudflared support has been introduced to axonshell. Numerous new options are now available:


  -cfu, --cf-url TEXT             CLOUDFLARE ACCESS TOKEN: URL to use in
                                  cloudflared commands, will fallback to url
                                  if not supplied  [env var: CF_URL, AX_URL]
  -cft, --cf-token TEXT           CLOUDFLARE ACCESS TOKEN: token supplied by
                                  user, will be checked for validity if not
                                  empty  [env var: CF_TOKEN]
  -cfr, --cf-run / -ncfr, --no-cf-run
                                  CLOUDFLARE ACCESS TOKEN: If no token
                                  supplied or in OS env vars, try to get token
                                  from cloudflared commands  [env var: CF_RUN;
                                  default: no-cf-run]
  -cfrac, --cf-run-access / -ncfrac, --no-cf-run-access
                                  CLOUDFLARE ACCESS TOKEN: If run is True, try
                                  to get token from `access token` command
                                  [env var: CF_RUN_ACCESS; default: cf-run-
                                  access]
  -cfrlc, --cf-run-login / -ncfrlc, --no-cf-run-login
                                  CLOUDFLARE ACCESS TOKEN: If run is True and
                                  no token returned from `access token`
                                  command, try to get token from `access
                                  login` command  [env var: CF_RUN_LOGIN;
                                  default: cf-run-login]
  -cfp, --cf-path TEXT            CLOUDFLARE ACCESS TOKEN: Path to cloudflared
                                  binary to run, can be full path or path in
                                  OS env var $PATH  [env var: CF_PATH;
                                  default: cloudflared]
  -cfta, --cf-timeout-access INTEGER
                                  CLOUDFLARE ACCESS TOKEN: Timeout for `access
                                  token` command in seconds  [env var:
                                  CF_TIMEOUT_ACCESS; default: 60]
  -cftl, --cf-timeout-login INTEGER
                                  CLOUDFLARE ACCESS TOKEN: Timeout for `access
                                  login` command in seconds  [env var:
                                  CF_TIMEOUT_LOGIN; default: 180]
  -cfe, --cf-error / -ncfe, --no-cf-error
                                  CLOUDFLARE ACCESS TOKEN: Raise error if an
                                  invalid token is found or no token can be
                                  found  [env var: CF_ERROR; default: no-cf-
                                  error]
  -cfeac, --cf-error-access / -ncfeac, --no-cf-error-access
                                  CLOUDFLARE ACCESS TOKEN: Raise exc if
                                  `access token` command fails and login is
                                  False  [env var: CF_ERROR_ACCESS; default:
                                  cf-error-access]
  -cfel, --cf-error-login / -ncfel, --no-cf-error-login
                                  CLOUDFLARE ACCESS TOKEN: Raise exc if
                                  `access login` command fails  [env var:
                                  CF_ERROR_LOGIN; default: cf-error-login]
  -cfec, --cf-echo / -ncfec, --no-cf-echo
                                  CLOUDFLARE ACCESS TOKEN: Echo commands and
                                  results to STDERR  [env var: CF_ECHO;
                                  default: cf-echo]
  -cfev, --cf-echo-verbose / -ncfev, --no-cf-echo-verbose
                                  CLOUDFLARE ACCESS TOKEN: Echo more stuff to
                                  STDERR  [env var: CF_ECHO_VERBOSE; default:
                                  no-cf-echo-verbose]

With these new options and with cloudflared installed, axonshell can use cloudflared to automate the authentication and access to an Axonius instance is protected by a CF_ACCESS_TOKEN.

For example, to always automatically run cloudflared (and error if a cloudflare access token can not be fetched):

echo 'CF_RUN="yes"' >> .env
echo 'CF_ERROR="yes"' >> .env

axonshell devices count

Or to run cloudflared for a specific command:

axonshell --cf-run --cf-error devices count

Updated Enforcement Set Warning

The warning message displayed when creating an Enforcement Set has been updated to provide more information:


Enforcement Sets will be forced to the /Drafts folder if:
- Any configuration supplied for any action is invalid
- No Saved Query is supplied for the trigger

Easiest way to learn the correct configuration for an action:
- Create an Enforcement Set using the GUI
- export the Enforcement Set in JSON format using:
  axonshell enforcements get -v "enforcement name" -xf json
- Get the 'config' dictionary for the action you want to use from the JSON output
- Use the 'config' dictionary as appropriate 'config' argument for this method

This updated message helps users understand how to create a valid Enforcement Set and highlights potential issues that might force the Enforcement Set to the /Drafts folder.

Added new option to enable max logging

The --log-http-max option has been added to Axonshell to simplify enabling maximum logging with just a single option.

This provides a shortcut to include the maximum output for HTTP logging, which can be incredibly useful for debugging purposes or for reverse engineering the API calls made by the API client during various workflows.

  -lmax, --log-http-max / -nlmax, --no-log-http-max
                                  Shortcut to include_output http logging -
                                  overrides: log_request_body = True,
                                  log_response_body = True, log_level_http =
                                  "debug", log_level_package = "debug",
                                  log_level_console = "debug", log_level_file
                                  = "debug", log_request_attrs = "all",
                                  log_response_attrs = "all", log_body_lines =
                                  10000  [env var: AX_LOG_HTTP_MAX; default:
                                  no-log-http-max]

Using the new option:

axonshell -lmax -c devices count

Is equivalent to using:

axonshell \
  --log-request-body \
  --log-response-body \
  --log-request-attrs "all" \
  --log-response-attrs "all" \
  --log-level-console "debug" \
  --log-level-file "debug" \
  --log-body-lines 10000
  --log-console

By using the --log-http-max option, you can easily enable comprehensive logging to better understand the underlying API interactions and troubleshoot any issues that may arise.

This feature enhances the user experience by offering a more streamlined approach to enabling maximum logging, making it easier to analyze API calls and resolve potential problems.

Saved Query now required for Enforcement Sets

The --query-name option is now required when creating Enforcement Sets using axonshell:

axonshell enforcements create --query-name

Additionally, the axonshell enforcements update-remove-query command will now raise a NotAllowedError, as removing a saved query from an Enforcement Set is no longer allowed.

Add options to asset fetches to give more control over exports

The following commands have been updated to provide more control over CSV and XLSX exports:

axonshell devices get, get-by-saved-query
axonshell users get, get-by-saved-query
axonshell vulnerabilities get, get-by-saved-query

Previously, certain options were automatically set to True for --export-format csv or xslx.

Now, these options have been exposed to axonshell, giving users more control over their exports:

  --csv-field-flatten / --no-csv-field-flatten
                                  For CSV/XLSX Export: Enable flattening of
                                  complex fields  [env var:
                                  AX_CSV_FIELD_FLATTEN; default: csv-field-
                                  flatten]
  --csv-field-join / --no-csv-field-join
                                  For CSV/XLSX Export: Enable joining of list
                                  fields  [env var: AX_CSV_FIELD_JOIN;
                                  default: csv-field-join]
  --csv-field-null / --no-csv-field-null
                                  For CSV/XLSX Export: Enable null values for
                                  missing fields  [env var: AX_CSV_FIELD_NULL;
                                  default: csv-field-null]

Add support for using column filters in get-by-saved-query

The following commands have been updated to support using column filters when fetching assets:

axonshell devices get-by-saved-query
axonshell users get-by-saved-query
axonshell vulnerabilities get-by-saved-query

The following options have been added to support using column filters when fetching assets
by saved query:


  -if, --include-fields / -nif, --no-include-fields
                                  Include fields from the saved query GUI
                                  Path: Assets Table => Columns, REST API
                                  Saved Query path: view => query => fields,
                                  REST API get assets argument: fields, API
                                  Client get assets argument: fields:
                                  Optional[list[str]] = None, axonshell get
                                  assets argument: --fields/-f  [env var:
                                  AX_INCLUDE_FIELDS; default: include-fields]
  -iea, --include-excluded-adapters / -niea, --no-include-excluded-adapters
                                  Include column filters for excluded adapters
                                  from the saved query GUI Path: Assets Table
                                  => Columns => Column Filters => Field values
                                  - refine by adapter connection, REST API
                                  Saved Query path: view =>
                                  colExcludeAdapters, REST API get assets
                                  argument: excluded_adapters, API Client get
                                  assets argument: excluded_adapters:
                                  Optional[list[dict]] = None, axonshell get
                                  assets argument: NOT IMPLEMENTED (but is
                                  used in get-by-saved-query)  [env var:
                                  AX_INCLUDE_EXCLUDE_ADAPTERS; default:
                                  include-excluded-adapters]
  -iaea, --include-asset-excluded-adapters / -niaea, --no-include-asset-excluded-adapters
                                  Include column filters for asset excluded
                                  adapters fields from the saved query GUI
                                  Path: Assets Table => Columns => Column
                                  Filters => Field values - refine by adapter
                                  connection, REST API Saved Query path: view
                                  => colExcludeAdapters, REST API get assets
                                  argument: excluded_adapters, API Client get
                                  assets argument: excluded_adapters:
                                  Optional[list[dict]] = None, axonshell get
                                  assets argument: NOT IMPLEMENTED (but is
                                  used in get-by-saved-query)  [env var:
                                  AX_INCLUDE_ASSET_EXCLUDE_ADAPTERS; default:
                                  include-asset-excluded-adapters]
  -iff, --include-field-filters / -niff, --no-include-field-filters
                                  Include column filters for field filters
                                  from the saved query GUI Path: Assets Table
                                  => Columns => Column Filters => Field values
                                  - refine by condition, REST API Saved Query
                                  path: view => colFilters, REST API get
                                  assets argument: field_filters, API Client
                                  get assets argument: field_filters:
                                  Optional[list[dict]] = None, axonshell get
                                  assets argument: NOT IMPLEMENTED (but is
                                  used in get-by-saved-query)  [env var:
                                  AX_INCLUDE_FIELD_FILTERS; default: include-
                                  field-filters]
  -iaf, --include-asset-filters / -niaf, --no-include-asset-filters
                                  Include column filters for asset filters
                                  from the saved query GUI Path: Assets Table
                                  => Columns => Column Filters => Asset
                                  entities - refine by condition, REST API
                                  Saved Query path: view =>
                                  assetConditionExpressions, REST API get
                                  assets argument: asset_filters, API Client
                                  get assets argument: asset_filters:
                                  Optional[list[dict] = None, axonshell get
                                  assets argument: NOT IMPLEMENTED (but is
                                  used in get-by-saved-query)  [env var:
                                  AX_INCLUDE_ASSET_FILTERS; default: include-
                                  asset-filters]
  -uce, --use-cache-entry / -nuce, --no-use-cache-entry
                                  Ask the API to use a cache entry for this
                                  query, if available  [env var:
                                  AX_USE_CACHE_ENTRY; default: no-use-cache-
                                  entry]

In this release, support for using column filters when fetching assets by saved query has been added to Axonshell.

New options have been introduced to allow users to include fields, excluded adapters, asset excluded adapters, field filters, and asset filters from the saved query.

Additionally, an option has been added to ask the API to use a cache entry for the query if available.

Previously, the --include-fields option was automatically set to True for get-by-saved-query.

Now, you can disable it in order to exclude the fields defined in the saved query GUI with your fetch.

The API client now supports using column filters when fetching assets by saved query, as it has been brought up to date with the REST API models.

This update enhances the flexibility and functionality of Axonshell when fetching assets by saved query, providing users with more control over the data they retrieve.

Add options to asset fetches to support REST API features

The following commands have been updated to provide access to new REST API features:

axonshell devices get, get-by-saved-query
axonshell users get, get-by-saved-query
axonshell vulnerabilities get, get-by-saved-query

The following options have been added to support new REST API features for asset fetches:

  -anfne, --api-null-for-non-exist / -nanfne, --no-api-null-for-non-exist
                                  Ask the REST API to return null for non
                                  existent fields  [env var:
                                  AX_NULL_FOR_NON_EXIST; default: no-api-null-
                                  for-non-exist]
  -afonef, --api-filter-out-non-existing-fields / -nafonef, --no-api-filter-out-non-existing-fields
                                  Ask the REST API to filter out non existent
                                  fields  [env var:
                                  AX_FILTER_OUT_NON_EXISTING_FIELDS; default:
                                  api-filter-out-non-existing-fields]
  -amfi, --api-max-field-items INTEGER
                                  Ask the REST API to limit the number of
                                  values returned for a field  [env var:
                                  AX_MAX_FIELD_ITEMS]
  -amcfi, --api-complex-fields-preview-limit INTEGER
                                  Ask the REST API to limit the number of
                                  values returned for a complex field  [env
                                  var: AX_COMPLEX_FIELDS_PREVIEW_LIMIT]
  -ahfc, --api-use-heavy-fields-collection / -nahfc, --no-api-use-heavy-fields-collection
                                  Ask the REST API to use the heavy fields
                                  collection  [env var:
                                  AX_USE_HEAVY_FIELDS_COLLECTION; default: no-
                                  api-use-heavy-fields-collection]

These new options allow users to interact with the REST API in a more tailored and efficient manner.

Users can now:

  • request null values for non-existent fields (different logic than the API clients --field-null)
  • filter out non-existent fields
  • limit the number of values returned for a field or a complex field
  • decide whether to use the heavy fields collection during asset fetches

New help-detailed option for asset fetches

The following commands have a new --help-detailed choice:

axonshell devices get, get-by-saved-query
axonshell users get, get-by-saved-query
axonshell vulnerabilities get, get-by-saved-query

Example:

axonshell devices get --help-detailed asset_helper

This new --help-detailed choice provides comprehensive information on the various attributes used in fetching assets, creating saved queries, and more.

This new feature enhances user experience by offering more detailed guidance and support for using the Axonshell commands effectively.

Users can now easily access in-depth information on specific attributes or options in a convenient and streamlined manner.

Feel free to look at the other --help-detailed sections:

✗ axonshell devices get --help-detailed x
Usage: axonshell devices get [OPTIONS]
Try 'axonshell devices get --help' for help.

Error: Invalid value for '--help-detailed': 'x' is not one of
  'auth', 'query', 'assetexport', 'selectfields', 'wizard', 'asset_helper'.

Startup banner enhancements

The startup banner for axonshell has been improved to provide more useful information to users. This includes:

  • Basic details of the SSL certificate offered by the Axonius instance.
  • Basic details about the current user running axonshell.
  • Trial, license, and SSL expiry numbers are always displayed and color-coded
    based on their ranges.
** Connected to 'https://..:443', CLIENT v5.0.0, PYTHON v3.11.2 [signup on 2023-04-17 23:18:43.171026]
Axonius Version 'DEMO', Build Date: '2023-04-17' (14 days ago)
SSL Issued To: 'C=US, ST=California, L=San Francisco, O=Cloudflare, Inc., CN=axonius.com', Expires On: '2023-10-30 23:59:59+00:00'
User: 'admin', Source: 'internal', Role: 'Admin', Last Login Delta: 0:00:01.854351
** WARNING: Trial expires in 16 days (error<=15, warn<=30, info<=45, debug=None or > info)
** License expires in None days (error<=30, warn<=60, info<=90, debug=None or > info)
** SSL Certificate expires in 182 days (error<=60, warn<=90, info<=120, debug=None or > info)

These enhancements make it easier for users to quickly access relevant information about their Axonius instance, user account, and license status.

axonshell tools shell enhancements

The axonshell tools shell command has been enhanced to provide an updated list of shortcuts for various models, accounting for additions over time.

A helpful HELP string has also been added so that you can easily view the available shortcuts:

$ axonshell tools shell
Welcome human. We have some refreshments available for you:

Local variables available:
    - axonapi: API client package itself
    - client/c: API Client connection object
    - ctx: Click context object
    - jdump/j: Helper function to pretty print python objects
    - j(HELP): this message

Local variables as shortcuts from client properties:
    - activity_logs/al: Work with activity logs
    - adapters/a: Work with adapters and adapter connections
    - dashboard/db: Work with discovery cycle
    - dashboard_spaces/dbs: Work with dashboard spaces
    - data_scopes/ds: Work with data scopes
    - devices/d: Work with device assets
    - folders/f: Work with folders
    - instances/i: Work with instances
    - meta/m: Work with instance metadata
    - remote_support/rs: Work with configuring system remote support
    - settings_global/sgl: Work with Global system settings
    - settings_gui/sgu: Work with GUI system settings
    - settings_lifecycle/sl: Work with lifecycle system settings
    - settings_ip/sip: Work with Identity Provider system settings
    - enforcements/e: Work with enforcements
    - system_roles/sr: Work with system roles
    - system_users/su: Work with system users
    - users/u: Work with user assets
    - openapi/oas: Work with the OpenAPI specification file
    - vulnerabilities/v: Work with vulnerability assets

>>>

These enhancements make it easier and more convenient for users to access and work with different models using the axonshell tools shell.

Library changes

In this release, several significant changes have been made to the library structure.

New projects directory

A new "projects" directory has been created to accommodate packages that originated as projects and could potentially be moved into their own separate Python packages.

The cert_human package has been relocated to this new directory, along with the url_parser package and a newly created cf_token package, which has been developed to support this release.

These changes reflect the ongoing evolution and organization of the library, ensuring better maintainability and ease of use for developers working with these packages.

axonius_api_client.http.Http signature rewrite

The signature of the Http class has been restructured to make it more user-friendly and consistent with the rest of the library.

The most notable change is that all arguments are now exposed as keyword arguments, and many of them use default values that are defined as constants that can be overridden.

Additionally, the docstrings have been updated to provide more detailed information on the various arguments.

Previously, these options were hidden behind a complex kwargs dictionary that was difficult to use and understand.

class Http:
    def __init__(
        self,
        url: t.Union[UrlParser, str],
        certpath: t.Optional[PathLike] = None,
        certwarn: bool = CERT_WARN,
        certverify: bool = CERT_VERIFY,
        headers: t.Optional[T_Headers] = None,
        cookies: t.Optional[T_Cookies] = None,
        cert_client_both: t.Optional[PathLike] = None,
        cert_client_cert: t.Optional[PathLike] = None,
        cert_client_key: t.Optional[PathLike] = None,
        connect_timeout: t.Optional[t.Union[int, float]] = CONNECT_TIMEOUT,
        response_timeout: t.Optional[t.Union[int, float]] = RESPONSE_TIMEOUT,
        http_proxy: t.Optional[str] = None,
        https_proxy: t.Optional[str] = None,
        log_body_lines: int = LOG_BODY_LINES,
        log_hide_headers: t.Optional[PatternLikeListy] = HIDE_HEADERS,
        log_hide_str: t.Optional[str] = LOG_HIDE_STR,
        log_level: t.Union[int, str] = LOG_LEVEL,
        log_level_urllib: t.Union[int, str] = LOG_LEVEL_URLLIB,
        log_request_attrs: t.Optional[t.Union[str, t.Iterable[str]]] = None,
        log_request_body: bool = LOG_REQUEST_BODY,
        log_response_attrs: t.Optional[t.Union[str, t.Iterable[str]]] = None,
        log_response_body: bool = LOG_RESPONSE_BODY,
        save_history: bool = SAVE_HISTORY,
        save_last: bool = SAVE_LAST,
        cf_token: t.Optional[str] = None,
        cf_url: t.Optional[str] = None,
        cf_path: t.Optional[PathLike] = cf_constants.CF_PATH,
        cf_run: bool = cf_constants.CLIENT_RUN,
        cf_run_login: bool = cf_constants.FLOW_RUN_LOGIN,
        cf_run_access: bool = cf_constants.FLOW_RUN_ACCESS,
        cf_env: bool = cf_constants.FLOW_ENV,
        cf_echo: bool = cf_constants.FLOW_ECHO,
        cf_echo_verbose: bool = cf_constants.FLOW_ECHO_VERBOSE,
        cf_error: bool = cf_constants.CLIENT_ERROR,
        cf_error_login: bool = cf_constants.FLOW_ERROR,
        cf_error_access: bool = cf_constants.FLOW_ERROR,
        cf_timeout_access: t.Optional[int] = cf_constants.TIMEOUT_ACCESS,
        cf_timeout_login: t.Optional[int] = cf_constants.TIMEOUT_LOGIN,
        **kwargs,
    ):
        """HTTP client that wraps around :obj:`requests.Session`.

        Notes:
            * If certpath is supplied, certverify is ignored
            * private key supplied to cert_client_key or cert_client_both
              can **NOT** be password encrypted

        Args:
            url: URL, hostname, or IP address of Axonius instance
            certpath: token to CA bundle file to use when verifying certs offered by :attr:`url`
            certwarn: show insecure warning once or never show insecure warning
            certverify: raise exception if cert is self-signed or only if cert is invalid
            headers: headers to send with every request
            cookies: cookies to send with every request
            log_level: log level to use for this object
            log_body_lines: max length of request and response bodies to log
            log_hide_headers: headers to hide when logging
            save_last: save last request and response to :attr:`last_request` and
                :attr:`last_response`
            save_history: save all requests and responses to :attr:`history`
            connect_timeout: seconds to wait for connections to open to :attr:`url`
            response_timeout: seconds to wait for responses from :attr:`url`
            log_request_body: log the request body
            log_response_body: log the response body
            http_proxy: proxy to use when making http requests to :attr:`url`
            https_proxy: proxy to use when making https requests to :attr:`url`
            log_level_urllib: log level to use for urllib3
            cert_client_key: path to client private key file
            cert_client_both: path to client private key and cert file
            cert_client_cert: path to client cert file
            cf_url: URL to use in `access token` and `access login` commands,
                will fallback to url if not supplied
            cf_token: access token supplied by user, will be checked for validity if not empty
            cf_env: if no token supplied, try to get token from OS env var CF_TOKEN
            cf_run: if no token supplied or in OS env vars, try to get token from `access token` and
                `access login` commands
            cf_run_access: if run is True, try to get token from `access token`,
            cf_run_login: if run is True and no token returned from `access token` command,
                try to get token from `access login` command
            cf_path: path to cloudflared binary to run, can be full path or path in OS env var $PATH
            cf_timeout_access: timeout for `access token` command in seconds
            cf_timeout_login: timeout for `access login` command in seconds
            cf_error: raise error if an invalid token is found or no token can be found
            cf_error_access: raise exc if `access token` command fails and login is False
            cf_error_login: raise exc if `access login` command fails
            cf_echo: echo commands and results to stdout
            cf_echo_verbose: echo checks to stdout
            **kwargs: no longer used, will throw a deprecation warning

        Raises:
            :exc:`HttpError`:
                - if either cert_client_cert or cert_client_key are supplied, and the other is
                  not supplied
                - if any of cert_path, cert_client_cert, cert_client_key, or cert_client_both
                  are supplied and the file does not exist
        """

Docstring updates galore

I will be continuing to update docstrings to be more consistent and to include more information.

ApiEndpoint refactor

The ApiEndpoint class has been refactored to address some issues with the interface between ApiEndpoint and Connect objects.

get_env_connect returns more Connect args

Whereas previously get_env_connect returned only the url, key, secret, and certwarn arguments, it now returns some of the new arguments that are critical for authentication and connection.

import axonius_api_client as axonapi
connect_args = axonapi.get_env_connect()
print(list(connect_args.keys()))
['url', 'key', 'secret', 'certwarn', 'credentials', 'cf_token', 'cf_path', 'cf_run', 'cf_error']

JSONAPI models refactor

I am starting to refactor all the JSONAPI models and schemas to be:

  • standardized
  • only one schema & model pair per file
  • ensure they are in sync with the current model definitions in the REST API
  • have a consistent naming scheme.

This work will be finished over multiple releases.

Eventually I want to create a tool that will automatically generate the marshmallow schemas and dataclass containers and CLI arguments via click from the REST API definitions

AuthModel refactor

The AuthModel class has been refactored to bring it into line with the changes to Connect and Http.

AuthModel now has a much simpler signature, and the docstrings have been updated to provide more detailed information on the various arguments.

There are now 3 AuthModels: ApiKey, Credentials, and Null (used for Signup).

axonius_api_client.connect.Connect signature rewrite and refactor

Similar to the Http class, the signature of the Connect class has been rewritten to be easier to understand and use.

This was necessary because while Http is a wrapper around requests.Session, Connect is a wrapper around Http and axonius_api_client.auth.AuthModel.

The most notable change is that all arguments are now exposed as keyword arguments, and many of them use default values that are defined as constants that can be overridden.

Additionally, the docstrings have been updated to provide more detailed information on the various arguments.

Previously, these options were hidden behind a complex kwargs dictionary that was difficult to use and understand.

Additionally, much of the core logic of Connect was refactored to be more modular and easier to maintain.

class Connect:
    def __init__(
        self,
        url: str,
        key: str,
        secret: str,
        log_console: bool = False,
        log_file: bool = False,
        log_file_rotate: bool = False,
        certpath: t.Optional[PathLike] = None,
        certverify: bool = False,
        certwarn: bool = True,
        proxy: t.Optional[str] = None,
        headers: t.Optional[T_Headers] = None,
        cookies: t.Optional[T_Cookies] = None,
        credentials: bool = False,
        timeout_connect: t.Optional[t.Union[int, float]] = Http.CONNECT_TIMEOUT,
        timeout_response: t.Optional[t.Union[int, float]] = Http.RESPONSE_TIMEOUT,
        cert_client_key: t.Optional[PathLike] = None,
        cert_client_cert: t.Optional[PathLike] = None,
        cert_client_both: t.Optional[PathLike] = None,
        save_history: bool = False,
        log_level: t.Union[str, int] = "debug",
        log_request_attrs: t.Optional[t.Union[str, t.Iterable[str]]] = None,
        log_response_attrs: t.Optional[t.Union[str, t.Iterable[str]]] = None,
        log_request_body: bool = False,
        log_response_body: bool = False,
        log_logger: logging.Logger = LOG_LOGGER,
        log_level_package: t.Union[str, int] = LOG_LEVEL_PACKAGE,
        log_level_endpoints: t.Union[str, int] = LOG_LEVEL_ENDPOINTS,
        log_level_http: t.Union[str, int] = Http.LOG_LEVEL,
        log_level_auth: t.Union[str, int] = LOG_LEVEL_AUTH,
        log_level_api: t.Union[str, int] = LOG_LEVEL_API,
        log_level_console: t.Union[str, int] = LOG_LEVEL_CONSOLE,
        log_level_file: t.Union[str, int] = LOG_LEVEL_FILE,
        log_console_fmt: str = LOG_FMT_BRIEF,
        log_http_max: bool = LOG_HTTP_MAX,
        log_file_fmt: str = LOG_FMT_VERBOSE,
        log_file_name: t.Optional[PathLike] = LOG_FILE_NAME,
        log_file_path: t.Optional[PathLike] = LOG_FILE_PATH,
        log_file_max_mb: int = LOG_FILE_MAX_MB,
        log_file_max_files: int = LOG_FILE_MAX_FILES,
        log_hide_secrets: bool = True,
        log_body_lines: int = Http.LOG_BODY_LINES,
        wraperror: bool = True,
        cf_token: t.Optional[str] = None,
        cf_url: t.Optional[str] = None,
        cf_path: t.Optional[PathLike] = cf_constants.CF_PATH,
        cf_run: bool = cf_constants.CLIENT_RUN,
        cf_run_login: bool = cf_constants.FLOW_RUN_LOGIN,
        cf_run_access: bool = cf_constants.FLOW_RUN_ACCESS,
        cf_env: bool = cf_constants.FLOW_ENV,
        cf_echo: bool = cf_constants.FLOW_ECHO,
        cf_echo_verbose: bool = cf_constants.FLOW_ECHO_VERBOSE,
        cf_error: bool = cf_constants.CLIENT_ERROR,
        cf_error_login: bool = cf_constants.FLOW_ERROR,
        cf_error_access: bool = cf_constants.FLOW_ERROR,
        cf_timeout_access: t.Optional[int] = cf_constants.TIMEOUT_ACCESS,
        cf_timeout_login: t.Optional[int] = cf_constants.TIMEOUT_LOGIN,
        http: t.Optional[Http] = None,
        auth: t.Optional[AuthModel] = None,
        auth_null: t.Optional[AuthModel] = None,
        **kwargs,
    ):
        """Easy all-in-one connection handler.

        Args:
            url: URL, hostname, or IP address of Axonius instance
            key: API Key from account page in Axonius instance
            secret: API Secret from account page in Axonius instance
            log_console: include_output logging to console
            log_file: include_output logging to file
            certpath: path to CA bundle file to use when verifying certs offered by url
            certverify: raise exception if cert is self-signed or only if cert is invalid
            certwarn: show insecure warning once or never show insecure warning
            proxy: proxy to use when making https requests to url
            headers: additional headers to supply with every request
            cookies: additional cookies to supply with every request
            credentials: treat key as username as secret as password
            timeout_connect: seconds to wait for connections to open to url
            timeout_response: seconds to wait for responses from url
            cert_client_key: file with private key to offer to url
            cert_client_cert: file with client cert to offer to url
            cert_client_both: file with client cert and private key to offer to url
            save_history: save history of responses to Http.HISTORY
            log_level: log level to use for this object
            log_request_attrs: list of request attributes to log
            log_response_attrs: list of response attributes to log
            log_request_body: log request body
            log_response_body: log response body
            log_logger: Logger for the entire package, where console and file output
                handlers will be attached to
            log_level_package: log level to use for package root logger
            log_level_endpoints: log level to use for endpoint loggers
            log_level_http: log level to use for http loggers
            log_level_auth: log level to use for auth loggers
            log_level_api: log level to use for api loggers
            log_level_console: log level to use for console loggers
            log_level_file: log level to use for file loggers
            log_console_fmt: format string to use for console logging
            log_file_fmt: format string to use for file logging
            log_file_name: name of file to log to
            log_file_path: path to directory to log to
            log_file_max_mb: max size of log file in MB
            log_file_max_files: max number of log files to keep
            log_body_lines: max length of request/response body to log
            log_hide_secrets: hide secrets in logs
            log_http_max: Shortcut to include_output ALL http logging *warning: heavy log output*
            wraperror: wrap certain errors in a more user friendly format
            cf_url: URL to use in `access token` and `access login` commands,
                will fallback to url if not supplied
            cf_token: access token supplied by user, will be checked for validity if not empty
            cf_env: if no token supplied, try to get token from OS env var CF_TOKEN
            cf_run: if no token supplied or in OS env vars, try to get token from `access token` and
                `access login` commands
            cf_run_access: if run is True, try to get token from `access token`,
            cf_run_login: if run is True and no token returned from `access token` command,
                try to get token from `access login` command
            cf_path: path to cloudflared binary to run, can be full path or path in OS env var $PATH
            cf_timeout_access: timeout for `access token` command in seconds
            cf_timeout_login: timeout for `access login` command in seconds
            cf_error: raise error if an invalid token is found or no token can be found
            cf_error_access: raise exc if `access token` command fails and login is False
            cf_error_login: raise exc if `access login` command fails
            cf_echo: echo commands and results to stderr
            cf_echo_verbose: echo more to stderr
            http: http object to use for this connection
            auth: auth model to use for this connection
            auth_null: null auth model to use for this connection
            **kwargs: unused
        """

New ApiModel client.enforcements.tasks

Methods available:

count(): Get the number of tasks that match the provided filters in request_obj
get_filters(): Get all filters (enums) for all enforcements
get(): Get all tasks that match the provided filters in request_obj
build_get_request(): Build a request object for get() and count()
get_generator(): Get all tasks that match the provided filters in request_obj as a generator
direct_get_generator(): Direct API method to get all tasks for enforcements in basic model as a generator
direct_count(): Direct API method to get the number of tasks for enforcements.
direct_get(): Direct API method to get all tasks for enforcements in basic model.
get_full(): Direct API method to get a single task for an enforcement in full model.

New project cf_token

This project makes all the cloudflare access token magic available as a standalone package.

AssetMixin.get_generator signature rewrite

The signature of AssetMixin.get_generator has been rewritten to be more flexible and easier to use.

Many of these arguments were previously hidden behind kwargs.

There are still a ton of arguments hidden behind kwargs, they are all defined in
axonius_api_client.api.asset_callbacks.base.Base.args_map()

There are new arguments to allow for column filters to be supplied as part of the request object: field_filters, excluded_adapters, asset_excluded_adapters, asset_filters.

These column filters are all fairly complex and undocumented.

Create queries in the GUI with column filters defined in them to get an idea of how they work.

There are many new arguments as a result of updating the JSONAPI models to be in sync with the REST API model definitions.

Finally, the API client now sends a proper query ID and frontend_sent_time with every request, along with other new attributes that are used by the REST API.

    def get_generator(
        self,
        query: t.Optional[str] = None,
        fields: t.Optional[t.Union[t.List[str], str]] = None,
        fields_manual: t.Optional[t.Union[t.List[str], str]] = None,
        fields_regex: t.Optional[t.Union[t.List[str], str]] = None,
        fields_regex_root_only: bool = True,
        fields_fuzzy: t.Optional[t.Union[t.List[str], str]] = None,
        fields_default: bool = True,
        fields_root: t.Optional[str] = None,
        fields_error: bool = True,
        max_rows: t.Optional[int] = None,
        max_pages: t.Optional[int] = None,
        row_start: int = 0,
        page_size: int = MAX_PAGE_SIZE,
        page_start: int = 0,
        page_sleep: int = 0,
        export: str = DEFAULT_CALLBACKS_CLS,
        sort_field: t.Optional[str] = None,
        sort_descending: bool = False,
        history_date: t.Optional[t.Union[str, datetime.timedelta, datetime.datetime]] = None,
        history_days_ago: t.Optional[int] = None,
        history_exact: bool = False,
        wiz_entries: t.Optional[t.Union[t.List[dict], t.List[str], dict, str]] = None,
        wiz_parsed: t.Optional[dict] = None,
        file_date: t.Optional[str] = None,
        use_heavy_fields_collection: bool = False,
        sort_field_parsed: t.Optional[str] = None,
        search: t.Optional[str] = None,
        history_date_parsed: t.Optional[str] = None,
        field_filters: t.Optional[t.List[dict]] = None,
        excluded_adapters: t.Optional[t.List[dict]] = None,
        asset_excluded_adapters: t.Optional[t.List[dict]] = None,
        asset_filters: t.Optional[t.List[dict]] = None,
        expressions: t.Optional[t.List[dict]] = None,
        fields_parsed: t.Optional[t.Union[dict, t.List[str]]] = None,
        include_details: bool = False,
        include_notes: bool = False,
        use_cursor: bool = True,
        cursor_id: t.Optional[str] = None,
        saved_query_id: t.Optional[str] = None,
        query_id: t.Optional[t.Union[str, uuid.UUID]] = None,
        is_refresh: bool = False,
        null_for_non_exist: bool = False,
        source_component: t.Optional[str] = None,
        frontend_sent_time: t.Optional[datetime.datetime] = None,
        filter_out_non_existing_fields: bool = True,
        complex_fields_preview_limit: t.Optional[int] = None,
        max_field_items: t.Optional[int] = None,
        initial_count: t.Optional[int] = None,
        request_obj: t.Optional[AssetRequest] = None,
        export_templates: t.Optional[dict] = None,
        http_args: t.Optional[dict] = None,
        **kwargs,
    ) -> t.Generator[dict, None, None]:
        """Get assets from a query.

        See Also:
            If ``export`` is not supplied, see
            :meth:`axonius_api_client.api.asset_callbacks.base.Base.args_map`.

            If ``export`` equals ``json``, see
            :meth:`axonius_api_client.api.asset_callbacks.base_json.Json.args_map`.

            If ``export`` equals ``csv``, see
            :meth:`axonius_api_client.api.asset_callbacks.base_csv.Csv.args_map`.

            If ``export`` equals ``json_to_csv``, see
            :meth:`axonius_api_client.api.asset_callbacks.base_json_to_csv.JsonToCsv.args_map`.

            If ``export`` equals ``table``, see
            :meth:`axonius_api_client.api.asset_callbacks.base_table.Table.args_map`.

            If ``export`` equals ``xlsx``, see
            :meth:`axonius_api_client.api.asset_callbacks.base_xlsx.Xlsx.args_map`.

            :obj:`axonius_api_client.constants.asset_helpers.ASSET_HELPERS` for a list of
            helpers that translate between GUI titles, API request attributes, and saved query
            paths.

        Args:
            query: if supplied, only get the assets that match the query
            fields: fields to return for each asset (will be validated)
            fields_manual: fields to return for each asset (will NOT be validated)
            fields_regex: regex of fields to return for each asset
            fields_regex_root_only: only match fields_regex values against root fields
            fields_fuzzy: string to fuzzy match of fields to return for each asset
            fields_default: include the default fields in :attr:`fields_default`
            fields_root: include all fields of an adapter that are not complex sub-fields
            fields_error: throw validation errors on supplied fields
            max_rows: only return N rows
            max_pages: only return N pages
            row_start: start at row N
            page_size: fetch N rows per page
            page_start: start at page N
            page_sleep: sleep for N seconds between each page fetch
            export: export assets using a callback method
            include_notes: include any defined notes for each adapter
            include_details: include details fields showing the adapter source of agg values
            saved_query_id: ID of saved query this fetch is associated with
            expressions: expressions used by query wizard to create query
            sort_field: sort the returned assets on a given field
            sort_descending: reverse the sort of the returned assets
            history_date: return assets for a given historical date
            history_days_ago: return assets for a history date N days ago
            history_exact: Use the closest match for history_date and history_days_ago
            wiz_entries: wizard expressions to create query from
            file_date: string to use in filename templates for {DATE}
            wiz_parsed: parsed output from a query wizard
            fields_parsed: previously parsed fields
            sort_field_parsed: previously parsed sort field
            history_date_parsed: previously parsed history date
            initial_count: previously fetched initial count
            search: search string to use for this query
            use_heavy_fields_collection: unknown
            use_cursor: use cursor based pagination
            field_filters: field filters to apply to this query
            excluded_adapters: adapters to exclude from this query
            asset_excluded_adapters: adapters to exclude from this query
            asset_filters: asset filters to apply to this query
            cursor_id: cursor ID to use for this query
            query_id: query ID to use for this query
            is_refresh: is this a refresh query
            null_for_non_exist: return null for non existent fields
            source_component: source component to use for this query
            export_templates: filename template replacement mappings
            filter_out_non_existing_fields: filter out fields that do not exist
            complex_fields_preview_limit: limit the number of complex fields to preview
            max_field_items: max number of items to return for a field
            frontend_sent_time: frontend sent time to use for this query
            http_args: http args to pass to :meth:`axonius_api_client.http.Http.__call__` for each
                page fetched
            request_obj: request object to use for this query
            **kwargs: passed thru to the asset callback defined in ``export``
        """
    def get_generator(
        self,
        query: t.Optional[str] = None,
        fields: t.Optional[t.Union[t.List[str], str]] = None,
        fields_manual: t.Optional[t.Union[t.List[str], str]] = None,
        fields_regex: t.Optional[t.Union[t.List[str], str]] = None,
        fields_regex_root_only: bool = True,
        fields_fuzzy: t.Optional[t.Union[t.List[str], str]] = None,
        fields_default: bool = True,
        fields_root: t.Optional[str] = None,
        fields_error: bool = True,
        max_rows: t.Optional[int] = None,
        max_pages: t.Optional[int] = None,
        row_start: int = 0,
        page_size: int = MAX_PAGE_SIZE,
        page_start: int = 0,
        page_sleep: int = 0,
        export: str = DEFAULT_CALLBACKS_CLS,
        sort_field: t.Optional[str] = None,
        sort_descending: bool = False,
        history_date: t.Optional[t.Union[str, datetime.timedelta, datetime.datetime]] = None,
        history_days_ago: t.Optional[int] = None,
        history_exact: bool = False,
        wiz_entries: t.Optional[t.Union[t.List[dict], t.List[str], dict, str]] = None,
        wiz_parsed: t.Optional[dict] = None,
        file_date: t.Optional[str] = None,
        use_heavy_fields_collection: bool = False,
        sort_field_parsed: t.Optional[str] = None,
        search: t.Optional[str] = None,
        history_date_parsed: t.Optional[str] = None,
        field_filters: t.Optional[t.List[dict]] = None,
        excluded_adapters: t.Optional[t.List[dict]] = None,
        asset_excluded_adapters: t.Optional[t.List[dict]] = None,
        asset_filters: t.Optional[t.List[dict]] = None,
        expressions: t.Optional[t.List[dict]] = None,
        fields_parsed: t.Optional[t.Union[dict, t.List[str]]] = None,
        include_details: bool = False,
        include_notes: bool = False,
        use_cursor: bool = True,
        cursor_id: t.Optional[str] = None,
        saved_query_id: t.Optional[str] = None,
        query_id: t.Optional[t.Union[str, uuid.UUID]] = None,
        is_refresh: bool = False,
        null_for_non_exist: bool = False,
        source_component: t.Optional[str] = None,
        frontend_sent_time: t.Optional[datetime.datetime] = None,
        filter_out_non_existing_fields: bool = True,
        complex_fields_preview_limit: t.Optional[int] = None,
        max_field_items: t.Optional[int] = None,
        initial_count: t.Optional[int] = None,
        request_obj: t.Optional[AssetRequest] = None,
        export_templates: t.Optional[dict] = None,
        http_args: t.Optional[dict] = None,
        **kwargs,
    ) -> t.Generator[dict, None, None]:
        """Get assets from a query.

        See Also:
            If ``export`` is not supplied, see
            :meth:`axonius_api_client.api.asset_callbacks.base.Base.args_map`.

            If ``export`` equals ``json``, see
            :meth:`axonius_api_client.api.asset_callbacks.base_json.Json.args_map`.

            If ``export`` equals ``csv``, see
            :meth:`axonius_api_client.api.asset_callbacks.base_csv.Csv.args_map`.

            If ``export`` equals ``json_to_csv``, see
            :meth:`axonius_api_client.api.asset_callbacks.base_json_to_csv.JsonToCsv.args_map`.

            If ``export`` equals ``table``, see
            :meth:`axonius_api_client.api.asset_callbacks.base_table.Table.args_map`.

            If ``export`` equals ``xlsx``, see
            :meth:`axonius_api_client.api.asset_callbacks.base_xlsx.Xlsx.args_map`.

            :obj:`axonius_api_client.constants.asset_helpers.ASSET_HELPERS` for a list of
            helpers that translate between GUI titles, API request attributes, and saved query
            paths.

        Args:
            query: if supplied, only get the assets that match the query
            fields: fields to return for each asset (will be validated)
            fields_manual: fields to return for each asset (will NOT be validated)
            fields_regex: regex of fields to return for each asset
            fields_regex_root_only: only match fields_regex values against root fields
            fields_fuzzy: string to fuzzy match of fields to return for each asset
            fields_default: include the default fields in :attr:`fields_default`
            fields_root: include all fields of an adapter that are not complex sub-fields
            fields_error: throw validation errors on supplied fields
            max_rows: only return N rows
            max_pages: only return N pages
            row_start: start at row N
            page_size: fetch N rows per page
            page_start: start at page N
            page_sleep: sleep for N seconds between each page fetch
            export: export assets using a callback method
            include_notes: include any defined notes for each adapter
            include_details: include details fields showing the adapter source of agg values
            saved_query_id: ID of saved query this fetch is associated with
            expressions: expressions used by query wizard to create query
            sort_field: sort the returned assets on a given field
            sort_descending: reverse the sort of the returned assets
            history_date: return assets for a given historical date
            history_days_ago: return assets for a history date N days ago
            history_exact: Use the closest match for history_date and history_days_ago
            wiz_entries: wizard expressions to create query from
            file_date: string to use in filename templates for {DATE}
            wiz_parsed: parsed output from a query wizard
            fields_parsed: previously parsed fields
            sort_field_parsed: previously parsed sort field
            history_date_parsed: previously parsed history date
            initial_count: previously fetched initial count
            search: search string to use for this query
            use_heavy_fields_collection: unknown
            use_cursor: use cursor based pagination
            field_filters: field filters to apply to this query
            excluded_adapters: adapters to exclude from this query
            asset_excluded_adapters: adapters to exclude from this query
            asset_filters: asset filters to apply to this query
            cursor_id: cursor ID to use for this query
            query_id: query ID to use for this query
            is_refresh: is this a refresh query
            null_for_non_exist: return null for non existent fields
            source_component: source component to use for this query
            export_templates: filename template replacement mappings
            filter_out_non_existing_fields: filter out fields that do not exist
            complex_fields_preview_limit: limit the number of complex fields to preview
            max_field_items: max number of items to return for a field
            frontend_sent_time: frontend sent time to use for this query
            http_args: http args to pass to :meth:`axonius_api_client.http.Http.__call__` for each
                page fetched
            request_obj: request object to use for this query
            **kwargs: passed thru to the asset callback defined in ``export``
        """

AssetMixin.get_by_saved_query rewrite

    def get_by_saved_query(
        self,
        name: str,
        include_fields: bool = True,
        include_excluded_adapters: bool = True,
        include_asset_excluded_adapters: bool = True,
        include_field_filters: bool = True,
        include_asset_filters: bool = True,
        **kwargs,
    ) -> GEN_TYPE:
        """Get assets that would be returned by a saved query.

        Examples:
            First, create a ``client`` using :obj:`axonius_api_client.connect.Connect` and assume
            ``apiobj`` is ``client.devices`` or ``client.users``
            >>> import axonius_api_client as axonapi
            >>> connect_args: dict = axonapi.get_env_connect()
            >>> client: axonapi.Connect = axonapi.Connect(**connect_args)
            >>> apiobj: axonapi.api.assets.AssetMixin = client.devices
            >>>       # or client.users or client.vulnerabilities

            Get assets from a saved query with complex fields flattened
            >>> assets: t.List[dict] = apiobj.get_by_saved_query(name="test", field_flatten=True)

        See Also:
            :obj:`axonius_api_client.constants.asset_helpers.ASSET_HELPERS` for a list of
            helpers that translate between GUI titles, API request attributes, and saved query
            paths.

        Args:
            name: name of saved query to get assets from
            include_fields: include fields from saved query
            include_excluded_adapters: include column filters for excluded adapters from saved query
            include_asset_excluded_adapters: include column filters for asset excluded adapters
                from saved query
            include_field_filters: include column filters for field filters from saved query
            include_asset_filters: include column filters for asset filters from saved query
            **kwargs: passed to :meth:`get`
        """

AssetMixin.count rewrite

    def count(
        self,
        query: t.Optional[str] = None,
        history_date: t.Optional[t.Union[str, datetime.timedelta, datetime.datetime]] = None,
        history_days_ago: t.Optional[int] = None,
        history_exact: bool = False,
        wiz_entries: t.Optional[t.Union[t.List[dict], t.List[str], dict, str]] = None,
        wiz_parsed: t.Optional[t.List[dict]] = None,
        history_date_parsed: t.Optional[str] = None,
        use_cache_entry: bool = False,
        use_heavy_fields_collection: bool = False,
        frontend_sent_time: t.Optional[datetime.datetime] = None,
        query_id: t.Optional[t.Union[str, uuid.UUID]] = None,
        saved_query_id: t.Optional[str] = None,
        request_obj: t.Optional[CountRequest] = None,
        http_args: t.Optional[dict] = None,
        sleep: t.Optional[t.Union[int, float]] = 0.5,
        **kwargs,
    ) -> int:
        """Get the count of assets from a query.

        Examples:
            >>> import axonius_api_client as axonapi
            >>> connect_args: dict = axonapi.get_env_connect()
            >>> client: axonapi.Connect = axonapi.Connect(**connect_args)
            >>> apiobj: axonapi.api.assets.AssetMixin = client.devices
            >>>       # or client.users or client.vulnerabilities
            Get count of all assets
            >>> path: int = apiobj.count()
            Get count of all assets for a given date
            >>> path: int = apiobj.count(history_date="2020-09-29")
            Get count of assets matching a query built by the GUI query wizard
            >>> use_query: str = '(specific_data.data.name == "test")'
            >>> path: int = apiobj.count(query=use_query)
            Get count of assets matching a query built by the API client query wizard
            >>> entries: str = 'simple name equals test'
            >>> path: int = apiobj.count(wiz_entries=entries)
            Same as above but using a list of dicts instead of a string for wiz_entries
            >>> entries: t.List[dict] = [{'type': 'simple', 'path': 'name equals test'}]
            >>> path: int = apiobj.count(wiz_entries=entries)

        Args:
            query: only return the count of assets that match the query
            history_date: return asset count for a given historical date
            history_days_ago: return asset count for a given historical date that is N days ago
            history_exact: if True, return the exact asset count for a given historical date
                if False, return the asset count for the closest historical date
            wiz_entries: build a query from the entries and return the count of
                assets that match the query
            wiz_parsed: previously parsed wiz_entries
            history_date_parsed: previously parsed history_date
            use_cache_entry: if True, use the last query that was run to get the count
            use_heavy_fields_collection: if True, use the HEAVV fields collection to get the count
            frontend_sent_time: time that the query was sent from the frontend
            query_id: ID to identify this query
            saved_query_id: ID of saved query that count is being issued for
            request_obj: request object to use instead of building one
            http_args: args to pass to http request
            sleep: time to sleep between requests
            **kwargs: sent to :meth:`build_count_request`
        """

Remove v4.0 from all ApiEndpoints

v4.0 is now considered deprecated and will be removed in a future release.

All ApiEndpoints have been updated to remove v4.0 from the path.

What's Changed

  • back-merge 4.60.4 by @lifehackjim in #238
  • Sa 3421/feature/enforcement tasks by @lifehackjim in #240
  • 5.0.0 by @lifehackjim in #241

Full Changelog: 4.60.4...5.0.0