The plugin shown below will send an Email notification to the defined list of stakeholders if an instance was spun up within Amazon Web Services which is not defined in the approved whitelist. This is simply a notification plugin, but you could just as easily automatically delete/terminate the instance to apply enforcement policies and prevent users from spinning up unauthorized, expensive intense types.
from DivvyPlugins.plugin_metadata import PluginMetadata from DivvyPlugins.hookpoints import hookpoint from DivvyUtils.mail import send_email class metadata(PluginMetadata): """ Information about this plugin """ version = '1.0' last_updated_date = '2015-10-27' author = 'DivvyCloud' nickname = 'Instance Blacklist' default_language_description = 'Plugin which identifies newly created instances which fall into a defined blacklist' support_email = 'email@example.com' support_url = 'http://support.divvycloud.com' main_url = 'http://www.divvycloud.com' type = 'compliance' managed = False INSTANCE_TYPE_BLACKLIST = [ 'm4.4xlarge', 'm4.10xlarge', 'c4.8xlarge', 'c3.8xlarge', 'r3.8xlarge', 'g2.8xlarge', 'i2.8xlarge', 'd2.8xlarge' ] FROM_EMAIL = 'firstname.lastname@example.org' STAKEHOLDERS = ['email@example.com', 'firstname.lastname@example.org'] @hookpoint('divvycloud.instance.created') def validate_instance_type(resource, user_resource_id=None, project_resource_id=None): """ This plugin will check the instance_type parameter of a newly created instance if the instance is an Amazon Web Services system, and then compare it against blacklisted instance types which are very costly. The purpose of this is to notify stakeholders if an unauthorized instance type was used which does not conform to company policy. :param resource: The instance resource which we can manipulate :param user_resource_id: The resource ID of the user who created the resource. If this was created externally it will be None :param project_resource_id: The project that the resource belongs to. """ # First get the cloud_type_id. Amazon Web Services ID is AWS. if resource.get_organization_service().cloud_type_id != 'AWS': return if resource.instance_flavor.flavor_id in INSTANCE_TYPE_BLACKLIST: email_body = """ A blaklisted instance type was found. Instance %s within account %s has an instance type [%s] which has been blacklisted. Please login at your convenience to investigate.""" % (resource.instance_id, resource.get_organization_service().name, resource.instance_flavor.flavor_id) send_email(subject='A blacklisted instance has been identified', message=email_body, from_email=FROM_EMAIL, recipient_list=STAKEHOLDERS, organization_id=resource.get_organization_id()) def load(): """The load() function must be present for the plugin to load, but does not have to have a body""" pass
How Does It Work?¶
Towards the base of the plugin file above, you will see a load function with a pass statement. Every plugin must have this top level function function in order to be detected and loaded into memory by our plugin system. We have imposed this requirement on plugins files in order to dynamically detect changes and reload plugins whenever they are modified on disk.
def load(): pass
Important to note: The load method does not require a body for the system to recognize the plugin file as a valid plugin module (behind the scenes, we are simply using a getattr(module, ‘load’) check) – just make sure to include a “pass” to avoid Python’s whitespace errors!
The next part to call out is the hookpoint statement listed above. This particular Python decorator attaches a listener which will trigger when a new instance is created. As discussed earlier in the Hookpoints section of the documentation, the hookpoint for resource creation will fire when the resource is observed for the first time. This means that you can expect this event to trigger when an instance is first created or you add a new Amazon Web Services (AWS) account to the software which DivvyCloud was not configured with.
As we traverse down into the validate_instance_type function, it’s worth noting that you can name the underlying function anything you want. Our naming strategy at DivvyCloud is to try and stick with meaningful function names, but you could name the function foo() if you wanted.
The meat of the plugin lives within this validate_instance_type function. It’s sole purpose is to validate the instance type within AWS. If the newly created instance resides in another cloud then the plugin will return. If the instance type falls into a defined blacklist, which you as the plugin author can tailor to your liking, then an Email notification will be sent out to stakeholders to make them aware of the policy violation.
You could just as easily take a more intrusive action and terminate the instance; however, we typically recommend that you get more comfortable with the plugin system and it’s capabilities prior to performing write operaitons against resource types. You could also change your notification to go over say Slack or Hipchat instead of Email. The choice is yours!