Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion DEPRECATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ features:
| Deprecated | [Node.js 20](#nodejs-20) | v1.3.0 | |
| Deprecated | [`renewQuery` parameter of the `/v1/load` endpoint](#renewquery-parameter-of-the-v1load-endpoint) | v1.3.73 | |
| Deprecated | [Elasticsearch driver](#elasticsearch-driver) | v1.6.0 | |
| Deprecated | [`context_to_roles`](#context-to-roles) | v1.6.4 | |

### Node.js 8

Expand Down Expand Up @@ -426,4 +427,11 @@ options and use the new `cache` parameter of the `/v1/load` endpoint instead.

**Deprecated in Release: v1.6.0**

The Elasticsearch driver is deprecated and will be removed in a future release.
The Elasticsearch driver is deprecated and will be removed in a future release.

### `context_to_roles`

**Deprecated in Release: v1.6.4**

The `context_to_roles` configuration option is deprecated and will be removed in a future
release. Please use `context_to_groups` instead.
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ To filter data based on user attributes, implement an access policy in your view
views:
- name: orders_view
access_policy:
- role: "*" # Applies to all roles
- group: "*" # Applies to all groups
row_level:
filters:
- member: customers_city
Expand Down
31 changes: 27 additions & 4 deletions docs/pages/product/auth.mdx
Original file line number Diff line number Diff line change
@@ -1,15 +1,38 @@
# Access control

Access control in Cube involves _authentication_ and _authorization_.

Cube has a data access control layer built into the data model. Access control in Cube involves _authentication_ and _authorization_.
## Authentication

Authentication determines if a user can access Cube.

**Cube** cloud platform provides built-in authentication abstractions alongside [user attributes][ref-user-attributes] and groups for managing data access. **Cube Core** users can control the [security context][ref-sec-ctx] directly to implement authentication.
* **Cube** cloud platform provides built-in authentication mechanisms. Users are assigned
[roles and permissions][ref-roles-perms] that determine available features of the Cube
platform.
* **Cube Core** provides several [authentication methods][ref-auth-methods] for its API
endpoints.

## Authorization

Authorization is based on [access policies][ref-dap] and dynamic controls for advanced use cases.
Authorization determines what data a user can access though Cube.

Authorization is managed declaratively via [access policies][ref-dap], a built-in
capability of Cube's data modeling layer. There are also programmatic controls for
advanced use cases, such as the [`query_rewrite`][ref-query-rewrite] configuration
parameter.

* **Cube** cloud platform applies access policies to users based on their
[groups][ref-user-groups] and [attributes][ref-user-attributes].
* **Cube Core** applies access policies to users based on their groups derived from the
[security context][ref-sec-ctx]. See the [`context_to_groups`][ref-ctx-to-groups]
configuration parameter for details.


[ref-roles-perms]: /product/administration/users-and-permissions/roles-and-permissions
[ref-auth-methods]: /product/auth/methods
[ref-user-groups]: /product/administration/users-and-permissions/user-groups
[ref-user-attributes]: /product/administration/users-and-permissions/user-attributes
[ref-sec-ctx]: /product/auth/context
[ref-dap]: /product/auth/data-access-policies
[ref-dap]: /product/auth/data-access-policies
[ref-query-rewrite]: /product/configuration/reference/config#query_rewrite
[ref-ctx-to-groups]: /product/configuration/reference/config#context_to_groups
42 changes: 1 addition & 41 deletions docs/pages/product/auth/data-access-policies.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -302,38 +302,6 @@ view(`country_data_view`, {

</CodeTabs>

## Troubleshooting

Be careful with the [_any group_ shorthand][ref-ref-dap-role] (`group: "*"`) in access
policies that don't restrict access on member __and__ row level. Given that policies for
multiple groups are [combined together](#policy-evaluation) using the _OR_ semantics,
a policy that allows access for _any group_ without restrictions on a certain level will
effectively grant unrestricted access on that level to all users:

```yaml
cubes:
- name: orders
# ...

access_policy:
# No access on member level, __full access__ on row level for any group
- group: "*"
member_level:
includes: []

# Some restrictions on row level for the `restricted` group
- group: restricted
row_level:
filters:
- member: country
operator: equals
values: [ "USA" ]
```

In the example above, all users will have full access to all members and all rows of the
`orders` cube, regardless of their groups, because the first policy applies to _any
group_ and is combined with the second one using the _OR_ semantics.

## Custom mapping

Cube cloud platform automatically maps authenticated users to groups for access policies.
Expand Down Expand Up @@ -406,17 +374,9 @@ cube(`orders`, {

</CodeTabs>

## Using roles

In prior versions of Cube, we were using `roles` instead of `groups`. We have changed that to `groups` to avoid conflict with [Cube roles][ref-cube-roles].

In Cube Core, you can still use roles. You would need to define `context_to_roles` instead of `context_to_groups`.


[ref-mls-public]: /product/auth/member-level-security#managing-member-level-access
[ref-sec-ctx]: /product/auth/context
[ref-ctx-to-roles]: /product/configuration/reference/config#context_to_roles
[ref-ref-dap]: /product/data-modeling/reference/data-access-policies
[ref-ref-dap-role]: /product/data-modeling/reference/data-access-policies#role
[ref-core-data-apis]: /product/apis-integrations/core-data-apis
[ref-cube-roles]: /product/administration/users-and-permissions/roles-and-permissions
[ref-core-data-apis]: /product/apis-integrations/core-data-apis
89 changes: 75 additions & 14 deletions docs/pages/product/configuration/reference/config.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -1363,26 +1363,27 @@ module.exports = {

</CodeTabs>

### `context_to_roles`
### `context_to_groups`

Used by [access policies][ref-dap]. This option is used to derive a list of
[data access roles][ref-dap-roles] from the [security context][ref-sec-ctx].
Used by [access policies][ref-dap]. This option is used to derive a list of groups that
the user belongs to from the [security context][ref-sec-ctx]. These groups can then be
used to match [access policies][ref-dap-roles].

<CodeTabs>

```python
from cube import config

@config('context_to_roles')
def context_to_roles(ctx: dict) -> list[str]:
return ctx['securityContext'].get('roles', ['default'])
@config('context_to_groups')
def context_to_groups(ctx: dict) -> list[str]:
return ctx['securityContext'].get('groups', ['default'])
```

```javascript

module.exports = {
contextToRoles: ({ securityContext }) => {
return securityContext.roles || ['default']
contextToGroups: ({ securityContext }) => {
return securityContext.groups || ['default']
}
}
```
Expand All @@ -1391,24 +1392,24 @@ module.exports = {

If the [user roles mapping][ref-ldap-roles-mapping] in the [LDAP integration][ref-ldap-integration]
is configured and the [authentication integration][ref-auth-integration] is enabled,
the `context_to_roles` option might be defined as follows:
the `context_to_groups` option might be defined as follows:

<CodeTabs>

```python
from cube import config

@config('context_to_roles')
def context_to_roles(ctx: dict) -> list[str]:
cloud_ctx = ctx['securityContext'].get('cubeCloud', {'roles': []})
@config('context_to_groups')
def context_to_groups(ctx: dict) -> list[str]:
cloud_ctx = ctx['securityContext'].get('cubeCloud', {'groups': []})
return cloud_ctx.get('roles', [])
```

```javascript

module.exports = {
contextToRoles: ({ securityContext }) => {
const cloud_ctx = securityContext.cubeCloud || { roles: [] }
contextToGroups: ({ securityContext }) => {
const cloud_ctx = securityContext.cubeCloud || { groups: [] }
return cloud_ctx.roles || []
}
}
Expand Down Expand Up @@ -1504,6 +1505,66 @@ Usually used for [multitenancy][ref-multitenancy].
If not defined, Cube will lookup for environment variable
`CUBEJS_DB_TYPE` to resolve the data source type.

### `context_to_roles`

<WarningBox>

`context_to_roles` is deprecated and will be removed in a future release.
Use [`context_to_groups`](#context_to_groups) instead.

</WarningBox>

Used by [access policies][ref-dap]. This option is used to derive a list of
[data access roles][ref-dap-roles] from the [security context][ref-sec-ctx].

<CodeTabs>

```python
from cube import config

@config('context_to_roles')
def context_to_roles(ctx: dict) -> list[str]:
return ctx['securityContext'].get('roles', ['default'])
```

```javascript

module.exports = {
contextToRoles: ({ securityContext }) => {
return securityContext.roles || ['default']
}
}
```

</CodeTabs>

If the [user roles mapping][ref-ldap-roles-mapping] in the [LDAP integration][ref-ldap-integration]
is configured and the [authentication integration][ref-auth-integration] is enabled,
the `context_to_roles` option might be defined as follows:

<CodeTabs>

```python
from cube import config

@config('context_to_roles')
def context_to_roles(ctx: dict) -> list[str]:
cloud_ctx = ctx['securityContext'].get('cubeCloud', {'roles': []})
return cloud_ctx.get('roles', [])
```

```javascript

module.exports = {
contextToRoles: ({ securityContext }) => {
const cloud_ctx = securityContext.cubeCloud || { roles: [] }
return cloud_ctx.roles || []
}
}
```

</CodeTabs>


[gh-jsonwebtoken-algs]:
https://github.com/auth0/node-jsonwebtoken#algorithms-supported
Expand Down
56 changes: 24 additions & 32 deletions rust/cubestore/cubestore-sql-tests/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3348,10 +3348,9 @@ async fn planning_hints(service: Box<dyn SqlClient>) {
assert_eq!(
pp_phys_plan_ext(p.worker.as_ref(), &show_hints),
"Worker, sort_order: [0, 1]\
\n CoalescePartitions, sort_order: [0, 1]\
\n Scan, index: default:1:[1], fields: [id1, id2], sort_order: [0, 1]\
\n Sort, sort_order: [0, 1]\
\n Empty"
\n Scan, index: default:1:[1], fields: [id1, id2], sort_order: [0, 1]\
\n Sort, sort_order: [0, 1]\
\n Empty"
);

let p = service
Expand All @@ -3362,10 +3361,9 @@ async fn planning_hints(service: Box<dyn SqlClient>) {
pp_phys_plan_ext(p.worker.as_ref(), &show_hints),
"Worker, sort_order: [1, 0]\
\n Projection, [id2, id1], sort_order: [1, 0]\
\n CoalescePartitions, sort_order: [0, 1]\
\n Scan, index: default:1:[1], fields: [id1, id2], sort_order: [0, 1]\
\n Sort, sort_order: [0, 1]\
\n Empty"
\n Scan, index: default:1:[1], fields: [id1, id2], sort_order: [0, 1]\
\n Sort, sort_order: [0, 1]\
\n Empty"
);

// Unsorted when skips columns from sort prefix.
Expand All @@ -3390,10 +3388,9 @@ async fn planning_hints(service: Box<dyn SqlClient>) {
assert_eq!(
pp_phys_plan_ext(p.worker.as_ref(), &show_hints),
"Worker, sort_order: [0]\
\n CoalescePartitions, sort_order: [0]\
\n Scan, index: default:1:[1], fields: [id1, id3], sort_order: [0]\
\n Sort, sort_order: [0]\
\n Empty"
\n Scan, index: default:1:[1], fields: [id1, id3], sort_order: [0]\
\n Sort, sort_order: [0]\
\n Empty"
);

// Single value hints.
Expand Down Expand Up @@ -3433,10 +3430,9 @@ async fn planning_hints(service: Box<dyn SqlClient>) {
pp_phys_plan_ext(p.worker.as_ref(), &show_hints),
"Worker, sort_order: [0, 1]\
\n Filter, sort_order: [0, 1]\
\n CoalescePartitions, sort_order: [0, 1, 2]\
\n Scan, index: default:1:[1], fields: *, sort_order: [0, 1, 2]\
\n Sort, sort_order: [0, 1, 2]\
\n Empty"
\n Scan, index: default:1:[1], fields: *, sort_order: [0, 1, 2]\
\n Sort, sort_order: [0, 1, 2]\
\n Empty"
);
}

Expand Down Expand Up @@ -3733,10 +3729,9 @@ async fn planning_simple(service: Box<dyn SqlClient>) {
assert_eq!(
pp_phys_plan(p.worker.as_ref()),
"Worker\
\n CoalescePartitions\
\n Scan, index: default:1:[1], fields: [id, amount]\
\n Sort\
\n Empty"
\n Scan, index: default:1:[1], fields: [id, amount]\
\n Sort\
\n Empty"
);

let p = service
Expand All @@ -3751,10 +3746,9 @@ async fn planning_simple(service: Box<dyn SqlClient>) {
pp_phys_plan(p.worker.as_ref()),
"Worker\
\n Filter\
\n CoalescePartitions\
\n Scan, index: default:1:[1], fields: [id, amount]\
\n Sort\
\n Empty"
\n Scan, index: default:1:[1], fields: [id, amount]\
\n Sort\
\n Empty"
);

let p = service
Expand All @@ -3776,10 +3770,9 @@ async fn planning_simple(service: Box<dyn SqlClient>) {
"Sort\
\n Worker\
\n Filter\
\n CoalescePartitions\
\n Scan, index: default:1:[1], fields: [id, amount]\
\n Sort\
\n Empty"
\n Scan, index: default:1:[1], fields: [id, amount]\
\n Sort\
\n Empty"
);

let p = service
Expand All @@ -3801,10 +3794,9 @@ async fn planning_simple(service: Box<dyn SqlClient>) {
"GlobalLimit, n: 10\
\n Worker\
\n Filter\
\n CoalescePartitions\
\n Scan, index: default:1:[1], fields: [id, amount]\
\n Sort\
\n Empty"
\n Scan, index: default:1:[1], fields: [id, amount]\
\n Sort\
\n Empty"
);

let p = service
Expand Down
Loading
Loading