In this installment we turn to Jon Henrik Bjørnstad. In this particular
piece read about configuring, and managing connected devices with
CFEngine. If you have other such stories of CFEngine use, we would love
to hear back from you. Thanks Jon Henrik for a great post!
The
world of partially connected devices forms the basis of both mobile
IT and the much discussed Internet of Things (“IoT”). Hand-held tablets
and phones equipped with applications for interacting with various
services are merely the beginning of the pervasive computing experience,
and smart home projects by Xerox, HP and Google merely underestimate the
possible role of embedded devices in society at large. The Android
operating system is based on a stripped down Linux kernel, and is highly
portable. This open platform has spread to everything from television
sets and refrigerators to cars and in-flight entertainment systems. This
diaspora of partially-connected devices is the interaction point for
users and contributes in no small part to creating WebScale workloads.
Fortunately, the issue of configuration, security and maintenance in a
partially connected environment is the natural domain of CFEngine due to
its distributed architecture and lightweight autonomous agent.
Self-healing configuration on the move CFEngine was designed with
the world of embedded computing firmly in mind (see CFEngine founder
Mark Burgess’ novel
Slogans
from 2005, if you want to see how Mark was thinking). Today, any device
- whether an interactive Parisian billboard, car system, smartphone, or experimental robot at the National Institute of Standards - can benefit from CFEngine’s configuration technology. Unlike MDM solutions, CFEngine works offline and is self-repairing. What kinds of issues are there for configuration in a distributed on-and-offline embedded world? There are plenty of issues, but to see how a simple policy works, here is an example of how we might configure certain application defaults to make a device (in this case idle phones) less vulnerable to casual interference. Database configuration settings Android’s “system registry” is the SQLite key-value store, and database promises in CFEngine Enterprise 3.6.x may be used to handle SQLite with simple row manipulation. Many embedded systems use SQLite as the backend for storing system configuration as key-value pairs; among them are the feature rich and Open Source Storage operating system FreeNAS in addition to the omnipresent platform for mobile devices, Android. We will cover configuration within FreeNAS in a later post. Key-value pair tables are ideal for the type of simple row manipulation CFEngine offers. Rows are simply updated or added according to a condition (a WHERE in classical SQL) and the values that should converge. When used with associative arrays this becomes a flexible and handy way of expressing system configuration. This example is quite mundane, but imagine that you cared about the screen timeout setting on your Android device because you don’t want a phone lying around to remain unlocked. You want it to be set to 15 seconds (15000ms). In CFEngine you would express this as configuration setting as follows:
bundle agent android_settings
{
databases:
“settings.db/system”
database_server => sqlite("/data/data/com.android.providers.settings/databases"),
database_rows => { “name=‘screen_off_timeout’,value=>‘15000’” },
}
Now, even barring upgrades, resets or manual tampering, this policy will
be checked regularly and restored to the policy settings by CFEngine’s
agent. There is no need for a network connection. Everything is local.
The database table you currently want to configure are expressed as the
promiser, in this case the “system” table in the “settings.db” database.
As SQLite databases are embedded, you would also need to provide the
path to the database which happens through the SQLite database_server
body. The WHERE clause is expressed with a simple ‘=’ sign while the
values that should be set (or converge) are expressed with an ‘=>’ sign
(read: converge to). CFEngine imposes no limit on the number of WHERE
clauses you can use or values you could set, but it will of course need
to match the underlying table schema. Picture 1 below shows state before
policy is applied (screenshot of a Samsung S2 phone):
We run the policy and see the following:
**# cf-agent -I **
2014-07-02T13:41:51+0200 info: /default/android_settings/databases/‘settings.db/system’[0]: Table ‘system’ is as promised
2014-07-02T13:41:51+0200 info: /default/android_settings/databases/‘settings.db/system’[0]: Updating promised row ‘update system set value=‘15000’ where name=‘screen_off_timeout’’ to database table ‘settings.db/system’
Picture 2 below shows the resultant system state after running the
policy:
Run it again and CFEngine reports that the system is convergent with
regards to the setting you have defined, ie. the promise is kept.
# cf-agent -I
2014-07-02T13:41:43+0200 info: /default/android_settings/databases/‘settings.db/system’[0]: Table ‘system’ is as promised
This example is fairly simple, but it can be extended to be even more flexible and easier. As settings in Android are usually key-value pairs, it is desirable to express the configuration as that too. In CFEngine this is possible through the use of associative arrays. Consider the following bundle:
bundle agent android_vars {
vars:
“settings[screen_off_timeout]” string => “15000”;
}
Here we can define as many system settings as we’d like and hide away the complexity of how the settings are applied in a separate bundle as shown below:
bundle agent android_settings {
vars:
“settings” slist => maparray(“name=’$(this.k)’,value=>’$(this.v)’”, “android_vars.settings”);
databases:
“settings.db/system”
database_server => sqlite("/data/data/com.android.providers.settings/databases"),
database_rows => { @(settings) };
}
These examples clearly show how CFEngine enables you to describe system policy on Android in a transparent and convenient manner, and at the same time have the entire end-to-end software stack policy enforced by a true distributed configuration management system - truly WebScale.