.. -*- mode: rst -*- .. _server-plugins-connectors-properties: ========== Properties ========== The Properties plugin is a connector plugin that adds information from XML, JSON, and YAML files into client metadata instances. Enabling Properties =================== First, ``mkdir /var/lib/bcfg2/Properties``. Each property 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. A property file can be one of three types: * If the filename ends with ``.xml``, it will be parsed as XML and handled by :class:`Bcfg2.Server.Plugins.Properties.XMLPropertyFile`. See `XML Property Files`_ below. * If the filename ends with ``.json`` and JSON libraries are installed (either ``json`` or ``simplejson``, although ``json`` is highly recommended), it will be parsed as `JSON `_ and handled by :class:`Bcfg2.Server.Plugins.Properties.JSONPropertyFile`. See `JSON Property Files`_ below. * If the filename ends with ``.yaml`` or ``.yml`` and PyYAML is installed, it will be parsed as `YAML `_ and handled by :class:`Bcfg2.Server.Plugins.Properties.YAMLPropertyFile`. See `YAML Property Files`_ below. The XML interface is undoubtably the most powerful, as it natively supports schemas to check the data validity, client- and group-specific data, and data encryption. Usage ===== Common Interface ---------------- Different data types have different interfaces, but there are some usage patterns common to all properties files. Specific property files can be referred to in templates as ``metadata.Properties[]``. The data in property files is accessible via different attributes: +-----------+----------------+ | Data Type | Data Attribute | +===========+================+ | XML | ``xdata`` | +-----------+----------------+ | JSON | ``json`` | +-----------+----------------+ | YAML | ``yaml`` | +-----------+----------------+ For instance, in a :ref:`Genshi template `, you might do:: {% for item in metadata.Properties['foo.json'].json %}\ ${item} {% end %}\ {% for key, value in metadata.Properties['foo.yml'].yaml %}\ ${key} = ${value} {% end %}\ {% for el in metadata.Properties['foo.xml'].xdata.findall("Tag") %}\ ${el.get("name")} = ${el.text} {% end %}\ The raw contents of a properties file as a string are available via the ``data`` attribute, e.g., ``metadata.Properties['prop-file'].data``. .. _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 :class:`Bcfg2.Server.Plugins.Properties.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 interface is the same for YAML or JSON data. If writing XML data, 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 XML Property Files ------------------ The data in an XML property file can be accessed with the ``xdata`` attribute, an :class:`lxml.etree._Element` object documented `here `_. 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")] %} ``XMLMatch()`` can be run automatically on properties files by using the :ref:`server-plugins-connectors-properties-automatch` feature. 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 ```` tag.) 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 ````. JSON Property Files ------------------- .. versionadded:: 1.3.0 The data in a JSON property file can be accessed with the ``json`` attribute, which is the loaded JSON data. The JSON properties interface does not provide any additional functionality beyond the `Common Interface`_. YAML Property Files ------------------- .. versionadded:: 1.3.0 The data in a YAML property file can be accessed with the ``yaml`` attribute, which is the loaded YAML data. Only a single YAML document may be included in a file. The YAML properties interface does not provide any additional functionality beyond the `Common Interface`_. .. _server-plugins-connectors-properties-automatch: Automatch ========= .. versionadded:: 1.3.0 You can enable :func:`Bcfg2.Server.Plugin.helpers.StructFile.XMLMatch()` for all XML Property files by setting ``automatch`` to ``true`` in the ``[properties]`` section of ``bcfg2.conf``. This makes ``metadata.Properties`` values :class:`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"`` on the top-level ```` tag. Conversely, if automatch is enabled by default in ``bcfg2.conf``, you can disable it for an individual Property file by setting ``automatch="false"`` on the top-level ```` tag. If you want to see what ``XMLMatch()``/automatch would produce for a given client on a given Properties file, you can use :ref:`bcfg2-info `:: bcfg2-info automatch props.xml foo.example.com If automatch is not enabled, you can force ``bcfg2-info`` to perform it anyway with ``-f``:: bcfg2-info automatch -f props.xml foo.example.com .. note:: Be sure to notice that enabling automatch changes the type of the data in ``metadata.Properties``; with automatch disabled, the values of the ``metadata.Properties`` dict are :class:`Bcfg2.Server.Plugins.Properties.PropertyFile` objects. With automatch enabled, they are :class:`lxml.etree._Element` objects. .. _server-plugins-connectors-properties-encryption: Encrypted Properties data ========================= .. versionadded:: 1.3.0 You can encrypt selected data in XML Properties files to protect that data from other people who need access to the repository. See :ref:`server-encryption-configuration` 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. Encryption is only supported on XML properties files. .. 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. By default, decryption is *strict*; that is, if any element cannot be decrypted, parsing of the file is aborted. If you wish for parsing to continue, with unencryptable elements simply skipped, then you can set decryption to *lax* in one of two ways: * Set ``decrypt=lax`` in the ``[encryption]`` section of ``bcfg2.conf`` to set lax decryption on all files by default; or * Set the ``decrypt="lax"`` attribute on the top-level ``Properties`` tag of a Properties file to set lax decryption for a single file. Note that you could, for instance, set lax decryption by default, and then set strict decryption on individual files. To encrypt or decrypt a file, use :ref:`bcfg2-crypt`. See :ref:`server-encryption` for more details on encryption in Bcfg2 in general. Accessing Properties contents from Genshi Templates =================================================== 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. Module Documentation ==================== .. automodule:: Bcfg2.Server.Plugins.Properties