Skip to content

Improve config upgrade – Ep 02 – Minimal model for OpenSsh’s sshd_config

May 19, 2010

Hello

Currently Config::Model can upgrade /etc/ssh/sshd_config file because Sshd model is complete. All 80 parameters mentioned in sshd_config man pages are described there.  The whole model (including doc is about 1000 lines long).

If one just want configuration upgrade capability, requiring a complete model is too much work. The aim of this GSoC project is to find a way to provide upgrades at a reasonable cost.

Ep 01 focused on what feature was missing from Config::Model to provide a model that could handle unknown parameters in most cases to enable upgrades without a complete model. This covered the use case of an unmaintained model facing software evolution.

Now, let’s go on with the OpenSsh example and let’s see what would be the minimal model that would enable upgrades from older sshd_config version to a more recent one. (Note that this blog is based on upgrade requirements mentioned in sshd_config man page). This will cover the use case of a maintained model targeted for upgrades.

From last blog, we know that this minimal model must feature:

  • structural information (i.e. Match parameter)
  • upgrade information (KeepAlive to TCPKeepAlive)

Let’s tackle the structure of this minimal model by re-using the current model structure. We will need 2 classes:

  1. Sshd: to handle all leaf parameters a the the Match parameter
  2. Sshd::MatchElement: to handle parameters within a Match block

Sshd::MatchElement will need to handle unknown leaf parameters (exceptd Match parameters), so its declaration should be like:

'Sshd::MatchElement' => {
   accept => {
     match_not =>  '/Match/i'' ,
     type => 'leaf',
     value_type => 'string'
   }
 }
 

Note that there’s no element declaration. The accept structure means that Config::Model will accept any parameter that does not contain “match” in its name and will handle it as a string parameter. (Note that this feature is not yet implemented in Config::Model)

Now, we must declare the main class: Sshd. It will feature the a wider “accept” statement and element declarations for the following parameters:

  • Match (the only structural element)
  • KeepAlive (obsolete parameter)
  • TCPKeepAlive (value migrated from KeepAlive)

Here we go: Any unknown parameter will be accepted by Sshd configuration class:

 accept => {
   type => 'leaf',
   value_type => 'string'
 },

Here are the element that require a special treatment: Match just refer to the class declared above


 Match => {
   type => 'hash',
   index_type => 'uniline',
   cargo => {
     type => 'node',
     config_class_name => 'Sshd::MatchElement'
   }
},

KeepAlive is the obsolete parameter. Parameter with status ‘deprecated’ are handled by Config::Model but will not be written back in the configuration file. Hence re-using the deprecated information elsewhere is more than recommended.


KeepAlive => {
  type => 'leaf',
  value_type => 'enum',
  status => 'deprecated',
  choice => [ 'no', 'yes' ]
},

Here’s the new parameter. It’s value is computed from KeepAlive.


TCPKeepAlive => {
  type => 'leaf',
  value_type => 'enum',
  choice => [ 'no', 'yes' ],
  migrate_from => {
    formula => '$keep_alive',
    variables => { keep_alive => '- KeepAlive' }
  },
},

Now that we have the model, we must figure out how to read and write value with minimal coding efforts. Due to the mismatch between the syntax of the file (flat structure) and the actual structure (special Match parameter), a dumb parser/writer cannot be used. A parser that takes into account Match is required. Either dedicated Perl code (like the parser/writer delivered with Config::Model::OpenSsh) or use Augeas and its sshd lenses.

In summary, we’ve seen that the model required to perform upgrades is about 30 lines instead of the 1000 lines required for a complete model. On the other hand, the syntax of sshd_config makes the parser and writer harder to write. But, normally, this parser/writer should not evolve during the life of OpenSsh project.

Now the question that I cannot answer is: Can a packager handle the extra work to maintain this minimal model ? Feedback is welcome here 😉

Next episode will study how upgrades based on Config::Model can be applied on files with other syntaxes.

All the best

From → computer

Leave a Comment

Leave a comment