diff options
| author | Todd Willey <todd@ansolabs.com> | 2011-06-23 21:44:29 +0000 |
|---|---|---|
| committer | Tarmac <> | 2011-06-23 21:44:29 +0000 |
| commit | 654350a1cf93e8ecf8d38f07802e0c3ed7039562 (patch) | |
| tree | 9306635ab8cdba9f9a8fb8ae941cf8586b1c083a /nova/api | |
| parent | 006cbeb5f145ea0e8ccf51163f4611d784876160 (diff) | |
| parent | 203f3f85b6d66735f52013cbe5a736ef82d7a083 (diff) | |
This adds a way to create global firewall blocks that apply to all instances in your nova installation.
The mechanism for managing these rules is very similar to how security group rules are managed except there is only ever one instance of the provider rule table, as opposed to multiple security group tables. Each instance will simply jump into the provider firewall table as one of its first actions (before security groups, so these rules cannot be overridden on a per-user basis).
Most of the changes are straightforward if you understand how security groups work. There are a few small logging and variable name changes as well.
Right now this only exposes the creation of provider firewall rules. If we agree this is the best path forward I will quickly be adding a list and destroy method and updating nova-adminclient.
Diffstat (limited to 'nova/api')
| -rw-r--r-- | nova/api/ec2/admin.py | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/nova/api/ec2/admin.py b/nova/api/ec2/admin.py index 57d0a0339..343bc61c4 100644 --- a/nova/api/ec2/admin.py +++ b/nova/api/ec2/admin.py @@ -21,7 +21,11 @@ Admin API controller, exposed through http via the api worker. """ import base64 +import datetime +import netaddr +import urllib +from nova import compute from nova import db from nova import exception from nova import flags @@ -117,6 +121,9 @@ class AdminController(object): def __str__(self): return 'AdminController' + def __init__(self): + self.compute_api = compute.API() + def describe_instance_types(self, context, **_kwargs): """Returns all active instance types data (vcpus, memory, etc.)""" return {'instanceTypeSet': [instance_dict(v) for v in @@ -324,3 +331,41 @@ class AdminController(object): rv.append(host_dict(host, compute, instances, volume, volumes, now)) return {'hosts': rv} + + def _provider_fw_rule_exists(self, context, rule): + # TODO(todd): we call this repeatedly, can we filter by protocol? + for old_rule in db.provider_fw_rule_get_all(context): + if all([rule[k] == old_rule[k] for k in ('cidr', 'from_port', + 'to_port', 'protocol')]): + return True + return False + + def block_external_addresses(self, context, cidr): + """Add provider-level firewall rules to block incoming traffic.""" + LOG.audit(_('Blocking traffic to all projects incoming from %s'), + cidr, context=context) + cidr = urllib.unquote(cidr).decode() + # raise if invalid + netaddr.IPNetwork(cidr) + rule = {'cidr': cidr} + tcp_rule = rule.copy() + tcp_rule.update({'protocol': 'tcp', 'from_port': 1, 'to_port': 65535}) + udp_rule = rule.copy() + udp_rule.update({'protocol': 'udp', 'from_port': 1, 'to_port': 65535}) + icmp_rule = rule.copy() + icmp_rule.update({'protocol': 'icmp', 'from_port': -1, + 'to_port': None}) + rules_added = 0 + if not self._provider_fw_rule_exists(context, tcp_rule): + db.provider_fw_rule_create(context, tcp_rule) + rules_added += 1 + if not self._provider_fw_rule_exists(context, udp_rule): + db.provider_fw_rule_create(context, udp_rule) + rules_added += 1 + if not self._provider_fw_rule_exists(context, icmp_rule): + db.provider_fw_rule_create(context, icmp_rule) + rules_added += 1 + if not rules_added: + raise exception.ApiError(_('Duplicate rule')) + self.compute_api.trigger_provider_fw_rules_refresh(context) + return {'status': 'OK', 'message': 'Added %s rules' % rules_added} |
