summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Ruderich <simon@ruderich.org>2013-11-12 23:48:25 +0100
committerChris St. Pierre <chris.a.st.pierre@gmail.com>2013-11-14 09:27:08 -0500
commitd8bbfbdf8b503538fff01bff80c5e6e12bfb44b3 (patch)
tree95b76849268d44bcf6ea81f957159e3a568dcf69
parent557377e8a1d0492f4c26b95c4a74172a9210ac3e (diff)
downloadbcfg2-d8bbfbdf8b503538fff01bff80c5e6e12bfb44b3.tar.gz
bcfg2-d8bbfbdf8b503538fff01bff80c5e6e12bfb44b3.tar.bz2
bcfg2-d8bbfbdf8b503538fff01bff80c5e6e12bfb44b3.zip
Add probes.allowed_groups option to restrict group assignments.
-rw-r--r--doc/server/plugins/probes/index.txt40
-rw-r--r--doc/unsorted/dynamic_groups.txt27
-rw-r--r--src/lib/Bcfg2/Options.py17
-rw-r--r--src/lib/Bcfg2/Server/Plugins/Probes.py10
4 files changed, 65 insertions, 29 deletions
diff --git a/doc/server/plugins/probes/index.txt b/doc/server/plugins/probes/index.txt
index 306a752b6..6f745e359 100644
--- a/doc/server/plugins/probes/index.txt
+++ b/doc/server/plugins/probes/index.txt
@@ -13,6 +13,9 @@ the system disk, you would want to know this information to correctly
generate an `/etc/auto.master` autofs config file for each type. Here
we will look at how to do this.
+Probes also allow dynamic group assignment for clients, see
+:ref:`_server-plugins-probes-dynamic-groups`.
+
First, create a ``Probes`` directory in our toplevel repository
location::
@@ -119,6 +122,43 @@ is to add the ``/etc/auto.master`` to a Bundle:
<Path name='/etc/auto.master'/>
+.. _server-plugins-probes-dynamic-groups:
+
+Dynamic Group Assignment
+========================
+
+The output lines of the probe matching "group:" are used to
+dynamically assign hosts to groups. These dynamic groups need not already
+exist in ``Metadata/groups.xml``. If a dynamic group is defined in
+``Metadata/groups.xml``, clients that include this group will also get
+all included groups and bundles.
+
+Consider the following output of a probe::
+
+ group:debian-wheezy
+ group:amd64
+
+This assigns the client to the groups debian-wheezy and amd64.
+
+To prevent clients from manipulating the probe output and choosing
+unexpected groups (and receiving their potential sensitive files) you
+can use the ``allowed_groups`` option in the ``[probes]`` section of
+``bcfg2.conf`` on the server. This whitespace-separated list of anchored
+regular expressions (must match the complete group name) controls
+dynamic group assignments. Only matching groups are allowed. The
+default allows all groups.
+
+.. versionadded:: TODO
+
+Example::
+
+ [probes]
+ allowed_groups = debian-(squeeze|wheezy|sid) i386
+
+This allows the groups debian-squeeze, debian-wheezy, debian-sid and
+i386. With the probe output from above, this setting would disallow
+the group amd64.
+
Handling Probe Output
=====================
diff --git a/doc/unsorted/dynamic_groups.txt b/doc/unsorted/dynamic_groups.txt
deleted file mode 100644
index 11535dc8b..000000000
--- a/doc/unsorted/dynamic_groups.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-.. -*- mode: rst -*-
-
-.. _unsorted-dynamic_groups:
-
-==============
-Dynamic Groups
-==============
-
-Bcfg2 supports the use of dynamic groups. These groups are not included
-in a client's profile group, but instead are derived from the results
-of probes executed on the client. These dynamic groups need not already
-exist in ``Metadata/groups.xml``. If a dynamic group is defined in
-``Metadata/groups.xml``, clients that include this group will also get
-all included groups and bundles.
-
-Setting up dynamic groups
-=========================
-
-In order to define a dynamic group, setup a probe that outputs the text
-based on system properties::
-
- group:groupname
-
-This output is processed by the Bcfg2 server, and results in dynamic
-group membership in groupname for the client. See the :ref:`Probes
-<server-plugins-probes-index>` page for a more thorough description
-of probes.
diff --git a/src/lib/Bcfg2/Options.py b/src/lib/Bcfg2/Options.py
index 95abe64ae..f9b6a998b 100644
--- a/src/lib/Bcfg2/Options.py
+++ b/src/lib/Bcfg2/Options.py
@@ -311,6 +311,14 @@ def list_split(c_string):
return re.split(r'\s*,\s*', c_string)
return []
+def list_split_anchored_regex(c_string):
+ """ like list_split but split on whitespace and compile each element as
+ anchored regex """
+ try:
+ return [re.compile('^' + x + '$') for x in re.split(r'\s+', c_string)]
+ except re.error:
+ raise ValueError("Not a list of regexes", c_string)
+
def colon_split(c_string):
""" split an option string on colons, returning a list """
@@ -641,6 +649,12 @@ SERVER_CHILDREN = \
cf=('server', 'children'),
cook=get_int,
long_arg=True)
+SERVER_PROBE_ALLOWED_GROUPS = \
+ Option('Whitespace-separated list of group names (as regex) to which '
+ 'probes can assign a client by writing "group:" to stdout.',
+ default=['.*'],
+ cf=('probes', 'allowed_groups'),
+ cook=list_split_anchored_regex)
# database options
DB_ENGINE = \
@@ -1225,7 +1239,8 @@ SERVER_COMMON_OPTIONS = dict(repo=SERVER_REPOSITORY,
perflog=LOG_PERFORMANCE,
perflog_interval=PERFLOG_INTERVAL,
children=SERVER_CHILDREN,
- client_timeout=CLIENT_TIMEOUT)
+ client_timeout=CLIENT_TIMEOUT,
+ probe_allowed_groups=SERVER_PROBE_ALLOWED_GROUPS)
CRYPT_OPTIONS = dict(encrypt=ENCRYPT,
decrypt=DECRYPT,
diff --git a/src/lib/Bcfg2/Server/Plugins/Probes.py b/src/lib/Bcfg2/Server/Plugins/Probes.py
index 84e1638d6..59a73c4aa 100644
--- a/src/lib/Bcfg2/Server/Plugins/Probes.py
+++ b/src/lib/Bcfg2/Server/Plugins/Probes.py
@@ -204,6 +204,7 @@ class Probes(Bcfg2.Server.Plugin.Probing,
err = sys.exc_info()[1]
raise Bcfg2.Server.Plugin.PluginInitError(err)
+ self.allowed_cgroups = core.setup['probe_allowed_groups']
self.probedata = dict()
self.cgroups = dict()
self.load_data()
@@ -391,11 +392,18 @@ class Probes(Bcfg2.Server.Plugin.Probing,
if line.split(':')[0] == 'group':
newgroup = line.split(':')[1].strip()
if newgroup not in cgroups:
- cgroups.append(newgroup)
+ if self._group_allowed(newgroup):
+ cgroups.append(newgroup)
+ else:
+ self.logger.info("Disallowed group assignment %s from %s"
+ % (newgroup, client.hostname))
dlines.remove(line)
dobj = ProbeData("\n".join(dlines))
cprobedata[data.get('name')] = dobj
+ def _group_allowed(self, group):
+ return any(r.match(group) for r in self.allowed_cgroups)
+
def get_additional_groups(self, meta):
return self.cgroups.get(meta.hostname, list())
get_additional_groups.__doc__ = \