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 islogging.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 andFalse
otherwiseReturn 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
objectsUsage:
>>> import canarytools >>> devices = console.devices.all()
-
dead
()¶ Get all registered disconnected devices
Returns: List of dead devices Return type: List of Device
objectsUsage:
>>> 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
objectRaises: 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
objectsUsage:
>>> 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
objectRaises: 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
objectsUsage:
>>> 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
objectsUsage:
>>> 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
objectRaises: 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
objectRaises: 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
objectRaises: 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
objectsUsage:
>>> 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
objectsRaises: 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
objectRaises: - 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
objectRaises: 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
objectsRaises: 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
objectRaises: 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
objectUsage:
>>> 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
objectUsage:
>>> 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
objectsUsage:
>>> 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
objectRaises: 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 objectParameters: - 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
objectRaises: 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
objectRaises: - 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
objectsUsage:
>>> 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
objectUsage:
>>> 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()
-
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
objectRaises: 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
objectRaises: 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
objectRaises: 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
objectRaises: - 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
objectRaises: 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
objectRaises: 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