- #!/usr/bin/env python
- # pylint: disable-msg=C0103
- # vim: tabstop=4 shiftwidth=4 softtabstop=4
- # Copyright 2010 United States Government as represented by the
- # Administrator of the National Aeronautics and Space Administration.
- # All Rights Reserved.
- #
- # Licensed under the Apache License, Version 2.0 (the "License");
- # you may not use this file except in compliance with the License.
- # You may obtain a copy of the License at
- #
- # http://www.apache.org/licenses/LICENSE-2.0
- #
- # Unless required by applicable law or agreed to in writing, software
- # distributed under the License is distributed on an "AS IS" BASIS,
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- # See the License for the specific language governing permissions and
- # limitations under the License.
- import gettext
- import os
- import sys
- import time
- # If ../nova/__init__.py exists, add ../ to Python search path, so that
- # it will override what happens to be installed in /usr/(local/)lib/python...
- possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
- os.pardir,
- os.pardir))
- if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')):
- sys.path.insert(0, possible_topdir)
- gettext.install('nova', unicode=1)
- from nova.auth import manager
- from nova import context
- from nova import db
- from nova import exception
- from nova import flags
- from nova import log as logging
- from nova import rpc
- from nova import utils
- from nova.db.sqlalchemy import session
- from nova.db.sqlalchemy import models
- FLAGS = flags.FLAGS
- LOG = logging.getLogger('nova-allow')
- admin = context.get_admin_context()
- def set_engine(conn_string):
- if FLAGS.sql_connection != conn_string:
- session._ENGINE = None
- session._MAKER = None
- FLAGS.sql_connection = conn_string
- def get_networks(last_check=0):
- set_engine(FLAGS.sql_connection)
- sess = session.get_session()
- return sess.query(models.Network).filter_by(deleted=False).all()
- def add_rules_for(project_id, cidr):
- LOG.info("Checking add for project %s / %s", project_id, cidr)
- ensure_default_security_groups(admin, project_id)
- security_group = db.security_group_get_by_name(admin,
- project_id,
- 'default')
- def add_rule(rule):
- if not security_group_rule_exists(security_group, rule):
- LOG.info("Adding rule %s: %s", rule['protocol'], rule)
- db.security_group_rule_create(admin, rule)
- return True
- return False
- did_update = (
- add_rule({'cidr': cidr,
- 'user_id': 'admin',
- 'from_port': 0,
- 'to_port': 65535,
- 'protocol': 'tcp',
- 'parent_group_id': security_group['id']}) or
- add_rule({'cidr': cidr,
- 'user_id': 'admin',
- 'from_port': 0,
- 'to_port': 65535,
- 'protocol': 'udp',
- 'parent_group_id': security_group['id']}) or
- add_rule({'cidr': cidr,
- 'user_id': 'admin',
- 'from_port': -1,
- 'to_port': -1,
- 'protocol': 'icmp',
- 'parent_group_id': security_group['id']}))
- if did_update:
- update_nodes(security_group)
- else:
- LOG.info("No new rules needed for %s", project_id)
- def ensure_default_security_groups(context, project_id):
- try:
- db.security_group_get_by_name(context,
- project_id,
- 'default')
- except exception.NotFound:
- values = {'name': 'default',
- 'description': 'default',
- 'user_id': 'admin',
- 'project_id': project_id}
- group = db.security_group_create(context, values)
- try:
- db.security_group_get_by_name(context,
- project_id,
- 'default')
- except exception.NotFound:
- values = {'name': 'default',
- 'description': 'default',
- 'user_id': 'admin',
- 'project_id': project_id}
- group = db.security_group_create(context, values)
- def security_group_rule_exists(security_group, values):
- """Indicates whether the specified rule values are already
- defined in the given security group.
- """
- for rule in security_group.rules:
- is_duplicate = True
- for key in ('cidr', 'from_port', 'to_port', 'protocol'):
- if rule[key] != values[key]:
- is_duplicate = False
- break
- if is_duplicate:
- return True
- return False
- def update_nodes(security_group):
- nodes = set([instance['host'] for instance in security_group.instances
- if instance['host'] is not None])
- for node in nodes:
- LOG.info("Triggering update on node %s", node)
- rpc.cast(admin,
- '%s.%s' % (FLAGS.compute_topic, node),
- {"method": "refresh_security_group_rules",
- "args": {"security_group_id": security_group.id}})
- def main():
- # first, make sure every project member has sysadmin and netadmin roles
- auth = manager.AuthManager()
- for project in db.project_get_all(admin):
- if project:
- for member in project.members:
- roles = db.user_get_roles(admin, member.id)
- if not auth.has_role(member.id, 'sysadmin'):
- try:
- auth.add_role(member.id, 'sysadmin')
- auth.add_role(member.id, 'sysadmin', project.id)
- except e:
- LOG.info("Couldn't add roles for %s, %s",
- member.id, project.id)
- if not auth.has_role(member.id, 'netadmin'):
- try:
- auth.add_role(member.id, 'netadmin')
- auth.add_role(member.id, 'netadmin', project.id)
- except e:
- LOG.info("Couldn't add roles for %s, %s",
- member.id, project.id)
- LOG.info("User roles up-to-date")
- # next, authorize all ports
- nets = get_networks()
- for net in nets:
- cidr = "0.0.0.0/0"
- add_rules_for(net['project_id'], cidr)
- if __name__ == '__main__':
- utils.default_flagfile('/etc/nova/nova.conf')
- argv = FLAGS(sys.argv)
- logging.setup()
- main()