Exemple #1
0
def register_models(oso: Oso, base):
    """Register all models in model base class ``base`` with oso as classes."""
    # TODO (dhatch): Not sure this is legit b/c it uses an internal interface?
    for name, model in base._decl_class_registry.items():
        if name == "_sa_module_registry":
            continue

        oso.register_class(model)
Exemple #2
0
def test_oso():
    oso = Oso()
    oso.register_class(Actor, name="test_oso::Actor")
    oso.register_class(Widget, name="test_oso::Widget")
    oso.register_class(Company, name="test_oso::Company")
    oso.load_file(Path(__file__).parent / "test_oso.polar")

    return oso
Exemple #3
0
def test_quickstart_policy_4():
    oso = Oso()
    oso.register_class(Expense)
    oso.load_file("../polar/expenses-04.polar")
    assert oso.is_allowed("*****@*****.**", "GET", EXPENSES[1])
    assert not oso.is_allowed("*****@*****.**", "GET", EXPENSES[3])
    assert not oso.is_allowed("*****@*****.**", "GET", EXPENSES[1])
    assert oso.is_allowed("*****@*****.**", "GET", EXPENSES[3])
Exemple #4
0
def init_oso(app):
    base_oso = Oso()
    oso = FlaskOso(base_oso)

    register_models(base_oso, Base)
    set_get_session(base_oso, lambda: g.session)
    base_oso.load_file("app/authorization.polar")
    app.oso = oso
Exemple #5
0
def init_oso(db: Session):
    oso = Oso()
    register_models(oso, Base)
    set_get_session(oso, lambda: db)
    oso.load_file("app/authorization/rules/role_basics.polar")
    oso.load_file("app/authorization/rules/organization_permissions.polar")
    oso.load_file("app/authorization/rules/team_permissions.polar")
    oso.load_file("app/authorization/rules/dataroom_permissions.polar")
    enable_roles(oso)

    return oso
Exemple #6
0
def test_quickstart_policy_2():
    oso = Oso()
    alice = "*****@*****.**"
    expense = EXPENSES[1]
    assert not oso.is_allowed(alice, "GET", expense)
    oso.register_class(Expense)
    oso.load_file("../polar/expenses-02.polar")
    assert oso.is_allowed(alice, "GET", expense)
    assert not oso.is_allowed("*****@*****.**", "GET", expense)
Exemple #7
0
def test_quickstart_policy_3():
    oso = Oso()
    oso.register_class(Expense)
    oso.load_file("../polar/expenses-03-py.polar")
    expense = EXPENSES[1]
    assert oso.is_allowed("*****@*****.**", "GET", expense)
    assert not oso.is_allowed("*****@*****.**", "GET", expense)
def test_multi():
    oso = Oso()
    oso.load_str("allow(x, y) if x == y;")

    tp = ThreadPoolExecutor(max_workers=8)

    futures = []
    for _ in range(32):
        futures.append(tp.submit(torch_oso, oso))

    for i, future in enumerate(concurrent.futures.as_completed(futures)):
        future.result()

    # If we got here none of these crashed.
    assert True
Exemple #9
0
def update_team_role(
        org_id: UUID,
        team_id: UUID,
        role_id: UUID,
        req: schemas.TeamRoleRequest,
        current_user: models.User = Depends(deps.get_current_active_user),
        db: Session = Depends(deps.get_db),
        auth: Oso = Depends(deps.get_oso),
):
    team = crud.team.get(db, team_id)

    if team is None or team.organization_fk != org_id:
        raise HTTPException(status_code=404)

    if not auth.is_allowed(current_user, "DELETE_ROLE", team):
        raise HTTPException(status_code=403)

    role = db.query(models.TeamRole).filter_by(id=role_id).first()

    if role is None:
        raise HTTPException(status_code=404)

    if role.user_id != req.user_id:
        raise HTTPException(status_code=404)

    user = crud.user.get(db, id=role.user_id)

    if user is None:
        raise HTTPException(status_code=404)

    crud.team_roles.update_user_role(db,
                                     user=user,
                                     resource=team,
                                     role_name=req.user_role)
    return "OK"
Exemple #10
0
def create_team_role(
        org_id: UUID,
        team_id: UUID,
        req: schemas.TeamRoleRequest,
        current_user: models.User = Depends(deps.get_current_active_user),
        db: Session = Depends(deps.get_db),
        auth: Oso = Depends(deps.get_oso),
):
    team = crud.team.get(db, team_id)

    if team is None or team.organization_fk != org_id:
        raise HTTPException(status_code=404)

    if not auth.is_allowed(current_user, "CREATE_ROLE", team):
        raise HTTPException(status_code=403)

    user_to_add = crud.user.get(db, id=req.user_id)

    if user_to_add is None:
        raise HTTPException(status_code=404)

    crud.team_roles.add_user_role(db,
                                  user=user_to_add,
                                  resource=team,
                                  role_name=req.user_role)
    return "OK"
Exemple #11
0
def create_team(
        org_id: UUID,
        req: schemas.TeamCreateRequest,
        current_user: models.User = Depends(deps.get_current_active_user),
        db: Session = Depends(deps.get_db),
        auth: Oso = Depends(deps.get_oso),
):
    org = crud.org.get(db, org_id)

    if org is None:
        raise HTTPException(status_code=404)

    # check if user is allowed to create a new team
    create_team = schemas.TeamCreate(
        creator=current_user,
        organization=org,
        name=req.name,
        description=req.description,
        is_active=True,
    )
    new_team = crud.team.create_model(create_team)
    if not auth.is_allowed(current_user, "CREATE", new_team):
        raise HTTPException(status_code=403)

    # add the newly created model to db
    created_team = crud.team.add_model_to_db(db, model=new_team)

    # add the user as the team owner
    crud.team_roles.add_user_role(db, current_user, created_team, "OWNER")

    return created_team
Exemple #12
0
def delete_dataroom_team_role(
        org_id: UUID,
        dataroom_id: UUID,
        role_id: UUID,
        current_user: models.User = Depends(deps.get_current_active_user),
        db: Session = Depends(deps.get_db),
        auth: Oso = Depends(deps.get_oso),
):
    dataroom = crud.dataroom.get(db, dataroom_id)

    if dataroom is None or dataroom.organization_fk != org_id:
        raise HTTPException(status_code=404)

    if not auth.is_allowed(current_user, "DELETE_ROLE", dataroom):
        raise HTTPException(status_code=403)

    role = db.query(models.DataRoomRole).filter_by(id=role_id).first()

    if role is None:
        raise HTTPException(status_code=404)

    if role.team_id != role.team_id:
        raise HTTPException(status_code=404)

    crud.room_roles.delete_team_role(db, team_role_id=role.id)

    return "OK"
Exemple #13
0
def create_dataroom_team_role(
        org_id: UUID,
        dataroom_id: UUID,
        req: schemas.DataRoomTeamRoleRequest,
        current_user: models.User = Depends(deps.get_current_active_user),
        db: Session = Depends(deps.get_db),
        auth: Oso = Depends(deps.get_oso),
):
    dataroom = crud.dataroom.get(db, dataroom_id)

    if dataroom is None or dataroom.organization_fk != org_id:
        raise HTTPException(status_code=404)

    if not auth.is_allowed(current_user, "CREATE_ROLE", dataroom):
        raise HTTPException(status_code=403)

    team_to_add = crud.team.get(db, id=req.team_id)

    if team_to_add is None:
        raise HTTPException(status_code=404)

    crud.room_roles.add_team_role(db,
                                  team=team_to_add,
                                  room=dataroom,
                                  role_name=req.team_role)
    return "OK"
Exemple #14
0
def set_get_session(oso: Oso, get_session_func):
    """Set the function that oso uses to expose a SQLAlchemy session to the policy

    :param oso: The Oso instance used to evaluate the policy.
    :type oso: Oso

    :param get_session_func: A function that returns a SQLAlchemy session
    :type get_session_func: lambda

    The session can be accessed from polar via the OsoSession constant. E.g.,

    .. code-block:: polar

        OsoSession.get().query(...)
    """
    _OsoSession.set_get_session(get_session_func)
    oso.register_constant(_OsoSession, "OsoSession")
Exemple #15
0
def load_oso():
    """Loads and returns the oso policy"""
    oso = Oso()
    policy_path = Path(__file__).resolve().parent.parent / "expenses"
    ## Policy Data
    oso.load_file(policy_path / "data.polar")
    ## Role definitions
    oso.load_file(policy_path / "roles.polar")
    ## ABAC policy
    oso.load_file(policy_path / "abac.polar")
    return oso
Exemple #16
0
class Oso(models.AbstractModel):
    _name = "oso"
    _description = "global oso state"
    oso = Oso()

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        policy = get_resource_path("oso_auth", "security", "base.polar")
        self.oso.load_file(policy)
Exemple #17
0
def create_invite_to_room(
        dataroom_id: UUID,
        org_id: UUID,
        req: schemas.InviteAPIRequest,
        current_user: models.User = Depends(deps.get_current_active_user),
        db: Session = Depends(deps.get_db),
        auth: Oso = Depends(deps.get_oso),
):
    # check whether the path is correct so that dataroom belongs to org
    # and dataroom actually exists
    room = crud.dataroom.get(db, id=dataroom_id)
    if not room:
        raise HTTPException(status_code=400)

    if not room.organization_fk == org_id:
        raise HTTPException(status_code=400)

    # check whether the user is allowed to create invites
    if not auth.is_allowed(current_user, "INVITE_GUESTS", room):
        raise HTTPException(status_code=404, detail="Not enough privileges")

    # check whether the invitee already exists in db, if not create him/her
    create_user = schemas.UserCreate(email=req.email,
                                     password=security.random_password())
    invitee = crud.user.create_if_not_exists(db, obj_in=create_user)

    # add user to the specific role
    crud.room_roles.add_user_role(db, invitee, room, req.user_role)

    # generate access url
    access_token_expires = timedelta(days=req.expires_in)
    token = security.create_access_token(invitee.id,
                                         expires_delta=access_token_expires)

    # generate invitation entry in db
    create_invite = schemas.InviteCreate(
        invitee=invitee,
        jwt_token=token,
        dataroom=room,
        creator=current_user,
        expires_in=security.calculate_expires_in_days(req.expires_in),
    )
    crud.invite.create(db, obj_in=create_invite)

    # generate access link
    access_link = f"{settings.DOMAIN_NAME}/access?token={token}"

    # generate email and send invite to the user
    send_access_email(
        email_to=req.email,
        access_link=access_link,
        invitor_name=f"{current_user.first_name} {current_user.last_name}",
    )
    return "OK"
Exemple #18
0
def test_set_get_session():
    from sqlalchemy_oso.session import set_get_session
    from oso import Oso

    def get_session():
        engine = create_engine("sqlite://")
        Base.metadata.create_all(engine)

        Session = sessionmaker(bind=engine)
        session = Session()

        load_fixture_data(session)

        return session

    oso = Oso()
    set_get_session(oso, get_session)
    register_models(oso, Base)
    test_str = """get_repo(name: String) if
                    session = OsoSession.get() and
                    repo = session.query(Repository).filter_by(name: name).first() and
                    repo.name = name;
                    """

    oso.load_str(test_str)
    results = oso.query_rule("get_repo", "Abbey Road")
    assert next(results)
    results = oso.query_rule("get_repo", "Abbey Road")
    assert next(results)
Exemple #19
0
def rmdir(path):
    import shutil
    import getpass
    from oso import Oso
    oso = Oso()
    oso.register_class(PathAttributes)
    oso.load_files(["rmdir.polar"])
    path_attributes = get_path_attributes(path)
    user_id = getpass.getuser()
    if oso.is_allowed(user_id, "can_remove", path_attributes):
        shutil.rmtree(path)
    else:
        raise PermissionError(f"You cannot delete {path}")
Exemple #20
0
def load_oso():
    """Loads and returns the oso policy"""
    oso = Oso()
    policy_path = Path(__file__).resolve().parent.parent / "policies"
    # Role definitions
    oso.load_file(policy_path / "rbac.polar")
    # ABAC policy
    oso.load_file(policy_path / "abac.polar")

    return oso
Exemple #21
0
def list_documents(
    dataroom_id: UUID,
    org_id: UUID,
    db: Session = Depends(deps.get_db),
    auth: Oso = Depends(deps.get_oso),
    current_user: models.User = Depends(deps.get_current_active_user),
) -> Any:
    # check whether the path is correct and dataroom belongs to org
    room = crud.dataroom.get(db, id=dataroom_id)
    if not room.organization_fk == org_id:
        raise HTTPException(status_code=400)

    # make sure user is allowed to list documents
    if not auth.is_allowed(current_user, "LIST_DOCUMENTS", room):
        raise HTTPException(status_code=404)

    documents = crud.document.get_multi_by_room(db, dataroom_id)
    return documents
Exemple #22
0
def get_datarooms(
        org_id: UUID,
        db: Session = Depends(deps.get_db),
        auth: Oso = Depends(deps.get_oso),
        current_user: models.User = Depends(deps.get_current_active_user),
):
    org = crud.org.get(db, org_id)

    if org is None:
        raise HTTPException(status_code=404)

    # first find out if the user is allowed to list rooms in a given org
    if not auth.is_allowed(current_user, "LIST_ROOMS", org):
        raise HTTPException(status_code=400, detail="Not enough privileges")

    rooms = crud.dataroom.get_multi_by_org(db, org)

    return rooms
Exemple #23
0
def authorize_model_filter(oso: Oso, actor, action, session: Session, model):
    """Return SQLAlchemy expression that applies the policy to ``model``.

    Executing this query will return only authorized objects. If the request is
    not authorized, a query that always contains no result will be returned.

    :param oso: The oso class to use for evaluating the policy.
    :param actor: The actor to authorize.
    :param action: The action to authorize.

    :param session: The SQLAlchemy session.
    :param model: The model to authorize, must be a SQLAlchemy model.
    """
    try:
        mapped_class = inspect(model, raiseerr=True).class_
    except AttributeError:
        raise TypeError(f"Expected a model; received: {model}")

    partial_resource = Partial("resource",
                               TypeConstraint(polar_model_name(mapped_class)))
    results = oso.query_rule("allow", actor, action, partial_resource)

    combined_filter = None
    has_result = False
    for result in results:
        has_result = True

        resource_partial = result["bindings"]["resource"]
        filter = partial_to_filter(resource_partial,
                                   session,
                                   model,
                                   get_model=oso.get_class)
        if combined_filter is None:
            combined_filter = filter
        else:
            combined_filter = combined_filter | filter

    if not has_result:
        return sql.false()

    return combined_filter
Exemple #24
0
def update_invitation(
        dataroom_id: UUID,
        org_id: UUID,
        invite_id: UUID,
        req: schemas.InviteAPIRequest,
        current_user: models.User = Depends(deps.get_current_active_user),
        db: Session = Depends(deps.get_db),
        auth: Oso = Depends(deps.get_oso),
):
    # check whether the path is correct so that dataroom belongs to org
    # and dataroom actually exists
    room = crud.dataroom.get(db, id=dataroom_id)
    if not room:
        raise HTTPException(status_code=400)

    if not room.organization_fk == org_id:
        raise HTTPException(status_code=400)

    # check whether the user is allowed to create invites
    if not auth.is_allowed(current_user, "INVITE_GUESTS", room):
        raise HTTPException(status_code=404, detail="Not enough privileges")

    invitation = crud.invite.get(db, invite_id)

    if not invitation:
        raise HTTPException(status_code=404)

    if not invitation.invitee.email == req.email:
        raise HTTPException(status_code=400)

    crud.room_roles.update_user_role(db, invitation.invitee, room,
                                     req.user_role)

    expires_in_timestamp = security.calculate_expires_in_days(req.expires_in)
    invitation_update_schema = schemas.InviteUpdate(
        expires_in=expires_in_timestamp)

    crud.invite.update(db, db_obj=invitation, obj_in=invitation_update_schema)

    return "OK"
Exemple #25
0
def update_team(
        org_id: UUID,
        team_id: UUID,
        req: schemas.TeamCreateRequest,
        current_user: models.User = Depends(deps.get_current_active_user),
        db: Session = Depends(deps.get_db),
        auth: Oso = Depends(deps.get_oso),
):
    team = crud.team.get(db, team_id)

    if team is None or team.organization_fk != org_id:
        raise HTTPException(status_code=404)

    if not auth.is_allowed(current_user, "UPDATE", team):
        raise HTTPException(status_code=403)

    update_team = schemas.TeamUpdate(name=req.name,
                                     description=req.description)

    updated_team = crud.team.update(db, db_obj=team, obj_in=update_team)

    return updated_team
Exemple #26
0
def test_team_dataroom_roles(db: Session, data: Data, oso: Oso):
    # make sure that a user that does not have direct
    # room roles can still manage room because of a team
    # role
    user_roles_in_room_1: List = oso_roles.get_user_roles(
        db, data.member_team_1, Dataroom, data.room_1.id)

    # user does not have direct access to the room
    count_of_roles = len(user_roles_in_room_1)
    assert count_of_roles == 0

    # but still gets it via his team role (which is a members role)
    assert oso.is_allowed(data.member_team_1, "READ", data.room_1) is True
    assert oso.is_allowed(data.member_team_1, "LIST_DOCUMENTS",
                          data.room_1) is True
    assert oso.is_allowed(data.member_team_1, "DELETE", data.room_1) is False
    assert oso.is_allowed(data.member_team_1, "UPDATE", data.room_1) is False
    assert oso.is_allowed(data.member_team_1, "INVITE_GUESTS",
                          data.room_1) is False

    # does not have access to other rooms
    assert oso.is_allowed(data.member_team_1, "READ", data.room_2) is False
    assert oso.is_allowed(data.member_team_1, "LIST_DOCUMENTS",
                          data.room_2) is False

    # is allowed to create his own documents in a room
    new_document_team_member_1 = Document(
        name="New Doc Team Member 1",
        description="Test",
        file_name="new_doc_team_member_1",
        extension="txt",
        md5_sum=UUID("87a6909ab71ec463f013325dbf9f3543"),
        mime_type="text/plain",
        size=50,
        creator=data.member_team_1,
        dataroom=data.room_1,
    )

    assert (oso.is_allowed(data.member_team_1, "CREATE",
                           new_document_team_member_1) is True)
Exemple #27
0
def create_dataroom(
        org_id: UUID,
        dataroom_request: schemas.DataRoomCreateRequest,
        db: Session = Depends(deps.get_db),
        auth: Oso = Depends(deps.get_oso),
        current_user: models.User = Depends(deps.get_current_active_user),
):
    org = crud.org.get(db, org_id)

    if org is None:
        raise HTTPException(status_code=404)

    # create the room model in order to verify if user is allowed to create it
    create_room_schema = schemas.DataRoomCreate(creator=current_user,
                                                organization=org,
                                                name=dataroom_request.name)
    new_room = crud.dataroom.create_model(create_room_schema)
    # first find out if the user is allowed to create rooms in a given org
    if not auth.is_allowed(current_user, "CREATE", new_room):
        raise HTTPException(status_code=403, detail="Not enough privileges")

    new_room = crud.dataroom.add_model_to_db(db, model=new_room)

    return new_room
Exemple #28
0
def oso_with_session(test_db_session):
    oso = Oso()
    set_get_session(oso, lambda: test_db_session)
    register_models(oso, Base)

    return oso
Exemple #29
0
def oso():
    return Oso()
Exemple #30
0
import math
import os

from polar.exceptions import UnrecognizedEOF
from oso import Oso, OsoException, Variable

oso = Oso()

# Application class with default kwargs constructor, registered with the
# decorator.
class A:
    def __init__(self, x):
        self.x = x

    def foo(self):
        return -1


oso.register_class(A)


# Test inheritance; doesn't need to be registered.
class D(A):
    pass


# Namespaced application class (to be aliased) with custom
# constructor.
class B:
    class C:
        def __init__(self, y):