def _find_and_add_policy(self, data, name, action, protocol): protocol_set = () for value in data[action][protocol]: protocol_set += (Eq(value),) protocol_set = set(protocol_set) if protocol_set: self.add_policy( ied=Eq(name), action=Eq(action), address={'mac': Or(*protocol_set)}, protocol=Eq(protocol.upper()) )
def _from_file(self, path): for ied, value in parse_scd(path).items(): self.add_policy( ied=Eq(ied), action=Any(), address={'ip': Eq(value['ip'])}, protocol=Eq('MMS')) self._find_and_add_policy(value, ied, 'publish', 'goose') self._find_and_add_policy(value, ied, 'publish', 'sv') self._find_and_add_policy(value, ied, 'subscribe', 'goose') self._find_and_add_policy(value, ied, 'subscribe', 'sv')
def do_convert(input): if isinstance(input, str): if input == "*": return Any() else: return Eq(input) elif isinstance(input, Rule): return input return None
def test_same_inquiries_are_cached(self): guard, storage, cache = create_cached_guard(MemoryStorage(), RulesChecker(), maxsize=256) p1 = Policy(1, actions=[Eq('get')], resources=[Eq('book')], subjects=[Eq('Max')], effect=ALLOW_ACCESS) storage.add(p1) inq1 = Inquiry(action='get', resource='book', subject='Max') inq2 = Inquiry(action='get', resource='book', subject='Jamey') assert guard.is_allowed(inq1) assert guard.is_allowed(inq1) assert guard.is_allowed(inq1) assert guard.is_allowed(inq1) assert guard.is_allowed(inq1) assert not guard.is_allowed(inq2) assert 4 == cache.info().hits assert 2 == cache.info().misses assert 2 == cache.info().currsize
def test_cache_is_invalidated_on_policy_change(self): def assert_after_modification(): assert 0 == cache.info().hits assert 0 == cache.info().misses assert 0 == cache.info().currsize assert not guard.is_allowed(inq1) assert not guard.is_allowed(inq1) assert guard.is_allowed(inq2) assert guard.is_allowed(inq2) assert guard.is_allowed(inq2) assert 3 == cache.info().hits assert 2 == cache.info().misses assert 2 == cache.info().currsize inq1 = Inquiry(action='get', resource='book', subject='Max') inq2 = Inquiry(action='get', resource='book', subject='Jim') guard, storage, cache = create_cached_guard(MemoryStorage(), RulesChecker(), maxsize=256) p1 = Policy(1, actions=[Eq('get')], resources=[Eq('book')], subjects=[Eq('Max')], effect=ALLOW_ACCESS) p2 = Policy(2, actions=[Eq('get')], resources=[Eq('magazine')], subjects=[Eq('Max')], effect=ALLOW_ACCESS) storage.add(p1) assert guard.is_allowed(inq1) assert guard.is_allowed(inq1) assert 1 == cache.info().hits assert 1 == cache.info().misses assert 1 == cache.info().currsize # start modifications p1.subjects = [Eq('Jim')] storage.update(p1) assert_after_modification() storage.add(p2) assert_after_modification() storage.delete(p2) assert_after_modification()
def __init__(self, auto=None): self._storage = MemoryStorage() if auto: self._from_file(auto) self.add_policy( ied=Any(), action=[Eq('publish'), Eq('subscribe')], address={'mac': Not(StartsWith('01:0c:cd:01'))}, protocol=Eq('GOOSE'), access=DENY_ACCESS) self.add_policy( ied=Any(), action=[Eq('publish'), Eq('subscribe')], address={'mac': Not(StartsWith('01:0c:cd:04'))}, protocol=Eq('SV'), access=DENY_ACCESS) self._guard = Guard(self._storage, RulesChecker())
import logging import uuid import os import Pyro4 import pymongo import vakt from vakt.rules import Eq, Any, NotEq, StartsWith, In, RegexMatch, CIDR, And, Greater, Less from vakt.storage.mongo import MongoStorage # Policies that guard our tiny Github clone. policies = [ vakt.Policy( str(uuid.uuid4()), actions=[Eq('get'), Eq('list'), Eq('read')], resources=[StartsWith('repos/google/tensor')], subjects=[Any()], effect=vakt.ALLOW_ACCESS, description= 'Grant read-access for all Google repositories starting with "tensor" to any User' ), vakt.Policy( str(uuid.uuid4()), actions=[In('delete', 'prune', 'exterminate')], resources=[RegexMatch(r'repos\/.*?\/.*?')], subjects=[{ 'name': Any(), 'role': Eq('admin')
import vakt from vakt.rules import CIDR, Eq, Any, And, Greater, Less, SubjectMatch from vakt import Policy, ALLOW_ACCESS, DENY_ACCESS from resources import USERS from flask import abort, Response import sys adminFullAcces = Policy( 1, effect=ALLOW_ACCESS, subjects=[{ 'group': Eq('Admin') }], resources=[Any()], actions=[Any()], description= "Users with this policy can perform any actions on any resources with any methods" ) ownerAccess = Policy( 2, effect=ALLOW_ACCESS, subjects=[Any()], resources=[{ 'owner_id': SubjectMatch('id') }], actions=[Eq('GET'), Eq('POST'), Eq('PUT')], ) policies = [adminFullAcces, ownerAccess] storage = vakt.MemoryStorage() for policy in policies:
import Pyro4 import pymongo from vakt.storage.mongo import MongoStorage from vakt.storage.sql import SQLStorage from vakt.storage.sql.model import Base from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker, scoped_session # Policies that guard our tiny Github clone. policies = [ vakt.Policy( str(uuid.uuid4()), actions=[Eq('get'), Eq('list'), Eq('read')], resources=[StartsWith('repos/google/tensor')], subjects=[Any()], effect=vakt.ALLOW_ACCESS, description='Grant read-access for all Google repositories starting with "tensor" to any User' ), vakt.Policy( str(uuid.uuid4()), actions=[In('delete', 'prune', 'exterminate')], resources=[RegexMatch(r'repos\/.*?\/.*?')], subjects=[{'name': Any(), 'role': Eq('admin')}, {'name': Eq('defunkt')}, Eq('defunkt')], effect=vakt.ALLOW_ACCESS, description='Grant delete-access for any repository to any User with "admin" role, or to a User named defunkt' ), vakt.Policy( str(uuid.uuid4()),
import uuid import vakt from vakt.rules import Eq, Any, StartsWith, Not, Or storage = vakt.MemoryStorage() policy = vakt.Policy( str(uuid.uuid4()), subjects=[Eq('ied01')], actions=[{ 'type': Or(Eq('publish')), 'dest': Eq('01:0c:cd:01:00:01') }], resources=[Eq('GOOSE')], effect=vakt.ALLOW_ACCESS, ) storage.add(policy) policy = vakt.Policy( str(uuid.uuid4()), subjects=[Eq('ied02')], actions=[{ 'type': Or(Eq('subscribe')), 'dest': Eq('01:0c:cd:01:00:01') }], resources=[Eq('GOOSE')], effect=vakt.ALLOW_ACCESS, ) storage.add(policy) policy = vakt.Policy(
import logging import uuid import os import vakt from vakt.rules import Eq, Any, NotEq, StartsWith, In, RegexMatch, CIDR, And, Greater, Less policies = [ vakt.Policy( str(uuid.uuid4()), actions=[Eq('get'), Eq('list'), Eq('read')], resources=[{'platform': Eq('lib/states'), 'id': Any()}], # resources=[{'platform': Eq('lib/states')}], subjects=[Eq('user:joe')], effect=vakt.DENY_ACCESS, # effect=vakt.ALLOW_ACCESS, description='Grant read access to all states' ), vakt.Policy( str(uuid.uuid4()), actions=[Eq('get'), Eq('list'), Eq('read')], resources=[{'platform': Eq('lib/states'), 'id': Eq("one")}], subjects=[Eq('user:joe')], effect=vakt.ALLOW_ACCESS, # effect=vakt.DENY_ACCESS, description='Grant read access to all states' ), # vakt.Policy( # str(uuid.uuid4()),
def new(self, attachment: Type[AuthMixin], machine_label: str, label: str, description: str, actions, resources, subjects: Optional[list] = None, effect: Union[None, vakt.ALLOW_ACCESS, vakt.DENY_ACCESS] = None, request_by: Optional[str] = None, request_by_type: Union[None, str] = None, request_context: Optional[str] = None, authentication: Optional[Type[AuthMixin]] = None, permission_id=None, load_source=None): """ Create a new permission and attach to a role, user, or authkey. To track how the permission was created, either request_by and request_by_type or an authentication item can be anything with the authmixin, such as a user, websession, or authkey. :param attachment: A role, authkey, or user. :param machine_label: Permission machine_label :param label: Permission human label. :param description: Permission description. :param actions: :param resources: :param subjects: :param effect: :param request_by: Who created the permission. "alexamodule" :param request_by_type: What type of item created it: "module" :param request_context: Some additional information about where the request comes from. :param authentication: An auth item such as a websession or authkey. :param permission_id: permission the role was loaded. :param load_source: How the permission was loaded. :return: """ _request_by, _request_by_type = self.request_by_info(authentication, request_by, request_by_type) if permission_id is None: permission_id = random_string(length=38) # else: # permission_id = self._Hash.sha224_compact(f"{_request_by}:{_request_by_type}:{machine_label}:{permission_id}") try: found = self.get_advanced({"machine_label": machine_label, "permission_id": permission_id}, multiple=False) raise YomboWarning(f"Found a matching permission: {found.machine_label} - {found.label}") except KeyError: pass if effect in (None, True, 1, 'allow'): effect = vakt.ALLOW_ACCESS else: effect = vakt.DENY_ACCESS if subjects is None: subjects = [Eq(f"{attachment.auth_type}:{attachment.auth_id}")] else: subjects = self.convert_items_to_vakt(subjects) policy = vakt.Policy( permission_id, actions=self.convert_items_to_vakt(actions), resources=self.convert_items_to_vakt(resources), subjects=subjects, effect=effect, # context=self.convert_items_to_vakt(context), description=description, ).to_json() if label is None: label = machine_label if description is None: description = label results = yield self.load_an_item_to_memory( { "id": permission_id, "attach_id": attachment.auth_id, "attach_type": attachment.auth_type, "policy": policy, "machine_label": machine_label, "label": label, "description": description, "request_by": request_by, "request_by_type": request_by_type, "request_context": request_context, }, authentication=authentication, load_source=load_source, generated_source=caller_string()) return results
def setup_system_permissions(self): Roles = self._Roles # print(f'permissions - init - roles: {Roles.roles}') # define admin # print("11 permissions, about to define system admin.") permission_id = self._Hash.sha224_compact(f"auto-admin-{self.system_seed}") if permission_id not in self.permissions: # print(f"creating admin permission: {permission_id}") role = Roles.get("admin") yield self.new( role, machine_label="admin", label="Administrator", description="Grant access to everything for admins.", actions=[Any()], resources=[{"platform": Any(), "id": Any()}], # subjects=[f"role:{role.role_id}"], permission_id=permission_id, effect=vakt.ALLOW_ACCESS, request_by="permissions", request_by_type="library", request_context="setup_system_permissions", load_source="local", ) for platform, data in AUTH_PLATFORMS.items(): platform_parts = platform.split(".") # define platform admins platform_machine_label = f"{platform_parts[0]}_{platform_parts[1]}_{platform_parts[2]}_admin".lower() platform_label = f"{platform_parts[2]} {platform_parts[1]} {platform_parts[0]}" permission_id = self._Hash.sha224_compact(f"admin-{platform_machine_label} {self.system_seed}") role_id = self._Hash.sha224_compact(permission_id) try: role = self._Roles.get_advanced({"role_id": role_id, "machine_label": platform_machine_label}, multiple=False) except KeyError: # print(f'data["actions"]["possible"]: {data["actions"]["possible"]}') actions_string = ", ".join(data["actions"]["possible"]) description = f"Admin access to '{platform_label}', actions: {actions_string}" role = yield self._Roles.new( role_id=role_id, machine_label=platform_machine_label, label=f"{platform_label} admin", description=description, request_by="permissions", request_by_type="library", request_context="setup_system_permissions", load_source="local", ) # print(f"22 permissions, about to define platform admin: {platform_label}") if permission_id not in self.permissions: yield self.new( role, machine_label=platform_machine_label, label=f"{platform_label} admin", description=description, actions=data["actions"]["possible"], resources=[{"platform": Eq(platform), "id": Any()}], # subjects=[Eq(f"role:{role.role_id}")], permission_id=permission_id, effect=vakt.ALLOW_ACCESS, request_by="permissions", request_by_type="library", request_context="setup_system_permissions", load_source="local", ) # else: # self.attach_ # define platform actions for more fine grained controls for action in data["actions"]["possible"]: platform_machine_label = f"{platform_parts[0]}_{platform_parts[1]}_{platform_parts[2]}_{action}".lower() platform_label = f"{platform_parts[0]} {platform_parts[1]} {platform_parts[2]}" permission_id = self._Hash.sha224_compact(f"action-{platform_machine_label} {action} {self.system_seed}") role_id = self._Hash.sha224_compact(permission_id) try: role = self._Roles.get_advanced({"role_id": role_id, "machine_label": platform_machine_label}, multiple=False) except KeyError: description = f"Allow '{platform_label}', action: {action}" role = yield self._Roles.new( role_id=role_id, label=f"{platform_label} {action}", machine_label=platform_machine_label, description=description, request_by="permissions", request_by_type="library", request_context="setup_system_permissions", load_source="local" ) if permission_id not in self.permissions: yield self.new( role, machine_label=platform_machine_label, label=f"{platform_label} {action}", description=description, actions=[action], resources=[{"platform": Eq(platform), "id": Any()}], # subjects=[f"role:{role.role_id}"], permission_id=permission_id, effect=vakt.ALLOW_ACCESS, request_by="permissions", request_by_type="library", request_context="setup_system_permissions", load_source="local" ) # else: # attach.... # Grant all users basic access rights. This can be revoked using new policies to negate this. platform_machine_label = f"{platform_parts[0]}_{platform_parts[1]}_{platform_parts[2]}_user".lower() platform_label = f"{platform_parts[2]} {platform_parts[1]} {platform_parts[0]}" permission_id = self._Hash.sha224_compact(f"user-{platform_machine_label} {self.system_seed}") if permission_id not in self.permissions: if len(data["actions"]["user"]): role = Roles.get("users") actions_string = ", ".join(data["actions"]["user"]) # print(f"44 permissions, about to define platform user: {platform_machine_label} - {actions_string}") yield self.new( role, machine_label=platform_machine_label, label=platform_label, description=f"All users access to '{platform_machine_label}', actions: {actions_string}", actions=data["actions"]["user"], resources=[{"platform": Eq(platform), "id": Any()}], # subjects=[Eq(f"role:{role.role_id}")], permission_id=permission_id, effect=vakt.ALLOW_ACCESS, request_by="permissions", request_by_type="library", request_context="setup_system_permissions", load_source="local" )