Пример #1
0
 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())
         )
Пример #2
0
    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')
Пример #3
0
 def do_convert(input):
     if isinstance(input, str):
         if input == "*":
             return Any()
         else:
             return Eq(input)
     elif isinstance(input, Rule):
         return input
     return None
Пример #4
0
 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
Пример #5
0
    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()
Пример #6
0
    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())
Пример #7
0
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')
Пример #8
0
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:
Пример #9
0
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()),
Пример #10
0
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(
Пример #11
0
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()),
Пример #12
0
    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
Пример #13
0
    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"
                )