Config file validation

Related ticket(s):

Problem statement

Typos in option names are not detected. If conflicting options are used or required options are missing, SSSD should produce easy to understand error/debug message so that administrators can fix the problem easier.

Overview of the solution

Application developers that use libini from Ding libs will be able to specify constraints that the configuration must respect. These constraints will be written using INI format in form of rules. Each rule will use one validator. The validator can be internal (provided by libini) or external (provided by applications). The rules will be written in a separate file and their usage will be optional. Validators will generate errors in form of strings that should be readable for users. Applications that use libini will then be able to write these strings somewhere appropriate (for example log files or stderr).

Format of rules

[rule/NAME]
validator = validator_name
validator_specific_parameter1 = ...
validator_specific_parameter2 = ...
.
.
.
validator_specific_parameterN = ...

Each rule needs to specify validator that will be used, other parameters depend on the validator. Some validators may not require any additional parameters.

Using the rules

The rules are used from applications in the following way:

  1. rules are loaded from file using the function int ini_read_rules_from_file(const char *filename, struct ini_cfgobj **_rules_obj);

  2. rules and configuration are passed as two fist parameters to the function

    int ini_rules_check(struct ini_cfgobj *rules_obj,
                           struct ini_cfgobj *config_obj,
                           struct ini_validator *extra_validators,
                           int num_extra_validators,
                           struct ini_errobj *errobj);
    

The last parameter is special structure used to hold all errors generated by the validators. libini will provide API to create, destroy, read errors from and write errors into this structure. The extra_validators and num_extra validators are used to specify external validators (see section ‘External validators’ below).

Internal validators

Internal validators will be simple validators that may be used by projects outside SSSD. More complicated and application specific validators will be written as external validators. First two internal validators will be ini_allowed_options and ini_allowed_sections.

Validator ini_allowed_options

Example:

[rule/allowed_options_for_section_foo]
validator = ini_allowed_options
section_re = ^foo$
option = foo
option = bar
option = baz

The rule above uses the ini_allowed_option validator and enumerates all allowed options for sections with names that match regular expression :sup:`foo$. The options allowed here are foo, bar and baz. Config file like this:

[foo]
bar = 1
baz = 1
foo = 1

will generate no errors, because all options in section foo are allowed. Config file

[foo]
baaaar = 1
baz = 1
foo = 1

will result in errors being generated because there is an unknown option baaaar used in section foo.

The ini_allowed_options validator controls only sections that match regular expression specified in section_re. Other sections are ignored by the validator.

Validator ini_allowed_sections

This validator is used to enumerate all allowed sections. The format is following.

[rule/enumerate_sections]
validator = ini_allowed_sections
section_re = regex1
section_re = regex2
.
.
.

section_re = regexN

The validator will generate error if the config file contains section that is not matched by any of the regular expressions specified by one of the section_re parameters.

External validators

External validators are specified using following structures:

struct ini_validator {
     const char *name;
     ini_validator_func *func;
};

The name attribute is sting that is used inside rules in the validator parameter. The func attribute is pointer to function of type ini_validator_func which is defined using typedef as following:

typedef int (ini_validator_func)(const char *rule_name,
                                 struct ini_cfgobj *rules_obj,
                                 struct ini_cfgobj *config_obj,
                                 struct ini_errobj *errobj);

This function has following parameters:

  • rule_name - this is name of rule that uses this validator (for example “rule/myrule”)
  • rules_obj - this is config object with all the rules
  • config_obj - this is config object with the actual configuration that is being checked by the rules
  • errobj - this ini_errobj structure used to propagate errors

Users of libini can specify array of struct ini_validator structures and pass them to ini_rules_check() function. After this they can be used in the same way as internal validators.

Configuration changes

In order to take advantage of this feature in SSSD the constraint file will have to be created.

How To Test

Unit tests in Ding libs. Integration and unit tests for SSSD.

Authors

Michal Židek mzidek@redhat.com