def test_special_k8s_approved(self): # Creating an auto_add_approved group should not change its member list. group = PortalGroup.objects.get(special_k8s_accounts=True) self.assertEqual(group.members.count(), 0) # Create a new user should not change the member list User = get_user_model() u = User(username="******", email="*****@*****.**") u.save() self.assertEqual(group.members.count(), 0) # walk through approval workflow url = reverse('welcome') request = self.factory.get(url) u.send_access_request(request) u.save() # Just sending an approval request should not change to member list self.assertEqual(group.members.count(), 0) # Build full-fledged request object for logged-in admin request = self._build_full_request_mock('admin:index') # Prepare K8S namespace ns = KubernetesNamespace(name="default") ns.save() new_svc = KubernetesServiceAccount(name="foobar", namespace=ns) new_svc.save() # Perform approval assert (u.approve(request, new_svc)) u.save() # Should lead to addition of user to the add_approved group self.assertEqual(group.members.count(), 1)
def test_new_ns_sync(random_namespace_name): run_minikube_sync() new_ns = KubernetesNamespace(name=random_namespace_name) new_ns.save() run_minikube_sync() ns_names = [ns.metadata.name for ns in api.get_namespaces()] assert random_namespace_name in ns_names
def test_exists_both_sides_sync(self): self._call_sync() api.create_k8s_ns("new-external-ns2") new_ns = KubernetesNamespace(name="new-external-ns2") new_ns.save() try: self._call_sync() finally: api.delete_k8s_ns("new-external-ns2")
def test_new_ns_broken_name_sync(self): test_cases = {"foo_bar": "foobar", "ABCDEF": "abcdef"} for old, new in test_cases.items(): new_ns = KubernetesNamespace(name=old) new_ns.save() self._call_sync() ns_names = [ns.metadata.name for ns in api.get_namespaces()] self.assertNotIn(old, ns_names) self.assertIn(new, ns_names)
def test_new_ns_broken_name_sync(): run_minikube_sync() test_cases = {"foo_bar": "foobar", "ABCDEF": "abcdef"} for old, new in test_cases.items(): new_ns = KubernetesNamespace(name=old) new_ns.save() run_minikube_sync() ns_names = [ns.metadata.name for ns in api.get_namespaces()] assert old not in ns_names assert new in ns_names api.delete_k8s_ns(new)
def get_context_data(self, *args, **kwargs): context = super().get_context_data(*args, **kwargs) context['site_header'] = settings.BRANDING + " (Admin Backend)" context['title'] = "Clean Up" context[ 'namespaces_no_service_acc'] = KubernetesNamespace.without_service_accounts( ) context['namespaces_no_pods'] = KubernetesNamespace.without_pods() context['months'] = settings.LAST_LOGIN_MONTHS_AGO context['inactive_users'] = User.inactive_users() return context
def test_user_merge_access_approved(admin_index_request, django_user_model): run_minikube_sync() primary = django_user_model( username="******", email="*****@*****.**") primary.save() ns = KubernetesNamespace(name="default") ns.save() new_svc = KubernetesServiceAccount(name="foobar", namespace=ns) new_svc.save() secondary = django_user_model( username="******", state=User.ACCESS_APPROVED, email="*****@*****.**", comments="secondary user comment", service_account=new_svc) secondary.save() group1 = PortalGroup(name="testgroup1") group1.save() group2 = PortalGroup(name="testgroup2") group2.save() secondary.portal_groups.add(group1) secondary.portal_groups.add(group2) secondary.save() # Build full-fledged request object for logged-in admin # approve secondary for cluster access secondary.approve(admin_index_request, new_svc) # the merge method only accepts a queryset of users since that's what # the admin interface creates queryset_of_users = django_user_model.objects.filter( pk__in=[primary.id, secondary.id]) # merge both users. shouldn't return anything assert(not merge_users(UserAdmin, admin_index_request, queryset_of_users)) # the primary user has been altered but the old object is still in memory # we need to query for the updated user again primary = django_user_model.objects.get(pk=primary.id) # Does primary have all the values of secondary user? assert primary.comments == "secondary user comment" assert primary.portal_groups.filter(name=group1.name) assert primary.portal_groups.filter(name=group2.name) assert primary.has_access_approved
def create_missing_in_portal(cls): """ Scans the Kubernetes cluster for service accounts that have no representation as KubernetesServiceAccount object, and creates the latter accordingly. """ try: k8s_svca_list = api.get_service_accounts() if k8s_svca_list: for k8s_svca in k8s_svca_list: # First calling exists(), and creating it in case, is faster than get_or_create() # but may impose an extremely small danger of race conditions. # We trade performance for reliability here. if not cls.objects.filter( name=k8s_svca.metadata.name, uid=k8s_svca.metadata.uid).exists(): logger.info( f"Found new Kubernetes service account {k8s_svca.metadata.name}, creating record." ) ns = KubernetesNamespace.get_or_sync( k8s_svca.metadata.namespace) new_obj = cls(name=k8s_svca.metadata.name, uid=k8s_svca.metadata.uid, namespace=ns) new_obj.save() return True except Exception as e: logger.exception( f"Syncing new cluster service accounts into the portal failed." ) return False
def test_special_k8s_unapproved(self): group = PortalGroup.objects.get(special_k8s_accounts=True) ns = KubernetesNamespace(name="default") ns.save() new_svc = KubernetesServiceAccount(name="foobar", namespace=ns) new_svc.save() User = get_user_model() # create approved user u = User(username="******", email="*****@*****.**", state=UserState.ACCESS_APPROVED, service_account=new_svc) u.save() self.assertEqual(group.members.count(), 1) # unapprove u.state = UserState.ACCESS_REJECTED u.save() self.assertEqual(group.members.count(), 0)
def test_special_k8s_unapproved(django_user_model, random_namespace_name): run_minikube_sync() group = PortalGroup.objects.get(special_k8s_accounts=True) ns = KubernetesNamespace(name=random_namespace_name) ns.save() new_svc = KubernetesServiceAccount(name="foobar", namespace=ns) new_svc.save() # create approved user u = django_user_model(username="******", email="*****@*****.**", state=User.ACCESS_APPROVED, service_account=new_svc) u.save() assert group.members.count() == 1 # unapprove u.state = User.ACCESS_REJECTED u.save() assert group.members.count() == 0
def test_backend_cleanup_view(self): User = get_user_model() u = User(username="******", email="*****@*****.**") u.save() # we need an inactive user for the the filter to work from dateutil.parser import parse u.last_login = parse("2017-09-23 11:21:52.909020") u.save() ns = KubernetesNamespace(name="aaasdfadfasdfasdf", visible=True) ns.save() new_svc = KubernetesServiceAccount(name="foobar", namespace=ns) new_svc.save() new_svc.delete() request = self._build_full_request_mock('admin:cleanup') assert (request)
def test_backend_cleanup_view(rf, admin_user, random_namespace_name): run_minikube_sync() User = get_user_model() u = User( username="******", email="*****@*****.**") u.save() # we need an inactive user for the the filter to work u.last_login = parse("2017-09-23 11:21:52.909020 +02:00") u.save() ns = KubernetesNamespace(name=random_namespace_name) ns.save() new_svc = KubernetesServiceAccount(name="foobar", namespace=ns) new_svc.save() new_svc.delete() assert admin_request(rf, admin_user, 'admin:cleanup')
def test_user_merge_access_rejected(self): request = self._build_full_request_mock('admin:index') User = get_user_model() primary = User(username="******", email="*****@*****.**") primary.save() ns = KubernetesNamespace(name="default") ns.save() new_svc = KubernetesServiceAccount(name="foobar", namespace=ns) new_svc.save() # Perform approval assert (primary.approve(request, new_svc)) primary.save() secondary = User(username="******", state=UserState.ACCESS_APPROVED, email="*****@*****.**", comments="secondary user comment", service_account=new_svc) secondary.save() # Build full-fledged request object for logged-in admin request = self._build_full_request_mock('admin:index') # reject cluster access for secondary secondary.reject(request) # the merge method only accepts a queryset of users since that's what # the admin interface creates queryset_of_users = User.objects.filter( pk__in=[primary.id, secondary.id]) # merge both users. shouldn't return anything assert (not merge_users(UserAdmin, request, queryset_of_users)) # the primary user has been altered but the old object is still in memory # we need to query for the updated user again primary = User.objects.get(pk=primary.id) assert primary.has_access_rejected
def sync(request=None): ''' Synchronizes the local shallow copy of Kubernetes data. Returns True on success. ''' try: res1 = KubernetesNamespace.create_missing_in_portal() res2 = KubernetesNamespace.create_missing_in_cluster() res3 = KubernetesServiceAccount.create_missing_in_portal() res4 = KubernetesServiceAccount.create_missing_in_cluster() if request: messages.info(request, "Synchronization finished.") logger.debug("Synchronization finished.") return True == res1 == res2 == res3 == res4 except client.rest.ApiException as e: msg = json.loads(e.body)['message'] logger.error( "API server exception during synchronization: {0}".format(msg)) if request: messages.error( request, "Kubernetes returned an error during synchronization: {0}".format(msg)) return False
def test_user_merge_access_rejected(admin_index_request, django_user_model, random_namespace_name): run_minikube_sync() primary = django_user_model( username="******", email="*****@*****.**") primary.save() ns = KubernetesNamespace(name=random_namespace_name) ns.save() new_svc = KubernetesServiceAccount(name="foobar", namespace=ns) new_svc.save() # Perform approval assert(primary.approve(admin_index_request, new_svc)) secondary = django_user_model( username="******", state=User.ACCESS_APPROVED, email="*****@*****.**", comments="secondary user comment", service_account=new_svc) secondary.save() # reject cluster access for secondary secondary.reject(admin_index_request) # the merge method only accepts a queryset of users since that's what # the admin interface creates queryset_of_users = django_user_model.objects.filter( pk__in=[primary.id, secondary.id]) # merge both users. shouldn't return anything assert(not merge_users(UserAdmin, admin_index_request, queryset_of_users)) # the primary user has been altered but the old object is still in memory # we need to query for the updated user again primary = django_user_model.objects.get(pk=primary.id) assert primary.has_access_rejected
def test_special_k8s_approved(rf, admin_index_request, django_user_model, random_namespace_name): run_minikube_sync() # Creating an auto_add_approved group should not change its member list. group = PortalGroup.objects.get(special_k8s_accounts=True) assert group.members.count() == 0 # Create a new user should not change the member list u = django_user_model(username="******", email="*****@*****.**") u.save() assert group.members.count() == 0 # walk through approval workflow url = reverse('welcome') request = rf.get(url) u.send_access_request(request) # Just sending an approval request should not change to member list assert group.members.count() == 0 # Prepare K8S namespace ns = KubernetesNamespace(name=random_namespace_name) ns.save() new_svc = KubernetesServiceAccount(name="foobar", namespace=ns) new_svc.save() # Perform approval assert(u.approve(admin_index_request, new_svc)) # Should lead to addition of user to the add_approved group assert group.members.count() == 1
def test_backend_cleanup_entitity_getters(django_user_model, admin_user, random_namespace_name): run_minikube_sync() admin_user.last_login = parse("2017-09-23 11:21:52.909020 +02:00") admin_user.save() ns = KubernetesNamespace(name=random_namespace_name) ns.save() assert admin_user in django_user_model.inactive_users() assert ns in KubernetesNamespace.without_pods() assert ns in KubernetesNamespace.without_service_accounts()
def test_new_svc_sync(random_namespace_name): run_minikube_sync() ns = KubernetesNamespace(name=random_namespace_name) ns.save() ns.create_in_cluster() new_svc = KubernetesServiceAccount(name="foobar", namespace=ns) new_svc.save() run_minikube_sync() svc_list = api.get_service_accounts() for svc in svc_list: if svc.metadata.name == "foobar" and svc.metadata.namespace == random_namespace_name: return assert False
def test_backend_cleanup_entitity_getters(): User = get_user_model() from django.utils import dateparse # we need an inactive user for the the filter to work u = User(username="******", email="*****@*****.**", last_login=dateparse.parse_datetime( "2017-09-23 11:21:52.909020 +02.00")) u.save() ns = KubernetesNamespace(name="asdfadfasdfasdf", visible=True) ns.save() assert (User.inactive_users()[0] == User.objects.get( username=u.username)) assert (KubernetesNamespace.without_pods()[0] == ns) assert (KubernetesNamespace.without_service_accounts()[0] == ns)
def test_new_ns_sync(self): new_ns = KubernetesNamespace(name="foo") new_ns.save() self._call_sync() ns_names = [ns.metadata.name for ns in api.get_namespaces()] self.assertIn("foo", ns_names)
def test_exists_both_sides_sync(random_namespace_name): run_minikube_sync() api.create_k8s_ns(random_namespace_name) new_ns = KubernetesNamespace(name=random_namespace_name) new_ns.save() run_minikube_sync()