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

Catch up v23.0 branch #655

Merged
merged 9 commits into from
Jan 5, 2024
20 changes: 20 additions & 0 deletions content/dql/dql-schema.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,8 +187,28 @@ Query:
}
```

### Unique Directive


The unique constraint enables us to guarantee that all values of a predicate are distinct. To implement the @unique
directive for a predicate, you should define it in the schema and create an index on the predicate based on its type.
If a user does not add the proper index to the predicate, then Dgraph will return an error.

Dgraph will automatically include the @upsert directive for the predicate. To enforce this uniqueness constraint,
a predicate must have an index, as explained below. Currently, we only support the @unique directive on newly created
predicates with the data types string and integer.

| Data Type | Index |
| -------- | ------- |
| string | hash, exact |
| int | int |

This is how you define the unique directive for a predicate.

```
email: string @unique @index(exact) .
```

### Upsert directive


Expand Down
45 changes: 45 additions & 0 deletions content/enterprise-features/binary-backups.md
Original file line number Diff line number Diff line change
Expand Up @@ -648,6 +648,51 @@ mutation{
}
}
```

## Namespace Aware Restore

You can use namespace-aware restore to restore a single namespace from a backup that contains multiple namespaces.
The created restore will be available in the default namespace. For example, if you restore namespace 2 using the
restoreTenant API, then after the restore operation is completed, the cluster will have only the default namespace,
and it will contain the data from namespace 2. Namespace aware restore supports incremental restore.

To restore from a backup to a live cluster, execute a mutation on the `/admin` endpoint with the following format:

```graphql
mutation {
restoreTenant(
input: {
restoreInput: {
incrementalFrom: "incremental_backup_from"
location: "/path/to/backup/directory"
backupId: "id_of_backup_to_restore"
}
fromNamespace: namespaceToBeRestored
}
) {
message
code
}
}
```

Documentation of restoreTenant inputs

```
input RestoreTenantInput {
"""
restoreInput contains fields that are required for the restore operation,
i.e., location, backupId, and backupNum
"""
restoreInput: RestoreInput

"""
fromNamespace is the namespace of the tenant that needs to be restored into namespace 0 of the new cluster.
"""
fromNamespace: Int!
}
```

## Offline restore

The restore utility is now a standalone tool. A new flag, `--encryption key-file=value`, is now part of the restore utility, so you can use it to decrypt the backup. The file specified using this flag must contain the same key that was used for encryption during backup. Alternatively, starting with `v20.07.0`, the `vault` superflag can be used to restore a backup.
Expand Down
27 changes: 27 additions & 0 deletions content/graphql/schema/directives/directive-withsubscription.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
+++
title = "@withSubscription"
weight = 7
[menu.main]
parent = "directives"
identifier = "directive-withsubscription"
+++


The `@withSubscription` directive enables **subscription** operation on a GraphQL type.

A subscription notifies your client with changes to back-end data using the WebSocket protocol.
Subscriptions are useful to get low-latency, real-time updates.

To enable subscriptions on any type add the `@withSubscription` directive to the schema as part of the type definition, as in the following example:

```graphql
type Todo @withSubscription {
id: ID!
title: String!
description: String!
completed: Boolean!
}
```

Refer to [GraphQL Subscriptions]({{< relref "graphql/subscriptions" >}}) to learn how to use subscriptions in you client application.

48 changes: 41 additions & 7 deletions content/graphql/security/RBAC-rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,51 @@ type User @auth(
delete: ...
)
```
RBAC rule supports ``eq`` or ``in`` functions to test the value of a [JWT claim]({{< relref "graphql/security/_index.md#jwt-claims" >}}) from the JWT token payload.

Where `<claim>` is a [JWT claim]({{< relref "graphql/security/_index.md#jwt-claims" >}}) from the JWT token payload.

You can use ``eq`` or ``in`` function to test the value of any claim.
The claim value may be a string or array of strings.

For example the following schema has a @auth directive specifying that a delete operation on a User object can only be done if the connected user has a 'ROLE' claim in the JWT token with the value "admin" :
```graphql
type User @auth(
delete: { rule: "{$ROLE: { eq: \"admin\" } }"}
) {
username: String!
@id todos: [Todo]
}
```
The following JWT token payload will pass the test (provided that Dgraph.Authorization is configured correctly with the right namespace)
```json
{
"aud": "dgraph",
"exp": 1695359621,
"https://dgraph.io/jwt/claims": {
"ROLE": "admin",
"USERID": "testuser@dgraph.io"
},
"iat": 1695359591,
...
}
```
The rule is also working with an array of roles in the JWT token:
```json
{
"aud": "dgraph",
"exp": 1695359621,
"https://dgraph.io/jwt/claims": {
"ROLE": ["admin","user"]
"USERID": "testuser@dgraph.io"
},
"iat": 1695359591,
...
}
```
In the case of an array used with the "in" function, the rule is valid is at least one of the claim value is "in" the provided list.

For example the following schema has a @auth directive specifying that a delete operation on a User object can only be done in the connected user has a 'ROLE' claim in the JWT token with the value "ADMIN" :
For example, with the following rule, the previous token will be valid because one of the ROLE is in the authorized roles.
```graphql
type User @auth(
delete: { rule: "{$ROLE: { eq: \"ADMIN\" } }"}
delete: { rule: "{$ROLE: { in: [\"admin\",\"superadmin\"] } }"}
) {
username: String!
@id todos: [Todo]
Expand Down Expand Up @@ -70,12 +105,11 @@ For example, given the following JWT payload
"https://xyz.io/jwt/claims": [
"ROLE": "ADMIN"
],
"USERROLE": "user1",
"email": "random@example.com"
}
```

The authorization rules can use ``$ROLE`` (if `https://xyz.io/jwt/claims` is declared as the namespace to use ) and also ``$USERROLE`` or ``$email``.
If `https://xyz.io/jwt/claims` is declared as the namespace to use, the authorization rules can use ``$ROLE`` but also ``$email``.

In cases where the same claim is present in the namespace and at the root level, the claim value in the namespace takes precedence.

Expand Down
57 changes: 52 additions & 5 deletions content/graphql/security/jwt.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ When deploying a GraphQL schema, the admin user can set a ``# Dgraph.Authorizat
This line must start with the exact string ``# Dgraph.Authorization`` and be at the bottom of the schema file.


### Configure JWT token handling
## Configure JWT token handling

To configure how Dgraph should handle JWT token for ``/graphql`` endpoint :
1. Add a line starting with ``# Dgraph.Authorization`` and with the following parameters at the very end of your GraphQL schema.
Expand Down Expand Up @@ -51,8 +51,51 @@ See the [RBAC rules]({{< relref "RBAC-rules.md">}}) and [Graph traversal rules](
### Require JWT token
To not only accept but to require the JWT token regardless of @auth directives in your GraphQL schema, set option "ClosedByDefault" to true in the `# Dgraph.Authorization` line.

### Examples
## Working with Authentication providers
Dgraph.Authorization is fully configurable to work with various authentication providers.
Authentication providers have options to configure how to generate JWT tokens.

Here are some configuration examples.

### Clerk.com

In your clerk dashboard, Access `JWT Templates` and create a template for Dgraph.

Your template must have an `aud` (audience), this is mandatory for Dgraph when the token is verified using JWKURL.

Decide on a claim namespace and add the information you want to use in your RBAC rules.

We are using 'https://dgraph.io/jwt/claims' namespace in this example and have decided to get the user current organization, role ( clerk has currently two roles 'admin' and 'basic_member') and email.

This is our JWT Template in Clerk:
```json
{
"aud": "dgraph",
"https://dgraph.io/jwt/claims": {
"org": "{{org.name}}",
"role": "{{org.role}}",
"userid": "{{user.primary_email_address}}"
}
}
```

In the same configuration panel
- set the **token lifetime**
- copy the **JWKS Endpoint**

Configure your Dgraph GraphQL schema with the following authorization
```
# Dgraph.Authorization {"header":"X-Dgraph-AuthToken","namespace":"https://dgraph.io/jwt/claims","jwkurl":"https://<>.clerk.accounts.dev/.well-known/jwks.json","audience":["dgraph"],"closedbydefault":true}
```
Note that
- **namespace** matches the namespace used in the JWT Template
- **audience** is an array and contains the **aud** used in the JWT token
- **jwkurl** is the **JWKS Endpoint** from Clerk

You can select the header to receive the JWT token from your client app, `X-Dgraph-AuthToken` is a header authorized by default by Dgraph GraphQL API to pass CORS requirements.


## Other Dgraph.Authorization Examples

To use a single JWK URL:

Expand Down Expand Up @@ -82,7 +125,7 @@ Using HMAC-SHA256 token in `X-My-App-Auth` header and authorization claims in `h
### JWT format

The value of the JWT ``header`` is expected to be in one of the following forms:
* Just the JWT token.
* Bare token.
For example:
```
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJodHRwczovL215LmFwcC5pby9qd3QvY2xhaW1zIjp7fX0.Pjlxpf-3FhH61EtHBRo2g1amQPRi0pNwoLUooGbxIho
Expand All @@ -96,7 +139,7 @@ The value of the JWT ``header`` is expected to be in one of the following forms:

### Error handling

If ClosedByDefault is set to true, and the JWT is not present or if the JWT token does not include the proper audience information, or is not properly encoded, Dgraph replies to requests on `/graphql` endpoint with an error message rejecting the operation similar to:
If ClosedByDefault is set to true, and the JWT is not present or if the JWT token does not include the proper audience information, or is not properly encoded, or is expired, Dgraph replies to requests on `/graphql` endpoint with an error message rejecting the operation similar to:
```
{
"errors": [
Expand All @@ -111,4 +154,8 @@ If ClosedByDefault is set to true, and the JWT is not present or if the JWT toke
"queryContact": []
},...
```

**Error messages**
- "couldn't rewrite query queryContact because a valid JWT is required but was not provided"
- "couldn't rewrite query queryMessage because unable to parse jwt token:token is expired by 5h49m46.236018623s"
- "couldn't rewrite query queryMessage because JWT `aud` value doesn't match with the audience"
- "couldn't rewrite query queryMessage because unable to parse jwt token:token signature is invalid"
Loading