canari.config - Canari Configuration Files

New in version 3.0.

additional child configuration files specified in the canari.local.configs option. These files are usually located in the .canari/ directory in your home directory (i.e ~/.canari/ in Mac/Linux or %HOMEPATH%\.canari\ in Windows). Canari configuration files are loaded in the following manner:

  1. Canari checks to see whether or not the transform package being loaded is in the global Python site-package directory. If it is, the canari.conf file in the global .canari directory is loaded. Otherwise, the canari.conf file in the current working directory is used, if present.
  2. Once the main configuration file is loaded, Canari will inspect the canari.local.configs option to determine whether there are any additional configuration files to be loaded. Typically this option is populated with a list of configuration files belonging to all the transform packages that have been installed (via canari create-profile) using Canari.
  3. Canari will then iterate over each configuration filename entry in canari.local.configs and load the configuration files in the same order as they appear in the configuration file. If a configuration option in one configuration file shares the same name and section as one from another, the latest configuration value will be used.

Common use-cases for using the configuration file is to retrieve information such as backend API keys or credentials that you may use to connect to third-party services. Here’s an example of how to use the configuration object in your transforms:

class MyTransform(Transform):
    def do_transform(request, response, config):
        db = connect_to_db(config['foo.local.username'], config['foo.local.password'])
        results = db.query('SELECT name FROM users WHERE id=?', request.entity.value)
        for r in results:
            response += Phrase(r)
        return response

In the example above, the canari.conf file would look like this:

[canari.local]
configs = foo.conf

# ...

The transform package’s configuration file, foo.conf, would look like this:

[foo.local]
username = bar
password = baz

Note

As a best practice for remote transforms, only backend architectural details and license keys should be stored in the configuration file. Client-side API keys can and should be received from the Maltego transform request parameters.

The config parameter in our Transform.do_transform() method is a CanariConfigParser object. By default all transform runners instantiate the configuration object using the load_config() function with no parameters and pass the result to the transforms. If however, you wish to load a separate configuration file, manually, you can use the load_config() function in the following manner:

canari.config.load_config(config_file=None, recursive_load=True)
Parameters:
  • config_file (str) – the absolute path to a custom configuration file.
  • recursive_load (bool) – True if your configuration file has a canari.local.configs option and you wish to load the additional configuration files specified in that option. False otherwise.

If recursive_load is True but your configuration file does not have a canari.local section or a configs option specified under that section, it will be quietly ignored.

Once loaded, configuration objects can be queried in the following manner (where c is the configuration object):

Operation Meaning
'section.name' in c Does the configuration contain the specified section.
'section.name.option' in c Does the configuration contain the specified section and option.
c['section.name.option'] Retrieve the value of the specified option and section.

Configuration objects have two additional features over and above regular configuration objects in Python, automatic type marshalling, and advanced string interpolation.

Automatic Type Marshalling

One of the biggest advantages in using the CanariConfigParser over other configuration parsers in Python is its ability to automatically marshal options to the appropriate type. For example, say you had the following configuration file:

[foo.local]
username = admin
threshold = 1000
timeout = 0.5
servers = 10.0.0.1, 10.0.0.2
validator = object://foo.validators/simple

These options would translate to the following when retrieve from your transform:

>>> config['foo.local.username'] # string
'admin'
>>> config['foo.local.threshold'] # integer
1000
>>> config['foo.local.timeout'] # float
0.5
>>> config['foo.local.servers'] # list of strings
['10.0.0.1', '10.0.0.2']
>>> config['foo.local.validator'] # foo.validators.simple object
<function foo.local.validator at 0x1337b33f>
>>>

Attention

Options starting with object:// will return the option as a string in remote transform execution mode.

Option String Interpolation

In addition to automatic type marshalling, CanariConfigParser objects support additional string interpolation features. This allows you to reference other options within your configuration file as well as system environment variables. For example, querying options from the following configuration file:

[foo.local]
bar = %(baz)
baz = 1
mypaths = ${PATH}:/custom/path

Would result in the following:

>>> config['foo.local.bar']
1
>>> config['foo.local.mypaths']
/usr/bin:/bin:/usr/local/bin:/custom/path
>>>