License Supported versions https://readthedocs.org/projects/groundwork-validation/badge/?version=latest Travis-CI Build Status https://coveralls.io/repos/github/useblocks/groundwork-validation/badge.svg?branch=master Code quality PyPI Package latest release

Welcome to groundwork validation

This Python package is designed for applications, which are based on the groundwork application framework.

All of its plugins and patterns are focused on application validation during runtime.

This package contains the following groundwork extensions:

Plugins

  • GwDbValidator - Validates automatically all database model requests.

Patterns

Why validation is needed

Validation is mostly needed, if your application needs input data and must be sure that this data is valid and not somehow corrupted.

A common case is the usage of files, which must be copied from an external source. During the transport over the network, the data may get corrupted. To be sure that this is not the case, a hash of this file can be build and stored beside the file. After the file is downloaded, the hash is rebuild and compared to the stored one.

Another use case is the usage of databases. If your application is the only one which is allowed to store and change specific data inside a database, you should be able to validate these data before your plugin is using it again (This use case is supported by GwDbValidatorsPattern and GwDbValidator).

Who requests validation?

In most cases validation may be overengineered, if you are developing a small script for yourself.

However there are scenarios and domains, which need a proven validation of data, so that your application is allowed and verified to be used inside this domains.

For instance if you are developing solutions for the automotive industry and your solutions may affect the software, which runs on electronic control units (ECUs) of a car, your application must be ISO 26262 compliant. And this normally needs a proven validation of in- and output data (beside a lot of other stuff).

Installation

Via pip

To install groundwork-validation simply use pip:

pip install groundwork-validation

From sources

Using git and pip:

git clone https://github.com/useblocks/groundwork-validation
cd groundwork-validation
pip install -e .

Content

Plugins

GwDbValidator

This plugin automatically activates the validation of all database models, which are and will be registered via groundwork-database.

On activation GwDbValidator fetches all existing database models and activates their validation by using register() of GwValidatorsPattern.

It also registers a receiver to get notified, if a new database model is registered. If this is the case, it also registers a new validator for this new model.

Activation and Usage

All you have to do is to activate the plugin, which is done by adding its name to your application configuration:

LOAD_PLUGINS = ["MyDbPlugin", "MyOtherPlugin", "GwDbValidator"]

That’s it. From now on all important database actions get validated.

Configuration

GwDbValidator is based on DbValidatorsPlugin and therefore needs the same Configuration.

You need to set the parameter HASH_DB, which defines the database to be used for storing hash values:

HASH_DB = "sqlite://%s/hash_db" % APP_PATH
Requirements & Specifications

The following sections describes the implemented requirements and their related specifications.

Available requirements

ID Title Type Status Links Tags
R_002 Validated read requests on database tables Requirement implemented gwdbvalidator_plugin;
R_003 Configuration only Requirement implemented gwdbvalidator_plugin;
R_001 Hashed write requests on database tables Requirement implemented gwdbvalidator_plugin;

Available specifications

ID Title Type Status Links Tags
S_001 Using of groundwork pattern GwDbValidatorPattern Specification implemented R_001; R_002 gwdbvalidator_plugin;
S_002 Automatic database table registration for validation Specification implemented R_003 gwdbvalidator_plugin;
Requirements

Requirement: Hashed write requests on database tables (R_001)

As developer I want my write requests being hashed and available for later use.

status: implemented

tags: gwdbvalidator_plugin;

Requirement: Validated read requests on database tables (R_002)

As developer I want to be sure, that all read requests on database tables are validated based on a stored hash

status: implemented

tags: gwdbvalidator_plugin;

Requirement: Configuration only (R_003)

As developer I want to activate the validation of all database tables by configuration options only.

status: implemented

tags: gwdbvalidator_plugin;

Specification

Specification: Using of groundwork pattern GwDbValidatorPattern (S_001)

We are using the GwDbValidatorsPattern to implement Hashed write requests on database tables (R_001) und Validated read requests on database tables (R_002).

status: implemented

tags: gwdbvalidator_plugin;

links: R_001 ; R_002

Specification: Automatic database table registration for validation (S_002)

To easily activate validation of all registered database tables, the plugin needs to perform the following actions during activation:

  • Request all already registered database tables and register a new db-validator for them
  • Register a listener for the signal db_class_registered and register a new validator every time the signal is send and the newly registered database class is provided.

status: implemented

tags: gwdbvalidator_plugin;

links: R_003

Patterns

GwValidatorsPattern

This pattern allows plugins to register validators, which can be used to hash and validate python objects.

A validator can be configured to use a specific hash algorithm and hash specific attributes of an given object only. This maybe necessary, if unhashable python object types are used inside given object.

Note

GwValidatorsPattern uses the pickle function of Python to build a hashable, binary-based representation of your data. There are some data types, which can not be pickeled. In this case the validator must be configured to ignore these specific attributes of your data.

Register a new validator

To register a new validator, a plugin must inherit from GwValidatorsPattern and use register() for registration:

from groundwork_validation.patterns import GwValidatorsPattern

 class My_Plugin(GwValidatorsPattern):
     def __init__(self, app, **kwargs):
         self.name = "My_Plugin"
         super(My_Plugin, self).__init__(app, **kwargs)

     def activate(self):
         self.validator = self.validators.register("my_validator", "test validator")
Creating a hash

Hashes can be build for nearly each python object by using hash():

class My_Plugin(GwValidatorsPattern):
    ...

    def get_hash(self):
         data = "test this"
         self.my_hash = self.validator.hash(data)
Validate an object by given hash

To validate an object, all you need is the hash and the function validate():

class My_Plugin(GwValidatorsPattern):
    ...

    def validate_hash(self):
        data = "test this"
        if self.validator.validate(data, self.my_hash) is True:
            print("Data is valid")
        else:
            print("Data is invalid. We stop here!")
            sys.exit(1)

Note

The plugin developer is responsible for safely storing hashes (e.g. inside a database).

Requirements & Specifications

The following sections describes the implemented requirements and their related specifications.

Available requirements

ID Title Type Status Links Tags
R_6A8AF Getting a validator Requirement   gwvalidator
R_D8C4B Validator registration Requirement   gwvalidator
R_E3793 Validator functions Requirement   gwvalidator

Available specifications

ID Title Type Status Links Tags
S_10710 hash() function for validator Specification   R_E3793 gwvalidator
S_1FB7D validate() function for validator Specification   R_E3793 gwvalidator
S_F7DDB register() function for self.validators Specification   R_D8C4B; R_6A8AF gwvalidator
Requirements

Requirement: Validator registration (R_D8C4B)

As developer I want to register my own specific validator to be able so speccify:

  • name
  • description
  • hash algorithm
  • whitelist for hashable attributes

tags: gwvalidator

Requirement: Getting a validator (R_6A8AF)

As developer I want to get a validator object to use it for handling validations tasks on selected objects.

tags: gwvalidator

Requirement: Validator functions (R_E3793)

As developer I want my validators to provide the following functions to me:

  • Creating of hashes
  • Validating of hashes

tags: gwvalidator

Specification

Specification: register() function for self.validators (S_F7DDB)

A function self.validators.register must be implemented, to allow the registration and requesting of validators.

The register function will have the following parameters:

  • name
  • description
  • algorithm - default is hashlib.sha256
  • whitelist - default is []

The returned object must be a instance of the class Validator.

tags: gwvalidator

links: R_D8C4B ; R_6A8AF

Specification: hash() function for validator (S_10710)

An instance of the class Validator has a hash() function, which has the following parameters:

  • data
  • return_hash_object
  • hash_object
  • strict

Where data is the object to hash.

hash_object can be used to provide an hash object, which gets updated instead of creating a new one.

If strict is True, all configured attirbutes from the whitelist must exist inside the given data.

If return_hah_object is True, the hash object, which is used by hashlib will be returned. Otherwise a hexdigest string representation.

tags: gwvalidator

links: R_E3793

Specification: validate() function for validator (S_1FB7D)

An instance of the class Validator has a validate() function, which has the following parameters:

  • data
  • hash_string

The data is hashed and the calculated hash values is compared against the given hash_string. If they are equal, True must be returned. Otherwise False.

tags: gwvalidator

links: R_E3793

GwDbValidatorsPattern

This patterns provides functions to automatically hash and validate data requests on SQLAlchemy models.

It is used to prove that data handling of used libraries and services works correct. The below image shows the flow of data which is stored to a database and requested back. As you can see at least 3 libraries/services are used, which behavior and source code is not under your full control.

_images/db_hash_workflow.png

Every time a registered database model is updated and uploaded to the database (add -> commit), GwDbValidatorsPattern creates and stores a hash of the updated data model.

And every time a request is made on a registered database model (e.g by model.query.filter_by(x=”abc”).all()), GwDbValidatorsPattern validates each received row against stored hashes.

Hashes are stored inside a database (via groundwork-database) and based on its configuration, an external database may be used so that hashes are still available and valid after application restarts.

Register a new database validator

To register a new database validator, a plugin must inherit from GwDbValidatorsPattern and use register() for registration:

from groundwork_validation.patterns import GwDbValidatorsPattern

class My_Plugin(GwDbValidatorsPattern):
    def __init__(self, app, **kwargs):
        self.name = "My_Plugin"
        super(My_Plugin, self).__init__(app, **kwargs)
        self.db = None
        self.Test = None

    def activate(self):

        # START: groundwork-database related configuration
        ##########################################################################

        # Let's create a new database, which models shall use validated request.
        self.db = self.app.databases.register("test_db",
                                              "sqlite://",
                                              "database for test values")

        # A simple SQLAlchemy database model
        class Test(self.db.Base):
            __tablename__ = "test"
            id = Column(Integer, primary_key=True)
            name = Column(String(512), nullable=False, unique=True)

        # Register our database model
        self.Test = self.db.classes.register(Test)
        # Create all tables
        self.db.create_all()

        ###########################################################################
        # END: groundwork-database related configuration

        # Register and activate validation for your model
        self.validators.db.register("db_test_validator",
                                    "my db test validator",
                                    self.Test)
Validate requests

Your validation has already started. The registration of a database model is enough to start the validation for each request. If a validation problem occurs, groundwork-validation will throw the exception ValidationError.

Test validation

To test the validation, you need to manipulate the data of a stored and monitored data model. This could be done via an external database editor like the Sqlite Browser or by executing SQL statements directly:

from groundwork_validation.patterns import GwDbValidatorsPattern

class My_Plugin(GwDbValidatorsPattern):
    ...

    def activate(self):
        ...
        my_test = self.Test(name="blub")
        self.db.add(my_test)
        self.db.commit()
        self.db.query(self.Test).all()

        my_test.name = "Boohaaaa"
        self.db.add(my_test)
        self.db.commit()
        self.db.query(self.Test).all()

        # Execute sql-statement, which does not trigger the sqlalchemy events.
        # So no hash gets updated.
        self.db.engine.execute("UPDATE test SET name='not_working' WHERE id=1")

        # Reloads the data from db and will throw an exception
        self.db.session.refresh(my_test)
Configuration

GwDbValidatorsPattern stores the hashes in its own database. Like other databases in groundwork, the used database connection string can be configured inside the application configuration file by setting HASH_DB:

HASH_DB = "sqlite://%s/hash_db" % APP_PATH

The format of the connection string is documented inside the SQLAlchemy documentation.

If no connection string is configured, “sqlite://” is used as default value.

Technical background

To provide a reliable validation, the GwDbValidatorsPattern hooks into the event system of SQLAlchemy to get notified about each important action and run own validation tasks.

To store its own hashes, GwDbValidatorsPattern is using its own database, which is registered and available in groundwork under the name hash_db.

For each database model, GwDbValidatorsPattern registers a validator with the help of GwValidatorsPattern. As attributes only the table columns are taking into account. So no additional attributes like SQLALchemy internal ones or model functions are used.

Storing data

GwDbValidatorsPattern has registered its own hash creation function for the SQLAlchemy events after_update and after_insert.

If one of these events is triggered, GwDbValidatorsPattern gets the model instance and creates with the help of GwValidatorsPattern a new hash.

This hash gets stored together with an ID into the hash database. The ID must be unique and our function must be able to regenerate it based on given and static information. So the ID contains: validator name, database table name and model instance id. Example: my_validator.user_table.5. This kind of an ID allows us to store hashes for all database models into one single database table.

Receiving data

GwDbValidatorsPattern has registered its own hash validation function for the SQLAlchemy event refresh.

If this gets called, GwDbValidatorsPattern retrieves the received database model instance. For this it regenerates the hash ID and requests the stored hash value. With the configured validator of the GwValidatorsPattern it validates the stored hash against the retrieved database model instance.

If the validation fails, the exception ValidationError gets raised. If this happens, the plugin developer is responsible to handle this exception the correct way.

Requirements & Specifications

The following sections describes the implemented requirements and their related specifications.

Available requirements

ID Title Type Status Links Tags
R_7F7C2 Validation per database table Requirement   gwdbvalidator_pattern

Available specifications

ID Title Type Status Links Tags
S_5917A DB Validation registration Specification   R_7F7C2 gwdbvalidator_pattern
Requirements

Requirement: Validation per database table (R_7F7C2)

As developer I want to be able to to activate the validation of single database table so that I’m sure retrieved data is valid.

tags: gwdbvalidator_pattern

Specification

Specification: DB Validation registration (S_5917A)

A function self.validators.db.register must be implemented, to allow the registration of database classes for validation. The following parameters must be available:

  • name of the registered db validator.
  • description of the registered db validator.
  • database class (sqlalchemy), which write/read operations shall be validated.

tags: gwdbvalidator_pattern

links: R_7F7C2

GwFileValidatorsPattern

Creating a hash

For each file a hash value can be created. GwFileValidatorsPattern cares about the correct handling of files, even if the file size is too big to get handled in one step.

To create a hash, all you have to do is to use the function hash():

from groundwork_validation.patterns import GwFileValidatorsPattern

class My_Plugin(GwFileValidatorsPattern):
    def __init__(self, app, **kwargs):
        self.name = "My_Plugin"
        super(My_Plugin, self).__init__(app, **kwargs)

    def activate(self):
        my_file = "/path/to/file.txt"

        # Generate and retrieve a string based hash value
        my_hash = self.validators.file.hash(my_file)

        # Store hash value directly into a file
        my_hash = self.validators.file.hash(my_file, hash_file = "/path/to/file.txt.hash")

    def deactivate(self):
        pass

Please see hash() for a complete list of available parameters.

Validate a file
Using a hash string

For validation the function validate() is available:

from groundwork_validation.patterns import GwFileValidatorsPattern

class My_Plugin(GwFileValidatorsPattern):
    def __init__(self, app, **kwargs):
        self.name = "My_Plugin"
        super(My_Plugin, self).__init__(app, **kwargs)

    def activate(self):
        my_file = "/path/to/file.txt"

        my_hash = self.validators.file.hash(my_file)  # Generate a hash

        if self.validators.file.validate(my_file, my_hash):
            print("Hash is valid")
        else:
            print("Hash is NOT valid")

    def deactivate(self):
        pass
Using a hash file

It is also possible to validate a file against a hash file, which has stored the hash at the first line:

from groundwork_validation.patterns import GwFileValidatorsPattern

class My_Plugin(GwFileValidatorsPattern):
    def __init__(self, app, **kwargs):
        self.name = "My_Plugin"
        super(My_Plugin, self).__init__(app, **kwargs)

    def activate(self):
        my_file = "/path/to/file.txt"
        my_hash_file = "/path/to/file.hash"

        if self.validators.file.validate(my_file, hash_file=my_hash_file):
            print("Hash is valid")
        else:
            print("Hash is NOT valid")

    def deactivate(self):
        pass

Please see validate() for a complete list of available parameters.

Requirements & Specifications

The following sections describes the implemented requirements and their related specifications.

Available requirements

ID Title Type Status Links Tags
R_8E18E File validation Requirement   gwfilevalidators

Available specifications

ID Title Type Status Links Tags
S_31C31 Validating a file Specification   R_8E18E gwfilevalidators
S_CFBC1 Hashing a file Specification   R_8E18E gwfilevalidators
Requirements

Requirement: File validation (R_8E18E)

As developer I want to be able to easily hash and validate files to detect every kind of file corruption.

tags: gwfilevalidators

Specifications

Specification: Hashing a file (S_CFBC1)

A function hash is implemented for self.validators.file, which is able to create a hash value for a given file path. The function must have the following parameters:

  • file - file path
  • validator - An instance of Validator. Can be None
  • hash_file - File to store the hash value. optional
  • blocksize - Max. size of a block, which gets read in gets hashed and maybe update the prior hash value.
  • return_hash_object - Returns the hashlib hash object instead of a string representation

tags: gwfilevalidators

links: R_8E18E

Specification: Validating a file (S_31C31)

A function validate is implemented for self.validators.file, which allows the validation of a file against a given hash.

The function has the following attributes:

  • file - file path
  • hash_value
  • hash_file - if given, hash_value is read from this file path
  • validator - An instance of Validator. Can be None
  • blocksize - Max. size of a block, which gets read in gets hashed and maybe update the prior hash value.

Returns True, if calculated hash values is euqal to the given hash value.

tags: gwfilevalidators

links: R_8E18E

GwCmdValidatorsPattern

The GwCmdValidatorsPattern can be used to valid the execution of a command.

This can helpful to verify the version of an installed tool by checking, if the output contains the correct version.

For some cases also the correct behavior can be validated by checking the correct return value or by setting a limit for the maximum allowed execution time.

Validating the output of a command

All different types of command validations are available by using the function validate():

import sys
from groundwork_validation.patterns import GwCmdValidatorsPattern

class My_Plugin(GwCmdValidatorsPattern):
      def __init__(self, app, **kwargs):
          self.name = "My_Plugin"
          super(My_Plugin, self).__init__(app, **kwargs)

      def activate(self):
          if self.validators.cmd.validate("dir", search="my_folder"):
              print("Command 'dir' works as expected.")
          else:
              print("Command 'dir' seems not to work correctly. We stop here")
              sys.exit(1)

      def deactivate(self):
          pass

Instead of searching for a specific string, you can also use a regular expression:

# Checks for an e-mail address
if self.validators.cmd.validate("dir",
                                regex="(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)"):
    print("Found at least one e-mail address")
Validating the return code

By validating the return code, you can easily check if the command is available and exits like expected. If the return code is not allowed, the exception NotAllowedReturnCode is raised:

import sys
from groundwork_validation.patterns import GwCmdValidatorsPattern
from groundwork_validation.patterns.gw_cmd_validators_pattern.gw_cmd_validators_pattern import NotAllowedReturnCode

 class My_Plugin(GwCmdValidatorsPattern):
        def __init__(self, app, **kwargs):
            self.name = "My_Plugin"
            super(My_Plugin, self).__init__(app, **kwargs)

        def activate(self):
            try:
                if self.validators.cmd.validate("dir", search="my_folder", allowed_return_codes=[0, 1]):
                    print("Command 'dir' works a expected.")
                else:
                    print("Command 'dir' seems not to work correctly. We stop here")
                    sys.exit(1)
            except NotAllowedReturnCode:
                print("Command exists with not allowed status code. Validation failed!")
                sys.exit(1)
Setting a timeout

By default the command is killed after a timeout of 2 seconds and CommandTimeoutExpired is raised. You are free to set your own timeout for each validation:

import sys
from groundwork_validation.patterns import GwCmdValidatorsPattern
from groundwork_validation.patterns.gw_cmd_validators_pattern.gw_cmd_validators_pattern \
    import NotAllowedReturnCode, CommandTimeoutExpired

class My_Plugin(GwCmdValidatorsPattern):
        def __init__(self, app, **kwargs):
            self.name = "My_Plugin"
            super(My_Plugin, self).__init__(app, **kwargs)

        def activate(self):
            try:
                if self.validators.cmd.validate("dir", search="my_folder", timeout=5):
                    print("Command 'dir' works a expected.")
                else:
                    print("Command 'dir' seems not to work correctly. We stop here")
                    sys.exit(1)
            except CommandTimeoutExpired:
                print("Command has not finished and raised a timeout. This is not expected. We stop here!")
                sys.exit(1)

test:

pip install
Requirements & Specifications

The following sections describes the implemented requirements and their related specifications.

Available requirements

ID Title Type Status Links Tags
R_79027 Command output validation Requirement   gwcmdvalidators
R_72AC6 Command exit code validation Requirement   gwcmdvalidators
R_77A07 Command runtime validation Requirement   gwcmdvalidators

Available specifications

ID Title Type Status Links Tags
S_2C5EC Command execution Specification   R_79027; R_72AC6; R_77A07 gwcmdvalidators
S_102F8 command output check Specification   R_79027 gwcmdvalidators
S_EB190 command exit code check Specification   R_72AC6 gwcmdvalidators
S_8C1D8 command timeout check Specification   R_77A07 gwcmdvalidators
Requirements

Requirement: Command output validation (R_79027)

As developer I want to be able to validate the correct output of an executed command.

tags: gwcmdvalidators

Requirement: Command exit code validation (R_72AC6)

As developer I want to be able to validate the correct exit code of an executed command

tags: gwcmdvalidators

Requirement: Command runtime validation (R_77A07)

As developer I want to be able to validate the maximum needed run time of an executed command

tags: gwcmdvalidators

Specifications

Specification: Command execution (S_2C5EC)

With self.validators.cmd.validate the developer is able to execute a command on command line. This execution takes place in a subprocess, but the application must wait till it ends.

The first argument must be the command to execute

tags: gwcmdvalidators

links: R_79027 ; R_72AC6 ; R_77A07

Specification: command output check (S_102F8)

As keyword argument “search” of self.validators.cmd.validate the output on STDOUT is checked, if the given string is part of it.

If yes, True is returned. Otherwise False

tags: gwcmdvalidators

links: R_79027

Specification: command exit code check (S_EB190)

As keyword argument “allowed_return_codes” of self.validators.cmd.validate as list of allowed return codes can be defined.

If the retrieved return code is not in this list, the Error NotAllowedReturnCode is raised.

tags: gwcmdvalidators

links: R_72AC6

Specification: command timeout check (S_8C1D8)

As keyword argument “timeout” of self.validators.cmd.validate a time in seconds can be set.

If the execution of the given command takes longer as specified, the execution is aborted and the error CommandTimeoutExpired is raised.

tags: gwcmdvalidators

links: R_77A07

Traceability

This project has documented its requirements, specifications and test cases.

Requirements

ID Title Type Status Links Tags
R_79027 Command output validation Requirement   gwcmdvalidators
R_002 Validated read requests on database tables Requirement implemented gwdbvalidator_plugin;
R_6A8AF Getting a validator Requirement   gwvalidator
R_003 Configuration only Requirement implemented gwdbvalidator_plugin;
R_001 Hashed write requests on database tables Requirement implemented gwdbvalidator_plugin;
R_D8C4B Validator registration Requirement   gwvalidator
R_7F7C2 Validation per database table Requirement   gwdbvalidator_pattern
R_72AC6 Command exit code validation Requirement   gwcmdvalidators
R_8E18E File validation Requirement   gwfilevalidators
R_E3793 Validator functions Requirement   gwvalidator
R_77A07 Command runtime validation Requirement   gwcmdvalidators

Specifications

ID Title Type Status Links Tags
S_31C31 Validating a file Specification   R_8E18E gwfilevalidators
S_CFBC1 Hashing a file Specification   R_8E18E gwfilevalidators
S_5917A DB Validation registration Specification   R_7F7C2 gwdbvalidator_pattern
S_2C5EC Command execution Specification   R_79027; R_72AC6; R_77A07 gwcmdvalidators
S_10710 hash() function for validator Specification   R_E3793 gwvalidator
S_001 Using of groundwork pattern GwDbValidatorPattern Specification implemented R_001; R_002 gwdbvalidator_plugin;
S_1FB7D validate() function for validator Specification   R_E3793 gwvalidator
S_102F8 command output check Specification   R_79027 gwcmdvalidators
S_F7DDB register() function for self.validators Specification   R_D8C4B; R_6A8AF gwvalidator
S_EB190 command exit code check Specification   R_72AC6 gwcmdvalidators
S_8C1D8 command timeout check Specification   R_77A07 gwcmdvalidators
S_002 Automatic database table registration for validation Specification implemented R_003 gwdbvalidator_plugin;

Test Cases

ID Title Type Status Links Tags
T_4B1C4 gwvalidator tests Test Case   S_1FB7D; S_10710 gwvalidator

API

Plugins

GwDbValidator
class GwDbValidator(app, **kwargs)

Automatically adds and activate validation to eahc database model.

activate()

During activation, a receiver is created and listing for new database models. Existing database models are collected and validation gets activated.

Returns:None
deactivate()

Currently nothing happens here sigh

Returns:None

Patterns

GwValidatorsPattern
class GwValidatorsPattern(app, **kwargs)

Allows the creation of hashes for python objects (and its validation).

activate()

Must be overwritten by the plugin class itself.

deactivate()

Must be overwritten by the plugin class itself.

class ValidatorsPlugin(plugin)

Cares about the Validator handling on plugin level.

get(name)

Returns a single or a list of validator instance, which were registered by the current plugin.

Parameters:name – Name of the validator. If None, all validators of the current plugin are returned.
Returns:Single or list of Validator instances
register(name, description, algorithm=None, attributes=None)

Registers a new validator on plugin level.

Parameters:
  • name – Unique name of the validator
  • description – Helpful description of the validator
  • algorithm – A hashlib compliant function. If None, hashlib.sha256 is taken.
  • attributes – List of attributes, for which the hash must be created. If None, all contained attributes are used.
Returns:

Validator instance

unregister(name)
class ValidatorsApplication(app)

Cares about the Validator handling on application level.

get(name, plugin)

Returns a single or a list of validator instance

Parameters:
  • name – Name of the validator. If None, all validators are returned.
  • plugin – Plugin instance, which has registered the requested validator. If None, all validators are returned.
Returns:

Single or list of Validator instances

register(name, description, plugin, algorithm=None, attributes=None)

Registers a new validator on application level.

Parameters:
  • name – Unique name of the validator
  • description – Helpful description of the validator
  • algorithm – A hashlib compliant function. If None, hashlib.sha256 is taken.
  • attributes – List of attributes, for which the hash must be created. If None, all contained attributes are used.
  • plugin – Plugin instance, for which the validator gets registered.
Returns:

Validator instance

unregister(name)
class Validator(name, description, algorithm=None, attributes=None, plugin=None)

Represent the final validator, which provides functions to hash a given python object and to validate a python object against a given hash.

get_hash_object()

Returns a hash object, which can be used as input for validate functions.

Returns:An unused hash object
hash(data, hash_object=None, return_hash_object=False, strict=False, no_pickle=False)

Generates a hash of a given Python object.

Parameters:
  • data – Python object
  • return_hash_object – If true, the complete hashlib object is returned instead of a hexdigest representation as string.
  • hash_object – An existing hash object, which will be updated. Instead of creating a new one.
  • strict – If True, all configured attributes must exist in the given data, otherwise an exception is thrown.
  • no_pickle – If True data is not pickled before hash is calculated. Helpful, if data is already serialised (like file inputs)
Returns:

hash as string

validate(data, hash_string, no_pickle=False)

Validates a python object against a given hash

Parameters:
  • data – Python object
  • hash_string – hash as string, which must be compliant to the configured hash algorithm of the used validator.
  • no_pickle – If True data is not pickled before hash is calculated. Helpful, if data is already serialised (like file inputs)
Returns:

True, if object got validated by hash. Else False

GwDbValidatorsPattern
class GwDbValidatorsPattern(app, **kwargs)

Allows the validation of database model requests.

Builds automatically hashes of table rows/model instances and validates these hashes, if a request is made on these rows.

activate()

Must be overwritten by the plugin class itself.

deactivate()

Must be overwritten by the plugin class itself.

class DbValidatorsPlugin(plugin)

Cares about database validators on plugin level

get(name)
register(name, description, db_class)

Registers a new database model and starts its validation.

Parameters:
  • name – Unique name
  • description – Meaningful description
  • db_class – sqlalchemy based database model
Returns:

Instance of DbValidator

unregister(name)
class DbValidatorsApplication(app)

Cares about database validators on application level

get(name, plugin)
register(name, description, db_class, plugin)

Registers a new database model and starts its validation.

Parameters:
  • name – Unique name
  • description – Meaningful description
  • db_class – sqlalchemy based database model
  • plugin – Plugin, which registers the DbValidator
Returns:

Instance of DbValidator

unregister(name)
class DbValidator(name, description, db_class, db, hash_model, plugin=None)

Class for storing a database validator. For each registered database validator an instance of this class gets created and configured.

class ValidationError

Exception, which is thrown if a validation fails.

GwFileValidatorsPattern
class GwFileValidatorsPattern(app, **kwargs)

Allows the creation and validation of hashes for given files.

Usage:

from groundwork_validation.patterns import GwFileValidatorsPattern

class My_Plugin(GwFileValidatorsPattern):
    def __init__(self, app, **kwargs):
        self.name = "My_Plugin"
        super(My_Plugin, self).__init__(app, **kwargs)

    def activate(self):
        my_hash = self.validators.file.hash("/path/to/file.txt")
        self.validators.file.validate("/path/to/file.txt", my_hash)
activate()

Must be overwritten by the plugin class itself.

deactivate()

Must be overwritten by the plugin class itself.

class FileValidatorsPlugin(plugin)
hash(file, validator=None, hash_file=None, blocksize=65536, return_hash_object=False)

Creates a hash of a given file.

Parameters:
  • file – file path of the hashable file
  • validator – validator, which shall be used. If none is given, a default validator will be used. validator should be registered be the GwValidatorsPattern. Default is None
  • hash_file – Path to a file, which is used to store the calculated hash value. Default is None
  • blocksize – Size of each file block, which is used to update the hash. Default is 65536
  • return_hash_object – Returns the hash object instead of the hash itself. Default is False
Returns:

string, which represents the hash (hexdigest)

validate(file, hash_value=None, hash_file=None, validator=None, blocksize=65536)

Validates a file against a given hash. The given hash can be a string or a hash file, which must contain the hash on the first row.

Parameters:
  • file – file path as string
  • hash_value – hash, which is used for comparision
  • hash_file – file, which contains a hash value
  • validator – groundwork validator, which shall be used. If None is given, a default one is used.
  • blocksize – Size of each file block, which is used to update the hash.
Returns:

True, if validation is correct. Otherwise False

GwCmdValidatorsPattern
class GwCmdValidatorsPattern(app, **kwargs)

Allows the validation of output, return code and execution time of a given command.

Usage:

class My_Plugin(GwCmdValidatorsPattern):
    def __init__(self, app, **kwargs):
        self.name = "My_Plugin"
        super(My_Plugin, self).__init__(app, **kwargs)

    def activate(self):
        if self.validators.cmd.validate("dir", search="my_folder"):
            print("Command 'dir' works a expected.")
        else:
            print("Command 'dir' seems not to work correctly. We stop here")
            sys.exit(1)

    def deactivate(self):
        pass
activate()

Must be overwritten by the plugin class itself.

deactivate()

Must be overwritten by the plugin class itself.

class CmdValidatorsPlugin(plugin)
validate(command, search=None, regex=None, timeout=2, allowed_return_codes=None, decode='utf-8')

Validates the output of a given command.

The validation can be based on a simple string search or on a complex regular expression. Also the return_code can be validated. As well as the execution duration by setting a timeout.

Parameters:
  • command – string, which is used as command for a new subprocess. E.g. ‘git -v’.
  • search – string, which shall be contained in the output of the command. Default is None
  • regex – regular expression, which is tested against the command output. Default is None
  • timeout – Time ins seconds, after which the execution is stopped and the validation fails. Default is 2 seconds
  • allowed_return_codes – List of allowed return values. Default is []
  • decode – Format of the console encoding, which shall be used. Default is ‘utf-8’
Returns:

True, if validation succeeded. Else False.

class NotAllowedReturnCode
class CommandTimeoutExpired

Test Cases

Plugins

GwDbValidatorsPlugin

Patterns

GwDbValidatorPattern
GwValidatorPattern
test_validator_init()[source]

Test Case: gwvalidator tests (T_4B1C4)

Test of initialisation, hashing and validation of GwValidatorsPattern

tags: gwvalidator

links: S_1FB7D ; S_10710

GwFileValidatorPattern
GwCmdValidatorPattern