summaryrefslogtreecommitdiffstats
path: root/doc/server/plugins/connectors/properties.txt
blob: b56c2a488095b1e8e39151419a92865f42fd8296 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
.. -*- mode: rst -*-

.. _server-plugins-connectors-properties:

==========
Properties
==========

The Properties plugin is a connector plugin that adds information from
properties files into client metadata instances.

Enabling Properties
===================

First, ``mkdir /var/lib/bcfg2/Properties``. Each property XML file goes
in this directory. Each will automatically be cached by the server,
and reread/reparsed upon changes. Add **Properties** to your ``plugins``
line in ``/etc/bcfg2.conf``.

Data Structures
===============

Properties adds a new dictionary to client metadata instances that maps
property file names to PropertyFile instances. PropertyFile instances
contain parsed XML data as the "data" attribute.

The XML data in a property file is arbitrary, but a matching ``.xsd``
file can be created to assign a schema to a property file, which will
be checked when running ``bcfg2-lint``.  For instance, given::

    Properties/dns-config.xml
    Properties/dns-config.xsd

``dns-config.xml`` will be validated against ``dns-config.xsd``.

Although Properties files are technically freeform XML, the top-level
XML tag should be ``<Properties>``.

Usage
=====

Specific property files can be referred to in templates as
``metadata.Properties[<filename>]``. The ``xdata`` attribute is an
lxml.etree._Element object. (Documented `here
<http://codespeak.net/lxml/tutorial.html#the-element-class>`_)

In addition to the ``xdata`` attribute that can be used to access the
raw data, the following access methods are defined:

* ``Match()`` parses the Group and Client tags in the file and returns
  a list of elements that apply to the client described by a set of
  metadata.  For instance::

    {% python
    ntp_servers = [el.text
                   for el in metadata.Properties['ntp.xml'].Match(metadata)
                   if el.tag == "Server"]
    %}
* ``XMLMatch()`` parses the Group and Client tags in the file and
  returns an XML document containing only the data that applies to the
  client described by a set of metadata.  (The Group and Client tags
  themselves are also removed, leaving only the tags and data
  contained in them.)  For instance::

    {% python
    ntp_servers = [el.text
                   for el in metadata.Properties['ntp.xml'].XMLMatch(metadata).findall("//Server")]
    %}

As we formulate more common use cases, we will add them to the
``PropertyFile`` class as methods. This will simplify templates.

You can also access the XML data that comprises a property file
directly in one of several ways:

* ``metadata.Properties['prop-file'].xdata`` is an lxml.etree._Element
  object representing the top-level element in the file.
* ``metadata.Properties['prop-file'].data`` is the raw contents of the
  property file as a string.
* ``metadata.Properties['prop-file'].entries`` is a list of
  lxml.etree._Element objects representing the direct children of the
  top-level element.  (I.e., everything directly under the
  ``<Properties>`` tag.)

.. _server-plugins-connectors-properties-automatch:

Automatch
=========

.. versionadded:: 1.3.0

You can enable ``XMLMatch()`` for all Property files by setting
``automatch`` to ``true`` in the ``[properties]`` section of
``bcfg2.conf``.  This makes ``metadata.Properties`` values
lxml.etree._Element objects that contain only matching data.  (This
makes it impossible to do
:ref:`server-plugins-connectors-properties-write-back` as a
side-effect.)

In Python terms, setting ``automatch=true`` is the same as doing the
following at the top of each template::

    {% python
    for prop in metadata.Properties.values():
        prop = prop.XMLMatch(metadata)
    %}

The example above that describes ``XMLMatch()`` would then become
simply::

    {% python
    ntp_servers = [el.text
                   for el in metadata.Properties['ntp.xml'].findall("//Server")]
    %}

You can also enable automatch for individual Property files by setting
the attribute ``automatch="true"`` in the top-level ``<Property>`` tag.

.. _server-plugins-connectors-properties-write-back:

Writing to Properties files
===========================

.. versionadded:: 1.2.0

If you need to make persistent changes to properties data, you can use
the ``write`` method of the ``PropertyFile`` class::

    {% python
    import lxml.etree
    from genshi.template import TemplateError
    lxml.etree.SubElement(metadata.Properties['foo.xml'],
                          "Client",
                          name=metadata.hostname)
    if not metadata.Properties['foo.xml'].write():
        raise TemplateError("Failed to write changes back to foo.xml")

The ``write`` method checks the data in the object against its schema
before writing it; see `Data Structures`_ for details.

Note that use of the ``write`` method can cause race conditions if you
run more than one Bcfg2 server.  If you run more than one Bcfg2
server, you can disable Properties write-back by setting the following
in ``bcfg2.conf``::

    [properties]
    writes_enabled = false

.. _server-plugins-connectors-properties-encrypted:

Encrypted Properties data
=========================

.. versionadded:: 1.3.0

You can encrypt selected data in Properties files to protect that data
from other people who need access to the repository.  See
:ref:`server-plugins-generators-cfg-configuring-encryption` for
details on configuring encryption passphrases.  The data is decrypted
transparently on-the-fly by the server; you never need to decrypt the
data in your templates.

.. note::

    This feature is *not* intended to secure the files against a
    malicious attacker who has gained access to your Bcfg2 server, as
    the encryption passphrases are held in plaintext in
    ``bcfg2.conf``.  This is only intended to make it easier to use a
    single Bcfg2 repository with multiple admins who should not
    necessarily have access to each other's sensitive data.

Properties files are encrypted on a per-element basis; that is, rather
than encrypting the whole file, only the character content of
individual elements is encrypted.  This makes it easier to track
changes to the file in a VCS, and also lets unprivileged users work
with the other data in the file.  Only character content of an element
can be encrypted; attribute content and XML elements themselves cannot
be encrypted.

To encrypt a file, use ``bcfg2-crypt``, e.g.::

    bcfg2-crypt foo.xml

If the top-level tag of a Properties file is not ``<Properties>``,
then you need to use the ``--properties`` flag to ``bcfg2-crypt``::

    bcfg2-crypt --properties foo.xml

The first time you run ``bcfg2-crypt`` on a Properties file, it will
encrypt all character data of all elements.  Additionally, it will add
``encrypted="<key name>"`` to each element that has encrypted character
data.  It also adds ``encryption="true"`` to the top-level
``<Properties>`` tag as a flag to the server that it should try to
decrypt the data in that file.  (If you are using Properties schemas,
you will need to make sure to add support for these attributes.)  On
subsequent runs, only those elements flagged with ``encrypted="*"``
are encrypted or decrypted.

To decrypt a Properties file, simply re-run ``bcfg2-crypt``::

    bcfg2-crypt foo.xml

This decrypts the encrypted elements, but it does *not* remove the
``encrypted`` attribute; this way, you can decrypt a Properties
file, modify the contents, and then simply re-run ``bcfg2-crypt`` to
encrypt it again.  If you added elements that you also want to be
encrypted, you can either add the ``encrypted`` attribute to
them manually, or run::

    bcfg2-crypt --xpath '*' foo.xml

You can also use the ``--xpath`` option to specify more restrictive
XPath expressions to only encrypt a subset of elements, or to encrypt
different elements with different passphrases.  Alternatively, you can
manally set the ``encrypted`` attribute on various elements and
``bcfg2-crypt`` will automatically do the right thing.

Accessing Properties contents from TGenshi
==========================================

Access contents of ``Properties/auth.xml``::

    ${metadata.Properties['auth.xml'].xdata.find('file').find('bcfg2.key').text}

Configuration
=============

``bcfg2.conf`` contains several miscellaneous configuration options
for the Properties plugin, which can be set in the ``[properties]``
section. Any booleans in the config file accept the values "1", "yes",
"true", and "on" for True, and "0", "no", "false", and "off" for
False.

It understands the following directives:

* ``automatch``: Enable
  :ref:`server-plugins-connectors-properties-automatch`.  Default is
  false.
* ``writes_enabled``: Enable
  :ref:`server-plugins-connectors-properties-write-back`.  Default is
  true.