def security_policy_create(request, repo_base, repo, table): ''' Creates a security policy for a table. ''' username = request.user.get_username() try: policy = request.POST['security-policy'] policy_type = request.POST['policy-type'] grantee = request.POST['policy-grantee'] RowLevelSecurityManager.create_security_policy(policy=policy, policy_type=policy_type, grantee=grantee, grantor=username, repo_base=repo_base, repo=repo, table=table ) except Exception as e: return HttpResponse( json.dumps( {'error': str(e)}), content_type="application/json") return HttpResponseRedirect( reverse('browse-security_policies', args=(repo_base, repo, table)))
def remove_user(username, remove_db=True, ignore_missing_user=False): # Delete the Django user try: DataHubManager._remove_django_user(username) except User.DoesNotExist as e: if not ignore_missing_user: raise e # Delete the user's db if remove_db: DataHubManager.remove_database(username) # Make a connection, and delete the user's database role with _superuser_connection() as conn: try: # Try the simple case first: delete the user when they have no # db permissions left result = conn.remove_user(username=username) except: # Assume the failure was outstanding db permissions. Remove # them and try again. all_db_list = DataHubManager.list_all_databases() for db in all_db_list: DataHubManager.drop_owned_by(username=username, repo_base=db) result = conn.remove_user(username=username) RowLevelSecurityManager.remove_user_from_policy_table( username=username) return result
def security_policy_create(request, repo_base, repo, table): ''' Creates a security policy for a table. ''' username = request.user.get_username() try: policy = request.POST['security-policy'] policy_type = request.POST['policy-type'] grantee = request.POST['policy-grantee'] RowLevelSecurityManager.create_security_policy(policy=policy, policy_type=policy_type, grantee=grantee, grantor=username, repo_base=repo_base, repo=repo, table=table ) except Exception as e: return HttpResponse( json.dumps( {'error': str(e)}), content_type="application/json") return HttpResponseRedirect( reverse('browse-security_policies', args=(repo_base, repo, table)))
def setUp(self): self.username = "******" self.repo_base = "test_username" self.repo = "test_repo" self.table = "test_table" self.user = User.objects.create_user(self.username) self.mock_connection = self.create_patch( 'core.db.rlsmanager.core.db.connection.DataHubConnection') self.manager = RowLevelSecurityManager(self.username, self.repo_base)
def test_find_security_policies(self): find_policies = self.mock_connection.return_value\ .find_security_policies RowLevelSecurityManager.find_security_policies( repo_base=self.repo_base, repo=self.repo, table=self.table, policy="visible='True", policy_type="insert", grantee="test", grantor="test_grantor") self.assertTrue(find_policies.called)
def add_user_to_policy_table(sender, instance, **kwargs): """ Adds default policies for user to row level security policy table. Does nothing if the user already has an entry in the policy table. """ username = instance.username # Create row level security policies in the dh_public policy table # granting user select, insert, update access to policies he create try: RowLevelSecurityManager.add_user_to_policy_table(username) except Exception: # Ignore failures when the user already has a policy. pass
def find_table_policies(self, table, repo, policytype, repo_base): ''' Look up policies associated with the table and repo and returns a list of all the policies defined for the user. ''' if repo_base is None: repo_base = self.repo_base # policies that are meant to apply to specific users user_policies = RowLevelSecurityManager.find_security_policies( repo_base=repo_base, repo=repo, table=table, policy_type=policytype, grantee=self.user, safe=False) # policies that are meant to apply to all users all_policies = RowLevelSecurityManager.find_security_policies( repo_base=repo_base, repo=repo, table=table, policy_type=policytype, grantee=settings.RLS_ALL, safe=False) # People collaborating on this repo collaborators = Collaborator.objects.filter(repo_base=repo_base, repo_name=repo) # If the user is not explicitly granted access, also load the # public_policies public_policies = [] if self.user not in collaborators: public_policies = RowLevelSecurityManager.find_security_policies( repo_base=repo_base, repo=repo, table=table, policy_type=policytype, grantee=settings.RLS_PUBLIC, safe=False) security_policies = user_policies + all_policies + public_policies result = [] for policy_tuple in security_policies: result.append(policy_tuple.policy) return result
def add_user_to_policy_table(sender, instance, **kwargs): """ Adds default policies for user to row level security policy table. Does nothing if the user already has an entry in the policy table. """ username = instance.username # Create row level security policies in the dh_public policy table # granting user select, insert, update access to policies he create try: RowLevelSecurityManager.add_user_to_policy_table(username) except Exception: # Ignore failures when the user already has a policy. pass
def find_table_policies(self, table, repo, policytype, repo_base): ''' Look up policies associated with the table and repo and returns a list of all the policies defined for the user. ''' if repo_base is None: repo_base = self.repo_base # policies that are meant to apply to specific users user_policies = RowLevelSecurityManager.find_security_policies( repo_base=repo_base, repo=repo, table=table, policy_type=policytype, grantee=self.user, safe=False) # policies that are meant to apply to all users all_policies = RowLevelSecurityManager.find_security_policies( repo_base=repo_base, repo=repo, table=table, policy_type=policytype, grantee=settings.RLS_ALL, safe=False) # People collaborating on this repo collaborators = Collaborator.objects.filter(repo_base=repo_base, repo_name=repo) # If the user is not explicitly granted access, also load the # public_policies public_policies = [] if self.user not in collaborators: public_policies = RowLevelSecurityManager.find_security_policies( repo_base=repo_base, repo=repo, table=table, policy_type=policytype, grantee=settings.RLS_PUBLIC, safe=False) security_policies = user_policies + all_policies + public_policies result = [] for policy_tuple in security_policies: result.append(policy_tuple.policy) return result
def security_policy_delete(request, repo_base, repo, table, policy_id): ''' Deletes a security policy defined for a table given a policy_id. ''' username = request.user.get_username() policy_id = int(policy_id) try: RowLevelSecurityManager.remove_security_policy(policy_id, username) except Exception as e: return HttpResponse(json.dumps({'error': str(e)}), content_type="application/json") return HttpResponseRedirect( reverse('browse-security_policies', args=(repo_base, repo, table)))
def security_policies(request, repo_base, repo, table): ''' Shows the security policies defined for a table. ''' username = request.user.get_username() # get the security policies on a given repo.table try: policies = RowLevelSecurityManager.find_security_policies( repo_base=repo_base, repo=repo, table=table, grantor=username, safe=True) except LookupError: policies = [] # repack the named tuples. This is a bit of a hack, (since we could just # get the view to display named tuples) # but is happening for expediency policies = [(p.id, p.policy, p.policy_type, p.grantee, p.grantor) for p in policies] res = { 'login': username, 'repo_base': repo_base, 'repo': repo, 'table': table, 'policies': policies} res.update(csrf(request)) return render_to_response("security-policies.html", res)
def security_policies(request, repo_base, repo, table): ''' Shows the security policies defined for a table. ''' username = request.user.get_username() # get the security policies on a given repo.table try: policies = RowLevelSecurityManager.find_security_policies( repo_base=repo_base, repo=repo, table=table, grantor=username, safe=True) except LookupError: policies = [] # repack the named tuples. This is a bit of a hack, (since we could just # get the view to display named tuples) # but is happening for expediency policies = [(p.id, p.policy, p.policy_type, p.grantee, p.grantor) for p in policies] res = { 'login': username, 'repo_base': repo_base, 'repo': repo, 'table': table, 'policies': policies } res.update(csrf(request)) return render_to_response("security-policies.html", res)
def security_policy_delete(request, repo_base, repo, table, policy_id): ''' Deletes a security policy defined for a table given a policy_id. ''' username = request.user.get_username() policy_id = int(policy_id) try: RowLevelSecurityManager.remove_security_policy( policy_id, username) except Exception as e: return HttpResponse( json.dumps( {'error': str(e)}), content_type="application/json") return HttpResponseRedirect( reverse('browse-security_policies', args=(repo_base, repo, table)))
def test_create_security_policy(self): create_pol = self.mock_connection.return_value.create_security_policy mock_find_security_policies = self.create_patch( 'core.db.rlsmanager' '.RowLevelSecurityManager.find_security_policies') mock_find_security_policies.return_value = [] RowLevelSecurityManager.create_security_policy( policy="policy='True'", policy_type="select", grantee="test_grantee", grantor=self.username, repo_base=self.repo_base, repo=self.repo, table=self.repo) self.assertTrue(create_pol.called)
def security_policy_edit(request, repo_base, repo, table, policyid): ''' Edits a security policy defined for a table given a policy_id. ''' username = request.user.get_username() try: policy = request.POST['security-policy-edit'] policy_type = request.POST['policy-type-edit'] grantee = request.POST['policy-grantee-edit'] RowLevelSecurityManager.update_security_policy(policyid, policy, policy_type, grantee, username) except Exception as e: return HttpResponse(json.dumps({'error': str(e)}), content_type="application/json") return HttpResponseRedirect( reverse('browse-security_policies', args=(repo_base, repo, table)))
def process_permissions(self, permission): ''' Takes in the SQL permissions statement, extracts all the necessary components (permission type, grantee, repo_name, table_name, and permission) and creates a security policy for it in the policy table. ''' permission_type = self.extract_permission_type(permission) access_type = self.extract_access_type(permission) grantee = self.extract_grantee(permission) extract_table_info = self.extract_table_info(permission) policy = self.extract_policy(permission) repo = extract_table_info[0] table = extract_table_info[1] if permission_type == "grant": RowLevelSecurityManager.create_security_policy( policy=policy, policy_type=access_type, grantee=grantee, grantor=self.user, repo_base=self.repo_base, repo=repo, table=table) else: # Need to remove policy if it is remove policies = RowLevelSecurityManager.find_security_policies( repo_base=self.repo_base, repo=repo, table=table, policy=policy, policy_type=access_type, grantee=grantee, grantor=self.user, safe=False) if len(policies) == 1: RowLevelSecurityManager.remove_security_policy( policy_id=policy[0][0], username=self.user, repo_base=self.repo_base) else: raise Exception('Error identifying security policy.')
def process_permissions(self, permission): ''' Takes in the SQL permissions statement, extracts all the necessary components (permission type, grantee, repo_name, table_name, and permission) and creates a security policy for it in the policy table. ''' permission_type = self.extract_permission_type(permission) access_type = self.extract_access_type(permission) grantee = self.extract_grantee(permission) extract_table_info = self.extract_table_info(permission) policy = self.extract_policy(permission) repo = extract_table_info[0] table = extract_table_info[1] if permission_type == "grant": RowLevelSecurityManager.create_security_policy( policy=policy, policy_type=access_type, grantee=grantee, grantor=self.user, repo_base=self.repo_base, repo=repo, table=table) else: # Need to remove policy if it is remove policies = RowLevelSecurityManager.find_security_policies( repo_base=self.repo_base, repo=repo, table=table, policy=policy, policy_type=access_type, grantee=grantee, grantor=self.user, safe=False) if len(policies) == 1: RowLevelSecurityManager.remove_security_policy( policy_id=policy[0][0], username=self.user, repo_base=self.repo_base) else: raise Exception('Error identifying security policy.')
def security_policy_edit(request, repo_base, repo, table, policyid): ''' Edits a security policy defined for a table given a policy_id. ''' username = request.user.get_username() try: policy = request.POST['security-policy-edit'] policy_type = request.POST['policy-type-edit'] grantee = request.POST['policy-grantee-edit'] RowLevelSecurityManager.update_security_policy( policyid, policy, policy_type, grantee, username) except Exception as e: return HttpResponse( json.dumps( {'error': str(e)}), content_type="application/json") return HttpResponseRedirect( reverse('browse-security_policies', args=(repo_base, repo, table)))
def update_security_policy( self, policy_id, new_policy, new_policy_type, new_grantee): res = RowLevelSecurityManager.update_security_policy( policy_id=policy_id, new_policy=new_policy, new_policy_type=new_policy_type, new_grantee=new_grantee, username=self.username) return res
def find_security_policies( self, repo=None, table=None, policy_id=None, policy=None, policy_type=None, grantee=None): res = RowLevelSecurityManager.find_security_policies( repo_base=self.username, repo=repo, table=table, policy_id=policy_id, policy=policy, policy_type=policy_type, grantee=grantee, grantor=self.username, safe=True) policies = [p._asdict() for p in res] return policies
def create_security_policy( self, policy, policy_type, grantee, repo, table): res = RowLevelSecurityManager.create_security_policy( policy=policy, policy_type=policy_type, grantee=grantee, grantor=self.username, repo_base=self.username, repo=repo, table=table, safe=True) return res
def security_policies(request, repo_base, repo, table): ''' Shows the security policies defined for a table. ''' username = request.user.get_username() # get the security policies on a given repo.table try: policies = RowLevelSecurityManager.list_security_policies( repo_base, repo, table, username) except LookupError: policies = [] res = { 'login': username, 'repo_base': repo_base, 'repo': repo, 'table': table, 'policies': policies } res.update(csrf(request)) return render_to_response("security-policies.html", res)
def remove_security_policy(self, policy_id): res = RowLevelSecurityManager.remove_security_policy( policy_id=policy_id, username=self.username) return res
class RowLevelSecurityManagerTests(TestCase): @factory.django.mute_signals(signals.pre_save) def setUp(self): self.username = "******" self.repo_base = "test_username" self.repo = "test_repo" self.table = "test_table" self.user = User.objects.create_user(self.username) self.mock_connection = self.create_patch( 'core.db.rlsmanager.core.db.connection.DataHubConnection') self.manager = RowLevelSecurityManager(self.username, self.repo_base) def create_patch(self, name): # helper method for creating patches patcher = patch(name) thing = patcher.start() self.addCleanup(patcher.stop) return thing def test_create_security_policy(self): create_pol = self.mock_connection.return_value.create_security_policy mock_find_security_policies = self.create_patch( 'core.db.rlsmanager' '.RowLevelSecurityManager.find_security_policies') mock_find_security_policies.return_value = [] RowLevelSecurityManager.create_security_policy( policy="policy='True'", policy_type="select", grantee="test_grantee", grantor=self.username, repo_base=self.repo_base, repo=self.repo, table=self.repo) self.assertTrue(create_pol.called) def test_list_security_policies(self): list_policy = self.create_patch( 'core.db.rls_permissions.RowLevelSecurityManager.' 'list_security_policies') self.manager.list_security_policies(self.repo, self.table) self.assertTrue(list_policy.called) def test_find_security_policies(self): find_policies = self.mock_connection.return_value\ .find_security_policies RowLevelSecurityManager.find_security_policies( repo_base=self.repo_base, repo=self.repo, table=self.table, policy="visible='True", policy_type="insert", grantee="test", grantor="test_grantor") self.assertTrue(find_policies.called) def test_find_security_policy_by_id(self): find_id = self.mock_connection.return_value.find_security_policy_by_id self.manager.find_security_policy_by_id(policy_id=1) self.assertTrue(find_id.called) def test_update_security_policy(self): update_pol = self.create_patch( 'core.db.rls_permissions.RowLevelSecurityManager.' 'update_security_policy') self.manager.update_security_policy( policy_id=1, new_policy="visible=False", new_policy_type="select", new_grantee="test_grantor", username=self.username) self.assertTrue(update_pol.called) def test_remove_security_policy(self): remove_pol = self.create_patch( 'core.db.rls_permissions.RowLevelSecurityManager.' 'remove_security_policy') self.manager.remove_security_policy( policy_id=1, username=self.username, repo_base=self.repo_base) self.assertTrue(remove_pol.called)