Skip to content

Commit

Permalink
Merge branch 'main' into upgrade-export-import
Browse files Browse the repository at this point in the history
  • Loading branch information
shilgapira committed Nov 14, 2024
2 parents 19a7318 + 18d2b8d commit d1f0da9
Show file tree
Hide file tree
Showing 10 changed files with 404 additions and 163 deletions.
2 changes: 1 addition & 1 deletion .github/actions/tests/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ runs:
shell: bash

- name: Upload coverage HTML
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: coverage.html
path: |
Expand Down
210 changes: 52 additions & 158 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ These sections show how to use the SDK to perform API management functions. Befo
10. [Impersonate](#impersonate)
11. [Audit](#audit)
12. [Embedded Links](#embedded-links)
13. [Manage ReBAC Authz](#manage-rebac-authz)
13. [Manage FGA (Fine-grained Authorization)](#manage-fga-fine-grained-authorization)
14. [Manage Project](#manage-project)
15. [Manage SSO Applications](#manage-sso-applications)

Expand Down Expand Up @@ -958,7 +958,7 @@ You can create, update, delete or load access keys, as well as search according
// If customClaims is supplied, then those claims will be present in the JWT returned by calls to ExchangeAccessKey.
// If description is supplied, then the access key will hold a descriptive text.
// If permittedIPs is supplied, then we will only allow using the access key from those IP addresses or CIDR ranges.
res, err := descopeClient.Management.AccessKey().Create(context.Background(), "access-key-1", 0, nil, []*descope.AssociatedTenant{
res, err := descopeClient.Management.AccessKey().Create(context.Background(), "access-key-1", "key-description", 0, nil, []*descope.AssociatedTenant{
{TenantID: "tenant-ID1", RoleNames: []string{"role-name1"}},
{TenantID: "tenant-ID2"},
},
Expand All @@ -980,7 +980,7 @@ if err == nil {
// Update access key
// If description, roles, tenants, customClaims, or permittedIPs are nil, their existing values will be preserved. If you want to remove them, pass an empty slice or map.
updatedDescription := "Updated description"
res, err := descopeClient.Management.AccessKey().Update(context.Background(), "access-key-id", "updated-name", &updatedDescription, []string{"role"}, []*descope.AssociatedTenant{{TenantID: "t1", Roles: []string{"role"}}}, map[string]any{"k1": "v1"}, []string{"1.2.3.4"})
res, err := descopeClient.Management.AccessKey().Update(context.Background(), "access-key-id", "updated-name", &updatedDescription, []string{"role"}, nil, map[string]any{"k1": "v1"}, []string{"1.2.3.4"})

// Access keys can be deactivated to prevent usage. This can be undone using "activate".
err := descopeClient.Management.AccessKey().Deactivate(context.Background(), "access-key-id")
Expand Down Expand Up @@ -1319,181 +1319,75 @@ err := descopeClient.Management.Audit().CreateEvent(context.Background(), &desco
})
```

### Manage ReBAC Authz
### Manage FGA (Fine-grained Authorization)

Descope supports full relation based access control (ReBAC) using a zanzibar like schema and operations.
A schema is comprized of namespaces (entities like documents, folders, orgs, etc.) and each namespace has relation definitions to define relations.
Each relation definition can be simple (either you have it or not) or complex (union of nodes).
A schema is comprized of types (entities like documents, folders, orgs, etc.) and each type has relation definitions and permission to define relations to other types.

A simple example for a file system like schema would be:

```yaml
# Example schema for the authz tests
name: Files
namespaces:
- name: org
relationDefinitions:
- name: parent
- name: member
complexDefinition:
nType: union
children:
- nType: child
expression:
neType: self
- nType: child
expression:
neType: relationLeft
relationDefinition: parent
relationDefinitionNamespace: org
targetRelationDefinition: member
targetRelationDefinitionNamespace: org
- name: folder
relationDefinitions:
- name: parent
- name: owner
complexDefinition:
nType: union
children:
- nType: child
expression:
neType: self
- nType: child
expression:
neType: relationRight
relationDefinition: parent
relationDefinitionNamespace: folder
targetRelationDefinition: owner
targetRelationDefinitionNamespace: folder
- name: editor
complexDefinition:
nType: union
children:
- nType: child
expression:
neType: self
- nType: child
expression:
neType: relationRight
relationDefinition: parent
relationDefinitionNamespace: folder
targetRelationDefinition: editor
targetRelationDefinitionNamespace: folder
- nType: child
expression:
neType: targetSet
targetRelationDefinition: owner
targetRelationDefinitionNamespace: folder
- name: viewer
complexDefinition:
nType: union
children:
- nType: child
expression:
neType: self
- nType: child
expression:
neType: relationRight
relationDefinition: parent
relationDefinitionNamespace: folder
targetRelationDefinition: viewer
targetRelationDefinitionNamespace: folder
- nType: child
expression:
neType: targetSet
targetRelationDefinition: editor
targetRelationDefinitionNamespace: folder
- name: doc
relationDefinitions:
- name: parent
- name: owner
complexDefinition:
nType: union
children:
- nType: child
expression:
neType: self
- nType: child
expression:
neType: relationRight
relationDefinition: parent
relationDefinitionNamespace: doc
targetRelationDefinition: owner
targetRelationDefinitionNamespace: folder
- name: editor
complexDefinition:
nType: union
children:
- nType: child
expression:
neType: self
- nType: child
expression:
neType: relationRight
relationDefinition: parent
relationDefinitionNamespace: doc
targetRelationDefinition: editor
targetRelationDefinitionNamespace: folder
- nType: child
expression:
neType: targetSet
targetRelationDefinition: owner
targetRelationDefinitionNamespace: doc
- name: viewer
complexDefinition:
nType: union
children:
- nType: child
expression:
neType: self
- nType: child
expression:
neType: relationRight
relationDefinition: parent
relationDefinitionNamespace: doc
targetRelationDefinition: viewer
targetRelationDefinitionNamespace: folder
- nType: child
expression:
neType: targetSet
targetRelationDefinition: editor
targetRelationDefinitionNamespace: doc
```
model AuthZ 1.0

type user

type org
relation member: user
relation parent: org

type folder
relation parent: folder
relation owner: user | org#member
relation editor: user
relation viewer: user

permission can_create: owner | parent.owner
permission can_edit: editor | can_create
permission can_view: viewer | can_edit

type doc
relation parent: folder
relation owner: user | org#member
relation editor: user
relation viewer: user

permission can_create: owner | parent.owner
permission can_edit: editor | can_create
permission can_view: viewer | can_edit
```
Descope SDK allows you to fully manage the schema and relations as well as perform simple (and not so simple) checks regarding the existence of relations.
```go
// Load the existing schema
schema, err := descopeClient.Management.Authz().LoadSchema(context.Background())
if err != nil {
// handle error
}

// Save schema and make sure to remove all namespaces not listed
err := descopeClient.Management.Authz().SaveSchema(context.Background(), schema, true)
// Save schema
err := descopeClient.Management.FGA().SaveSchema(context.Background(), schema)

// Create a relation between a resource and user
err := descopeClient.Management.Authz().CreateRelations(context.Background(), []*descope.AuthzRelation {
{
resource: "some-doc",
relationDefinition: "owner",
namespace: "doc",
target: "u1",
err := descopeClient.Management.FGA().CreateRelations(context.Background(), []*descope.FGARelation {
{
Resource: "some-doc",
ResourceType: "doc",
Relation: "owner",
Target: "u1",
TargetType: "user"
},
})

// Check if target has the relevant relation
// The answer should be true because an owner is also a viewer
relations, err := descopeClient.Management.Authz().HasRelations(context.Background(), []*descope.AuthzRelationQuery{
// Check if target has a relevant relation
// The answer should be true because an owner can also view
relations, err := descopeClient.Management.FGA().Check(context.Background(), []*descope.FGARelation{
{
resource: "some-doc",
relationDefinition: "viewer",
namespace: "doc",
target: "u1",
Resource: "some-doc",
ResourceType: "doc",
Relation: "can_view",
Target: "u1",
TargetType: "user"
}
})
```


### Manage Project

You can update a project's name, as well as clone the current project to create a new one:
Expand Down
25 changes: 25 additions & 0 deletions descope/api/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,10 @@ var (
authzRETargetAll: "mgmt/authz/re/targetall",
authzRETargetWithRelation: "mgmt/authz/re/targetwithrelation",
authzGetModified: "mgmt/authz/getmodified",
fgaSaveSchema: "mgmt/fga/schema",
fgaCreateRelations: "mgmt/fga/relations",
fgaDeleteRelations: "mgmt/fga/relations/delete",
fgaCheck: "mgmt/fga/check",
},
logout: "auth/logout",
logoutAll: "auth/logoutall",
Expand Down Expand Up @@ -408,6 +412,11 @@ type mgmtEndpoints struct {
authzRETargetAll string
authzRETargetWithRelation string
authzGetModified string

fgaSaveSchema string
fgaCreateRelations string
fgaDeleteRelations string
fgaCheck string
}

func (e *endpoints) SignInOTP() string {
Expand Down Expand Up @@ -1090,6 +1099,22 @@ func (e *endpoints) ManagementAuthzGetModified() string {
return path.Join(e.version, e.mgmt.authzGetModified)
}

func (e *endpoints) ManagementFGASaveSchema() string {
return path.Join(e.version, e.mgmt.fgaSaveSchema)
}

func (e *endpoints) ManagementFGACreateRelations() string {
return path.Join(e.version, e.mgmt.fgaCreateRelations)
}

func (e *endpoints) ManagementFGADeleteRelations() string {
return path.Join(e.version, e.mgmt.fgaDeleteRelations)
}

func (e *endpoints) ManagementFGACheck() string {
return path.Join(e.version, e.mgmt.fgaCheck)
}

type sdkInfo struct {
name string
version string
Expand Down
22 changes: 22 additions & 0 deletions descope/authztypes.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,25 @@ type AuthzModified struct {
Targets []string `json:"targets"`
SchemaChanged bool `json:"schemaChanged"`
}

// FGA

// FGASchema holds the schema for a project
type FGASchema struct {
Schema string `json:"schema"`
}

// FGARelation defines a relation between resource and target
type FGARelation struct {
Resource string `json:"resource"`
ResourceType string `json:"resourceType"`
Relation string `json:"relation"`
Target string `json:"target"`
TargetType string `json:"targetType"`
}

// FGACheck holds the result of a check
type FGACheck struct {
Allowed bool `json:"allowed"`
Relation *FGARelation `json:"relation"`
}
Loading

0 comments on commit d1f0da9

Please sign in to comment.