Source

wheezy.security / doc / userguide.rst

Full commit

User Guide

The objective of security is protection of information from theft or corruption, while allowing the information to remain accessible to its intended users.

Ticket

Ticket is a short packet of bytes generated by a network server for a client, which can be delivered to itself as a means of authentication or proof of authorization, and cannot easily be forged.

:py:class:`~wheezy.security.crypto.ticket.Ticket` has the following characteristics:

  • It is valid for certain period of time, namely has explicitly set expiration time.
  • It value is signed to prove it authenticity.
  • It is encrypted to protect sensitive information.
  • It has noise to harden forgery.

:py:class:`~wheezy.security.crypto.ticket.Ticket` can be instantiated by passing the following arguments:

  • max_age - period of time (in seconds) this Ticket is considered valid.
  • salt - a random sequence that harden ticket forgery. That is prepended to validation key and encryption key.
  • digestmod - hash algorithm used with HMAC (Hash-based Message Authentication Code) to sign ticket. Defaults to SHA1.
  • cypher - cryptography algorithm. Defaults to AES128.
  • options - a dictionary that hold the following configuration values: CRYPTO_VALIDATION_KEY (used by signature) and CRYPTO_ENCRYPTION_KEY (used by encryption).

Validation and Encryption Keys

Keys used for validation and encryption are ensured to be of length 320 bits at least. :py:meth:`~wheezy.security.crypto.ticket.ensure_strong_key` function appends HMAC signature to the key.

If cryptography library is not available you will see a warning message:

Ticket: cypher not available

While Ticket continue to function even cryptography library is not installed it strongly recommended to be used in production environment.

Thread Safety

Ticket does not alter it state once initialized. It is guaranteed to be thread safe.

Typical Use Case

Here is typical use case when all possible configuration attributes are used:

from wheezy.security.crypto.comp import aes192
from wheezy.security.crypto.comp import sha1
from wheezy.security.crypto import Ticket

options = {
    'CRYPTO_VALIDATION_KEY': 'LkLlYR5WbTk54kaIgJOp',
    'CRYPTO_ENCRYPTION_KEY': 'rH64daeXBZdgrR7WNawf'
}

ticket = Ticket(
        max_age=1200,
        salt='CzQnV0KazDKElBYiIC2w',
        digestmod=sha1,
        cypher=aes192,
        options=options)

The ticket instance can be shared application wide. encode / decode methods are used this way:

protected_value = ticket.encode('hello')

assert 'hello' == ticket.decode(protected_value)

In case validity of ticket can not be confirmed decode method returns None.

Extensibility

Ticket cypher can be any callable that satisfy the following contract:

  • Initialization is called with encryption key. Returned object must be a factory for actual algorithm instance.
  • Algorithm factory must return new algorithm via simple callable with no arguments.
  • Algorithm implementation must support two methods: encrypt(value) and decrypt(value).

Principal

:py:class:`~wheezy.security.principal.Principal` is a container of user specific security information. It includes the following attributes:

  • id - user identity, e.g. number 755345, UUID f102a87b-ee36-4a2e-97de-8f803f470867 or whatever else is valid to look up a user quickly in your application.
  • roles - a list of authorized user roles, e.g. user, manager, etc.
  • alias - a user friendly name, display name, etc. This can be something like John Smith, etc.
  • extra - any string you would like to hold in security context.

Here is a sample how to instantiate new Principal:

principal = Principal(
        id='125134788',
        roles=['user'],
        alias='John Smith')

:py:class:`~wheezy.security.principal.Principal` supports the following methods:

  • dump - converts instance to a string.
  • load - reverse operation to dump.

You can use Ticket to secure Principal pass across network boundary. Combining them both you can introduce authentication/authorization cookie to your application.

Authorization

Authorization specify access rights to resources and provide access control in particular to your application.

You are able to request authorization by decorating your method with :py:meth:`~wheezy.security.authorization.authorized`. Here is typical use case:

from wheezy.security import authorized

class MyBusinessLogic(object):

     principal = None

     @authorized
     def cancel_transfer(self, id):
         return True

     @authorized(roles=('operator',))
     def approve_transfer(self):
         return True

Note that :py:meth:`~wheezy.security.authorization.authorized` decorator requires the object to supply principal attribute of type :py:class:`~wheezy.security.principal.Principal`.

If caller is not authorized to perform requested operation :py:class:`~wheezy.security.errors.SecurityError` exception is raised. See :py:meth:`~wheezy.security.authorization.authorized` for more details.