Code¶
mah¶
This file contains the flask app object and describes the main entry points to the web application and maps these to urls.
-
class
mah.
MAH
(*args, **kwargs)¶ MAH-specific Flask object. Installs the SeaSurf instance under the csrf attribute, and initialises configuration and logging.
-
route
(rule, **options)¶ Modified route decorator that wraps all routes in an error handling routing to centralise logging and error handling.
-
unauthenticated_route
(rule, **options)¶ Special route decorator that marks this route as unauthenticated. Handlers for these routes must be public, or handle authentication checks themselves.
-
mah.verification¶
-
class
mah.verification.
Verification
(source_uid, dest_uid)¶ Represents a one-way authentication between two users. An authentication consists of a username/uid of the authenticator (referred to as the “source”) and the username/uid of the authenticated party (destination).
This class generates a short, human manageable shared secret and puts a short (ideally around 5 - 15 minutes) life span on the authentication. The shared secret is a pseudo random hash truncated to a reasonable (human memorable) configurable length (default: 6).
The expiry time is set a configurable number of seconds into the future (default 300).
This could be prone to collisions, but a given a reasonable length of the shared secret, a short expiry time and the fact authentication occurs between humans it provides a reasonable solution.
-
classmethod
all
(uid)¶ Retrieve all authentication objects for which the uid matches either the source or destination, regardless of expiry time.
Parameters: - src_uid – the source user id
- dst_uid – the destination user id.
Return type: a list of authentication objects or None.
-
auth_id
= Column(None, Integer(), table=None, primary_key=True, nullable=False, default=Sequence('user_id_seq'))¶ A unique identifer for the authentication. This is never displayed to the end user and is automatically incremented as authentications are added.
-
classmethod
by_dst
(uid)¶ Retrieve non-expired authentication objects with a given destination uid.
Parameters: - src_uid – the source user id
- dst_uid – the destination user id.
Return type: a list of authentication objects or None.
-
classmethod
by_id
(auth_id)¶ Retreive the authentication object which matches the unique id.
Parameters: - src_uid – the source user id
- dst_uid – the destination user id.
Return type: a single authentication object or None.
-
classmethod
by_src
(uid)¶ Retrieve non-expired authentication objects with a given source uid.
Parameters: - src_uid – the source user id
- dst_uid – the destination user id.
Return type: a list of authentication objects or None.
-
dest_name
= Column(None, String(length=200), table=None, nullable=False)¶ The human readable name of the source of the authentication. This is looked up from the staff directory.
-
dest_uid
= Column(None, String(length=32), table=None, nullable=False)¶ The username/uid of the person who was authenticated.
-
static
exists
(src_uid, dst_uid)¶ Given the source and destination of a authentication, check if an authentication already exists and if it does, return true.
Parameters: - src_uid – the source user id
- dst_uid – the destination user id.
Return type: bool
-
expiry
= Column(None, DateTime(), table=None, nullable=False, default=ColumnDefault(datetime.datetime(2019, 7, 8, 6, 44, 13, 533642)))¶ The expiry time of this authentication.
-
expiry_string
= ''¶ A user friendly and timezone independent string to represent the time before an auth expires. e.g. “20 seconds”, “4 minutes”. This is used to improve usability, by not having users exposed to timezone issues, where possible. This is not stored in the database, but instead calculated when objects are queried.
-
classmethod
get
(src_uid, dst_uid)¶ Retreive the unexpired authentication object, given a source and a destination uid. This function can only ever return 1 or 0 elements.
Parameters: - src_uid – the source user id
- dst_uid – the destination user id.
Return type: a single authentication object or None.
-
nato_code
= ''¶ The authentication strings in the phonetic alphabet (NATO) codes. This is not stored in the database, but instead generated when objected are queried.
-
reciprocated
= Column(None, Boolean(), table=None, nullable=False, default=ColumnDefault(False))¶ A flag to show if the authentication exists in the other direction (destination user -> source user). This is primarily used to simplify template logic.
A short, (relatively) unguessable string represent the shared secret in this authentication.
-
source_name
= Column(None, String(length=200), table=None, nullable=False)¶ The human readable name of the source. This is looked up from the staff directory.
-
source_uid
= Column(None, String(length=32), table=None, nullable=False)¶ The username/uid of the person who initiated the authentication.
-
classmethod
mah.database¶
mah.config¶
A simple, shared configuration configuration object based on the standard python ConfigParser.
- config
Global configuration object. Can be treated as a dictionary with case-insensitive keys, or as an object with attributes that correspond to configuration sections. For instance, the following are equivalent:
config['Application'] config['application'] config.application config.Application
The value of which can be another configuration object or a string, boolean, integer, or float value, or a list of strings, booleans, integers or floats.
See the Configuration section for details.
mah.log¶
A custom logger for the MAH application. This was implemented to be easily used by all parts of the mah package, without having to pass around the flask.app.logger object and to seperate the log formatting and configuration features.
Usually, this will be used like so:
from mah.log import log
log.debug("This is a debugging message")
-
mah.log.
init
(config)¶ Initialise the logging system.
Parameters: config – the logging subsection of the core configuration object, also available as mah.config.config.logging. See the Configuration section for details.
-
mah.log.
log
= <logging.Logger object>¶ This instance is imported and used in various places in MAH.
mah.report¶
Enable sending of suspicious authentication reports to administrators.
-
mah.report.
email_report
(text, reporter_uid, auth)¶ A email a report of a suspicious authentication interaction. The destination email address, from address, subject and mail server is read from a configuration file.
Parameters: - text – the text of the report
- reporter_uid – the uid (user id) of the reporter
- auth – the authentication id (a uniquely identifying int)
mah.nato¶
Nato alphabet mapping along with helper code to make the alphabet easy to use. Attempts to extract unknown NATO words will result in the unknown word being returned verbatim.
NATO source: https://en.wikipedia.org/wiki/NATO_phonetic_alphabet
>>> from mah.nato import NATO
>>> NATO['a']
'Alpha'
>>> NATO['A']
'Alpha'
>>> NATO['b']
'Bravo'
>>> NATO['.']
'Decimal'
>>> NATO['1']
'One'
>>> NATO['blah'] # Not a known NATO word
'blah'
mah.directory¶
Base classes for directory services.
-
class
mah.directory.
Directory
¶ Base class that directory modules should inherit from. Directory modules MUST expose their child class under the name ‘Directory’ - therefore, import this like:
from mah.directory import Directory as DirBase class Directory(DirBase): pass
Or just refer to it by its full name like so:
import mah.directory class Directory(mah.directory.Directory): pass
-
config
= None¶ The directory section of the main app configuration. cls.config is the same as mah.config.config.directory. This is None until the init classmethod is called successfully.
-
classmethod
init
(config, src)¶ Do class level initialisation. Should ONLY be called by the mah.config package on startup. config will be the same as mah.config.directory.
Parameters: - config – directory specific configuration object. Once configuration setup is complete, this will be available in mah.config.config.directory.
- src – raw source config as read by ConfigParser
-
search
(query)¶ Search a staff directory for a staff member.
Parameters: query (str) – the query string to search with. Returns: a list of Person (or a subclass) objects Return type: list
-
user
(uid)¶ Search a staff directory for a specific staff member.
Parameters: uid (str) – the user ID for a staff member to find. Returns: a Person (or subclass) object or None Return type: mah.directory.Person
-
-
class
mah.directory.
Person
(attributes)¶ Simple generic container to hold the information about a staff member.
mah.directory.ldap¶
Use LDAP or AD for directory services.
-
class
mah.directory.ldap.
Directory
¶ -
classmethod
init
(config, src)¶ Expects the following configuration variables set:
- ldap_filter
- Fields to compare search strings against. Defaults to [‘uid’, ‘cn’]
- ldap_size_limit
- Maximum number of search results to return. Defaults to 250.
- ldap_paged_size
- Maximum number of search results per page. Defaults to None, which turns off paging.
- ldap_time_limit
- Maximum number of seconds a search should run for. Defaults to 15.
- ldap_url
LDAP connection URL of the form SCHEME://USER:PASS @ HOST:PORT/BASE
- If SCHEME is ldaps, SSL will be used.
- USER and PASS are optional, and will be used as credentials.
- HOST is the LDAP or AD host to connect to.
- PORT is the port that the LDAP or AD service is listening on. By default this is 389
- BASE is the LDAP search base, something akin to ou=users,dc=corp,dc=com
-
search
(query)¶ Search the LDAP or AD directory, comparing against the fields listed in mah.config.config.directory.ldap_filter.
-
user
(uid)¶ Find a specific user in the LDAP/AD directory.
-
classmethod
-
class
mah.directory.ldap.
Person
(data, attributes)¶ Ensure all requested attributes are listed, even if they are set to None
mah.authentication¶
Base classes for authentication services.
-
class
mah.authentication.
Authentication
¶ Base class that authentication modules should inherit from. Authentication modules MUST expose their child class under the name ‘Authentication’ - therefore, import this like:
from mah.authentication import Authentication as AuthBase class Authentication(AuthBase): pass
Or just refer to it by its full name like so:
import mah.authentication class Authentication(mah.authentication.Authentication): pass
-
classmethod
authenticate
(form)¶ The main authentication method. Takes a form (a dict of form field names to string values), and uses the data therein to authenticate the user. Should return a tuple of the username and whether authentication was successful.
Parameters: form – A form object (dict-like) with fields entered by the user Returns: A 2-tuple of username (str) and success (bool)
-
config
= None¶ The login section of the main app configuration. cls.config is the same as mah.config.config.login. This is None until the init classmethod is called successfully.
-
static
for_production
()¶ If this is a ‘dummy’ authentication method (like the built in ‘none’ authentication module), this should return False - a warning will be displayed on the login page.
-
classmethod
init
(config, src)¶ Initialise the authenticator. By default we make sure the username and password inputs are updated by the config, and we store the config for future use
Parameters: - config – login specific configuration object. Once configuration setup is complete, this will be available in mah.config.config.login.
- src – raw source config as read by ConfigParser
-
inputs
= {'password': {'description': None, 'label': 'Password', 'name': 'password', 'order': 2, 'required': True, 'secret': True}, 'username': {'description': None, 'label': 'Username', 'name': 'username', 'order': 1, 'required': True, 'secret': False}}¶ A dictionary of fields accepted by the authenticator. Each key should be a field name (ie, will be used in an <input> tag as the name attribute) with a value of a dict describing the key. That dict should have the following keys.
- name
- The name of the field (ie, identical to the key of this input).
- label
- Display name for the field. This should be changable in config by using a *_label configuration variable.
- secret
- If True, the field will be considered password-like and a type of ‘password’ will be used for the <input> tag instead of ‘text’.
- required
- Boolean. Can be used to modify the interface, however the authenticator MUST check validity itself.
- description
- None, or a text string that will be displayed near the input to describe what is expected. This should be changable in config by using a *_description configuration variable.
- order
- A number defining in which order (ascending) the fields should be shown. If two fields have the same order, they will be sorted correctly in respect to all other fields, but will not be reliably ordered amongst themselves.
-
classmethod
mah.authentication.none¶
A debugging authentication method that doesn’t use any form of password - just a username
mah.authentication.radius¶
A simple wrapper around the pyrad API to talk to radius authentication servers.
-
class
mah.authentication.radius.
Authentication
¶ -
classmethod
authenticate
(form)¶ Authenticates to the configured RADIUS server.
-
classmethod
init
(config, src)¶ Expects the following configuration variables set:
- radius_server
- The host or IP of the radius server to authenticate against.
- radius_secret
- The secret for connecting to the radius server
- radius_dictionary
- The attribute dictionary
- radius_nas_identifier
- The NAS identifier attribute
- radius_nas_ip_address
- The IP address attribute
-
classmethod