flat-rose-25983
04/17/2023, 2:32 PMketo:
ingress:
read:
enabled: true
annotations:
<http://nginx.ingress.kubernetes.io/rewrite-target|nginx.ingress.kubernetes.io/rewrite-target>: /$2
hosts:
- host: keto.{{ .Values.baseDomain }}
paths:
- path: /read
pathType: Prefix
backend:
serviceName: ory-keto-read
servicePort: 4466
write:
enabled: true
annotations:
<http://nginx.ingress.kubernetes.io/rewrite-target|nginx.ingress.kubernetes.io/rewrite-target>: /$2
hosts:
- host: keto.{{ .Values.baseDomain }}
paths:
- path: /write
pathType: Prefix
backend:
serviceName: ory-keto-write
servicePort: 4467
keto:
autoMigrate: {{ .Values.ketoAutoMigrate }}
config:
dsn: <postgres://postgres>:{{ requiredEnv "POSTGRES_PASSWORD" }}@{{ .Values.dbhost }}:5432/identity?sslmode=disable
serve:
namespaces:
- id: 1
name: ukama
cold-motorcycle-49371
04/18/2023, 8:14 AMflat-rose-25983
04/19/2023, 3:40 PMpackage main
import (
"context"
"fmt"
"os"
ory "<http://github.com/ory/keto-client-go|github.com/ory/keto-client-go>"
)
// Use this context to access Ory APIs which require an Ory API Key.
var namespace = "Blog"
var object = "secret_post"
var relation = "view"
var subjectId = "Bob"
func main() {
payload := ory.CreateRelationshipBody{
Namespace: &namespace,
Object: &object,
Relation: &relation,
SubjectId: &subjectId,
}
configuration := ory.NewConfiguration()
configuration.Servers = []ory.ServerConfiguration{
{
URL: "<http://127.0.0.1:4467>", // Write API
},
}
writeClient := ory.NewAPIClient(configuration)
_, r, err := writeClient.RelationshipApi.CreateRelationship(context.Background()).CreateRelationshipBody(payload).Execute()
if err != nil {
fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r)
panic("Encountered error: " + err.Error())
}
fmt.Println("Successfully created tuple")
configuration.Servers = []client.ServerConfiguration{
{
URL: "<http://127.0.0.1:4466>", // Read API
},
}
readClient := client.NewAPIClient(configuration)
check, r, err := readClient.PermissionApi.CheckPermission(context.Background()).
Namespace(*&namespace).
Object(*&object).
Relation(*&relation).
SubjectId(*&subjectId).Execute()
if err != nil {
fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r)
panic("Encountered error: " + err.Error())
}
if check.Allowed {
fmt.Println(*&subjectId + " can " + *&relation + " the " + *&object)
}
}
thousands-megabyte-94914
04/19/2023, 8:17 PMimport { Namespace, Context } from "@ory/keto-namespace-types"
class User implements Namespace {}
class Document implements Namespace {
related: {
owners: User[]
editors: User[]
viewers: User[]
parents: Folder[]
}
permits = {
view: (ctx: Context): boolean =>
this.related.viewers.includes(ctx.subject) ||
this.permits.edit(ctx),
edit: (ctx: Context): boolean =>
this.related.editors.includes(ctx.subject) ||
this.permits.share(ctx),
delete: (ctx: Context): boolean =>
this.permits.share(ctx),
share: (ctx: Context): boolean =>
this.related.owners.includes(ctx.subject) || this.related.parents.traverse((parent) => parent.permits.share(ctx)),
}
}
class Folder implements Namespace {
related: {
owners: User[]
editors: User[]
viewers: User[]
parents: Folder[]
}
permits = {
delete: (ctx: Context): boolean =>
this.permits.share(ctx),
share: (ctx: Context): boolean =>
this.related.owners.includes(ctx.subject) || this.related.parents.traverse((parent) => parent.permits.share(ctx)),
}
}
I then use the go SDK to set a document as having a parent folder, and then make a user an owner of the folder. However when I go to check if the user has view permission on the document, the permissions api returns that they do not. Perhaps I’m misunderstanding something? For reference here’s the go code I have:
package main
import (
"context"
"fmt"
"os"
ory "<http://github.com/ory/keto-client-go|github.com/ory/keto-client-go>"
)
func Ptr[T any](v T) *T {
return &v
}
func main() {
configuration := ory.NewConfiguration()
configuration.Servers = []ory.ServerConfiguration{
{
URL: "<http://127.0.0.1:4467>", // Write API
},
}
writeClient := ory.NewAPIClient(configuration)
ctx := context.Background()
_, r, err := writeClient.RelationshipApi.CreateRelationship(ctx).CreateRelationshipBody(ory.CreateRelationshipBody{
Namespace: Ptr("Document"),
Object: Ptr("doc_1"),
Relation: Ptr("parents"),
SubjectId: Ptr("folder_1"),
}).Execute()
if err != nil {
fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r)
panic("Encountered error: " + err.Error())
}
_, r, err = writeClient.RelationshipApi.CreateRelationship(ctx).CreateRelationshipBody(ory.CreateRelationshipBody{
Namespace: Ptr("Folder"),
Object: Ptr("folder_1"),
Relation: Ptr("owners"),
SubjectId: Ptr("user_1"),
}).Execute()
if err != nil {
fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r)
panic("Encountered error: " + err.Error())
}
configuration.Servers = []ory.ServerConfiguration{
{
URL: "<http://127.0.0.1:4466>", // Read API
},
}
readClient := ory.NewAPIClient(configuration)
checkRelation(ctx, readClient, "Folder", "folder_1", "share", "user_1")
checkRelation(ctx, readClient, "Document", "doc_1", "view", "user_1")
}
func checkRelation(ctx context.Context, readClient *ory.APIClient, namespace, object, relation, subjectId string) {
check, r, err := readClient.PermissionApi.CheckPermission(ctx).
Namespace(namespace).
Object(object).
Relation(relation).
SubjectId(subjectId).Execute()
if err != nil {
fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r)
panic("Encountered error: " + err.Error())
}
if check.Allowed {
fmt.Println(subjectId + " CAN " + relation + " the " + object)
} else {
fmt.Println(subjectId + " CANNOT " + relation + " the " + object)
}
}
and here’s the output:
user_1 CAN share the folder_1
user_1 CANNOT view the doc_1
Any help would be greatly appreciated!full-petabyte-13526
04/19/2023, 9:36 PMview: (ctx: Context): boolean => true
but keto didn't like that on startup (expected this
where true
is). It isn't strictly necessary -- seems like the workaround / implication is to just not have a permit that relies on that for now (which means the application code wouldn't perform any check). That's fine. Means that I have to redeploy my application when I do want to change the model to legitimately implement view
though.full-petabyte-13526
04/19/2023, 10:48 PMketo relation-tuple create
) something I have in a permit
. Is that expected? Or put another way -- are permits supposed to be directly assignable as well as act as functions against relations (related
) / are permits relations themselves? e.g.:
class Connection implements Namespace {
related: {
owners: User[];
};
permits = {
view: (ctx: Context): boolean => this.permits.edit(ctx),
edit: (ctx: Context): boolean => this.related.owners.includes(ctx.subject),
...
then:
echo "Connection:1#edit@bob" | keto relation-tuple parse --format json - | keto relation-tuple create -
keto check bob edit Connection 1
Allowed
lemon-apartment-14887
04/21/2023, 7:49 AM/engines/acp/ory/regex/allowed
endpoint and receives a 404 error.
Seems like this particular endpoint just doesn't exist. Has anyone faced this issue before? Will appreciate any help.
Oathkeeper configuration and versions of ory products are in the thread below.full-petabyte-13526
04/21/2023, 2:25 PMpermits
, how do I check which object IDs allow that given a subject? Using the List API doesn't seem to return results -- it seems like permits are only considered relations when interacted with via the Check service, but nothing else? The use case is I want to determine which objects a subject has effective permissions to so I can filter them before returning them from an API service.thousands-megabyte-94914
04/21/2023, 5:47 PMechoing-postman-28418
04/24/2023, 8:10 AMunable to initialize config provider: open /home/ory/keto.yml: no such file or directory
docker compose file
version: "3"
services:
keto:
image: oryd/keto:v0.11.1
volumes:
- ./keto:/home/ory
ports:
- "4466:4466"
- "4467:4467"
command: serve -c /home/ory/keto.yml
restart: on-failure
volumes:
keto:
directory structure
keto/
keto.yml
namespaces.keto.ts
docker-compose.yaml
keto.yaml
version: v0.11.1
dsn: memory
namespaces:
location: file://./namespaces.keto.ts
log:
level: debug
serve:
read:
host: 0.0.0.0
port: 4466
write:
host: 0.0.0.0
port: 4467
echoing-postman-28418
04/24/2023, 9:31 AM// Copyright © 2023 Ory Corp
// SPDX-License-Identifier: Apache-2.0
import { Namespace, SubjectSet, Context } from "@ory/keto-namespace-types"
class User implements Namespace {
related: {
manager: User[]
}
}
class Group implements Namespace {
related: {
members: (User | Group)[]
}
}
class Folder implements Namespace {
related: {
parents: (File | Folder)[]
viewers: SubjectSet<Group, "members">[]
}
permits = {
view: (ctx: Context): boolean =>
this.related.viewers.includes(ctx.subject) ||
this.related.parents.traverse((p) => p.permits.view(ctx)),
}
}
class File implements Namespace {
related: {
parents: (File | Folder)[]
viewers: (User | SubjectSet<Group, "members">)[]
owners: (User | SubjectSet<Group, "members">)[]
}
permits = {
view: (ctx: Context): boolean =>
this.related.parents.traverse((p) => p.permits.view(ctx)) ||
this.related.viewers.includes(ctx.subject) ||
this.related.owners.includes(ctx.subject),
edit: (ctx: Context) => this.related.owners.includes(ctx.subject),
}
}
basically, i want that any user having the viewers access of parent should have viewer access for any of the childs. I created user group developer that has viewers access for folder keto/ and folder keto/ is parent folder keto/src/. I have two users in developer group.
when i run check for viewers access for the user in developer to keto/ it gives me allowed true, but when i run check for viewers access for keto/src/ it gives me false, even though the parent has the viewers access. As far as i could understand from the permission file the user should have viewers access for the children as well
#ketoaverage-policeman-69189
04/25/2023, 6:57 PMKeto Delete team: team=0070c83f-4214-4a95-a88a-5aa99e7dcfdc tenant=0c64fa2d-2c4b-4a8d-adaa-7dc15af64bfd status=error message=2 UNKNOWN: failed to close prepared statement: ERROR: current transaction is aborted, commands ignored until end of transaction block (SQLSTATE 25P02): ERROR: insert or update on table "keto_relation_tuples" violates foreign key constraint "keto_relation_tuples_nid_fk" (SQLSTATE 23503)
ⅹ tenant deletion failed (2 UNKNOWN: failed to close prepared statement: ERROR: current transaction is aborted, commands ignored until end of transaction block (SQLSTATE 25P02): ERROR: insert or update on table "keto_relation_tuples" violates foreign key constraint "keto_relation_tuples_nid_fk" (SQLSTATE 23503))
Not sure how the networks entry are generated in keto, when I try to list the tuples Keto return nothing, but my keto_relation_tuples
contains more then 14'000 entrieswide-machine-60917
04/27/2023, 2:35 PMclass LegalEntity implements Namespace {
related: {
readers: User[]
writers: User[]
}
permits = {
read: (ctx: Context): boolean =>
this.related.readers.includes(ctx.subject) ||
this.related.writers.includes(ctx.subject),
write: (ctx: Context): boolean => this.related.writers.includes(ctx.subject),
}
}
relationships.js:
[
{
"namespace": "LegalEntity",
"object": "entity1",
"relation": "readers",
"subject": "User:user1"
},
{
"namespace": "LegalEntity",
"object": "entity1",
"relation": "writers",
"subject": "User:user2"
}
]
And getting invalid memory address.echoing-postman-28418
04/28/2023, 9:46 AM// Copyright © 2023 Ory Corp
// SPDX-License-Identifier: Apache-2.0
import { Namespace, SubjectSet, Context } from "@ory/keto-namespace-types"
class User implements Namespace {
related: {
manager: User[]
}
}
class Group implements Namespace {
related: {
members: (User | Group)[]
}
}
class Folder implements Namespace {
related: {
parents: (File | Folder)[]
viewers: SubjectSet<Group, "members">[]
}
permits = {
view: (ctx: Context): boolean =>
this.related.viewers.includes(ctx.subject) ||
this.related.parents.traverse((p) => p.permits.view(ctx)),
}
}
class File implements Namespace {
related: {
parents: (File | Folder)[]
viewers: (User | SubjectSet<Group, "members">)[]
owners: (User | SubjectSet<Group, "members">)[]
}
permits = {
view: (ctx: Context): boolean =>
this.related.parents.traverse((p) => p.permits.view(ctx)) ||
this.related.viewers.includes(ctx.subject) ||
this.related.owners.includes(ctx.subject),
edit: (ctx: Context) => this.related.owners.includes(ctx.subject),
}
}
basically, i want that any user having the viewers access of parent should have viewer access for any of the childs. I created user group developer that has viewers access for folder keto/ and folder keto/ is parent folder keto/src/. I have two users in developer group.
when i run check for viewers access for the user in developer to keto/ it gives me allowed true, but when i run check for viewers access for keto/src/ it gives me false, even though the parent has the viewers access. As far as i could understand from the permission file the user should have viewers access for the children as well
this is my relationship tuple
{
"relation_tuples": [
{
"namespace": "Folder",
"object": "keto/",
"relation": "viewers",
"subject_set": {
"namespace": "Group",
"object": "developer",
"relation": "members"
}
},
{
"namespace": "Folder",
"object": "keto/src/",
"relation": "parents",
"subject_set": {
"namespace": "Folder",
"object": "keto/",
"relation": ""
}
},
{
"namespace": "Group",
"object": "developer",
"relation": "members",
"subject_set": {
"namespace": "User",
"object": "Tom",
"relation": ""
}
},
{
"namespace": "Group",
"object": "developer",
"relation": "members",
"subject_set": {
"namespace": "User",
"object": "John",
"relation": ""
}
},
{
"namespace": "File",
"object": "keto/README.md",
"relation": "parents",
"subject_set": {
"namespace": "Folder",
"object": "keto/",
"relation": ""
}
}
],
"next_page_token": ""
}
#ketovictorious-eye-56567
05/01/2023, 1:36 PMPermissionApi
to generate a client.
Then I have to use the checkPermission
function to test the permission.
What I don’t understand is why the checkPermission
function asks for a relation ?
The payload seems to be the same than for creating a relationship.
I checked the HTTP API and it asks for the same thing.
But in my case I want to test if “userId” can do the action “edit”.
I don’t want to check if “userId” is a member of “editors”.
I want to check actions not relations.
It should be the OPL that is in charge of translating permissions to relation membership based on my OPL rules.
What did I miss ?shy-exabyte-45922
05/01/2023, 11:32 PMimport { Namespace, Context } from "@ory/keto-namespace-types"
class User implements Namespace {}
class Workspace implements Namespace {
related: {
owners: User[]
editors: User[]
viewers: User[]
}
}
class Organization implements Namespace {
related: {
owners: User[]
editors: User[]
viewers: User[]
parents: Workspace[]
}
}
An Organization can be in one or more workspaces, and if the user is the owner of the Workspace (explicit) he will be the owner of the Organization (implicit).
Example:
User:user1 is in owners of Organization:org1
Workspace:ws1 is in parents of Organization:org1
User:user2 is in owners of Workspace:ws1
User 1 and 2 are owners of org1.
I believe an image will be better to understand ...
1. Detalle de usuário: user details page
2. Detalle de la organizacion: organization details page
3. Detalle ell ambient: workspace details pagecreamy-evening-80382
05/02/2023, 11:58 AMhas_perm
. However, I've encountered a problem with this approach: the page load time is significantly slowed down due to multiple ModelAdmins making calls to the check API when generating the admin view.
One potential solution is to leverage Django's permission system, which is based on user groups. This system loads the entire permissions model in memory for a given user and quickly evaluates the user's permissions for each ModelAdmin. However, it's unclear if Ory Keto supports this method.plain-nest-87853
05/02/2023, 11:00 PMclass File implements Namespace {
related: {
owners: (User | Group)[];
};
permits = {
view: (ctx: Context): boolean =>
this.related.owners.includes(ctx.subject) ||
this.related.owners.traverse((p) => p.permits.view(ctx)) // error throws here because user doesn't have a permit
};
}
echoing-postman-28418
05/04/2023, 7:20 AMversion: v0.11.1
dsn: memory
namespaces:
location: file:///home/ory/namespaces.keto.ts
log:
level: debug
format: json
leak_sensitive_values: true
serve:
read:
host: 0.0.0.0
port: 4466
write:
host: 0.0.0.0
port: 4467
I am making a post request to this endpoint : localhost:4466/opl/syntax/check
#ketoechoing-postman-28418
05/04/2023, 7:32 AM{
"namespace": "Folder",
"object": "keto/src/",
"relation": "parents",
"subject_set": {
"namespace": "Folder",
"object": "keto/",
"relation": ""
}
}
and i make multiple put request to the create API instead of keeping a single copy it adds multiple entries of the same relationship tuple.
#ketovictorious-eye-56567
05/04/2023, 5:36 PMuser
can edit
(action) the file myfile
from the File
namespace.
I do not want to check if user
is editors
(relation) of the file myFile
.echoing-postman-28418
05/05/2023, 10:37 AMbillowy-soccer-77917
05/05/2023, 6:08 PMimport { Namespace, SubjectSet, Context } from "@ory/permission-namespace-types"
class Account implements Namespace { }
class Organization implements Namespace {
related: {
members: Account[]
}
permits = {
view: (ctx: Context): boolean => this.related.members.includes(ctx.subject)
}
}
However, I get a denied when checking if an account has permission to view an Organization that it’s a member of:
$ ory list relationships
NAMESPACE OBJECT RELATION NAME SUBJECT
Organization b8cec46a-2544-487a-9a22-a1ce10aaa552 member Account:6ec2f549-0006-469e-af3b-1bd4207e7035
NEXT PAGE TOKEN
IS LAST PAGE true
$ ory is allowed Account:6ec2f549-0006-469e-af3b-1bd4207e7035 view Organization b8cec46a-2544-487a-9a22-a1ce10aaa552
Denied
Am I missing something simple here?billowy-soccer-77917
05/05/2023, 6:12 PMcurved-fountain-46946
05/11/2023, 3:48 PMvictorious-eye-56567
05/16/2023, 11:47 AMtraverse
function in my Keto OPL files.
Here are the permissions:
export class User implements Namespace {}
export class UserList implements Namespace {
related: {
members: User[]
community: Community[]
}
permits = {
view: (ctx: Context): boolean => this.related.community.traverse((c) => c.permits.view(ctx)),
add_member: (ctx: Context): boolean =>
this.related.community.traverse((c) => c.related.user_list_managers.includes(ctx.subject)),
remove_member: (ctx: Context): boolean =>
this.related.community.traverse((c) => c.related.user_list_managers.includes(ctx.subject)),
}
}
export class Community implements Namespace {
related: {
members: (User | SubjectSet<UserList, "members">)[]
user_list_managers: (User | SubjectSet<UserList, "members">)[]
}
permits = {
view: (ctx: Context): boolean => this.related.members.includes(ctx.subject),
create_user_list: (ctx: Context): boolean => this.related.user_list_managers.includes(ctx.subject),
}
}
My issue is that when using the Ory Network I can make it work and get allowed when intended (checking add_member
for example)
But when I use the self hosted version of Keto and I create exactly the same relations using the API I get “denied” instead of allowed.
What am I doing wrong ? Is there an issue with how I use traverse ? Or maybe with how I create relations ?
I put my Ory Network relations and my database relations in thread for comparison.victorious-eye-56567
05/16/2023, 2:50 PM{
"namespace": "UserList",
"object": "copains",
"relation": "community",
"subject_set": {
"namespace": "Community",
"object": "com",
"relation": ""
}
}
instead of this way:
{
"namespace": "UserList",
"object": "copains",
"relation": "community",
"subject_id": "com"
}
After using the proper way my issue is fixed!
Maybe this way of doing should be more documented as using an empty relation was not intuitive to me.victorious-eye-56567
05/18/2023, 6:08 PMmembers
of groups) and also as subject set (members
of myGroup
are admins
of a Community
).
If I only had relationships where the group is the object then I believe the endpoint would be enough but how about when it is a subject set ?
Do I have to do two requests, one with the group as the object and one as the subject set ?
What should be the payload of each request then ?
Thanks for any help!gray-father-90809
05/22/2023, 7:14 AMquaint-pager-64027
05/25/2023, 8:35 PM