Oso is an open source policy engine for authorization that’s embedded in your application

Overview

Oso

Development GitHub release (latest SemVer) Go version Maven version NPM version PyPI version RubyGems version Crates.io version Slack

What is Oso?

Oso is an open source policy engine for authorization that’s embedded in your application. It provides a declarative policy language for expressing authorization logic. You define this logic separately from the rest of your application code, but it executes inside the application and can call directly into it. Oso ships as a library with a built-in debugger and REPL.

Oso is ideal for building permissions into user-facing applications, but you can check out Use Cases to learn about other applications for Oso.

Using Oso consists of two parts:

  1. Writing Oso policies in a declarative policy language called Polar.
  2. Embedding Oso in your application using the appropriate language-specific authorization library.

Oso currently offers libraries for Java, Node.js, Python, Ruby, Rust and Go.

Getting started

To get up and running with Oso, check out the Getting Started guides in the Oso documentation.

Development

Core

Oso's Rust core is developed against Rust's latest stable release.

Language libraries

Oso's language libraries can be developed without touching the Rust core, but you will still need the Rust stable toolchain installed in order to build the core.

To build the WebAssembly core for the Node.js library, you will need to have wasm-pack installed and available on your system PATH.

Language requirements

To work on a language library, you will need to meet the following version requirements:

  • Java: 10+
    • Maven: 3.6+
  • Node.js: 10.14.2+
    • Yarn 1.22+
  • Python: 3.6+
  • Ruby: 2.4+
    • Bundler 2.1.4+
  • Rust: 1.46+
  • Go: 1.12+

Contributing

See: CONTRIBUTING.md.

License

See: LICENSE.

Comments
  • Trace Logging

    Trace Logging

    Trace output during execution of a query that shows what's happening. Should make debugging a bit easier.

    Notable features include.

    • Showing all the applicable rules when querying a call. This shows which rules and the order they will be tried after filtering and sorting has been done.
    • Showing Queries, Unifys, Matches, Comparisons and Math operations.
    • ShowingFFIi lookups and the results that come back.
    • Showing relevant bindings (bindings for variables used in the expressions being traced) alongside so it's easier to see what's happening.

    Looks something like this.

    query> f(1);
    [trace]   QUERY: 'f(1)', BINDINGS: {}
    [trace]     FILTERING RULES
    [trace]       UNIFY: '1' = '_x_4', BINDINGS: {}
    [trace]       UNIFY: '1' = '_x_6', BINDINGS: {}
    [trace]       UNIFY: '1' = '_x_7', BINDINGS: {}
    [trace]     SORTING RULES
    [trace]     APPLICABLE_RULES: [
    [trace]       f(x) if new (Foo{x: x}, _instance_2) and .(_instance_2, foo(), _value_1) and _value_1 = x;
    [trace]       f(x) if x = 1;
    [trace]       f(x) if x + 1 and _op_3 == 2;
    [trace]     ]
    [trace]     RULE:
    [trace]     f(x) if
    [trace]       new Foo{x: x}.foo() = x
    [trace]     UNIFY: '1' = '_x_10', BINDINGS: {}
    [trace]       QUERY: 'new (Foo{x: _x_10}, _instance_2_11) and .(_instance_2_11, foo(), _value_1_12) and _value_1_12 = _x_10', BINDINGS: {"_x_10": "1"}
    [trace]         QUERY: 'new (Foo{x: _x_10}, _instance_2_11)', BINDINGS: {"_x_10": "1"}
    [trace]           UNIFY: '_instance_2_11' = 'Foo{x: 1}', BINDINGS: {}
    [trace]         QUERY: '.(_instance_2_11, foo(), _value_1_12) and _value_1_12 = _x_10', BINDINGS: {"_instance_2_11": "Foo{x: 1}", "_x_10": "1"}
    [trace]           QUERY: '.(_instance_2_11, foo(), _value_1_12)', BINDINGS: {"_instance_2_11": "Foo{x: 1}"}
    [trace]             LOOKUP: Foo{x: 1}.foo()
    [trace]             => 2
    [trace]           QUERY: '_value_1_12 = _x_10', BINDINGS: {"_x_10": "1", "_value_1_12": "2"}
    [trace]             UNIFY: '_value_1_12' = '_x_10', BINDINGS: {"_value_1_12": "2", "_x_10": "1"}
    [trace]             UNIFY: '2' = '1', BINDINGS: {}
    [trace]             LOOKUP: Foo{x: 1}.foo()
    [trace]             => No more results.
    [trace]     RULE:
    [trace]     f(x) if
    [trace]       x = 1
    [trace]     UNIFY: '1' = '_x_13', BINDINGS: {}
    [trace]       QUERY: '_x_13 = 1', BINDINGS: {"_x_13": "1"}
    [trace]         UNIFY: '_x_13' = '1', BINDINGS: {"_x_13": "1"}
    [trace]         UNIFY: '1' = '1', BINDINGS: {}
    True
    [trace]     RULE:
    [trace]     f(x) if
    [trace]       x + 1 == 2
    [trace]     UNIFY: '1' = '_x_14', BINDINGS: {}
    [trace]       QUERY: '_x_14 + 1 and _op_3_15 == 2', BINDINGS: {"_x_14": "1"}
    [trace]         QUERY: '_x_14 + 1', BINDINGS: {"_x_14": "1"}
    [trace]           MATH: '1' + '1' = '_op_3_15', BINDINGS: {}
    [trace]           UNIFY: '2' = '_op_3_15', BINDINGS: {}
    [trace]         QUERY: '_op_3_15 == 2', BINDINGS: {"_op_3_15": "2"}
    [trace]           CMP: '2' == '2', BINDINGS: {}
    True
    query>
    
    opened by saolsen 19
  • refactor: Clarify error when right_path exists

    refactor: Clarify error when right_path exists

    Fixes #1552

    This commit catches the assertion error when verifying the right_path does not exist when a path has been identified on the left side of the policy. This refactor was made to better clarify the cause of the error for developers who may not be familiar with the technical limitations of the current SQLAlchemy integration.

    In my case, I had assumed that the use of foreign keys and paths on both sides would be more performant, and thus the best choice for a policy, when writing the authorization rules. The resulting error didn't include any context about what was wrong with the policy I had written. This commit aims to address this by providing a best effort guess to provide a starting point for developers to debug the policy issue themselves.

    PR checklist:

    • [ ] Added changelog entry.
    opened by kkirsche 13
  • __dirname is not defined in ES module scope

    __dirname is not defined in ES module scope

    ReferenceError: __dirname is not defined in ES module scope

    Unfortunately, oso appears to have trouble running when I build it as part of an ESM project because it references __dirname in certain parts of the code below:

    // [email protected]/node_modules/oso/dist/src/polar_wasm_api.js
    var path2 = __require("path").join(__dirname, "polar_wasm_api_bg.wasm");
    

    In my own code, where I load the .polar files, I work around this issue using the ESM recommended approach:

    import path from 'path';
    import { fileURLToPath } from 'url';
    
    const dirname = path.dirname(fileURLToPath(import.meta.url));
    
    await oso.loadFiles([path.resolve(dirname, 'main.polar')]);
    
    opened by pheuter 12
  • Derive `PolarClass` on Rust enums

    Derive `PolarClass` on Rust enums

    • [ ] PolarClass may now be derived on Rust enums.

    Hello :wave:

    I'm attempting to add support for Rust enums on the #[derive(PolarClass)] proc macro. This involves having the procedural macro generate code to store each enum variant on the Class that is being constructed. A loop in register_class then registers each constant.

    I sought to keep the API as simple as possible such that someone looking to add this functionality in their Rust project only needs to add #[derive(PolarClass)] onto their enums (thanks to @joshrotenberg for his input on this 🙂 ). However, this doesn't quite work; I'm hoping some additional eyes on it will help.

    The core of the problem seems to be fact that the constants are initially stored on the class as trait objects. Those are then passed around a few times before they get handed to register_constant. The compiler complains about the size of the trait objects not being known. I believe there are ways of handling this in nightly Rust, but I'm not sure what the pattern for addressing this is on stable.

    There's also the distinct possibility that I'm missing something simple 🙂

    opened by seanchen1991 12
  • isort, slight docstring formatting

    isort, slight docstring formatting

    Hello again :slightly_smiling_face: I've just gone for the auto-formatting route this time, except for one change.

    I've run isort & Black over all of the Python version of Oso (in that order,) removed the newlines under a few function docstrings that had them as per PEP 257. Black, as far as I know, doesn't have any guide on these, so it shouldn't interfere with anything.

    Now, for the manual change - I've removed the newlines between :param:s in oso/oso.py, as they weren't anywhere else - for consistency's sake and all that. Also extra newlines at the end of 2 docstrings in that same file.

    I do hope nothing breaks this time.

    opened by tomashozman 11
  • Fix file loading issue with Ruby gem - Fixes osohq/oso#1089

    Fix file loading issue with Ruby gem - Fixes osohq/oso#1089

    Here's a small fix to the Ruby gem for Oso that wasn't loading as expected out of the box. It fixes https://github.com/osohq/oso/issues/1089

    I wasn't able to find an applicable changelog file to register this. Nor did I know if I was supposed to bump the version in the code. Please let me know if this solution works.

    Since it's my first time contributing please give me instructions on accepting the contributors agreement.

    Thank you for Oso and the help on Slack!

    Docs 
    opened by davidpelaez 10
  • Memory Leak in Golang

    Memory Leak in Golang

    Hi OsoHQ,

    Been enjoying the library, and I hope to use it for an authorization service, however I believe I found a memory leak in the Golang library.

    Setup

    I was able to reproduce using the oso-go-quickstart example. I forked that repo and the only changes I made were:

    • upgraded to the latest oso v0.11.3 -> v0.12.3 (https://github.com/bhb603/oso-go-quickstart/blob/main/go.mod#L5)
    • added a policy:
      allow(actor: String, "GET", expense: Expense) if  
              expense.SubmittedBy = actor;
      
    • Dockerized the app and deployed it to a kubernetes cluster with this simple deployment (my ultimate use case would be to deploy in kubernetes, which is why I replicated that here)

    Testing

    I have some load-testing tooling which can generate requests against the service. Since this quickstart example only has one endpoint, it just requests:

    curl -H "user: [email protected]" http://oso-go-quickstart.oso:5050/expenses/1
    

    Which would check oso.IsAllowed(User("[email protected]"), "GET", expense) and return:

    HTTP/1.1 200 OK
    Content-Length: 40
    Content-Type: text/plain; charset=utf-8
    
    Expense{{500 coffee [email protected]}}
    

    Results

    Memory Usage increases linearly when the service is under load, until it reaches the limit I set for the container (256M) at which point Kubernetes kills the container (OOMKIlled) and it restarts, producing the saw tooth graph below.

    The rate of memory increase is proportional to the load (reqs per second), i.e. it increases ~2.5x faster when I was hitting it at 25rps vs 10rps, and flattens out with 0rps.

    Memory usage under load: Containers___Datadog

    More Metrics: image

    opened by bhb603 10
  • Diff docs on PR run.

    Diff docs on PR run.

    Add a job that looks for changes in the docs made by a diff by building the docs against the branch and base branch.

    If there are changes, will comment on the PR, as in #937 and require a comment to acknowledge the changes (you must manually re-run the job). The intent of this is to catch PRs that inadvertently break the docs, like changes to code included in code snippets.

    If you make a PR changing the docs intentionally, just comment "Docs changes ok" after uploading, and the job will pass on the first run.

    If you don't make any changes to the docs (#936), the job also passes, with no comment required.

    PR checklist:

    • [ ] Added changelog entry.
    opened by dhatch 10
  • Python `sqlalchemy-oso` for SQLAlchemy 1.4.x?

    Python `sqlalchemy-oso` for SQLAlchemy 1.4.x?

    Hi!

    Thanks for that awesome work on the Oso Framework! We are really enjoying working with it!

    Currently, we are evaluating whether the sqlalchemy-oso library would fit our needs. Are there any plans regarding the new SQLAlchemy 2 update?

    Trying to include it in our project leads to the following error message:

    Because sqlalchemy-oso (0.6.0) depends on sqlalchemy (>=1.3.20,<1.4.0) and no versions of sqlalchemy-oso match >0.6.0,<0.7.0, sqlalchemy-oso (>=0.6.0,<0.7.0) requires sqlalchemy (>=1.3.20,<1.4.0).

    Would love to hear from you!

    opened by moon-bits 10
  • (Java): Support M1

    (Java): Support M1

    • Bumps jnr-ffi to a newer version with Apple Silicon support.
    • Updates release workflow to build a fat (x86_64 + aarch64) .dylib and to use that in the .jar build

    Fixes the issue I mentioned in https://github.com/osohq/oso/issues/808#issuecomment-1023495977 (at least partially?).

    ~With the newer version I was able to build the .jar on a M1 machine and the final resulting .jar ran as expected with a aarch64 JRE. However the resulting .jar didn't run on the x86 JRE anymore (though I guess that is expected behavior).~

    ~Not sure how the .dylib for the release build is built (as the java Makefile references a debug build and specificlally makes a note that it shouldn't be used in release builds?), but I would assume that for properly building a fat .jar some additional step of cross-compiling and building a fat .dylib might be required.~

    EDIT: updated PR to include a build of a fat .dylib

    opened by hobofan 9
  • POLAR_LOG=0 should disable tracing

    POLAR_LOG=0 should disable tracing

    The documentation indicates that POLAR_LOG=1 enables tracing. Intuitively you would think that POLAR_LOG=0 disables tracing, particularly if you use the setting in a dotfile/docker-compose.yaml etc.

    However, it seems that POLAR_LOG just needs to be set to anything to enable tracing, and to be unset to disable tracing. I've tested this with the go, node, python and rust libraries, and it's the same with all four:

    Here's an example using the node library:

    ❯ which oso
    /Users/alexhafner/.volta/bin/oso
    ❯ echo $POLAR_LOG
    0
    ❯ oso
    query> 1+2=3
    [debug]   QUERY: 1 + 2 = _op_1 and _op_1 = 3, BINDINGS: {}
    [debug]     QUERY: 1 + 2 = _op_1, BINDINGS: {}
    [debug]     QUERY: _op_1 = 3, BINDINGS: {_op_1 = 3}
    true
    query> %
    ❯ unset POLAR_LOG
    ❯ oso
    query> 1+2=3
    true
    query> %
    ❯ export POLAR_LOG=foo
    ❯ oso
    query> 1+2=3
    [debug]   QUERY: 1 + 2 = _op_1 and _op_1 = 3, BINDINGS: {}
    [debug]     QUERY: 1 + 2 = _op_1, BINDINGS: {}
    [debug]     QUERY: _op_1 = 3, BINDINGS: {_op_1 = 3}
    true
    query>
    

    This was tested on main while reviewing the changes from https://github.com/osohq/oso/pull/1115

    It would be helpful for developers if tracing could be disabled by setting POLAR_LOG=0.

    opened by alexhafner 9
Releases(sqlalchemy-v0.26.2)
Owner
oso
Putting security into the hands of developers
oso
Jotsy is a self-hosted, free and open-source note taking app with a goal of simplicity in mind

Jotsy: Just your notes Jotsy is a self-hosted, free and open-source note taking app with a goal of simplicity in mind. It is powered by Skytable. Read

Sayan 411 Sep 19, 2022
Search Confluence from Alfred and open results in your browser.

Alfred Confluence Workflow Search Confluence from Alfred and open results in your browser. Features Search Confluence from Alfred and open results in

Johan M. 24 Sep 2, 2022
Build, bundle & ship your Rust WASM application to the web.

Trunk Build, bundle & ship your Rust WASM application to the web. ”Pack your things, we’re going on an adventure!” ~ Ferris Trunk is a WASM web applic

Anthony Dodd 1.9k Sep 23, 2022
A Rust application which funnels external webhook event data to an Urbit chat.

Urbit Webhook Funnel This is a simple Rust application which funnels external webhook event data to an Urbit chat. This application is intended to be

Robert Kornacki 15 Jan 2, 2022
The official DAW application of the RustyDAW project (name in progress)

rusty-daw-application The official DAW application of the RustyDAW project (name in progress) Take a look at the design doc. Join our community at the

null 15 Jun 14, 2021
a port of yaxpeax-dis that runs as a web application

this a rough translation of yaxpeax-dis, the CLI tool, to instead accept architectures and data to disassemble as an HTTP request. the package is then deployed to dis.yaxpeax.net as a [email protected] application.

iximeow 5 Aug 8, 2021
Sample serverless application written in Rust

This is a simple serverless application built in Rust. It consists of an API Gateway backed by four Lambda functions and a DynamoDB table for storage.

AWS Samples 132 Sep 21, 2022
A web application to configuration Caddy based on MoonZoon.

Cream A web application to configuration Caddy based on MoonZoon. MoonZoon is a Rust Fullstack Framework. Live demo Run on a local machine Check you'v

Tw 4 Sep 19, 2022
Experiments with Rust CRDTs using Tokio web application framework Axum.

crdt-genome Synopsis Experiments with Rust CRDTs using Tokio web application framework Axum. Background Exploring some ideas of Martin Kleppmann, part

dougfort 3 Mar 18, 2022
Reference implementation of a full-stack Rust application

Full-stack Rust with WebAssembly Look Ma, No JavaScript !!! My very first Rust project (implementation of the "Connect 5" game), I used as a learning

Vassil 52 Sep 16, 2022
Starknet application for Ledger Nano S, SP, X

Ledger Starkware app Please visit our website at zondax.ch This project contains the Starkware app (https://starkware.co/) for Ledger Nano S and X. Le

Ledger 12 Sep 8, 2022
Starlight is a JS engine in Rust which focuses on performance rather than ensuring 100% safety of JS runtime.

starlight Starlight is a JS engine in Rust which focuses on performance rather than ensuring 100% safety of JS runtime. Features Bytecode interpreter

null 431 Sep 21, 2022
A Google-like web search engine that provides the user with the most relevant websites in accordance to his/her query, using crawled and indexed textual data and PageRank.

Mini Google Course project for the Architecture of Computer Systems course. Overview: Architecture: We are working on multiple components of the web c

Max 11 Aug 10, 2022
Layers, extractors and template engine wrappers for axum based Web MVC applications

axum-template Layers, extractors and template engine wrappers for axum based Web MVC applications Getting started Cargo.toml [dependencies] axum-templ

Altair Bueno 4 Sep 8, 2022
Sentinel: The Sentinel of Your Microservices

Sentinel: The Sentinel of Your Microservices (WIP) Introduction As distributed systems become increasingly popular, the reliability between services i

Sentinel Group 61 Sep 5, 2022
Easy c̵̰͠r̵̛̠ö̴̪s̶̩̒s̵̭̀-t̶̲͝h̶̯̚r̵̺͐e̷̖̽ḁ̴̍d̶̖̔ ȓ̵͙ė̶͎ḟ̴͙e̸̖͛r̶̖͗ë̶̱́ṉ̵̒ĉ̷̥e̷͚̍ s̷̹͌h̷̲̉a̵̭͋r̷̫̊ḭ̵̊n̷̬͂g̵̦̃ f̶̻̊ơ̵̜ṟ̸̈́ R̵̞̋ù̵̺s̷̖̅ţ̸͗!̸̼͋

Rust S̵̓i̸̓n̵̉ I̴n̴f̶e̸r̵n̷a̴l mutability! Howdy, friendly Rust developer! Ever had a value get m̵̯̅ð̶͊v̴̮̾ê̴̼͘d away right under your nose just when

null 293 Sep 22, 2022
H2O Open Source Kubernetes operator and a command-line tool to ease deployment (and undeployment) of H2O open-source machine learning platform H2O-3 to Kubernetes.

H2O Kubernetes Repository with official tools to aid the deployment of H2O Machine Learning platform to Kubernetes. There are two essential tools to b

H2O.ai 15 May 31, 2022
Elemental System Designs is an open source project to document system architecture design of popular apps and open source projects that we want to study

Elemental System Designs is an open source project to document system architecture design of popular apps and open source projects that we want to study

Jason Shin 9 Apr 10, 2022
Example application using a Vue frontend with Rust backend that has authentication + authorization.

This project contains a Rust server that serves a single page application and has authentication + JWT-based authorization.

null 41 Sep 15, 2022
A high level language for SELinux policy

Introduction Cascade is a project to build a new high level language for defining SELinux policy. The overall structure of the language is essentially

Daniel Burgener 37 Aug 31, 2022