From 2ad03f81400e1c598892094f2ed29f455f12d1bf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= <fpeters@entrouvert.com>
Date: Mon, 12 Aug 2019 16:30:33 +0200
Subject: [PATCH] authentic agent: remove obsolete import-wcs-roles command
 (#35374)

---
 README                                        |   6 -
 .../management/commands/import-wcs-roles.py   | 202 ------------------
 2 files changed, 208 deletions(-)
 delete mode 100644 hobo/agent/authentic2/management/commands/import-wcs-roles.py

diff --git a/README b/README
index 3df0031..e96287e 100644
--- a/README
+++ b/README
@@ -156,12 +156,6 @@ adapted in the AUTHENTIC_MANAGE_COMMAND setting. It should be run with the
 same rights as the authentic2 process (redefine the command to use sudo if
 necessary).
 
-The agent also provide a commands to import roles from w.c.s named
-import-wcs-roles. It computes the web-service credentials from the hobo.json
-and use the email of the oldest superuser. Cron job can be created for calling
-this command when regular synchronization of roles with your w.c.s.  instances
-is needed. The sole option named "--delete" indicate if you want to delete
-stale roles, default is to not delete them.  
 
 Tests
 -----
diff --git a/hobo/agent/authentic2/management/commands/import-wcs-roles.py b/hobo/agent/authentic2/management/commands/import-wcs-roles.py
deleted file mode 100644
index 2ba2e64..0000000
--- a/hobo/agent/authentic2/management/commands/import-wcs-roles.py
+++ /dev/null
@@ -1,202 +0,0 @@
-# hobo - portal to configure and deploy applications
-# Copyright (C) 2015  Entr'ouvert
-#
-# This program is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Affero General Public License as published
-# by the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-import os
-import logging
-import requests
-import urllib
-import urlparse
-import hashlib
-import json
-
-from optparse import make_option
-
-from django.utils.text import slugify
-from django.core.management.base import BaseCommand
-from django.utils.translation import ugettext as _
-from django.conf import settings
-
-from authentic2.saml.models import LibertyProvider
-from authentic2.a2_rbac.models import Role, RoleAttribute
-from authentic2 import app_settings
-
-
-from hobo import signature
-from hobo.multitenant.middleware import TenantMiddleware
-
-from tenant_schemas.utils import tenant_context
-
-
-class WcsRoleImporter(object):
-    def __init__(self, liberty_provider, key, orig,
-                 attribute_name='role-slug', delete=False):
-        self.service = liberty_provider
-        self.slug = liberty_provider.slug
-        self.key = key
-        self.orig = orig
-        self.attribute_name = attribute_name
-        self.delete = delete
-        assert 'saml/metadata' in self.service.entity_id
-        self.wcs_url = self.service.entity_id.split('saml/metadata')[0]
-        self.logger = logging.getLogger('%s.%s' % (__name__,
-                                                   self.__class__.__name__))
-        self.seen_ids = set()
-
-    def import_roles(self):
-        for role_tpl in self.get_roles():
-            self.seen_ids.add(role_tpl.external_id)
-            self.create_role(role_tpl)
-        if self.delete:
-            self.delete_dead_roles()
-        su_role, created = Role.objects.get_or_create(
-            service=self.service, slug='_a2-hobo-superuser',
-            defaults={'name': _('Superuser')})
-        su_role.attributes.get_or_create(name='is_superuser', kind='string',
-                                         value='true')
-
-    def create_role(self, role_tpl):
-        defaults = {
-            'name': role_tpl.name,
-            # w.c.s. will always provide a slug but for other services we do
-            # not know
-            'slug': role_tpl.slug or slugify(role_tpl.name),
-        }
-        # search role by external id, create if not found
-        role, created = Role.objects.get_or_create(
-            ou=self.service.ou,
-            external_id=role_tpl.external_id,
-            defaults=defaults)
-        RoleAttribute.objects.filter(role=role).delete()
-        role_attribute, ra_created = RoleAttribute.objects.get_or_create(
-            role=role,
-            name=self.attribute_name,
-            kind='string',
-            defaults={
-                'value': role_tpl.external_id
-            })
-        if created:
-            self.logger.info('imported new role %r(%r) from service %s',
-                             role.external_id, role.name, self.slug)
-        # update role attribute value if it has changed
-        if not ra_created:
-            if role_attribute.value != role_tpl.external_id:
-                role_attribute.value = role_tpl.external_id
-                role_attribute.save()
-        # update role name if has changed
-        if not created:
-            # Update name and slug if they have changed
-            if role.name != role_tpl.name:
-                role.name = role_tpl.name
-                role.save()
-        # update emails, emails_to_members and details in RA
-        if role_tpl.emails:
-            ra, created = RoleAttribute.objects.get_or_create(
-                role=role, name='emails', kind='json',
-                defaults={'value': json.dumps(role_tpl.emails)})
-            if ra.value != json.dumps(role_tpl.emails):
-                ra.value = json.dumps(role_tpl.emails)
-                ra.save()
-        ra, created = RoleAttribute.objects.get_or_create(
-            role=role, name='emails_to_members', kind='json',
-            defaults={'value': json.dumps(role_tpl.emails_to_members)})
-        if ra.value != json.dumps(role_tpl.emails_to_members):
-            ra.value = json.dumps(role_tpl.emails_to_members)
-            ra.save()
-        if role_tpl.details:
-            value = json.dumps(role_tpl.details)
-            ra, created = RoleAttribute.objects.get_or_create(
-                role=role, name='details', kind='json',
-                defaults={'value': value})
-            if ra.value != value:
-                ra.value = value
-                ra.save()
-
-    def delete_dead_roles(self):
-        '''Deletes service roles whose id is not in self.seen_ids'''
-        qs = Role.objects.filter(service=self.service) \
-            .exclude(external_id__in=list(self.seen_ids))
-        for role in qs:
-            self.logger.info('deleted dead role %r(%r) from service %s',
-                             role.external_id, role.slug, self.slug)
-        qs.delete()
-
-    def get_roles(self):
-        '''Get w.c.s. from its roles web-service by sending a signed GET
-           request.
-        '''
-        url = self.wcs_url + 'api/roles?%s' % urllib.urlencode(
-            {'format': 'json', 'orig': self.orig})
-        signed_url = signature.sign_url(url, self.key)
-        response = requests.get(signed_url, verify=app_settings.A2_VERIFY_SSL)
-        if response.status_code == 200:
-            for role in response.json()['data']:
-                new_role = Role(name=role['text'], external_id=str(role['slug']),
-                                slug=str(role['slug']))
-                new_role.description = role.get('details', u'')
-                new_role.emails = role.get('emails', [])
-                new_role.emails_to_members = role.get('emails_to_members', False)
-                new_role.details = role.get('details', '')
-                yield new_role
-        else:
-            self.logger.warn('failed to get roles for %s (response: %s)',
-                             self.wcs_url, response.status_code)
-
-
-class Command(BaseCommand):
-    help = "Import W.C.S. roles"
-
-    requires_system_checks = False
-
-    def add_arguments(self, parser):
-        parser.add_argument('--delete', action="store_true", dest='delete')
-
-    def handle(self, *args, **options):
-        # traverse list of tenants
-        for tenant in TenantMiddleware.get_tenants():
-            with tenant_context(tenant):
-                if getattr(settings, 'HOBO_ROLE_EXPORT', True):
-                    continue
-                self.handle_tenant(tenant, **options)
-
-    def handle_tenant(self, tenant, **options):
-        # extract informations on deployed w.c.s. instances from hobo.json
-        hobo_json_path = os.path.join(tenant.get_directory(), 'hobo.json')
-        if not os.path.exists(hobo_json_path):
-            print 'skipping %s, no hobo.json found' % tenant
-            return
-        hobo_environment = json.load(open(hobo_json_path))
-        # compute our credentials from our hobo configuration
-        me = [x for x in hobo_environment['services'] if x.get('this')]
-        if not me:
-            print 'skipping %s, self services is not marked' % tenant
-            return
-        me = me[0]
-        orig = urlparse.urlsplit(me['base_url']).netloc.split(':')[0]
-        for service_id in settings.KNOWN_SERVICES:
-            if service_id != 'wcs':
-                continue
-            for service in settings.KNOWN_SERVICES[service_id].values():
-                if not service.get('secret'):
-                    continue
-                liberty_provider = LibertyProvider.objects.get(
-                    entity_id=service['url'] + 'saml/metadata')
-                importer = WcsRoleImporter(
-                    liberty_provider=liberty_provider,
-                    key=service['secret'],
-                    orig=orig,
-                    delete=options.get('delete', False),
-                )
-                importer.import_roles()
-- 
2.23.0.rc1

