atoti_query.security.security module#
- class atoti_query.security.Security#
Manage the parts of the security config that can be changed without restarting the
Session
.The roles and restrictions are stored in the
user content storage
. Multiple sessions configured with the same user content storage will thus share their roles and restrictions.Note
Users without the ROLE_USER will not be able to access the application.
- property basic: BasicSecurity#
- property individual_roles: IndividualRoles#
- property kerberos: KerberosSecurity#
- property ldap: LdapSecurity#
- property oidc: OidcSecurity#
- property restrictions: MutableMapping[str, Condition[ColumnIdentifier, Literal['eq', 'isin'], Constant, Literal['and'] | None]]#
Mapping from role name to corresponding restriction.
There are reserved roles for which restrictions cannot be declared:
ROLE_USER: gives access the application
ROLE_ADMIN: gives full access (read, write, delete, etc) to the application
The restrictions associated with a role can be modified at any time.
Restrictions apply on table columns and are inherited by all hierarchies based on these columns.
Restrictions on different hierarchies are intersected.
However, if a user has several roles with restrictions on the same hierarchies, access to the union of restricted elements will be granted.
Example
>>> df = pd.DataFrame( ... [ ... ("Asia", "Korea", "KRW"), ... ("Asia", "Japan", "JPY"), ... ("Europe", "France", "EUR"), ... ("Europe", "Germany", "EUR"), ... ("Europe", "Norway", "NOK"), ... ("Europe", "Sweden", "SEK"), ... ], ... columns=["Continent", "Country", "Currency"], ... ) >>> session = tt.Session(authentication=tt.BasicAuthenticationConfig()) >>> table = session.read_pandas( ... df, ... keys=["Continent", "Country", "Currency"], ... table_name="Restrictions example", ... ) >>> cube = session.create_cube(table) >>> h, l, m = cube.hierarchies, cube.levels, cube.measures >>> cube.hierarchies["Geography"] = [ ... table["Continent"], ... table["Country"], ... ] >>> for name in cube.hierarchies["Geography"].levels: ... del cube.hierarchies[name] ... >>> username, password = "john", "abcdef123456" >>> user = session.security.basic.credentials[username] = password
The user initially has no individual roles:
>>> username in session.security.individual_roles False
Adding ROLE_USER to grant access to the application:
>>> session.security.individual_roles[username] = {"ROLE_USER"}
Opening a query session to authenticate as the user just created:
>>> query_session = tt.QuerySession( ... f"http://localhost:{session.port}", ... auth=tt.BasicAuthentication( ... username=username, password=password ... ), ... ) >>> query_cube = query_session.cubes[cube.name] >>> l, m = query_cube.levels, query_cube.measures
ROLE_USER has no restrictions so all the countries and currencies are accessible:
>>> query_cube.query( ... m["contributors.COUNT"], levels=[l["Country"], l["Currency"]] ... ) contributors.COUNT Continent Country Currency Asia Japan JPY 1 Korea KRW 1 Europe France EUR 1 Germany EUR 1 Norway NOK 1 Sweden SEK 1
Adding a restricting role to the user so that only France is accessible:
>>> session.security.restrictions["ROLE_FRANCE"] = ( ... table["Country"] == "France" ... ) >>> session.security.individual_roles[username] |= {"ROLE_FRANCE"} >>> query_cube.query(m["contributors.COUNT"], levels=[l["Country"]]) contributors.COUNT Continent Country Europe France 1
Restrictions on the same hierarchy grant access to the union of the restricted elements:
>>> session.security.restrictions["ROLE_GERMANY"] = ( ... table["Country"] == "Germany" ... ) >>> session.security.individual_roles[username] |= {"ROLE_GERMANY"} >>> query_cube.query(m["contributors.COUNT"], levels=[l["Country"]]) contributors.COUNT Continent Country Europe France 1 Germany 1
Restrictions can grant access to multiple elements:
>>> session.security.restrictions["ROLE_NORDIC"] = table[ ... "Country" ... ].isin("Norway", "Sweden") >>> session.security.individual_roles[username] |= {"ROLE_NORDIC"} >>> query_cube.query(m["contributors.COUNT"], levels=[l["Country"]]) contributors.COUNT Continent Country Europe France 1 Germany 1 Norway 1 Sweden 1
Also give access to the Asian countries with a restriction on Continent:
>>> session.security.restrictions["ROLE_ASIA"] = ( ... table["Continent"] == "Asia" ... ) >>> session.security.individual_roles[username] |= {"ROLE_ASIA"} >>> query_cube.query(m["contributors.COUNT"], levels=[l["Country"]]) contributors.COUNT Continent Country Asia Japan 1 Korea 1 Europe France 1 Germany 1 Norway 1 Sweden 1
Restrictions on different hierarchies are intersected:
>>> session.security.restrictions["ROLE_EUR"] = ( ... table["Currency"] == "EUR" ... ) >>> session.security.individual_roles[username] |= {"ROLE_EUR"} >>> query_cube.query( ... m["contributors.COUNT"], levels=[l["Country"], l["Currency"]] ... ) contributors.COUNT Continent Country Currency Europe France EUR 1 Germany EUR 1
Removing the roles granting access to France and Germany leaves no remaining accessible countries:
>>> session.security.individual_roles[username] -= { ... "ROLE_FRANCE", ... "ROLE_GERMANY", ... } >>> query_cube.query(m["contributors.COUNT"], levels=[l["Country"]]) Empty DataFrame Columns: [contributors.COUNT] Index: []