Git Product home page Git Product logo

warrant-dev / warrant Goto Github PK

View Code? Open in Web Editor NEW
990.0 4.0 27.0 6.36 MB

Warrant is a highly scalable, centralized authorization service based on Google Zanzibar, used for defining, querying, and auditing application authorization models and access control rules.

Home Page: https://warrant.dev

License: Apache License 2.0

Go 89.84% Makefile 0.07% PLpgSQL 9.93% Dockerfile 0.15%
access-control authorization golang rbac acl fine-grained-access-control fine-grained-authorization permissions abac authz

warrant's People

Contributors

akajla09 avatar boiseitguru avatar dependabot[bot] avatar kkajla12 avatar stanleyphu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

warrant's Issues

Resource timestamps should be generated in code rather than at database level

Describe the bug
Currently each db implementation (except SQLite) has the underlying database generate the createdAt, updatedAt, and deletedAt timestamps. Because timestamp implementations can vary from database to database (e.g. SQLite's timestamp function doesn't support microsecond precision, but SQLite is able to store microsecond timestamps), we should generate the timestamp in code rather than relying on the underlying database timestamp generation.

To Reproduce
N/A

Expected behavior
The createdAt, updatedAt, and deletedAt timestamps for all resources should be generated in code and used in the repository layer to be persisted to the db.

Additional context
N/A

Add postgres ci job for PRs and merges

Add a GitHub actions ci job that runs the postgres db migrations (up/down) for both datastore + eventstore and runs the apirunner test suite against a server running with postgres.

Note: GH Actions runners ship with mysql and sqlite by default so it was easy to set those up. Running postgres will require starting up the postgres server on the runner.

Create a .NET/C# SDK

Warrant currently has native SDKs for Go, Java, Python, Node, Ruby, PHP. We've received requests from some folks to also add a .NET SDK.

If this is something you're interested in, please upvote.

Colon in Ids are not supported

Describe the bug

If you create, for example, a permission with a colon ":" in the ID, a query on that instance produce an Internal Server Error.

To Reproduce
Steps to reproduce the behavior:

  1. Given a installation
  2. Create a user
  3. Create a Permission with ID "this:is-a-permission"
  4. Assign permission to the user
  5. Go to Fine Grained Access Control page
  6. Click on 'Check'
  7. You will see the page with query: SELECT EXPLICIT warrant
  8. You will see a message "Invalid query"
  9. Check browser developer console, you will see the response from server "500 Internal server error".

In the UI:

image

Server response:

{"code":"internal_error","message":"Internal Server Error"}
Expected behavior

It could be one of the two:

  1. An error is reported disallowing the creation of an object with an ID having a colon
  2. The query success showing the first page of warrants

Additional context

I guess that because the colon is used as separator between object type and object id, it could be a restriction to use the colon in the object IDs.

We were using colon to organizar permissions (like user:create) so I tried for that specific case.

Add support for a `now` built-in method for warrant policies

Is your feature request related to a problem? Please describe.
In some use cases, access rules should only apply to a subject (user) for a specific time period each day/week/month/year. For example, a contract employee might only have access to a particular page in a dashboard on Monday each week. In order to write policies like this, the policy runtime needs to know the time at which the policy is being evaluated.

Describe the solution you'd like
To support writing policies with this type of behavior, we should add support for a built-in now method that returns the current time during evaluation of the policy. Developers can then use this timestamp to implement all sorts of time-based functionality like the example above and more.

Describe alternatives you've considered
Without the ability to get the current timestamp at time of policy evaluation, there is no alternative solution currently.

Additional context
N/A

OpenAPI specification for APIs

Is your feature request related to a problem? Please describe.

Warrant APIs are based on HTTP, well structured and mostly in REST format. It will be useful to integrate with other systems if an OpenAPI specification is provided.

Describe the solution you'd like

Providing an OpenAPI specification for the APIs will allow using it from a wide variety of languages. E.g. https://github.com/OpenAPITools/openapi-generator#overview

Describe alternatives you've considered

Not sure if this was considered. And whether it will be suitable for the APIs and useful to move the SDKs to use.

Additional context

  • none -

Add ability to attach a "policy" to warrants to support attribute based access control (ABAC)

Is your feature request related to a problem? Please describe.
Currently, contextual warrants support strict equality comparison (=) on the context values provided in an access check request. While this is powerful in scenarios where a strict equality check is good enough (e.g. tenant-specific RBAC), it doesn't offer a solution for various forms of attribute based access control (ABAC) that require a different comparison operator (e.g. <, >, etc). Instead, we should introduce the ability to attach a "policy" to warrants. A policy is an expression (written in a readily available expression language like expr) that evaluates to true or false and supports several comparison operators in addition to strict equality comparison. Policies can reference the context provided in access check requests and those values should be substituted into the expression at runtime to evaluate the policy. In warrants containing a policy, the warrant is only considered a match if both (1) the objectType, objectId, relation, and subject match and (2) the policy evaluates to true given the provided contextual values. Adding support for policies in this way will unlock support for a vast majority of ABAC use cases without the need for us to build an expression representation in JSON.

Describe the solution you'd like
Warrants should support an additional policy attribute which accepts a boolean expression dictating (in addition to the existing attributes) whether a warrant matches access checks or not. The underlying policy language The proposed representation for this is as follows:

{
    "objectType": "permission",
    "objectId": "create-transaction",
    "relation": "member",
    "subject": {
        "objectType": "role",
        "objectId": "basic"
    },
    "policy": "amount >= 50 && amount <= 100 && tenant == \"tenant-A\" && ip matches \"192.168\\.*\\.*\" && timestamp < 1684872281 && email contains \"@gmail.com\""
}

Describe alternatives you've considered
Currently, there are no alternatives to consider if your use-case requires a comparison operator other than strict equality (e.g. amount > 50).

Additional context
N/A

Add 'actor' in accessEvents and resourceEvents

Currently, accessEvents and resourceEvents track the event time, result, and other metadata for the underlying warrant/resource. We should also add actor (user/service that initiated the event).

Support persistence and reuse of warrant policies

Is your feature request related to a problem? Please describe.
Currently, warrant policies can only be defined ad-hoc per warrant. This approach/implementation doesn't lend itself well to reuse of policies. For example, a developer might want to apply a company-wide internal user (employee) policy (e.g. user.email endsWith "@warrant.dev") and reuse it across multiple warrants (too many to manually update). With the current approach, each warrant using this policy would need to define the expression in the policy field. Later on, if the policy itself needs to be updated (e.g. policy is updated to user.email endsWith "@warrant.dev" && clientIP matches X.X.X.X), it would require a bulk update of warrants.

Describe the solution you'd like
Reusing policies will be easier if warrant policies are tracked separately, each policy is given a unique identifier (perhaps a function name), and one or more policies can be referenced in a warrant's policy field. Policies can then be independently updated and updates can be reflected across all warrants referencing the updated policy.

Describe alternatives you've considered
Currently, there is no alternative if you're looking to reuse the same policy expression(s) across warrants.

Additional context
Warrants should still support defining ad-hoc policies, but the underlying behavior should be to create a policy out of the ad-hoc expression and then reference the newly created policy in the persisted warrant.

Auto-migrate should only run migrations included in the current version

Describe the bug
Currently, if using an older version of warrant, the auto-migrate will attempt to apply migrations from main which includes migrations that are not part of the running version.

To Reproduce
Steps to reproduce the behavior:

  1. Run an old version of warrant (e.g. v1.0.1)
  2. Upon startup, auto-migrate will run all migrations on main and cause the service to crash.

Expected behavior
The auto-migrate feature should fetch migrations from the relevant release/version rather than using the migrations on main.

Additional context
N/A

Add `expiresIn` built-in function for warrant policies to support time-based / expiring warrants

Is your feature request related to a problem? Please describe.
The newly available support for attaching policies to warrants as of #140 unlocks a lot of power that can be tapped to implement more functionality using policies. Having access to an expiresIn function would allow the creation of time-based warrants (e.g. a policy like expiresIn 4 * time.Hour should designate that a warrant should no longer apply 4 hours after its creation).

Describe the solution you'd like
Warrant policies should provide a built-in expiresAt method which can be given an argument specifying a time duration after which the warrant should no longer apply to access checks.

Describe alternatives you've considered
Currently, the only alternative available is to provide a policy such as currentTimestamp < <a-timestamp-in-the-future> and provide the current timestamp (as a Unix timestamp) in the context of every access check request. Aside from simplicity, another benefit of having a built-in function for this functionality would be the potential to clean up expired warrants every so often.

Additional context
The expiresIn built-in function can consider supporting Go's time durations (e.g. time.Hour, time.Minute, etc.) as arguments for improved developer experience. It's also worth considering how these warrants might be cleaned up over time.

Add support for 'zookie' protocol as described in Zanzibar spec

Is your feature request related to a problem? Please describe.
The Google Zanzibar paper describes a 'zookie' protocol that:

  • allows clients to dictate desired 'freshness' for authz checks based on a supplied zookie token
  • gives the server flexibility to implement caches that optimize for latency given clients' tolerance for 'freshness'

Describe the solution you'd like
Implement a similar 'zookie' protocol in the warrant server. Specifically:

  • Server should pass back an opaque 'Warrant-Token' on API calls that clients can cache and pass on subsequent checks. This token bookmarks a specific write and allows the server to determine its own 'freshness' on later checks.
  • At check time, the server compares the client-passed token to its own token(s) (could be multiple if multiple caches) and utilizes a cache/datastore that is 'at least as fresh as' the client-passed token to serve the request.
  • If a client does not pass a Warrant-Token, use the most up-to-date store (likely the db) to serve the request (preserving current functionality for backwards-compatibility)

Support Postgres as a Datastore

Is your feature request related to a problem? Please describe.
I would like to run Warrant with Postgres as the primary datastore.

Describe the solution you'd like
Warrant should support being configured to run with Postgres, so that all reads and writes are performed on a Postgres database. The name of the database should be configurable just like the database name for other databases (e.g. MySQL) is configurable.

Describe alternatives you've considered
N/A

Additional context
N/A

Make definition column on object type table non nullable

Is your feature request related to a problem? Please describe.
As currently defined, object type records in the database are allowed to have a NULL definition (this is also currently the default value if no value is provided for that column as part of the insert).

Describe the solution you'd like
The above behavior is incorrect and we should enforce that the definition column is not nullable at the database level (in addition to the application level enforcement already in place).

Describe alternatives you've considered
N/A

Additional context
We'll need to make sure this behavior is updated for all supported databases. Any migrations added to enforce this non-nullable constraint on the definition column should also be sure to handle existing object type records that might have a NULL definition.

Support SQLite as a Datastore

Is your feature request related to a problem? Please describe.
I would like to run Warrant with SQLite as the primary datastore.

Describe the solution you'd like
Warrant should support being configured to run with SQLite, so that all reads and writes are performed on a local SQLite database. The name of the database file should be configurable just like the database name for other databases (e.g. MySQL) is configurable.

Describe alternatives you've considered
N/A

Additional context
N/A

Default db migration behavior should be to use migrations from current source

Describe the bug
Currently, the default for go-migrate is to pull db migrations directly from Github (main branch) and run them (including with the autoMigrate flag). This means that you could potentially have a mismatch between the migrations being run and the server code if it is not up to date.

Expected behavior
Only the migrations up to the current version of source (whether built locally or pre-built) should run. This might mean packaging the migrations along with the binary.

Support sync with mongodb

Is your feature request related to a problem? Please describe.

There is a sync agent for MySQL to automatically create or update Warrants listening for databases changes.

We use mongodb for data store.

Describe the solution you'd like

A similar sync agent that uses the MongoDB stream to listen for new / updated documents and a similar configuration to create / update corresponding warrants.

Describe alternatives you've considered

We should create a similar agent for us.

Additional context
We want to deploy it as Kubernetes pod.

Pre-built Mac binaries from 'releases' prompt an untrusted developer error on Mac OS

Describe the bug
Mac OS compatible binaries downloaded from releases prompt an "untrusted developer" error message on initial run (similar to this). This is because the binaries are not code signed through Apple. As a workaround, you can right-click and run the binary from Finder and bypass the warning or compile a binary directly from the cloned repo.

Additional context
We might want to look at this library for code signing/notarization.

Support one time use warrants

An operator at a front desk wants to make a transaction above a certain threshold. To go ahead, the auth system must require another user with a certain role (“supervisor” say) to authorize this. To actually authorize this, the supervisor will create a warrant. This warrant should allow the operator to make the transaction, but only once. Further transactions must require fresh authentication. Furthermore, this warrant must expire in some time (say 5 minutes).

Warrants could have an optional added field for “max_uses”, “expiresat”

Describe alternatives you've considered
I have considered modifying my application to create and take down the warrant. However, I can foresee it getting messy and error-prone (consequently insecure and incorrect)

Support Policies + Context in Query API

Is your feature request related to a problem? Please describe.
Warrant supports creating and managing ABAC-style policies on warrants. The check endpoint accepts an optional context parameter that allows the client to pass relevant contextual values that can be used during the course of a check to evaluate any policies encountered along the way. The query endpoint does not currently support policies/context.

Describe the solution you'd like
The query endpoint should support a context parameter and correctly include/exclude results arrived at using warrants with attached policies.

Describe alternatives you've considered
N/A

Additional context
N/A

Add support for read replicas when using MySQL or PostgreSQL

Is your feature request related to a problem? Please describe.
The Warrant service currently supports MySQL, PostgreSQL and SQLite as databases. Even though the service itself is horizontally scalable (i.e. can add more service nodes), it is limited by the underlying dbs. A common HA deployment pattern for these single-master dbs is to deploy multiple read replicas (or readers) to take load off of the main writer node, especially in read-heavy deployments as is commonly the case for Warrant.

As such, the Warrant service should be able to make use of a multi-node db cluster (multiple readers, single writer) to enable even higher scale for check requests.

Describe the solution you'd like

  • Add the ability to maintain distinct reader and writer db connection pools.
  • Usage of 'zookie' (#161) will account for any replication lag between writer and its reader instances.

Additional context

  • Note that this solution is only for single-master dbs. Multi-master dbs (like Google Spanner) provide their own consistency guarantees.

Add support for scoped sessions

Add ability to generate scoped (user/tenant) short-lived sessions that can be used by front-ends to check and query warrants (same as Warrant Cloud).

Generate SQLite compatible Docker image

Is your feature request related to a problem? Please describe.
Our alpine-based Docker image doesn't support SQLite (binary compiled without CGO which the native sqlite lib relies on). This means that anyone wanting to use sqlite needs to manually build a compatible binary for use.

Describe the solution you'd like
We should consider creating a separate image (likely with a different base) where we can include sqlite.

Describe alternatives you've considered
Another alternative is to switch to a Go-native sqlite impl (will require more testing and analysis).

Generate Docker images for additional architectures

Is your feature request related to a problem? Please describe.
Currently, the only Docker image generated from the release pipeline is for linux/amd64 (built on the bare alpine img). We should consider adding images for arm (Mac etc).

Describe the solution you'd like
Goreleaser already generates Go binaries for multiple architectures, including arm and windows. We should also build appropriate Docker images.

Note: might have to pick a different base image (some research required)

Describe alternatives you've considered
Go binaries for other architectures are still built and available for download in case needed.

Application(API) Keys Scoping

In Tigris(or probably in other cloud platforms as well), an account is mapped to a user. This user can have multiple projects in his account. Each project can have Api keys that the user will use to interact with the platform. This means a single API key won't work for a user. API keys need to be scoped to a user and then to a project.

The ask here is whether a scoping can be introduced when generating API keys. Then that scoping actually can be anything. For example, in the future, for example, we can scope our keys like user-->project-->environment

Create pub sub connector(s) for events

Is your feature request related to a problem? Please describe.
Currently, Warrant's event store can be configured to track and persist events to a database (MySQL, Postgres, SQLite, etc). We should explore support for publishing events to pub sub systems like Kafka, SNS, etc.

Describe the solution you'd like
Warrant should add support for publishing events to pub sub systems like Kafka, SNS, etc. This would involve writing an event repository for each supported pub sub system that knows how to publish the events.

Describe alternatives you've considered
N/A

Additional context
We'll need to consider how the list events endpoints would work in the scenario that the event store was configured to publish events to a pub sub service. More than likely, these endpoints would not be supported in that case because the events would be sent outside of Warrant.

Update postgres timestamp columns to be type `TIMEZONETZ` to support timezones

Describe the bug
Currently the postgres migrations create the datastore and eventstore tables where the timestamp columns are of type TIMEZONE rather than TIMEZONETZ. This stores timestamps in the local timezone but the API treats the timestamp as UTC. We should update the timestamp columns to be of type TIMEZONETZ.

To Reproduce
Steps to reproduce the behavior:

  1. Create a Warrant resource, i.e. user. In the DB, the createdAt will look something like 2023-06-06 23:51:52.621361.
  2. Get the created resource from the API - the createdAt will look like 2023-06-06 23:51:52.621361Z, indicating a UTC timestamp.

Expected behavior
In my case, the createdAt timestamp is created in the PDT timezone. However, the API returns the timestamp as if it is a UTC timestamp. The timestamp should be of type TIMEZONETZ to include the correct timezone so that the API can make the correct conversion to UTC.

Allow Object Types with Empty Relations

Is your feature request related to a problem? Please describe.
For leaf object types (e.g. users) that won't have any relations assigned directly on them but will have relations assigned to them, it's currently required to create an object-type with a dummy/placeholder relation like this:

{
   "type": "user",
   "relations": {
      "placeholder": {}
   }
}

Describe the solution you'd like
We should add support for creating object-types with an empty relations block to prevent having to do this. Instead, the user object-type would look like this:

{
   "type": "user",
   "relations": {}
}

Describe alternatives you've considered
N/A

Additional context
N/A

Add support for wildcards in the warrant subject

Is your feature request related to a problem? Please describe.
Currently Warrant only supports wildcards in the objectId of a warrant. This makes it possible to specify rules on all objects of a particular type. For example, the rule user:A is editor of all reports can be specified via the warrant:

{
    "objectType": "report",
    "objectId": "*",
    "relation": "editor",
    "subject": {
        "objectType": "user",
        "objectId": "A"
    }
}

This is useful because it allows developers to specify coarse-grained rules for specific users or groups when/where necessary, making it easier to manage the set of warrants in certain scenario. For example, being a member of the admin role should grant a user editor privileges on all documents. With a single wildcard warrant, we don't need to add a new warrant every time a new document is created.

However, if we instead want similar functionality flowing in the opposite direction (e.g. *any* user is viewer of document:A), it is currently not possible to easily model via a warrant. To support this sort of functionality, we should add wildcard support in the warrant subject. The warrant fulfilling our example scenario would be:

{
    "objectType": "document",
    "objectId": "A",
    "relation": "viewer",
    "subject": {
        "objectType": "user",
        "objectId": "*"
    }
}

Describe the solution you'd like
Warrants should support the wildcard character as part of their subject.objectId parameter. A wildcard subject.objectId should specify that any subject of the type subject.objectType can match the warrant.

Describe alternatives you've considered
N/A

Additional context
Consider whether a warrant should be allowed to have a wildcard for both its objectId and its subject.objectId.

Consider supporting Open Policy Agent Rego as the policy language for warrant policies

Is your feature request related to a problem? Please describe.
Now that #140 is merged and warrants support attaching policies to them, it might make sense to support additional policy languages like OPA's Rego (due to wider adoption/familiarity).

Describe the solution you'd like
Warrants should support policies written in OPA's Rego policy language.

Describe alternatives you've considered
N/A

Additional context
It seems like using OPA purely for policy definition (in Rego) and evaluation is possible in Go services via their Go API: https://www.openpolicyagent.org/docs/latest/integration/#integrating-with-the-go-api

Add full file path to error logs that contain a stack

Is your feature request related to a problem? Please describe.
Warrant uses zerolog for structured logging (with stack enabled) to make debugging errors easier. Currently, zerolog only prints the filename (e.g. sqlite.go or repository.go) in the stack without the full file path which makes it difficult to quickly figure out which pkg the file belongs to, given that multiple Warrant packages have similar filenames (repository.go etc). For example, it's hard to tell at a first glance from the following log which sqlite.go repository is causing an error:

stack=[{"func":"SQL.ExecContext","line":"225","source":"sql.go"},{"func":"SQLiteRepository.DeleteByFeatureId","line":"252","source":"sqlite.go"}]

Describe the solution you'd like
There should be a configuration in zerolog to add the full path of the filename (including pkg subdir) so we can print /authz/object/sqlite.go vs. sqlite.go in the logs.

Note: depending on implementation and computational complexity, we might want to make this setting configurable so users can disable in prod if desired.

Additional context
https://github.com/rs/zerolog#add-file-and-line-number-to-log

List AccessEvent endpoint doesn't support wildcards

Describe the bug
Currently, the filters for the list AccessEvent endpoint perform an exact match on objectId. As a result, the endpoint won't return events related to wildcard warrants that match the filtered objectId.

To Reproduce
Steps to reproduce the behavior:

  1. Create a wildcard warrant on an object. For example, [role:admin] is a [member] of [pricing-tier:*]
  2. List access events for a specific pricing-tier. For example, [pricing-tier:free]
  3. The results of step 2 won't include any events related to the warrant created in step 1.

Expected behavior
The list AccessEvent endpoint should match the objectId filter against wildcards (*) so that it returns events related to wildcard warrants that match the filtered objectId.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.