Andrew Bogott has submitted this change and it was merged. ( 
https://gerrit.wikimedia.org/r/332899 )

Change subject: Keystone hooks:  Set up default security groups for new 
projects.
......................................................................


Keystone hooks:  Set up default security groups for new projects.

Nova sort of supports this, but it doesn't handle the
project-wide groups correctly.

Wikitech sort of handles this, but has a race.

Bug: T136871
Change-Id: I185651527faf0a44814a1acf3eea2ba5b64ad6bc
---
M modules/openstack/files/liberty/keystone/wmfkeystonehooks/wmfkeystonehooks.py
M modules/openstack/files/mitaka/keystone/wmfkeystonehooks/wmfkeystonehooks.py
M modules/openstack/templates/liberty/keystone/keystone.conf.erb
M modules/openstack/templates/mitaka/keystone/keystone.conf.erb
4 files changed, 185 insertions(+), 34 deletions(-)

Approvals:
  Andrew Bogott: Looks good to me, approved
  jenkins-bot: Verified



diff --git 
a/modules/openstack/files/liberty/keystone/wmfkeystonehooks/wmfkeystonehooks.py 
b/modules/openstack/files/liberty/keystone/wmfkeystonehooks/wmfkeystonehooks.py
index 70027ec..0456a9e 100644
--- 
a/modules/openstack/files/liberty/keystone/wmfkeystonehooks/wmfkeystonehooks.py
+++ 
b/modules/openstack/files/liberty/keystone/wmfkeystonehooks/wmfkeystonehooks.py
@@ -13,8 +13,12 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from keystoneclient.auth.identity import generic
+from keystoneclient import session as keystone_session
 from keystone.common import dependency
 from keystone import exception
+from novaclient import client as nova_client
+from novaclient import exceptions
 
 from oslo_log import log as logging
 from oslo_config import cfg
@@ -36,6 +40,12 @@
     cfg.StrOpt('admin_user',
                default='novaadmin',
                help='Admin user to add to all new projects'),
+    cfg.StrOpt('admin_pass',
+               default='',
+               help='Admin password, used to authenticate with other 
services'),
+    cfg.StrOpt('auth_url',
+               default='',
+               help='Keystone URL, used to authenticate with other services'),
     cfg.StrOpt('observer_user',
                default='novaobserver',
                help='Observer user to add to all new projects'),
@@ -48,10 +58,10 @@
     cfg.StrOpt('admin_role_name',
                default='projectadmin',
                help='Name of project-local admin role'),
-    cfg.MultiStrOpt('wmf_keystone_eventtype_whitelist',
+    cfg.MultiStrOpt('eventtype_whitelist',
                     default=['identity.project.deleted', 
'identity.project.created'],
                     help='Event types to always handle.'),
-    cfg.MultiStrOpt('wmf_keystone_eventtype_blacklist',
+    cfg.MultiStrOpt('eventtype_blacklist',
                     default=[],
                     help='Event types to always ignore.'
                     'In the event of a conflict, '
@@ -60,7 +70,7 @@
 
 
 CONF = cfg.CONF
-CONF.register_opts(wmfkeystone_opts)
+CONF.register_opts(wmfkeystone_opts, group='wmfhooks')
 
 
 @dependency.requires('assignment_api', 'resource_api', 'role_api')
@@ -82,25 +92,95 @@
         # Make a dict to relate role names to ids
         for role in rolelist:
             roledict[role['name']] = role['id']
-        if CONF.observer_role_name not in roledict.keys():
-            LOG.error("Failed to find id for role %s" % 
CONF.observer_role_name)
+        if CONF.wmfhooks.observer_role_name not in roledict.keys():
+            LOG.error("Failed to find id for role %s" % 
CONF.wmfhooks.observer_role_name)
             raise exception.NotImplemented()
-        if CONF.admin_role_name not in roledict.keys():
-            LOG.error("Failed to find id for role %s" % CONF.admin_role_name)
+        if CONF.wmfhooks.admin_role_name not in roledict.keys():
+            LOG.error("Failed to find id for role %s" % 
CONF.wmfhooks.admin_role_name)
             raise exception.NotImplemented()
-        if CONF.user_role_name not in roledict.keys():
-            LOG.error("Failed to find id for role %s" % CONF.user_role_name)
+        if CONF.wmfhooks.user_role_name not in roledict.keys():
+            LOG.error("Failed to find id for role %s" % 
CONF.wmfhooks.user_role_name)
             raise exception.NotImplemented()
 
-        self.assignment_api.add_role_to_user_and_project(CONF.admin_user,
+        
self.assignment_api.add_role_to_user_and_project(CONF.wmfhooks.admin_user,
                                                          project_id,
-                                                         
roledict[CONF.admin_role_name])
-        self.assignment_api.add_role_to_user_and_project(CONF.admin_user,
+                                                         
roledict[CONF.wmfhooks.admin_role_name])
+        
self.assignment_api.add_role_to_user_and_project(CONF.wmfhooks.admin_user,
                                                          project_id,
-                                                         
roledict[CONF.user_role_name])
-        self.assignment_api.add_role_to_user_and_project(CONF.observer_user,
+                                                         
roledict[CONF.wmfhooks.user_role_name])
+        
self.assignment_api.add_role_to_user_and_project(CONF.wmfhooks.observer_user,
                                                          project_id,
-                                                         
roledict[CONF.observer_role_name])
+                                                         
roledict[CONF.wmfhooks.observer_role_name])
+
+        # Use the nova api to set up security groups for the new project
+        auth = generic.Password(
+            auth_url=CONF.wmfhooks.auth_url,
+            username=CONF.wmfhooks.admin_user,
+            password=CONF.wmfhooks.admin_pass,
+            user_domain_name='Default',
+            project_domain_name='Default',
+            project_name=project_id)
+        session = keystone_session.Session(auth=auth)
+        client = nova_client.Client('2', session=session)
+        allgroups = client.security_groups.list()
+        defaultgroup = filter(lambda group: group.name == 'default', allgroups)
+        if defaultgroup:
+            groupid = defaultgroup[0].id
+            try:
+                client.security_group_rules.create(groupid,
+                                                   ip_protocol='icmp',
+                                                   from_port='-1',
+                                                   to_port='-1',
+                                                   cidr='0.0.0.0/0')
+            except (exceptions.ClientException):
+                LOG.warning("icmp security rule already exists.")
+            try:
+                client.security_group_rules.create(groupid,
+                                                   ip_protocol='tcp',
+                                                   from_port='22',
+                                                   to_port='22',
+                                                   cidr='10.0.0.0/8')
+            except (exceptions.ClientException):
+                LOG.warning("Port 22 security rule already exists.")
+            try:
+                client.security_group_rules.create(groupid,
+                                                   ip_protocol='tcp',
+                                                   from_port='5666',
+                                                   to_port='5666',
+                                                   cidr='10.0.0.0/8')
+            except (exceptions.ClientException):
+                LOG.warning("Port 5666 security rule already exists.")
+            try:
+                client.security_group_rules.create(groupid,
+                                                   ip_protocol='tcp',
+                                                   from_port='1',
+                                                   to_port='65535',
+                                                   cidr='',
+                                                   group_id=groupid)
+            except (exceptions.ClientException):
+                LOG.warning("Project security rule for TCP already exists.")
+
+            try:
+                client.security_group_rules.create(groupid,
+                                                   ip_protocol='udp',
+                                                   from_port='1',
+                                                   to_port='65535',
+                                                   cidr='',
+                                                   group_id=groupid)
+            except (exceptions.ClientException):
+                LOG.warning("Project security rule for UDP already exists.")
+
+            try:
+                client.security_group_rules.create(groupid,
+                                                   ip_protocol='icmp',
+                                                   from_port='1',
+                                                   to_port='65535',
+                                                   cidr='',
+                                                   group_id=groupid)
+            except (exceptions.ClientException):
+                LOG.warning("Project security rule for ICMP already exists.")
+        else:
+            LOG.warning("Failed to find default security group in new 
project.")
 
     def notify(self, context, message, priority, retry=False):
         event_type = message.get('event_type')
@@ -112,9 +192,9 @@
             self._on_project_create(message['payload']['resource_info'])
 
         # Eventually this will be used to update project resource pages:
-        if event_type in CONF.wmf_keystone_eventtype_blacklist:
+        if event_type in CONF.wmfhooks.eventtype_blacklist:
             return
-        if event_type not in CONF.wmf_keystone_eventtype_whitelist:
+        if event_type not in CONF.wmfhooks.eventtype_whitelist:
             return
 
         return
diff --git 
a/modules/openstack/files/mitaka/keystone/wmfkeystonehooks/wmfkeystonehooks.py 
b/modules/openstack/files/mitaka/keystone/wmfkeystonehooks/wmfkeystonehooks.py
index 70027ec..78c2796 100644
--- 
a/modules/openstack/files/mitaka/keystone/wmfkeystonehooks/wmfkeystonehooks.py
+++ 
b/modules/openstack/files/mitaka/keystone/wmfkeystonehooks/wmfkeystonehooks.py
@@ -13,8 +13,12 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from keystoneclient.auth.identity import generic
+from keystoneclient import session as keystone_session
 from keystone.common import dependency
 from keystone import exception
+from novaclient import client as nova_client
+from novaclient import exceptions
 
 from oslo_log import log as logging
 from oslo_config import cfg
@@ -36,6 +40,12 @@
     cfg.StrOpt('admin_user',
                default='novaadmin',
                help='Admin user to add to all new projects'),
+    cfg.StrOpt('admin_pass',
+               default='',
+               help='Admin password, used to authenticate with other 
services'),
+    cfg.StrOpt('auth_url',
+               default='',
+               help='Keystone URL, used to authenticate with other services'),
     cfg.StrOpt('observer_user',
                default='novaobserver',
                help='Observer user to add to all new projects'),
@@ -48,10 +58,10 @@
     cfg.StrOpt('admin_role_name',
                default='projectadmin',
                help='Name of project-local admin role'),
-    cfg.MultiStrOpt('wmf_keystone_eventtype_whitelist',
+    cfg.MultiStrOpt('eventtype_whitelist',
                     default=['identity.project.deleted', 
'identity.project.created'],
                     help='Event types to always handle.'),
-    cfg.MultiStrOpt('wmf_keystone_eventtype_blacklist',
+    cfg.MultiStrOpt('eventtype_blacklist',
                     default=[],
                     help='Event types to always ignore.'
                     'In the event of a conflict, '
@@ -60,7 +70,7 @@
 
 
 CONF = cfg.CONF
-CONF.register_opts(wmfkeystone_opts)
+CONF.register_opts(wmfkeystone_opts, group='wmfhooks')
 
 
 @dependency.requires('assignment_api', 'resource_api', 'role_api')
@@ -82,25 +92,75 @@
         # Make a dict to relate role names to ids
         for role in rolelist:
             roledict[role['name']] = role['id']
-        if CONF.observer_role_name not in roledict.keys():
-            LOG.error("Failed to find id for role %s" % 
CONF.observer_role_name)
+        if CONF.wmfhooks.observer_role_name not in roledict.keys():
+            LOG.error("Failed to find id for role %s" % 
CONF.wmfhooks.observer_role_name)
             raise exception.NotImplemented()
-        if CONF.admin_role_name not in roledict.keys():
-            LOG.error("Failed to find id for role %s" % CONF.admin_role_name)
+        if CONF.wmfhooks.admin_role_name not in roledict.keys():
+            LOG.error("Failed to find id for role %s" % 
CONF.wmfhooks.admin_role_name)
             raise exception.NotImplemented()
-        if CONF.user_role_name not in roledict.keys():
-            LOG.error("Failed to find id for role %s" % CONF.user_role_name)
+        if CONF.wmfhooks.user_role_name not in roledict.keys():
+            LOG.error("Failed to find id for role %s" % 
CONF.wmfhooks.user_role_name)
             raise exception.NotImplemented()
 
-        self.assignment_api.add_role_to_user_and_project(CONF.admin_user,
+        
self.assignment_api.add_role_to_user_and_project(CONF.wmfhooks.admin_user,
                                                          project_id,
-                                                         
roledict[CONF.admin_role_name])
-        self.assignment_api.add_role_to_user_and_project(CONF.admin_user,
+                                                         
roledict[CONF.wmfhooks.admin_role_name])
+        
self.assignment_api.add_role_to_user_and_project(CONF.wmfhooks.admin_user,
                                                          project_id,
-                                                         
roledict[CONF.user_role_name])
-        self.assignment_api.add_role_to_user_and_project(CONF.observer_user,
+                                                         
roledict[CONF.wmfhooks.user_role_name])
+        
self.assignment_api.add_role_to_user_and_project(CONF.wmfhooks.observer_user,
                                                          project_id,
-                                                         
roledict[CONF.observer_role_name])
+                                                         
roledict[CONF.wmfhooks.observer_role_name])
+
+        # Use the nova api to set up security groups for the new project
+        auth = generic.Password(
+            auth_url=CONF.wmfhooks.auth_url,
+            username=CONF.wmfhooks.admin_user,
+            password=CONF.wmfhooks.admin_pass,
+            user_domain_name='Default',
+            project_domain_name='Default',
+            project_name=project_id)
+        session = keystone_session.Session(auth=auth)
+        client = nova_client.Client('2', session=session)
+        allgroups = client.security_groups.list()
+        defaultgroup = filter(lambda group: group.name == 'default', allgroups)
+        if defaultgroup:
+            groupid = defaultgroup[0].id
+            try:
+                client.security_group_rules.create(groupid,
+                                                   ip_protocol='icmp',
+                                                   from_port='-1',
+                                                   to_port='-1',
+                                                   cidr='0.0.0.0/0')
+            except (exceptions.ClientException):
+                LOG.warning("icmp security rule already exists.")
+            try:
+                client.security_group_rules.create(groupid,
+                                                   ip_protocol='tcp',
+                                                   from_port='22',
+                                                   to_port='22',
+                                                   cidr='10.0.0.0/8')
+            except (exceptions.ClientException):
+                LOG.warning("Port 22 security rule already exists.")
+            try:
+                client.security_group_rules.create(groupid,
+                                                   ip_protocol='tcp',
+                                                   from_port='5666',
+                                                   to_port='5666',
+                                                   cidr='10.0.0.0/8')
+            except (exceptions.ClientException):
+                LOG.warning("Port 5666 security rule already exists.")
+            try:
+                client.security_group_rules.create(groupid,
+                                                   ip_protocol='tcp',
+                                                   from_port='1',
+                                                   to_port='65535',
+                                                   cidr='',
+                                                   group_id=groupid)
+            except (exceptions.ClientException):
+                LOG.warning("Project security rule already exists.")
+        else:
+            LOG.warning("Failed to find default security group in new 
project.")
 
     def notify(self, context, message, priority, retry=False):
         event_type = message.get('event_type')
@@ -112,9 +172,9 @@
             self._on_project_create(message['payload']['resource_info'])
 
         # Eventually this will be used to update project resource pages:
-        if event_type in CONF.wmf_keystone_eventtype_blacklist:
+        if event_type in CONF.wmfhooks.eventtype_blacklist:
             return
-        if event_type not in CONF.wmf_keystone_eventtype_whitelist:
+        if event_type not in CONF.wmfhooks.eventtype_whitelist:
             return
 
         return
diff --git a/modules/openstack/templates/liberty/keystone/keystone.conf.erb 
b/modules/openstack/templates/liberty/keystone/keystone.conf.erb
index 6ab3924..23c54a2 100644
--- a/modules/openstack/templates/liberty/keystone/keystone.conf.erb
+++ b/modules/openstack/templates/liberty/keystone/keystone.conf.erb
@@ -397,3 +397,9 @@
 dbpass = <%= @keystoneconfig["oath_dbpass"] %>
 dbname = <%= @keystoneconfig["oath_dbname"] %>
 dbhost = <%= @keystoneconfig["oath_dbhost"] %>
+
+[wmfhooks]
+
+admin_pass = <%= @keystoneconfig["ldap_user_pass"] %>
+auth_url = <%= @keystoneconfig["auth_protocol"] %>://<%= @fqdn %>:<%= 
@keystoneconfig["auth_port"] %>/v3
+
diff --git a/modules/openstack/templates/mitaka/keystone/keystone.conf.erb 
b/modules/openstack/templates/mitaka/keystone/keystone.conf.erb
index 6ab3924..688cfa5 100644
--- a/modules/openstack/templates/mitaka/keystone/keystone.conf.erb
+++ b/modules/openstack/templates/mitaka/keystone/keystone.conf.erb
@@ -397,3 +397,8 @@
 dbpass = <%= @keystoneconfig["oath_dbpass"] %>
 dbname = <%= @keystoneconfig["oath_dbname"] %>
 dbhost = <%= @keystoneconfig["oath_dbhost"] %>
+
+[wmfhooks]
+
+admin_pass = <%= @keystoneconfig["ldap_user_pass"] %>
+auth_url = <%= @keystoneconfig["auth_protocol"] %>://<%= @fqdn %>:<%= 
@keystoneconfig["auth_port"] %>/v3

-- 
To view, visit https://gerrit.wikimedia.org/r/332899
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I185651527faf0a44814a1acf3eea2ba5b64ad6bc
Gerrit-PatchSet: 4
Gerrit-Project: operations/puppet
Gerrit-Branch: production
Gerrit-Owner: Andrew Bogott <abog...@wikimedia.org>
Gerrit-Reviewer: Alex Monk <kren...@gmail.com>
Gerrit-Reviewer: Andrew Bogott <abog...@wikimedia.org>
Gerrit-Reviewer: Volans <rcocci...@wikimedia.org>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to