TokenService¶
- class gafaelfawr.services.token.TokenService(*, config, token_cache, token_db_store, token_redis_store, token_change_store, admin_store, session, logger)¶
Bases:
object
Manage tokens.
- Parameters:
config (
Config
) – Gafaelfawr configuration.token_cache (
TokenCacheService
) – Cache of internal and notebook tokens.token_db_store (
TokenDatabaseStore
) – Database backing store for tokens.token_redis_store (
TokenRedisStore
) – Redis backing store for tokens.token_change_store (
TokenChangeHistoryStore
) – Backing store for history of changes to tokens.admin_store (
AdminStore
) – Backing store for Gafaelfawr admins.session (
async_scoped_session
) – Database session.logger (
BoundLogger
) – Logger to use.
Methods Summary
audit
(*[, fix])Check Gafaelfawr data stores for consistency.
create_oidc_token
(auth_data, *, ip_address)Add a new OpenID Connect access token.
create_session_token
(user_info, *, scopes, ...)Create a new session token.
create_token_from_admin_request
(request, ...)Create a new service or user token from an admin request.
create_user_token
(auth_data, username, *, ...)Add a new user token.
Delete all stored tokens.
delete_token
(key, auth_data, username, *, ...)Delete a token.
Bookkeeping for expired tokens.
gather_state_metrics
(events)Gather metrics from the stored state and record them.
get_change_history
(auth_data, *[, cursor, ...])Retrieve the change history of a token.
get_data
(token)Retrieve the data for a token from Redis.
get_internal_token
(token_data, service, ...)Get or create a new internal token.
get_notebook_token
(token_data, ip_address, *)Get or create a new notebook token.
get_token_info
(key, auth_data, username)Get information about a token.
get_token_info_unchecked
(key[, username])Get information about a token without checking authorization.
list_tokens
(auth_data[, username])List tokens.
modify_token
(key, auth_data[, username, ...])Modify a token.
Drop history entries older than the cutoff date.
Methods Documentation
- async audit(*, fix=False)¶
Check Gafaelfawr data stores for consistency.
If any errors are found and Slack is configured, report them to Slack in addition to returning them.
- async create_oidc_token(auth_data, *, ip_address)¶
Add a new OpenID Connect access token.
- Parameters:
- Returns:
A new child token of type
oidc
.- Return type:
- Raises:
InvalidGrantError – Raised if the underlying authentication token has expired.
- async create_session_token(user_info, *, scopes, ip_address)¶
Create a new session token.
- Parameters:
user_info (
TokenUserInfo
) – The user information to associate with the token.scopes (
set
[str
]) – The scopes of the token.admin:token
will be added to these scopes if the user is an admin.ip_address (
str
) – The IP address from which the request came.
- Returns:
The newly-created token.
- Return type:
- Raises:
PermissionDeniedError – Raised if the provided username is invalid.
- async create_token_from_admin_request(request, auth_data, *, ip_address)¶
Create a new service or user token from an admin request.
- Parameters:
request (
AdminTokenRequest
) – The incoming request.auth_data (
TokenData
) – The data for the authenticated user making the request.ip_address (
str
|None
) – The IP address from which the request came, orNone
for internal requests by Gafaelfawr.
- Returns:
The newly-created token.
- Return type:
- Raises:
InvalidExpiresError – Raised if the provided expiration time is not valid.
InvalidScopesError – Raised if the requested scopes are not permitted.
PermissionDeniedError – Raised if the provided username is invalid.
- async create_user_token(auth_data, username, *, token_name, scopes, expires=None, ip_address)¶
Add a new user token.
- Parameters:
auth_data (
TokenData
) – The token data for the authentication token of the user creating a user token.username (
str
) – The username for which to create a token.token_name (
str
) – The name of the token.expires (
datetime
|None
, default:None
) – When the token should expire. If not given, defaults to the expiration of the authentication token taken fromdata
.ip_address (
str
) – The IP address from which the request came.
- Returns:
The newly-created token.
- Return type:
- Raises:
DuplicateTokenNameError – Raised if a token with this name for this user already exists.
InvalidExpiresError – Raised if the provided expiration time was invalid.
PermissionDeniedError – Raised if the given username didn’t match the user information in the authentication token, or if the specified username is invalid.
Notes
This can only be used by the user themselves, not by a token administrator for a different user, because this API does not provide a way to set the additional user information for the token and instead always takes it from the authentication token.
- async delete_all_tokens()¶
Delete all stored tokens.
This only purges them from Redis, not from the database. It is normally called in combination with truncating all database tables (which is much faster than deleting entries line by line).
- Return type:
- async delete_token(key, auth_data, username, *, ip_address)¶
Delete a token.
- async expire_tokens()¶
Bookkeeping for expired tokens.
Token expiration is primarily controlled by the Redis expiration, after which the token disappears from Redis and effectively expires from an authentication standpoint. However, we want to do some additional bookkeeping of expired tokens: remove them from the database and add an expiration entry to the token history table.
This method is meant to be run periodically, outside of any given user request.
- Return type:
- async gather_state_metrics(events)¶
Gather metrics from the stored state and record them.
- Parameters:
events (
StateEvents
) – Publishers for state events.- Return type:
- async get_change_history(auth_data, *, cursor=None, limit=None, since=None, until=None, username=None, actor=None, key=None, token=None, token_type=None, ip_or_cidr=None)¶
Retrieve the change history of a token.
- Parameters:
auth_data (
TokenData
) – Authentication information for the user making the request.cursor (
TokenChangeHistoryCursor
|None
, default:None
) – A pagination cursor specifying where to start in the results.limit (
int
|None
, default:None
) – Limit the number of returned results.since (
datetime
|None
, default:None
) – Limit the results to events at or after this time.until (
datetime
|None
, default:None
) – Limit the results to events before or at this time.username (
str
|None
, default:None
) – Limit the results to tokens owned by this user.actor (
str
|None
, default:None
) – Limit the results to actions performed by this user.key (
str
|None
, default:None
) – Limit the results to this token and any subtokens of this token. Note that this will currently pick up direct subtokens but not subtokens of subtokens.token (
str
|None
, default:None
) – Limit the results to only this token.token_type (
TokenType
|None
, default:None
) – Limit the results to tokens of this type.ip_or_cidr (
str
|None
, default:None
) – Limit the results to changes made from this IPv4 or IPv6 address or CIDR block.
- Returns:
A list of changes matching the search criteria.
- Return type:
safir.database.CountedPaginatedList of TokenChangeHistoryEntry
- Raises:
InvalidIPAddressError – Raised if the provided argument was syntactically invalid for both an IP address and a CIDR block.
- async get_data(token)¶
Retrieve the data for a token from Redis.
Doubles as a way to check the validity of the token.
- async get_internal_token(token_data, service, scopes, *, ip_address, minimum_lifetime=None)¶
Get or create a new internal token.
- Parameters:
token_data (
TokenData
) – The authentication data on which to base the new token.service (
str
) – The internal service to which the token is delegated.ip_address (
str
) – The IP address from which the request came.minimum_lifetime (
timedelta
|None
, default:None
) – If set, the minimum required lifetime of the token.
- Returns:
The newly-created token.
- Return type:
- Raises:
PermissionDeniedError – Raised if the username is invalid.
- async get_notebook_token(token_data, ip_address, *, minimum_lifetime=None)¶
Get or create a new notebook token.
- Parameters:
- Returns:
The newly-created token.
- Return type:
- Raises:
PermissionDeniedError – Raised if the username is invalid.
- async get_token_info(key, auth_data, username)¶
Get information about a token.
- Parameters:
- Returns:
Token information from the database, or
None
if the token was not found or username was given and the token was for another user.- Return type:
TokenInfo or None
- Raises:
PermissionDeniedError – Raised if the authenticated user doesn’t have permission to manipulate tokens for that user.
- async get_token_info_unchecked(key, username=None)¶
Get information about a token without checking authorization.
- async list_tokens(auth_data, username=None)¶
List tokens.
- Parameters:
- Returns:
Information for all matching tokens.
- Return type:
- Raises:
PermissionDeniedError – Raised if the user whose tokens are being listed does not match the authentication information.
- async modify_token(key, auth_data, username=None, *, ip_address, token_name=None, scopes=None, expires=None, no_expire=False)¶
Modify a token.
Token modification is only allowed for token administrators. Users who want to modify their own tokens should instead create a new token and delete the old one. Arguably, it shouldn’t be allowed for token administrators either, but it allows them to fix bugs and the code is tested and working.
- Parameters:
key (
str
) – The key of the token to modify.auth_data (
TokenData
) – The token data for the authentication token of the user making this modification.username (
str
|None
, default:None
) – If given, constrain modifications to tokens owned by the given user.ip_address (
str
) – The IP address from which the request came.token_name (
str
|None
, default:None
) – The new name for the token.scopes (
set
[str
] |None
, default:None
) – The new scopes for the token.expires (
datetime
|None
, default:None
) – The new expiration time for the token.no_expire (
bool
, default:False
) – If set, the token should not expire. This is a separate parameter because passingNone
toexpires
is ambiguous.
- Returns:
Information for the updated token or
None
if the token was not found.- Return type:
TokenInfo or None
- Raises:
InvalidExpiresError – Raised if the provided expiration time was invalid.
DuplicateTokenNameError – Raised if a token with this name for this user already exists.
PermissionDeniedError – Raised if the user modifiying the token is not a token administrator.