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

OPL: nested traverse are not allowed #1131

Open
3 of 6 tasks
zepatrik opened this issue Nov 14, 2022 · 2 comments
Open
3 of 6 tasks

OPL: nested traverse are not allowed #1131

zepatrik opened this issue Nov 14, 2022 · 2 comments
Assignees
Labels
bug Something is not working.

Comments

@zepatrik
Copy link
Member

zepatrik commented Nov 14, 2022

Preflight checklist

Describe the bug

It is not allowed to have nested traverse expressions.

Reproducing the bug

See the permits section of the S3ResourceType, the can_create permission has two nested traverse calls.

class Role implements Namespace {
  related: {
    principal: Project[]
  }
  permits = {
    can_assume: (ctx: Context) => this.related.principal.traverse((p) => p.related.access.includes(ctx.subject))
  }
}

class Policy implements Namespace {
  related: {
    attach: Role[]
  }
}

class S3ResourceType implements Namespace {
  related: {
    create: Policy[]
    edit: Policy[]
    read: Policy[]
  }

  permits = {
    can_create: (ctx: Context) => this.related.create.traverse((p) => p.related.attach.traverse((r) => r.permits.can_assume(ctx)))
  }
}

This is however only a limitation on the OPL level. The same result can be achieved by using:

class Policy implements Namespace {
  related: {
    attach: Role[]
  }

  permits = {
    can_create_tmp: (ctx: Context) => this.related.attach.traverse((r) => r.permits.can_assume(ctx))
  }
}

class S3ResourceType implements Namespace {
  related: {
    create: Policy[]
    edit: Policy[]
    read: Policy[]
  }

  permits = {
    can_create: (ctx: Context) => this.related.create.traverse((p) => p.can_create_tmp(ctx)),
  }
}

which is a lot more complex and harder to manage.

Relevant log output

No response

Relevant configuration

No response

Version

v0.10.0

On which operating system are you observing this issue?

No response

In which environment are you deploying?

No response

Additional Context

No response

@zepatrik zepatrik added the bug Something is not working. label Nov 14, 2022
@Erikvv
Copy link

Erikvv commented Dec 22, 2023

I have a bit more condensed version of this bug.

OPL:

class Project implements Namespace {
  related: {
    companies: Company[]
  }

  permits = {
    view: (ctx: Context) => this.related.companies.traverse(company => company.related.users.includes(ctx.subject))
  }
}

class User implements Namespace {}

class Company implements Namespace {
  related: {
    users: User[]
  }
}

So User has view permit on Project if he is in Company.

Relations:

{
	"namespace": "Company",
	"object": "zenmo",
	"relation": "users",
	"subject_id": "User:erik"
},
{
	"namespace": "Project",
	"object": "myproj",
	"relation": "companies",
	"subject_id": "Company:zenmo"
}

Permission check which returns false but should return true:

POST /relation-tuples/check/openapi
{
    "namespace": "Project",
    "object": "myproj",
    "relation": "view",
    "subject_id": "User:erik"
}

cmmoran added a commit to cmmoran/keto that referenced this issue Jan 2, 2024
cmmoran added a commit to cmmoran/keto that referenced this issue Jan 2, 2024
cmmoran added a commit to cmmoran/keto that referenced this issue Jan 17, 2024
cmmoran added a commit to cmmoran/keto that referenced this issue Jan 20, 2024
cmmoran added a commit to cmmoran/keto that referenced this issue Feb 7, 2024
@taylow
Copy link

taylow commented Mar 18, 2024

Could I ask where Keto OPL currently sits with nested traversals?

I just started using Keto again after a few months break, and spent a painful amount of time trying to get the following to work, only to find this limitation and issue via Slack 😅

import { Namespace, Context } from "@ory/keto-namespace-types"

class User implements Namespace {}

class Team implements Namespace {
    related: {
        owners: User[]
        members: User[]
    }

    permits = {
        delete: (ctx: Context): boolean => this.related.owners.includes(ctx.subject),
        manage: (ctx: Context): boolean => this.related.owners.includes(ctx.subject),
    }
}

class Project implements Namespace {
    related: {
        teams: Team[]
    }

    permits = {
        manage: (ctx: Context): boolean => this.related.teams.traverse((t) => t.permits.manage(ctx)),
        contribute: (ctx: Context): boolean => this.permits.manage(ctx),
    }
}

class File implements Namespace {
    related: {
        projects: Project[]
    }

    permits = {
        write: (ctx: Context): boolean => this.related.projects.traverse((p) => p.permits.manage(ctx)),
        read: (ctx: Context): boolean => this.related.projects.traverse((p) => p.permits.contribute(ctx)),
    }
}

With the following relations

[
  {
    "namespace": "Team",
    "object": "my_team",
    "relation": "owners",
    "subject_id": "User:taylor"
  },
  {
    "namespace": "Project",
    "object": "my_project",
    "relation": "teams",
    "subject_id": "Team:my_team"
  },
  {
    "namespace": "File",
    "object": "my_file",
    "relation": "projects",
    "subject_id": "Project:my_project"
  }
]

If I make the following requests, I get allowed: false

GET /relation-tuples/check
{
    "namespace": "Project",
    "object": "my_project",
    "relation": "manage",
    "subject_id": "User:taylor"
 }

GET /relation-tuples/check
{
    "namespace": "File",
    "object": "my_file",
    "relation": "write",
    "subject_id": "User:taylor"
 }

Yet, if I do the following, I get allowed: true

GET /relation-tuples/check
{
   "namespace": "Team",
   "object": "my_team",
   "relation": "manage",
   "subject_id": "User:taylor"
}

Any concrete information/status on this would be really useful, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something is not working.
Projects
None yet
Development

No branches or pull requests

4 participants