Normation: our mission, why Rudder and our offer

Yesterday, we held a seminar in our offices titled IT infrastructure: Balancing best practices and everyday constraints. Mark Burgess, pioneer of software configuration management and founding CTO of CFEngine AS, was our guest star, and gave a very interesting talk about the Third Wave of IT Management.

We took the opportunity to introduce Normation, presenting our mission, our strategic partnership with CFEngine AS, and the aims of Rudder. For those who weren’t there, we thought we’d share an extract of this presentation:

It was a great event, with many interesting questions and discussions, and we’d like to thank everyone who attended, and of course Mark for coming all the way to Paris for this, and his warm comments about Normation.

If you’re curious about Normation or Rudder, we’d love to hear from you – contact us by email, Twitter (@Normation and @RudderProject) or IRC (#rudder on FreeNode)!

Interactive key exchange with CFEngine

Here at Normation, we use CFEngine 3 extensively for configuration management across Linux and Windows servers.

CFEngine 3 is a very secure tool, that relies on keys to identify hosts and authorize connections. To set up a secure CFEngine infrastructure, you ought to exchange keys between hosts (note that if you don’t have confidential data on your promises, you can skip the security offered by the public key system).

Key exchange

The client-server communication is based on keys (very much like ssl). Each node must have a copy of the other public keys, obtained either via a remote copy (with scp), by trusting keys automatically, or using the bootstrap system introduced in Cfengine 3.2.0 (that would still require the server to accept automatically keys).

If you don’t want to accept keys based on automatic trust, you need to manually exchange them to set up the system. This article will show you how to do this using the cf-runagent tool, by connecting to each host from the main CFEngine server.

Assume a server with the following ip : 192.168.56.150
Assume a client with the following ip : 192.168.56.152

Client side

The initial promises on the client will need to configure the cf-serverd to run on it, and try to fetch its real promises from the policy server :

Note that the client trusts keys from the server

Server side

On the server, you’d have the following promise for the server component, authorizing hosts to connect, but not trusting their keys

Note: only the server itself is accepted on trust, hosts from the subnetwork 192.168.56.* can connect but their keys are not automatically trusted, and their DNS name is not deemed as reliable.

First execution (without prior key exchange)

If the agent on the client tries to connect to the server, without previous key exchange, you’ll have the following output on the server :

To relieve the burden of copying keys with scp, or the risk of trusking keys of every hosts, you can do a manual key exchange, from the server, using the cf-runagent interactive mode

Interactive key exchange

The interactive key exchange will happen from the server to the client. It will ask for the user to trust the key, and execute the remote promises of the client (in this case, the initial promises fetch the real promises from the server)

Here we accepted the key of 192.168.56.152 on the server, and the client could connect to download its new promises, and then apply them

Note: To prevent any risks, the new promises should not have 192.168.56.150 in the trustkeyfrom

Note 2: Since the version 3.2.0, if you are willing to automatically accept keys from the clients on the servers, you don’t need to copy any promises on the client, the bootstrap procedure from the Nova edition has been backported in the community edition; and it uses its own embedded promises

(Français) Formations Cfengine 3 à Paris et Bruxelles

Sorry, this entry is only available in Français.

Cfengine 3.1.5 is nearly out, what can we expect from it?

Here at Normation, we use Cfengine 3 extensively for configuration management across Linux and Windows servers. Cfengine 3 is an open source project, and as every good open source project, the trunk version is always available (but not always very reliable) and stable versions are released regularly. Prior to the release of a new version, a beta version is available, for the community to test and rule out any bugs in the stable version.

We’ve been testing this beta version, and we are quite thrilled about it. This post won’t go through every detail of the changelog (Eystein is much better at it that I would be) but will run over the changes that improve our ways of using Cfengine.

Bug fixes

Some nagging bugs have been corrected, most notably:

New features

An improved release system

For more robust and reliable stable versions, features have been added to industrialize building and releasing Cfengine itself:

  • New scripts to automate release, so that human error is mostly ruled out;
  • Units test, to prevent regressions. Users are even encouraged to create unit tests;
  • Easier compilation from sources. The following lines are enough to build Cfengine from sources:
    # ./autogen.sh [CONFIGURE OPTIONS]
    # make clean
    # make
    

Improved reporting in file editing

Classes can be set on every atomic file edit, meaning that each line insertion, replacement or removal can be tracked and reported.

Let’s say we want to enforce the content of the file /tmp/foo to be two lines containing foo and bar (yes, this is just an example), and be able to know if these lines are added or were already there (for the sake of simplicity, we won’t bother about knowing if other lines were present). The following promise defines a class for each added line, for each repaired line and for each line that couldn’t be added:

Note the reports in the bundle edit_line which does the reporting based on the classes defined in the insert_lines promise.

The first execution would result in:

# /var/cfengine/bin/cf-agent -Kf ./test.cf
R: Line foo added
R: Line bar added

So each line has been added, the agent did its job. A second execution would result in :

# /var/cfengine/bin/cf-agent -Kf ./test.cf
R: Line foo already present
R: Line bar already present

Which proves that no one tampered with the file while we were away.

Of course, this level of detailed reporting would probably be excessive in a real-life example, but this illustrates how classes can be used to build your own custom reporting systems.

Improved string manipulation

Cfengine 3 has pretty neat functions to read files, parse them and extract data into arrays (for instance, reading data from /etc/passwd). The 3.1.5 version introduces the same neat functions for parsing variables, rather than files. And that’s really cool to be able to manipulate complex strings rather than files if you, like me, generate your promises with external tools.

Here is an example that illustrates this new feature:

  • We generate a promise file, with a variable containing a list of users, and parameters for them
  • The variable is parsed and data are extracted in an array
  • The array is used to edit a passwd file, and a report is made if the line is added. This is a bit different from the ways described in a previous article on file editing.

Please note that the data are inserted in a random order. Indeed, the keys of an array are not ordered, being indexed by a kind of hash.

These new features are really great, and we’d like to thank the team behind Cfengine 3 and the Community for their great job at making Cfengine 3 a really powerful and reliable product.

Why we use Cfengine: file editing

Here at Normation, we use Cfengine 3 extensively for configuration management across Linux and Windows servers. A question we get often is why Cfengine?

I’d like to focus this post on file editing. Since Configuration Management has a lot to do with configuration files, file editing (either from a template, or just setting parameters) is one of the most common tasks.

Two ways to edit files

Managing configuration often implies setting up the content of configuration files. There are two main approaches to achieve this, each with its assets and drawbacks:

  1. Template based configuration: The easiest and safest way is to use templates, along with variables that hold the desired values. The file to configure is replaced by the result of the application of the values into the template. However, it doesn’t always fit well in an existing and heterogeneous environment, for instance if you want to gradually roll out Configuration Management.
  2. File editing: The most versatile approach is to edit the file, adding or modifying some lines, and removing the unwanted ones. It does fit well in heterogeneous systems, allowing for fine-grain tuning of what is to be managed and configured. However one has to think of all the potential lines of a file: those to be managed, those of no relative importance, and those which are critical.

Code examples

Next we provide examples on how to edit files using each method (specifically, how to edit the /etc/resolv.conf file – a simple but illustrative example).

Please note that the examples are self-contained, but in real world usages you should include the cfengine_stdlib.cf and re-use only the bundles (and the template in the first case) from these examples.

Template based file editing

When you want to set the content of a file based on a template, you need two items:

  • Some string variables, containing the values you want to set: in this example resolvers and searchlist,
  • A template (obviously), with the fully qualified variable names in place of the values to set.

The Cfengine file would be:

And the content of myTemplate.tml is:

#############################################################
### This file is configured by Cfengine.
### Manually editing the file might lead Cfengine
### to reset its content
#############################################################
search $(set_dns_configuration.searchlist)
nameserver $(set_dns_configuration.resolvers)

The variable names in the template are merely placeholders to be replaced by strings, so you can’t do any repetition, and if the variable doesn’t exist, you’ll end up with variable names in your resulting file (but you would test this in a development environment before going to production anyway, right?).

File edition

When you want to set up the content of a file by editing it, you need at least two things:

  • Variables holding the values (they may be strings or lists of strings (slists)): in this example resolvers and searchlist,
  • Definitions of how to add/set these values: in this example, in the bundle edit_line doresolv. Cfengine uses the power of regular expressions to define which line to edit and where to put it,
  • Optionally, you may define lines you do not wish to have in the files (this is not covered in this example).

The Cfengine file would be:

With this solution, you have much finer control over what is edited:

  • Lines can be repeated using slist rather than string,
  • Other fields can be left untouched (in this second example, the field domain remains as it was, leaving other administrators free to set it as they like).

I need to do something more complex!

Sometimes, the filse to edit are a more complex, with sections delimiting where lines must be.

Let’s imagine we have the following file :

[section=one]
value1=tokeep
value2=No
value3=don'twant

[section=two]
value2=tokeep
value3=Yes

What we want is to remove value3 from the first section, set value2 in this section to No, and set value3 in the second section to Yes.

This can be achieved with the following Cfengine file (once again, the body part comes from the cfengine_stdlib.cf) :

This example is a bit more complex, so some explanations might be helpful:

  1. The select_region INI_section selects the region where the editing will happen, based on section names in brackets,
  2. For simplication, the lines that are to be replaced are first deleted, then added. Advantages: we are sure that only the right number of lines are present, and the code is a bit more readable. Drawback: the order of the variables in the section is usually not kept.

Conclusions

These examples show only parts of what can be done in terms of file editing with Cfengine, but they give a general idea of the concept. You can also mix and match the different approaches (a section defined by a template, another one changed via editing, and another one left alone, except on servers A and C, for example).

The flexibility and versatility of these solutions allows for gradual rolling out of the configuration management across systems, which is especially important if you have existing systems managed by different teams, and need their voluntary cooperation on implementing configuration management.

Normation

87 rue Turbigo
75003 Paris

Tel : 01 83 62 26 96
Fax : 01 83 62 29 38
Contact us

Sign up for our newsletter

English
Français

Follow us