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 <[email protected]>
Gerrit-Reviewer: Alex Monk <[email protected]>
Gerrit-Reviewer: Andrew Bogott <[email protected]>
Gerrit-Reviewer: Volans <[email protected]>
Gerrit-Reviewer: jenkins-bot <>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits