Canary Console API Python Client v1

Main Interface

class Console(domain=None, api_key=None, timezone=<UTC>, debug=False, debug_level=10)

Initialize Console object. All API calls are made with this object

Parameters:
  • domain – The domain of the Canary console
  • api_key – The API key received on your Canary console
  • timezone – The timezone to be used when displaying objects with datetime information. pytz timezones to be used
  • debug – Debug flag for debugging requests/responses
  • debug_level – Debug level. logging debug level used. logging.DEBUG will display all requests and responses as well as response data. logging.INFO will only log the requests and responses. The default is logging.DEBUG
Raises:

ConfigurationError – Domain and/or API auth token not set

Usage:

>>> import canarytools
>>> console = canarytools.Console(domain='console_domain', api_key='test_key')

>>> import canarytools
>>> import logging
>>> console = canarytools.Console(debug=True)
ping()

Tests the connection to the Canary Console

Returns:Returns True if a connection could be established and False otherwise
Return type:bool

Usage:

>>> import canarytools
>>> console = canarytools.Console()
>>> console.ping()
True

Exceptions

All endpoints can raise the following errors:

Errors:
  • InvalidAuthTokenError – API authorization token is invalid
  • ConnectionError – A connection error occurred while sending a request to the console
  • ConsoleError – A general exception occurred

More specific endpoint errors are listed in an endpoint’s documentation.

Devices Interface

API calls for managing devices. All methods endpoints are accessed by first initializing a console object and by making calls as follows:

console.devices.dead()

console.devices.get_device('0000000000231c23')
class Devices(console)

Initialize the device

Parameters:console – The Console from which API calls are made
all()

Get all registered devices

Returns:List of all devices
Return type:List of Device objects

Usage:

>>> import canarytools
>>> devices = console.devices.all()
dead()

Get all registered disconnected devices

Returns:List of dead devices
Return type:List of Device objects

Usage:

>>> import canarytools
>>> devices = console.devices.dead()
get_device(node_id)

Get information on a particular device

Parameters:node_id – Get device with specific node id
Returns:Device with all information
Return type:A Device object
Raises:DeviceNotFoundError – The device could not be found

Usage:

>>> import canarytools
>>> device = console.devices.get_device(node_id='0000000000231c23')
live()

Get all registered connected devices

Returns:List of live devices
Return type:List of Device objects

Usage:

>>> import canarytools
>>> devices = console.devices.live()

Incidents Interface

API calls for managing incidents. All methods endpoints are accessed by first initializing a console object and by making calls as follows:

console.incidents.all()

console.incidents.delete()
class Incidents(console)

Initialize Incidents Object

acknowledge(node_id=None, src_host=None, older_than=None)
Mark all incidents as acknowledged. Use parameters to filter which
incidents are acknowledged. Calling this method with no parameters specified will acknowledge all incidents.
Parameters:
  • node_id (str) – Acknowledge incidents for a specific node NOTE: Cannot be used in conjunction with src_host
  • src_host (str) – Acknowledge incidents from a specific source IP address NOTE: Cannot be used in conjunction with node_id
  • older_than (str) – Acknowledge incidents older than the provided period. Periods are “[quantity][unit]”, where “[unit]” is one of ‘h’, ‘d’, ‘w’ (hours, days or weeks) e.g. ‘1h’ or ‘1d’ or ‘1w’
Returns:

Result indicator of the API call

Return type:

Result object

Raises:

InvalidParameterError – older_than was invalid / src_host and node_id cannot be used together

Usage:

>>> import canarytools
>>> result = console.incidents.acknowledge()

>>> import canarytools
>>> result = console.incidents.acknowledge(older_than='1d')
acknowledged(node_id=None, event_limit=None, newer_than=None)

Get list of all acknowledged incidents for a console.

Parameters:
  • node_id – Get all acknowledged incidents for a specific node
  • event_limit – Specify the maximum number of event logs to be returned with the incident
  • newer_than (str) – limit to incidents newer than a date like ‘2019-12-25-12:00:00’ (UTC)
Returns:

Return list of all acknowledged incidents

Return type:

List of Incident objects

Usage:

>>> import canarytools
>>> incidents = console.incidents.acknowledged()
all(node_id=None, event_limit=None, newer_than=None)

Get all incidents for this console.

Parameters:
  • node_id – Get all incidents for a specific node
  • event_limit – Specify the maximum number of event logs to be returned with the incident.
  • newer_than (str) – limit to incidents newer than a date like ‘2019-12-25-12:00:00’ (UTC)
Returns:

List of Incident objects

Return type:

List of Incident objects

Usage:

>>> import canarytools
>>> incidents = console.incidents.all()
delete(node_id=None, src_host=None, older_than=None)
Delete all acknowledged incidents. Use parameters to filter which
incidents are deleted. Calling this method with no parameters specified will delete all acknowledged incidents.
Parameters:
  • node_id (str) – Delete acknowledged incidents for a specific node NOTE: Cannot be used in conjunction with src_host
  • src_host (str) – Delete acknowledged incidents from a specific source IP address NOTE: Cannot be used in conjunction with node_id
  • older_than (str) – Delete acknowledged incidents older than the provided period. Periods are “[quantity][unit]”, where “[unit]” is one of ‘h’, ‘d’, ‘w’ (hours, days or weeks) e.g. ‘1h’ or ‘1d’ or ‘1w’
Returns:

Result indicator of the API call

Return type:

Result object

Raises:

InvalidParameterError – older_than was invalid / src_host and node_id cannot be used together

Usage:

>>> import canarytools
>>> result = console.incidents.delete()

>>> import canarytools
>>> result = console.incidents.delete(node_id='00000000042c23a')
get_incident(incident_id)

Get an Incident.

Parameters:incident – The id of the Incident
Returns:An Incident object
Return type:Incident object
Raises:IncidentNotFoundError – Could not find incident with this id

Usage:

>>> import canarytools
>>> incident = console.incidents.get_incident(incident_id='incident:ftplogin:0e4b47')
unacknowledge(node_id=None, src_host=None, older_than=None)
Mark all incidents as unacknowledged. Use parameters to filter which
incidents are unacknowledged. Calling this method with no parameters specified will unacknowledge all incidents.
Parameters:
  • node_id (str) – Unacknowledge incidents for a specific node NOTE: Cannot be used in conjunction with src_host
  • src_host (str) – Unacknowledge incidents from a specific source IP address NOTE: Cannot be used in conjunction with node_id
  • older_than (str) – Unacknowledge incidents older than the provided period. Periods are “[quantity][unit]”, where “[unit]” is one of ‘h’, ‘d’, ‘w’ (hours, days or weeks) e.g. ‘1h’ or ‘1d’ or ‘1w’
Returns:

Result indicator of the API call

Return type:

Result object

Raises:

InvalidParameterError – older_than was invalid / src_host and node_id cannot be used together

Usage:

>>> import canarytools
>>> result = console.incidents.unacknowledge()

>>> import canarytools
>>> result = console.incidents.unacknowledge(src_host='10.0.0.2')
unacknowledged(node_id=None, event_limit=None, newer_than=None)

Get list of all unacknowledged incidents for a console.

Parameters:
  • node_id – Get all unacknowledged incidents for a specific node
  • event_limit – Specify the maximum number of event logs to be returned with the incident.
  • newer_than (str) – limit to incidents newer than a date like ‘2019-12-25-12:00:00’ (UTC)
Returns:

Return list of all unacknowledged Incidents

Return type:

List of Incident objects

Usage:

>>> import canarytools
>>> incidents = console.incidents.unacknowledged()

Canarytokens Interface

API calls for managing Canarytokens. All methods endpoints are accessed by first initializing a console object and by making calls as follows:

console.tokens.all()

canarytools.tokens.create(memo='Desktop Token', kind=canarytools.CanaryTokenKinds.DOC_MSWORD)
class CanaryTokens(console)

Initialize CanaryToken

Parameters:console – The Console object from which API calls are made
all(include_endpoints=True)

Fetch all Canarytokens

Returns:A list of Canarytoken objects
Return type:List of CanaryToken objects
Raises:CanaryTokenError – Something went wrong while getting the CanaryTokens

Usage:

>>> import canarytools
>>> tokens = console.tokens.all()
create(memo, kind, flock_id=None, web_image=None, mimetype=None, cloned_web=None, browser_redirect_url=None, s3_source_bucket=None, s3_log_bucket=None, process_name=None)

Create a new Canarytoken

Parameters:
  • memo – Use this to remind yourself where you placed the Canarytoken
  • flock_id – Create token in different flock. Defaults to: ‘flock:default’
  • kind – The type of Canarytoken. Supported classes currently are: aws-id, cloned-web, dns, doc-msword, http, doc-msexcel, msexcel-macro, doc-msword, msword-macro, pdf-acrobat-reader, qr-code, sensitive-cmd, signed-exe, slack-api, web-image, windows-dir, wireguard
  • web_image – The path to an image file for use with web-image tokens.
  • mimetype – The type of image specified in web_image. e.g. ‘image/png’
  • cloned_web – Domain to be used in cloned-web tokens
  • browser_redirect_url – URL to redirect attackers to after triggering token (required when creating fast-redirect and slow-redirect tokens)
  • s3_source_bucket – S3 bucket to monitor for access (required when creating aws-s3 tokens)
  • s3_log_bucket – S3 bucket where logs will be stored (required when creating aws-s3 tokens)
  • process_name – Name of the process you want to monitor (required when creating sensitive-cmd tokens)
Returns:

A Result object

Return type:

Result object

Raises:
  • InvalidParameterError – One of the parameters was invalid
  • CanaryTokenError – Something went wrong while creating the CanaryToken

Usage:

>>> import canarytools
>>> result = console.tokens.create(memo='Desktop Token', kind=canarytools.CanaryTokenKinds.DOC_MSWORD)
get_token(canarytoken)

Gets a single Canarytoken

Parameters:canarytoken – The key specifying a unique Canarytoken
Returns:A Canarytoken object
Return type:CanaryToken object
Raises:CanaryTokenError – Could not find the CanaryToken

Usage:

>>> import canarytools
>>> token = console.tokens.get_token(canarytoken='gv3xjl75b3nr7vwsmvxexcle0')

Flocks Interface

API calls for managing Flocks. All methods endpoints are accessed by first initializing a console object and by making calls as follows:

console.flocks.all()

canarytools.flocks.create(name='Cape Town')
class Flocks(console)

Initialize Flock

Parameters:console – The Console object from which API calls are made
all()

Fetch all Flocks

Returns:A list of Flock objects
Return type:List of Flock objects
Raises:FlockError – Something went wrong while getting the Flocks

Usage:

>>> import canarytools
>>> flocks = console.flocks.all()
create(name)

Create a new Flock

Parameters:name – Use this to give your Flock a human readable name
Returns:A Result object
Return type:Result object
Raises:FlockError – Something went wrong while creating the Flock

Usage:

>>> import canarytools
>>> result = console.flocks.create(name='Cape Town')

Settings Interface

class Settings(console)

Initialize Settings object

Parameters:console – The Console from which API calls are made
is_ip_whitelisted(src_ip)

Is IP address Whitelisted

Parameters:src_ip – The IP address to be checked
Returns:Result object
Return type:Result object

Usage:

>>> import canarytools
>>> devices = canarytools.settings.is_ip_whitelisted(src_ip='10.0.0.2')
whitelist_ip_port(src_ip, dst_port=None)

Whitelist IP address and port

Parameters:
  • src_ip – The IP to be whitelisted
  • dst_port – The destination port
Returns:

Result object

Return type:

Result object

Usage:

>>> import canarytools
>>> devices = canarytools.settings.whitelist_ip_port(src_ip='10.0.0.2', dst_port='5000')

Updates Interface

class Updates(console)

Initialize Update object

Parameters:console – The Console from which API calls are made
list_updates()

List of available updates

Returns:List of Update objects
Return type:List of Update objects

Usage:

>>> import canarytools
>>> updates = canarytools.updates.list_updates()
update_device(node_id, update_tag)

Update the device

Parameters:
  • node_id – The node_id of the device to be updated
  • update_tag – The tag of the update to be updated to
Returns:

A Result object

Return type:

Result object

Raises:

UpdateError – Device update not permitted. Automatic updates are not configured. Or the update tag does not exist.

Usage:

>>> import canarytools
>>> result = canarytools.updates.update_device(node_id='00000000ff798b93', update_tag='4ae023bdf75f14c8f08548bf5130e861')

Returned Classes

This section describes the objects returned from the various interfaces described above. These objects represent console entities. For example, the Device object encapsulates all the information related to a specific device. Operations can be performed on these objects too. See below for more information.

class Device(console, data)

Device Initialize a Device object

Parameters:
  • console – The Console from which API calls are made
  • data – JSON data
Attributes:
  • id (str) – The device identification code
  • name (str) – The name of the device
  • description (str) – Device description
  • uptime_age (datetime) – The amount of time the device has been online for
  • first_seen (datetime) – The first time the device came online
  • last_heartbeat_age (str) – Time since device last communicated with the console
  • uptime (long) – The amount of time (in seconds) the device has been online
  • need_reboot (bool) – Has the device been scheduled for a reboot?
  • reconnect_count (int) – Number of times the device has reconnected to the console
  • live (bool) – Is the device online?
  • mac_address (str) – The MAC address of the device
  • ignore_notifications_disconnect (bool) – Should the console ignore disconnects?
  • notify_after_horizon_reconnect (bool) – Notify console after horizon reconnects
  • sensor (str) – The sensor of the device
  • first_seen_age (str) – Time since the device was first seen i.e ‘2 days’
  • ignore_notifications_general (bool) – Ignore all notifications
  • device_id_hash (str) – Hash of the devices ID
  • service_count (int) – Number of services running on the device
  • ip_address (str) – The IP address of the device
  • ippers (str) – Personality(s) of the device
  • ghost (bool) – Is this a ghost device? i.e the device has been registered but hasn’t come online
  • unacknowleged_incidents (list) – List of unacknowledged incidents for the device
  • last_seen (datetime) – Time the device was last seen
list_databundles()

Lists all DataBundles

Returns:List of DataBundle objects
Return type:List of DataBundle

Usage:

>>> import canarytools
>>> device = console.devices.get_device(node_id='0000000000231c23')
>>> databundles = device.list_databundles()
reboot()

Reboot the device

Returns:Result object
Return type:Result object
Raises:DeviceNotFoundError – The device could not be found

Usage:

>>> import canarytools
>>> device = console.devices.get_device(node_id='0000000000231c23')
>>> result = device.reboot()
refresh()

Refresh a Device object by pulling all changes

Raises:DeviceNotFoundError – The device could not be found

Usage:

>>> import canarytools
>>> device = console.devices.get_device(node_id='0000000000231c23')
>>> device.refresh()
update(update_tag)

Update the device

Parameters:

update_tag – The tag of the update

Returns:

Result object

Return type:

Result object

Raises:
  • UpdateError – Device update not permitted. Automatic updates are not configured. Or the update tag does not exist.
  • DeviceNotFoundError – The device could not be found

Usage:

>>> import canarytools
>>> device = console.devices.get_device(node_id='0000000000231c23')
>>> result = device.update(update_tag='4ae023bdf75f14c8f08548bf5130e861')
class Incident(console, data)

Initialize Incident Object

Attributes:
  • id (str) – The identification code of the incident
  • description (str) – The event description of the incident
  • flock_id (str) – The id of the flock this incident belongs to
  • acknowledged (bool) – Has the incident been acknowledged?
  • events (list) – List of events
  • logtype (str) – Log type
  • summary (str) – The event description of the incident
Subclasses:

List of classes which extend this base class.

IncidentDeviceReconnected, IncidentDeviceDied, IncidentFTPLogin, IncidentHTTPLogin, IncidentHTTPLoad, IncidentSSHLogin, IncidentTelnetLogin, IncidentHTTPProxyRequest, IncidentMySQLLogin, IncidentMSSQLLogin, IncidentTFTPRequest, IncidentNmapOSScan, IncidentNmapNULLScan, IncidentNmapXMASScan, IncidentNTPMonlist, IncidentVNCLogin, IncidentGitCloneRequest, IncidentTCPBannerRequest, IncidentModbusRequest, IncidentRedisCommand, IncidentUser, IncidentSNMPRequest, IncidentSIPRequest, IncidentSMBFileOpen, IncidentCanarytokenTriggered, IncidentHostPortScan, IncidentNetworkPortScan, IncidentConsolidatedNetworkPortScan

acknowledge()

Mark incident as acknowledged

Returns:Result indicator of the API call
Return type:Result objects

Usage:

>>> import canarytools
>>> incident = console.incidents.get_incident(incident_id='incident:ftplogin:0e4b47')
>>> result = incident.acknowledge()
delete()

Delete incident

Returns:Result indicator of the API call
Return type:Result object

Usage:

>>> import canarytools
>>> incident = console.incidents.get_incident(incident_id='incident:ftplogin:0e4b47')
>>> result = incident.delete()
refresh()

Refresh object after API calls to keep up-to-date

Usage:

>>> import canarytools
>>> incident = console.incidents.get_incident(incident_id='incident:ftplogin:0e4b47')
>>> incident.refresh()
unacknowledge()

Mark incident as unacknowledged

Returns:Result indicator of the API call
Return type:Result object

Usage:

>>> import canarytools
>>> incident = console.incidents.get_incident(incident_id='incident:ftplogin:0e4b47')
>>> result = incident.unacknowledge()
class CanaryToken(console, data)

Initialize a CanaryToken object

Parameters:
  • console – The Console from which the API calls are made
  • data – JSON data containing CanaryToken attributes
delete()

Delete a Canarytoken

Returns:A Result object
Return type:Result object
Raises:CanaryTokenError – Something went wrong while deleting the CanaryToken

Usage:

>>> import canarytools
>>> token = console.tokens.get_token(canarytoken='gv3xjl75b3nr7vwsmvxexcle0')
>>> result = token.delete()
disable()

Disable a Canarytoken

Returns:A Result object
Return type:Result object
Raises:CanaryTokenError – Something went wrong while disabling the CanaryToken

Usage:

>>> import canarytools
>>> token = console.tokens.get_token(canarytoken='gv3xjl75b3nr7vwsmvxexcle0')
>>> result = token.disable()
download(filename=None)

Download a Canarytoken

Parameters:

filename – Optional target filename. The console should provide a default value.

Returns:

The filename written to.

Return type:

str

Raises:
  • CanaryTokenError – Something went wrong while downloading the CanaryToken.
  • ValueError – This token doesn’t have a default filename, you need to provide one.

Usage:

>>> import canarytools
>>> token = console.tokens.create(memo="Excel file on Jim's Laptop", kind="doc-msexcel")
>>> token.download(filename="Payroll.xslx")
OR
>>> filename = token.download()
enable()

Enable a Canarytoken

Returns:A Result object
Return type:Result object
Raises:CanaryTokenError – Something went wrong while enabling the CanaryToken

Usage:

>>> import canarytools
>>> token = console.tokens.get_token(canarytoken='gv3xjl75b3nr7vwsmvxexcle0')
>>> result = token.enable()
update(memo)

Update a Canarytoken memo

Parameters:

memo – The new memo to be used

Returns:

A Result object

Return type:

Result object

Raises:
  • CanaryTokenError – Something went wrong while updating the CanaryToken
  • InvalidParameterError – The memo parameter is invalid

Usage:

>>> import canarytools
>>> token = console.tokens.get_token(canarytoken='gv3xjl75b3nr7vwsmvxexcle0')
>>> result = token.update(memo='Token in downloads folder')
class Flock(console, data)

Initialize a Flock object

Attributes:
  • flock_id (str) – The id the flock
  • name (str) – The name of the flock
Parameters:
  • console – The Console from which the API calls are made
  • data – JSON data containing Flock attributes
delete()

Delete a Flock

Parameters:flock_id – Unique identifier for your Flock
Returns:A Result object
Return type:Result object
Raises:FlockError – Something went wrong while deleting the Flock

Usage:

>>> import canarytools
>>> result = console.flocks.delete(flock_id='flock:0bd349d8514a8256a0f1c8e6acf77cf0')
rename(name)

Rename a Flock

Parameters:name – The new name to be used
Returns:A Result object
Return type:Result object
Raises:FlockError – Something went wrong while updating the Flock

Usage:

>>> import canarytools
>>> flocks = console.flocks.all()
>>> for flock in flocks:
>>>     if flock.flock_id == 'flock:id_im_looking_to_rename':
>>>         flock.rename("New name")
class Update(console, data)

Initialize an Update object

Parameters:
  • console – The Console from which API calls are made
  • data – JSON data
Attributes:
  • supported_versions (list) –List of Canary versions that support this update
  • description (str) – Description of the update
  • filename (str) – Name of update file
  • ignore (bool) – Should this update be ignored?
  • tag (str) – Update tag. Used to uniquely identify an update.
  • version (str) – Version to which the Canary is updated.
class DataBundle(console, data)

Initilaize a DataBundle object

Parameters:
  • console – The Console from which API calls are made
  • data – JSON data
Attributes:
  • settings_key (str) – Key that identifies this DataBundle
  • req_len (str) – The length of the request
  • bytes_copied (int) – Number of bytes sent in this DataBundle
  • name (str) – The name or type of this DataBundle
  • checksum (str) – Checksum of the DataBundle
  • ended_time (int) – Time the DataBundle completed in epoch time
  • tag (str) – The DataBundles tag
  • type_ (str) – The type of the DataBundle
  • bundle_size (int) – Size of theD DataBundle in bytes
  • state (str) – The state the DataBundle is in
  • node_id (str) – The id of the device for which this DataBundle is sent
  • started_time (int) – Time the DataBundle started being sent, in epoch time
  • created_time (int) – Time the DataBundle was created, in epoch time
  • updated_time (int) – Time of the update in epoch time
class Result(console, data)

Initialize Result. To be used as a result indicator

Parameters:
  • console – The Console from which API calls are made
  • data – JSON data
Attributes:
  • result – The result of the call. Usually ‘success’ or ‘error’.
class Event(console, data)

An event contains all the details relating to a incident occurence.

Parameters:
  • console – The Console from which API calls are made
  • data – JSON data

For a more detailed list of event attributes see Incidents and event attributes