Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Make authorization code pluggable #102

Merged
merged 6 commits into from
Nov 25, 2024
Merged

Conversation

jgadling
Copy link
Contributor

We expect that Cerbos is the main authorization tool used alongside platformics, but it was too deeply integrated into our system. This PR does a few things:

  • Renames some of our dependencies and authorization primitives so that they don't mention cerbos. ex: CerbosAction to AuthzAction
  • Ensures that we only import cerbos in our authorization module, it shouldn't be sprinkled around the codebase so liberally.
  • Encapsulate most of our authorization code in a class that can be overridden by a fastapi dependency override
  • Add docs and tests to ensure that overriding default functionality works.

@jgadling jgadling changed the title Make authorization code pluggable feat: Make authorization code pluggable Aug 27, 2024
@@ -119,13 +117,13 @@ def convert_where_clauses_to_sql(
for join_field, join_info in all_joins.items():
relationship = mapper.relationships[join_field] # type: ignore
related_cls = relationship.mapper.entity
cerbos_query = get_resource_query(principal, cerbos_client, action, related_cls)
secure_query = authz_client.get_resource_query(principal, action, related_cls)
Copy link
Contributor Author

@jgadling jgadling Aug 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

KEY CHANGE HERE: get_resource_query isn't called directly anymore, because it was impossible/impractical to override that function call. Instead, we've made that a method of AuthzClient, which is passed in as a FastAPI dependency and can be overridden.

raise PlatformicsError("Unauthorized: cannot update file") from None

# Fetch the entity if have access to it
entity_class, entity = await get_entity_by_id(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This call to get_entity_by_id checks to see whether the user has access to update the associated entity.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the get_resource_query() call below applies authz policies properly, we may not need this call!

joins = [(db.Entity, db.File.entity_id == db.Entity.id)] # type: ignore
else:
# Send all non-relationship columns to cerbos to make decisions
for col in sqlalchemy_helpers.model_class_cols(model_cls):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we use obj_to_dict or model_class_cols? Can we unify these???

@jgadling jgadling requested review from rzlim08 and removed request for ninabernick November 25, 2024 17:58
@@ -43,6 +43,8 @@ def run_migrations_offline() -> None:
)

with context.begin_transaction():
context.get_context()._ensure_version_table() # pylint: disable=protected-access
connection.execute(sa.sql.text("LOCK TABLE alembic_version IN ACCESS EXCLUSIVE MODE"))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This ensures that if multiple processes (e.g. k8s pods) try to run migrations at the same time, only one of them will actually be able to run them.

principal: Principal,
action: AuthzAction,
model_cls: type[db.Base], # type: ignore
) -> Select:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how overridable do you think this is if we're not using CERBOS?

Copy link
Contributor Author

@jgadling jgadling Nov 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's TBD honestly. This hopefully gets us one step closer by putting most of the policy enforcement code in one place and allowing it to be overridden, but I'd love to hear more about what the interface for the authz systems you've been working with recently look like!

@jgadling jgadling merged commit 09218c4 into main Nov 25, 2024
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants