atoti_plus.security module#
- class atoti_plus.security.BasicSecurity#
Manage basic authentication on the session.
Note
This requires a :~class:atoti.BasicAuthenticationConfig to be passed to
atoti.Session()
’s authentication parameter.- create_user(username, *, password=None, roles=())#
Add a user able to authenticate against the session using Basic Authentication.
The roles and password of the user can be changed at any time.
Example
>>> session = tt.Session(authentication=tt.BasicAuthenticationConfig()) >>> list(session.security.basic.users) [] >>> elon = session.security.basic.create_user("elon", password="X Æ A-12") >>> list(session.security.basic.users) ['elon'] >>> # The special ROLE_USER role is automatically added >>> elon.roles {'ROLE_USER'} >>> # Change the password >>> elon.password = "AE A-XII" >>> # Revoke access >>> del session.security.basic.users["elon"] >>> list(session.security.basic.users) []
- Return type
- class atoti_plus.security.BasicUsers#
Manage basic authentication users.
- class atoti_plus.security.DefaultRoles#
Roles granted to users who had no roles granted by
IndividualRoles
andRoleMapping
.
- class atoti_plus.security.IndividualRoles#
The roles given to users on top of the ones that can be added by authentication providers.
Users without the ROLE_USER will not be able to access the session.
Example
>>> session = tt.Session(authentication=tt.BasicAuthenticationConfig()) >>> elon = session.security.basic.create_user("John", password="X Æ A-12") >>> elon.roles {'ROLE_USER'} >>> session.security.individual_roles[elon.username].add("ROLE_USA") >>> sorted(elon.roles) ['ROLE_USA', 'ROLE_USER'] >>> session.security.individual_roles[elon.username].remove("ROLE_USA") >>> elon.roles {'ROLE_USER'} >>> # Removing all the roles will prevent the user from accessing the session: >>> del session.security.individual_roles[elon.username] >>> list(elon.roles) []
- update(__m: SupportsKeysAndGetItem[str, _UserRolesDescription], **kwargs: Union[Collection[str], atoti_plus.security._UserRoles]) None #
- update(__m: Iterable[Tuple[str, Union[Collection[str], atoti_plus.security._UserRoles]]], **kwargs: Union[Collection[str], atoti_plus.security._UserRoles]) None
- update(**kwargs: Union[Collection[str], atoti_plus.security._UserRoles]) None
Update the mapping.
- Return type
- class atoti_plus.security.KerberosSecurity#
Manage Kerberos authentication on the session.
Note
This requires
atoti.KerberosConfig
to be configured.- create_user(username, *, roles=())#
Add a user able to authenticate against the session using Kerberos. The roles of the user can be changed at any time. Users without the role ROLE_USER will not have access to the application.
See also
create_user()
for a similar usage example.- Return type
- default_roles: atoti_plus.security.DefaultRoles#
- class atoti_plus.security.KerberosUsers#
Manage Kerberos users.
- class atoti_plus.security.LdapSecurity#
Allows mapping roles granted by the authentication provider to the roles to use in the session.
Users who do not have the ROLE_USER session role will not be able to access the session.
Note
This requires
atoti.LdapConfig
to be configured.- Example
>>> session = tt.Session( ... authentication=tt.LdapConfig( ... url="ldap://example.com:389", ... base_dn="dc=example,dc=com", ... user_search_base="ou=people", ... group_search_base="ou=roles", ... ) ... ) >>> mathematicians_role = session.security.create_role( ... "ROLE_MATHS", restrictions={"City": ["Paris"]} ... )
Roles from the authentication provider can be mapped to roles in the session.
>>> session.security.ldap.role_mapping["MATHEMATICIANS"] = [ ... "ROLE_MATHS", ... "ROLE_USER", ... ] >>> sorted(session.security.ldap.role_mapping["MATHEMATICIANS"]) ['ROLE_MATHS', 'ROLE_USER']
Default roles can be given to users who had no individual or mapped roles granted.
>>> session.security.ldap.default_roles.add("ROLE_USER") >>> session.security.ldap.default_roles {'ROLE_USER'}
- default_roles: atoti_plus.security.DefaultRoles#
- role_mapping: atoti_plus.security.RoleMapping#
- class atoti_plus.security.OidcSecurity#
Allows mapping roles granted by the authentication provider’s ID Token to the roles to use in the session.
Users who do not have the ROLE_USER session role will not be able to access the session.
Note
This requires
atoti.OidcConfig
to be configured.Example
>>> import os >>> session = tt.Session( ... authentication=tt.OidcConfig( ... provider_id="auth0", ... issuer_url=os.environ["AUTH0_ISSUER"], ... client_id=os.environ["AUTH0_CLIENT_ID"], ... client_secret=os.environ["AUTH0_CLIENT_SECRET"], ... name_claim="email", ... scopes=["email", "profile", "username"], ... roles_claims=["https://activeviam:eu:auth0:com/roles"], ... ), ... port=1234, ... ) >>> france_role = session.security.create_role( ... "ROLE_FRANCE", restrictions={"Country": "France"} ... ) >>> uk_role = session.security.create_role( ... "ROLE_UK", restrictions={"Country": "UK"} ... )
Roles from the authentication provider’s ID Token can be mapped to roles in the session:
>>> session.security.oidc.role_mapping.update( ... {"atoti user": ["ROLE_USER"], "France": [france_role.name]} ... ) >>> session.security.oidc.role_mapping {'atoti user': {'ROLE_USER'}, 'France': {'ROLE_FRANCE'}}
Default roles can be given to users who had no individual or mapped roles granted.
>>> session.security.oidc.default_roles.add(uk_role.name) >>> session.security.oidc.default_roles {'ROLE_UK'}
- default_roles: atoti_plus.security.DefaultRoles#
- role_mapping: atoti_plus.security.RoleMapping#
- class atoti_plus.security.Restrictions#
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 members will be granted.
Example:
>>> from typing import List >>> 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] ... >>> password = "BYXV$9P_rEr4" >>> user = session.security.basic.create_user("john", password=password)
Opening a query session to authenticate as the user just created:
>>> query_session = tt.QuerySession( ... f"http://localhost:{session.port}", ... auth=tt.BasicAuthentication( ... username=user.username, password=password ... ), ... ) >>> query_cube = query_session.cubes[cube.name] >>> l, m = query_cube.levels, query_cube.measures
The user initially only has the ROLE_USER:
>>> user.roles {'ROLE_USER'}
This role 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:
>>> role_france = session.security.create_role( ... "ROLE_FRANCE", restrictions={"Country": ["France"]} ... ) >>> session.security.individual_roles[user.username].add( ... role_france.name ... ) >>> 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 members:
>>> role_germany = session.security.create_role( ... "ROLE_GERMANY", restrictions={"Country": ["Germany"]} ... ) >>> session.security.individual_roles[user.username].add( ... role_germany.name ... ) >>> query_cube.query(m["contributors.COUNT"], levels=[l["Country"]]) contributors.COUNT Continent Country Europe France 1 Germany 1
Restrictions can grant access to multiple members:
>>> role_nordic = session.security.create_role( ... "ROLE_NORDIC", restrictions={"Country": ["Norway", "Sweden"]} ... ) >>> session.security.individual_roles[user.username].add( ... role_nordic.name ... ) >>> 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:
>>> role_asia = session.security.create_role( ... "ROLE_ASIA", restrictions={"Continent": ["Asia"]} ... ) >>> session.security.individual_roles[user.username].add(role_asia.name) >>> 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:
>>> role_eur = session.security.create_role( ... "ROLE_EUR", restrictions={"Currency": ["EUR"]} ... ) >>> session.security.individual_roles[user.username].add(role_eur.name) >>> 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:
>>> for role in [role_france, role_germany]: ... session.security.individual_roles[user.username].remove( ... role.name ... ) ... >>> query_cube.query(m["contributors.COUNT"], levels=[l["Country"]]) Empty DataFrame Columns: [contributors.COUNT] Index: []
- class atoti_plus.security.Role#
A role and its restrictions.
- restrictions: atoti_plus.security.Restrictions#
- class atoti_plus.security.RoleMapping#
Mapping between roles or usernames coming from the authentication provider to those to use in the session.
- update(__m: SupportsKeysAndGetItem[str, _RoleMappingDescription], **kwargs: Union[Iterable[str], atoti_plus.security._MappedRoles]) None #
- update(__m: Iterable[Tuple[str, Union[Iterable[str], atoti_plus.security._MappedRoles]]], **kwargs: Union[Iterable[str], atoti_plus.security._MappedRoles]) None
- update(**kwargs: Union[Iterable[str], atoti_plus.security._MappedRoles]) None
Update the mapping.
- Return type
- class atoti_plus.security.Roles#
All of the roles defined in the session.
- class atoti_plus.security.Security#
Security management for the current session.
- create_role(name, *, restrictions={})#
Create a role with the given restrictions.
There are special roles which cannot be redefined:
ROLE_USER: required to access the application
ROLE_ADMIN: gives full access (read, write, delete, etc) to the application
- Return type
- individual_roles: atoti_plus.security.IndividualRoles#
- kerberos: atoti_plus.security.KerberosSecurity#
- roles: atoti_plus.security.Roles#