Skip to content

Commit 007d84c

Browse files
authored
Documentation - More details Database policy references and explanation (#1215)
* Update config/authorization documentation to detail database policies better and more visibly. Also fixes up grammar and styling. * Update docs/configuration-file.md * Add limitation of db policy for only update read delete. * updates to supported database policy actions. * Update to config doc mentioning SWA auth limitations and correcting malformed explanation sentence for a database policy. * Changed wording. * adding known issue * Update docs/configuration-file.md
1 parent 12ccbf4 commit 007d84c

File tree

3 files changed

+115
-54
lines changed

3 files changed

+115
-54
lines changed

docs/authorization.md

+29-1
Original file line numberDiff line numberDiff line change
@@ -125,9 +125,37 @@ As by default there are no pre-defined permission for the `anonymous` or `authen
125125
"source": "dbo.books",
126126
"permissions": [{
127127
"role": "administrator",
128-
"actions": [ * ]
128+
"actions": ["*"]
129129
}]
130130
}
131131
```
132132

133133
In the above configuration sample, only request carrying the `administrator` role in the authentication token and specifying the `administrator` value in the `X-MS-API-ROLE` HTTP header, will be able to operate on the `book` entity.
134+
135+
### Item level security
136+
137+
Database policy expressions enable results to be restricted even further. Database policies translate OData expressions to query predicates executed against the database. Database policy expressions are supported for the read, update, and delete actions. See the [configuration file](./configuration-file.md#policies) documentation for a detailed explanation of database policies.
138+
139+
|Action | Database Policy Support | Details |
140+
|---|:-:|---|
141+
|create |:x:| [Issue #1216](https://github.com/Azure/data-api-builder/issues/1216) |
142+
|read |:heavy_check_mark: | |
143+
|update |:heavy_check_mark: | |
144+
|delete |:heavy_check_mark: | |
145+
|execute |:x: |Database policies are not applicable to stored procedure execution. |
146+
147+
An example policy restricting the `read` action on the `consumer` role to only return records where the *title* is "Sample Title."
148+
149+
```json
150+
{
151+
"role": "consumer",
152+
"actions": [
153+
{
154+
"action": "read",
155+
"policy": {
156+
"database": "@item.title eq 'Sample Title'"
157+
}
158+
}
159+
]
160+
}
161+
```

docs/configuration-file.md

+83-53
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,35 @@
11
# Configuration File
22

3-
+ [Configuration File](#configuration-file)
4-
+ [Summary](#summary)
5-
+ [Environments Support](#environments-support)
6-
+ [Accessing Environment Variables](#accessing-environment-variables)
7-
+ [File Structure](#file-structure)
8-
+ [Schema](#schema)
9-
+ [Data Source](#data-source)
10-
+ [Runtime global settings](#runtime-global-settings)
11-
+ [REST](#rest)
12-
+ [GraphQL](#graphql)
13-
+ [Host](#host)
14-
+ [Entities](#entities)
15-
+ [GraphQL Settings](#graphql-settings)
16-
+ [REST Settings](#rest-settings)
17-
+ [Database object source](#database-object-source)
18-
+ [Relationships](#relationships)
19-
+ [One-To-Many Relationship](#one-to-many-relationship)
20-
+ [Many-To-One Relationship](#many-to-one-relationship)
21-
+ [Many-To-Many Relationship](#many-to-many-relationship)
22-
+ [Permissions](#permissions)
23-
+ [Roles](#roles)
24-
+ [Actions](#actions)
25-
+ [Mappings](#mappings)
3+
- [Configuration File](#configuration-file)
4+
- [Summary](#summary)
5+
- [Environments Support](#environments-support)
6+
- [Accessing Environment Variables](#accessing-environment-variables)
7+
- [File Structure](#file-structure)
8+
- [Schema](#schema)
9+
- [Data Source](#data-source)
10+
- [Runtime global settings](#runtime-global-settings)
11+
- [REST](#rest)
12+
- [GraphQL](#graphql)
13+
- [Host](#host)
14+
- [Entities](#entities)
15+
- [GraphQL Settings](#graphql-settings)
16+
- [GraphQL Type](#graphql-type)
17+
- [GraphQL Operation](#graphql-operation)
18+
- [REST Settings](#rest-settings)
19+
- [REST Path](#rest-path)
20+
- [REST Methods](#rest-methods)
21+
- [Database object source](#database-object-source)
22+
- [Relationships](#relationships)
23+
- [One-To-Many Relationship](#one-to-many-relationship)
24+
- [Many-To-One Relationship](#many-to-one-relationship)
25+
- [Many-To-Many Relationship](#many-to-many-relationship)
26+
- [Permissions](#permissions)
27+
- [Roles](#roles)
28+
- [Actions](#actions)
29+
- [Fields](#fields)
30+
- [Policies](#policies)
31+
- [Limitations](#limitations)
32+
- [Mappings](#mappings)
2633

2734
## Summary
2835

@@ -423,7 +430,7 @@ The section `permissions` defines who (in terms of roles) can access the related
423430
"permissions": [
424431
{
425432
"role": "...",
426-
"actions": [...],
433+
"actions": ["create", "read", "update", "delete"],
427434
}
428435
]
429436
}
@@ -441,43 +448,47 @@ The `role` string contains the name of the role to which the defined permission
441448

442449
##### Actions
443450

444-
The `actions` array is a mixed-type array that details what actions are allowed to related roles. When the entity is either a table or view, roles can be configured with the following actions: `create`, `read`, `update`, `delete`.
445-
In case of stored procedures, the roles can only be configured with `execute` action.
451+
The `actions` array details what actions are allowed on the associated role. When the entity is either a table or view, roles can be configured with a combination of the actions: `create`, `read`, `update`, `delete`.
446452

447-
For example:
453+
The following example tells Data API builder that the contributor role permits the `read` and `create` actions on the entity:
448454

449455
```json
450456
{
457+
"role": "contributor",
451458
"actions": ["read", "create"]
452459
}
453460
```
454461

455-
tells Data API builder that the related role can perform `read` and `create` actions on the related entity.
456-
457-
In case all actions are allowed, it is possible to use the wildcard character `*` to indicate that. For example:
462+
In case all actions are allowed, the wildcard character `*` can be used as a shortcut to represent all actions supported for the type of entity:
458463

459464
```json
460465
{
466+
"role": "editor",
461467
"actions": ["*"]
462468
}
463469
```
464-
`*` action expands based on the type of the entity. For tables and views, it expands to `create, read, update, delete` actions. For stored-procedures, it translates to `execute` action.
465470

466-
Another option is to specify an object with also details on what fields - defined in the `fields` object, are allowed and what are not:
471+
For stored procedures, roles can only be configured with `execute` action and the wildcard `*` action will expand to `execute`.
472+
For tables and views, the wildcard `*` action expands to the actions `create, read, update, delete`.
473+
474+
##### Fields
475+
476+
Role configuration supports granularly defining which database columns (fields) are permitted to be accessed in the section `fields`:
467477

468478
```json
469479
{
480+
"role": "read-only",
470481
"action": "read",
471-
"fields: {
482+
"fields": {
472483
"include": ["*"],
473484
"exclude": ["field_xyz"]
474485
}
475486
}
476487
```
477488

478-
That will indicate to Data API builder that the related role can `read` from all fields except from `field_xyz`.
489+
That will indicate to Data API builder that the role *read-only* can `read` from all fields except from `field_xyz`.
479490

480-
Both the simple and the more complex definition can be used at the same time, for example, to limit the `read` action to specific fields, while allowing create to operate on all fields:
491+
Both the simplified and granular `action` definitions can be used at the same time. For example, the following configuration limits the `read` action to specific fields, while implicitly allowing the `create` action to operate on all fields:
481492

482493
```json
483494
{
@@ -491,46 +502,64 @@ Both the simple and the more complex definition can be used at the same time, fo
491502
}
492503
},
493504
"create"
494-
]
495-
}
505+
]
496506
}
497507
```
498508

499-
In the `fields` objects, the `*` can be used as the wildcard character to indicate all fields. Exclusions have precedence over inclusions.
509+
In the `fields` section above, the wildcard `*` in the `include` section indicates all fields. The fields noted in the `exclude` section have precedence over fields noted in the `include` section. The definition translates to *include all fields except for the field 'last_updated'*.
510+
511+
##### Policies
512+
513+
The `policy` section, defined per `action`, defines item-level security rules (database policies) which limit the results returned from a request. The sub-section `database` denotes the database policy expression that will be evaluated during request execution.
514+
515+
```json
516+
"policy": {
517+
"database": "<Expression>"
518+
}
519+
```
520+
521+
- `database` policy: an OData expression that is translated into a query predicate that will be evaluated by the database.
522+
- e.g. The policy expression `@item.OwnerId eq 2000` is translated to the query predicate `WHERE Table.OwnerId = 2000`
500523

501-
The `policy` section contains detail about item-level security rules.
524+
> A *predicate* is an expression that evaluates to TRUE, FALSE, or UNKNOWN. Predicates are used in the search condition of [WHERE](https://learn.microsoft.com/sql/t-sql/queries/where-transact-sql) clauses and [HAVING](https://learn.microsoft.com/sql/t-sql/queries/select-having-transact-sql) clauses, the join conditions of [FROM](https://learn.microsoft.com/sql/t-sql/queries/from-transact-sql) clauses, and other constructs where a Boolean value is required.
525+
([Microsoft Learn Docs](https://learn.microsoft.com/sql/t-sql/queries/predicates?view=sql-server-ver16))
502526

503-
+ `database` policy: define a rule - a predicate - that will be injected in the query sent to the database
527+
In order for results to be returned for a request, the request's query predicate resolved from a database policy must evaluate to `true` when executing against the database.
504528

505-
In order for an request or item to be returned, the policies must be evaluated to `true`.
529+
Two types of directives can be used when authoring a database policy expression:
506530

507-
Two types of directives can be used when configuring a database policy:
531+
- `@claims`: access a claim within the validated access token provided in the request.
532+
- `@item`: represents a field of the entity for which the database policy is defined.
508533

509-
+ `@claims`: access a claim stored in the authentication token
510-
+ `@item`: access an entity's field in the underlying database.
534+
> [!NOTE]
535+
> When Azure Static Web Apps authentication (EasyAuth) is configured, a limited number of claims types are available for use in database policies: `identityProvider`, `userId`, `userDetails`, and `userRoles`. See Azure Static Web App's [Client principal data](https://learn.microsoft.com/azure/static-web-apps/user-information?tabs=javascript#client-principal-data) documentation for more details.
511536
512-
For example a policy could be the following:
537+
For example, a policy that utilizes both directive types, pulling the UserId from the access token and referencing the entity's OwnerId field would look like:
513538

514539
```json
515540
"policy": {
516541
"database": "@claims.UserId eq @item.OwnerId"
517542
}
518543
```
519544

520-
Data API Builder will take the value of the claim named `UserId` and it will compare it with the value of the field `OwnerId` existing in the entity where the policy has been defined. Only those elements for which the expression will result to be true, will be allowed to be accessed.
545+
Data API Builder will compare the value of the `UserId` claim to the value of the database field `OwnerId`. The result payload will only include records that fulfill **both** the request metadata and the database policy expression.
546+
547+
##### Limitations
521548

522-
*PLEASE NOTE* that at the moment support for policies is limited to:
549+
Database policies are supported for tables and views. Stored procedures cannot be configured with policies.
523550

524-
+ Tables and Views. Stored Procedures cannot be configured with policies.
525-
+ Binary operators [BinaryOperatorKind - Microsoft Learn](https://learn.microsoft.com/dotnet/api/microsoft.odata.uriparser.binaryoperatorkind?view=odata-core-7.0) such as `and`, `or`, `eq`, `gt`, `lt`, and more.
526-
+ Unary operators [UnaryOperatorKind - Microsoft Learn](https://learn.microsoft.com/dotnet/api/microsoft.odata.uriparser.unaryoperatorkind?view=odata-core-7.0) such as the negate (`-`) and `not` operators.
551+
Database policies are only supported for the `actions` **read**, **update**, and **delete**.
552+
553+
Database policy OData expression syntax supports:
554+
555+
- Binary operators [BinaryOperatorKind - Microsoft Learn](https://learn.microsoft.com/dotnet/api/microsoft.odata.uriparser.binaryoperatorkind?view=odata-core-7.0) such as `and`, `or`, `eq`, `gt`, `lt`, and more.
556+
- Unary operators [UnaryOperatorKind - Microsoft Learn](https://learn.microsoft.com/dotnet/api/microsoft.odata.uriparser.unaryoperatorkind?view=odata-core-7.0) such as the negate (`-`) and `not` operators.
527557

528558
#### Mappings
529-
The `mappings` section enables configuring aliases, or exposed names, for database object fields. The configured exposed names apply to both the GraphQL and REST endpoints. For entities with GraphQL enabled, the configured exposed name **must** meet GraphQL naming requirements. [GraphQL - October 2021 - Names ](https://spec.graphql.org/October2021/#sec-Names)
530559

531-
The format is:
560+
The `mappings` section enables configuring aliases, or exposed names, for database object fields. The configured exposed names apply to both the GraphQL and REST endpoints. For entities with GraphQL enabled, the configured exposed name **must** meet GraphQL naming requirements. [GraphQL - October 2021 - Names ](https://spec.graphql.org/October2021/#sec-Names)
532561

533-
`<database_field>: <entity_field>`
562+
The format is: `<database_field>: <entity_field>`
534563

535564
For example:
536565

@@ -540,4 +569,5 @@ For example:
540569
"sku_status": "status"
541570
}
542571
```
572+
543573
means the `sku_title` field in the related database object will be mapped to the exposed name `title` and `sku_status` will be mapped to `status`. Both GraphQL and REST will require using `title` and `status` instead of `sku_title` and `sku_status` and will additionally use those mapped values in all response payloads.

docs/known-issues.md

+3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ See issue [#452](https://github.com/Azure/data-api-builder/issues/452)
88

99
See issue [#479](https://github.com/Azure/data-api-builder/issues/479)
1010

11+
## Database authorization policies are not supported for the `create` action
12+
13+
See issue [#1216](https://github.com/Azure/data-api-builder/issues/1216)
1114
## Knowns issues with MySQL
1215
Here are some known issues specifically with MySQL database.
1316
- Update fails on tables with Computed columns. [Issue #1001](https://github.com/Azure/data-api-builder/issues/1001)

0 commit comments

Comments
 (0)