clients.xml

As submitted by dclark

Here is an example of maintaining the bcfg2 server’s /var/lib/bcfg2/Metadata/clients.xml file using Genshi templates.

There are two main advantages:

  1. Password storage is centralized in the Properties/passwords.xml file this helps maintain consistency, makes changing passwords easier, and also makes it easier to share your configurations with other sites/people.
  2. You can template the file using Genshi’s {% def %} syntax, which makes clients.xml much more readable. An important thing to note is how the name variable is handled - when just referring to it the standard ${name} syntax is used, but when it is used as a variable in the expression to get the password, password=”${metadata.Properties[‘passwords.xml’].xdata.find(‘password’).find(‘bcfg2-client’).find(name).text}”, it is just referred to as name.

There is the disadvantage that sometimes 2 passes will be needed to get to a consistent state.

Possible improvements:

  1. Wrapper for bcfg2 client runs on the bcfg2 server, perhaps using a call to bcfg2-info buildfile, so clients.xml is always generated before everything else happens (since the state of clients.xml can influence everything else bcfg2-server does).
  2. We really don’t care what the client passwords are, just that they exist, so instead of listing them a master password combined with some kind of one-way hash based on the name might make more sense, and make Properties/passwords.xml easier to maintain.
  • Cfg/var/lib/bcfg2/Metadata/clients.xml/clients.xml.genshi:

    <!-- Do not edit this file directly - edit only the above template -->
    
    {# Doc: http://bcfg2.org/wiki/Authentication #}\
    {% def static(profile,name,address) %}
        <Client
            profile="${profile}"
            name="${name}"
            uuid="${name}"
            password="${metadata.Properties['passwords.xml'].xdata.find('password').find('bcfg2-client').find(name).text}"
            address="${address}"
            location="fixed"
            secure="true"
        />\
    {% end %}\
    {% def dynamic(profile,name) %}
        <Client
            profile="${profile}"
            name="${name}"
            uuid="${name}"
            password="${metadata.Properties['passwords.xml'].xdata.find('password').find('bcfg2-client').find(name).text}"
            floating="true"
            secure="true"
        />\
    {% end %}\
    <Clients version="3.0">\
        ${static('group-server-collab','campaigns.example.com','192.168.111.1')}
        ${static('group-server-collab','info.office.example.com','192.168.111.2')}
        ${static('group-server-config','config.example.com','192.168.111.3')}
        ${dynamic('group-project-membercard','membercard')}
        ${dynamic('group-person-somename','somename.office.example.com')}
    </Clients>
    
  • Properties/passwords.xml snippit:

    <Properties>
            <password>
                    <bcfg2-client>
                            <campaigns.example.com>FAKEpassword1</campaigns.example.com>
                            <info.office.example.com>FAKEpassword2</info.office.example.com>
                            <config.example.com>FAKEpassword3</config.example.com>
                            <membercard>FAKEpassword4</membercard>
                            <somename.office.example.com>FAKEpassword5</somename.office.example.com>
                    </bcfg2-client>
            </password>
    </Properties>