With Canopy 3, we've added the ability to use plugins in order to more easily extend functionality within Canopy. We've helped users previously write plugins, such as:
- Custom tool format parsers, for use in importers (
plugin_type = 'parser'
) - Additional rating systems (
plugin_type = 'custom-rating'
) - XML postprocessors for adding custom functions to XML generation for Word reports and/or SoWs (
plugin_type = 'xml-postprocessor'
)
The addition of the plugin system provides a standard interface for adding custom code to your Canopy instance.
Plugins are currently supported using the python programming language.
Anatomy of a plugin
A plugin requires the following fields to ensure it is set up and registered by the plugin loader:
plugin_type = 'custom-rating' name = 'Example Custom Rating'
The plugin_type is used to register the type of the plugin. This is arbitrary, although guidelines (e.g. custom-rating) will be provided soon. The name registers the plugins name with the plugin system.
Example: custom rating plugin
The following example shows the implementation of a custom rating system for use within Canopy:
from canopy.modules.common.models import Rating plugin_type = 'custom-rating' name = 'Example Custom Rating' RATINGS_EDITABLE = False RATINGS = [ ['Info', 'Info', 'Info', 'Info', 'Low', 'Low', 'Low', 'Low', 'Medium', 'Medium'], ['Info', 'Info', 'Info', 'Info', 'Low', 'Low', 'Low', 'Medium', 'Medium', 'Medium'], ['Info', 'Info', 'Info', 'Low', 'Low', 'Low', 'Low', 'Medium', 'Medium', 'High'], ['Info', 'Info', 'Info', 'Low', 'Low', 'Low', 'Medium', 'Medium', 'High', 'High'], ['Info', 'Info', 'Low', 'Low', 'Low', 'Medium', 'Medium', 'Medium', 'High', 'High'], ['Info', 'Low', 'Low', 'Low', 'Low', 'Medium', 'Medium', 'Medium', 'High', 'High'], ['Info', 'Low', 'Low', 'Low', 'Medium', 'Medium', 'Medium', 'High', 'High', 'Critical'], ['Low', 'Low', 'Low', 'Medium', 'Medium', 'Medium', 'High', 'High', 'Critical', 'Critical'], ['Low', 'Low', 'Medium', 'Medium', 'Medium', 'Medium', 'High', 'High', 'Critical', 'Critical'], ['Low', 'Low', 'Medium', 'Medium', 'Medium', 'High', 'High', 'Critical', 'Critical', 'Critical'] ] OVERALL_RATINGS = { 'Info': 1, 'Low': 2, 'Medium': 3, 'High': 4, 'Critical': 5 } def calc_rating(finding): score = 0 rating = finding.rating custom_fields = {fv.field.name: fv.value for fv in finding.custom_fields.prefetch_related('field')} impact = int(custom_fields.get('impact', 0)) ease = int(custom_fields.get('ease', 0)) if impact and ease: rating = Rating.objects.get(type=RATINGS[impact-1][ease-1]) score = OVERALL_RATINGS[RATINGS[impact-1][ease-1]] return score, rating, None
TODO: explain the plugin line-by-line.
TODO: provide additional examples.
Loading plugins
Once you've written your plugin, it needs to be stored in a valid path. On production environments the correct path is:
- /var/opt/checksec/canopy/plugins
Further improvements
The plugin framework will be improved over the coming releases. Identified areas of improvement include:
- Making testing and validation of plugins easier
- Define a number of helper functions for certain types of plugins (e.g. markup formatting for tool importers)
- User-interface plugins to support customisation of the UI