summaryrefslogtreecommitdiffstats
path: root/doc
diff options
context:
space:
mode:
authorChris St. Pierre <chris.a.st.pierre@gmail.com>2013-01-03 13:40:24 -0600
committerChris St. Pierre <chris.a.st.pierre@gmail.com>2013-01-03 13:40:24 -0600
commit14406cc14a4d832fe83df5da27937051e41dd093 (patch)
tree1fb429513bc5483251412af8251aa24517bcbb68 /doc
parent10326a34dd813b88c6c8816115e91977a93a1f10 (diff)
downloadbcfg2-14406cc14a4d832fe83df5da27937051e41dd093.tar.gz
bcfg2-14406cc14a4d832fe83df5da27937051e41dd093.tar.bz2
bcfg2-14406cc14a4d832fe83df5da27937051e41dd093.zip
Cfg: Added feature to provide generation of SSH keys, authorized_keys file
Diffstat (limited to 'doc')
-rw-r--r--doc/development/cfg.txt16
-rw-r--r--doc/exts/xmlschema.py37
-rw-r--r--doc/server/plugins/generators/cfg.txt215
3 files changed, 254 insertions, 14 deletions
diff --git a/doc/development/cfg.txt b/doc/development/cfg.txt
index ba71232e7..6533e0d7a 100644
--- a/doc/development/cfg.txt
+++ b/doc/development/cfg.txt
@@ -20,10 +20,11 @@ implement more than one handler type.
Cfg Handler Types
=================
-There are four different types of Cfg handlers. A new handler must
+There are several different types of Cfg handlers. A new handler must
inherit either from one of these classes, or from an existing handler.
.. autoclass:: Bcfg2.Server.Plugins.Cfg.CfgGenerator
+.. autoclass:: Bcfg2.Server.Plugins.Cfg.CfgCreator
.. autoclass:: Bcfg2.Server.Plugins.Cfg.CfgFilter
.. autoclass:: Bcfg2.Server.Plugins.Cfg.CfgInfo
.. autoclass:: Bcfg2.Server.Plugins.Cfg.CfgVerifier
@@ -43,6 +44,7 @@ Cfg Exceptions
Cfg handlers may produce the following exceptions:
.. autoexception:: Bcfg2.Server.Plugins.Cfg.CfgVerificationError
+.. autoexception:: Bcfg2.Server.Plugins.Cfg.CfgCreationError
In addition, Cfg handlers may produce the following base plugin
exceptions:
@@ -53,10 +55,11 @@ exceptions:
.. autoexception:: Bcfg2.Server.Plugin.exceptions.PluginInitError
:noindex:
-Accessing Configuration Options
-===============================
+Global Variables
+================
.. autodata:: Bcfg2.Server.Plugins.Cfg.SETUP
+.. autodata:: Bcfg2.Server.Plugins.Cfg.CFG
Existing Cfg Handlers
=====================
@@ -70,6 +73,13 @@ Generators
.. autoclass:: Bcfg2.Server.Plugins.Cfg.CfgEncryptedGenerator.CfgEncryptedGenerator
.. autoclass:: Bcfg2.Server.Plugins.Cfg.CfgEncryptedGenshiGenerator.CfgEncryptedGenshiGenerator
.. autoclass:: Bcfg2.Server.Plugins.Cfg.CfgEncryptedCheetahGenerator.CfgEncryptedCheetahGenerator
+.. autoclass:: Bcfg2.Server.Plugins.Cfg.CfgAuthorizedKeysGenerator.CfgAuthorizedKeysGenerator
+
+Creators
+--------
+
+.. autoclass:: Bcfg2.Server.Plugins.Cfg.CfgPrivateKeyCreator.CfgPrivateKeyCreator
+.. autoclass:: Bcfg2.Server.Plugins.Cfg.CfgPublicKeyCreator.CfgPublicKeyCreator
Filters
-------
diff --git a/doc/exts/xmlschema.py b/doc/exts/xmlschema.py
index fc5788107..81affc610 100644
--- a/doc/exts/xmlschema.py
+++ b/doc/exts/xmlschema.py
@@ -299,15 +299,24 @@ class XMLDocumentor(object):
def document_complexType(self):
rv = nodes.definition_list()
+ content = self.entity.find("xs:simpleContent", namespaces=NSMAP)
+ if content is not None:
+ base = content.xpath("xs:extension|xs:restriction",
+ namespaces=NSMAP)[0]
+ attr_container = base
+ else:
+ base = None
+ attr_container = self.entity
+
##### ATTRIBUTES #####
table, tbody = self.get_attr_table()
- attrs = self.get_attrs(self.entity)
+ attrs = self.get_attrs(attr_container)
if attrs:
tbody.extend(attrs)
foreign_attr_groups = nodes.bullet_list()
- for agroup in self.entity.xpath("xs:attributeGroup",
- namespaces=NSMAP):
+ for agroup in attr_container.xpath("xs:attributeGroup",
+ namespaces=NSMAP):
# if the attribute group is in another namespace, just
# link to it
ns, name = self.split_ns(agroup.get('ref'))
@@ -349,11 +358,17 @@ class XMLDocumentor(object):
append_node(rv, nodes.definition, *groups)
##### TEXT CONTENT #####
- if (self.include['text'] and
- self.entity.get("mixed", "false").lower() == "true"):
- append_node(rv, nodes.term, text("Text content:"))
- append_node(rv, nodes.definition,
- build_paragraph(self.get_values_from_simpletype()))
+ if self.include['text']:
+ if self.entity.get("mixed", "false").lower() == "true":
+ append_node(rv, nodes.term, text("Text content:"))
+ append_node(rv, nodes.definition,
+ build_paragraph(self.get_values_from_simpletype()))
+ elif base is not None:
+ append_node(rv, nodes.term, text("Text content:"))
+ append_node(
+ rv, nodes.definition,
+ build_paragraph(self.get_values_from_simpletype(content)))
+
return [rv]
def document_attributeGroup(self):
@@ -544,8 +559,10 @@ class XMLDocumentor(object):
if entity is None:
entity = self.entity
# todo: xs:union, xs:list
- restriction = entity.find("xs:restriction", namespaces=NSMAP)
- if restriction is None:
+ try:
+ restriction = entity.xpath("xs:restriction|xs:extension",
+ namespaces=NSMAP)[0]
+ except IndexError:
return "Any"
doc = self.get_doc(restriction)
if len(doc) == 1 and len(doc[0]) == 0:
diff --git a/doc/server/plugins/generators/cfg.txt b/doc/server/plugins/generators/cfg.txt
index 94394f98f..a33028a13 100644
--- a/doc/server/plugins/generators/cfg.txt
+++ b/doc/server/plugins/generators/cfg.txt
@@ -29,7 +29,7 @@ in ``Cfg/etc/passwd/passwd``, while the ssh pam module config file,
``/etc/pam.d/sshd``, goes in ``Cfg/etc/pam.d/sshd/sshd``. The reason for
the like-name directory is to allow multiple versions of each file to
exist, as described below. Note that these files are exact copies of what
-will appear on the client machine (except when using genshi or cheetah
+will appear on the client machine (except when using Genshi or Cheetah
templating -- see below).
Group-Specific Files
@@ -355,6 +355,219 @@ either order, e.g.::
To encrypt or decrypt a file, use :ref:`bcfg2-crypt`.
+.. _server-plugins-generators-cfg-sshkeys:
+
+SSH Keys
+========
+
+.. versionadded:: 1.3.0
+
+Cfg can also be used to automatically create and distribute SSH key
+pairs and the ``authorized_keys`` file.
+
+Keys can be created one of two ways:
+
+* Host-specific keys, where each client has its own key pair. This is
+ the default.
+* Group-specific keys. To do this, you must set ``category`` in
+ either ``bcfg2.conf`` (see "Configuration" below) or in
+ ``privkey.xml``. Keys created for a given client will be specific
+ to that client's group in the specified category.
+
+Group-specific keys are useful if, for instance, you have multiple
+distinct environments (development, testing, production, for example)
+and want to maintain separate keys for each environment.
+
+This feature actually creates static keys, much like the
+:ref:`server-plugins-generators-sshbase` plugin creates SSH
+certificates. It doesn't generate them on the fly for each request;
+it generates the key once, then saves it to the filesystem.
+
+Creating key pairs
+------------------
+
+To create an SSH key pair, you need to define how the private key will
+be created in ``privkey.xml``. For instance, to create
+``/home/foo/.ssh/id_rsa``, you would create
+``/var/lib/bcfg2/Cfg/home/foo/.ssh/id_rsa/privkey.xml``.
+
+This will create *both* the private key and the public key; the latter
+is created by appending ``.pub`` to the private key filename. It is
+not possible to change the public key filename.
+
+You may *optionally* also create a corresponding ``pubkey.xml``, which
+will allow the key pair to be created when the public key is
+requested. (For the example above, you'd create
+``/var/lib/bcfg2/Cfg/home/foo/.ssh/id_rsa.pub/pubkey.xml``. This can
+speed up the propagation of SSH keys throughout your managed systems,
+particularly if you use the ``authorized_keys`` generation feature.
+
+``privkey.xml``
+~~~~~~~~~~~~~~~
+
+``privkey.xml`` contains a top-level ``PrivateKey`` element, and is
+structured as follows:
+
+.. xml:element:: PrivateKey
+ :linktotype:
+
+``pubkey.xml``
+~~~~~~~~~~~~~~~
+
+``pubkey.xml`` only ever contains a single line:
+
+.. code-block:: xml
+
+ <PublicKey/>
+
+.. xml:element:: PublicKey
+
+It acts only as a flag to Bcfg2 that a key pair should be generated, if
+none exists, using the associated ``privkey.xml`` file. The path to
+``privkey.xml`` is determined by removing ``.pub`` from the directory
+containing ``pubkey.xml``. I.e., if you create
+``/var/lib/bcfg2/Cfg/home/foo/.ssh/id_rsa.pub/pubkey.xml``, then Bcfg2
+will use ``/var/lib/bcfg2/Cfg/home/foo/.ssh/id_rsa/privkey.xml`` to
+create the key pair.
+
+Use of ``pubkey.xml`` is optional, but is recommended. If you do not
+use ``pubkey.xml`` files, you may encounter two problems:
+
+* On the first Bcfg2 client run on a given client, the private keys
+ may be present but the public keys may not be. This will be fixed
+ by running ``bcfg2`` again.
+* If you are including an automatically created public key in
+ ``authorized_keys``, it will not be created until the client the key
+ is for requests the key pair.
+
+As an example of this latter scenario, suppose that your
+``authorized_keys.xml`` allows access to foo.example.com from
+``/root/.ssh/id_rsa.pub`` for bar.example.com. If bar.example.com has
+not run the Bcfg2 client, then no key pair will have been generated,
+and generating the foo.example.com ``authorized_keys`` file will
+create a warning. But if you create
+``Cfg/root/.ssh/id_rsa.pub/pubkey.xml``, then building
+``authorized_keys`` for foo.example.com will create root's keypair for
+bar.example.com.
+
+.. note::
+
+ In order to use ``pubkey.xml``, there *must* be a corresponding
+ ``privkey.xml``. You cannot, for instance, populate a directory
+ with manually-generated private SSH keys, drop ``pubkey.xml`` in
+ the related public key directory, and expect Bcfg2 to generate the
+ public keys. It will not.
+
+Examples
+~~~~~~~~
+
+``privkey.xml`` can, at its simplest, be very simple indeed:
+
+.. code-block:: xml
+
+ <PrivateKey/>
+
+This will create a private key with all defaults. Or it can be more
+complex:
+
+.. code-block:: xml
+
+ <PrivateKey category="environment"/>
+ <Params bits="1024" type="dsa"/>
+ <Group name="secure">
+ <Passphrase encrypted="secure">U2FsdGVkX19xACol83uyPELP94s4CmngD12oU6PLLuE=</Passphrase>
+ </Group>
+ </PrivateKey>
+
+This creates a 1024-bit DSA key for each group in the ``environment``
+category, and keys for clients in the ``secure`` group will be
+protected with the given (encrypted) passphrase.
+
+To complete the example, assume that this file was saved at
+``/var/lib/bcfg2/Cfg/home/foo/.ssh/id_rsa/privkey.xml``. If a client
+in the ``development`` group, which is a group in the ``environment``
+category, requests the private key, then the following files would be
+created::
+
+ /var/lib/bcfg2/Cfg/home/foo/.ssh/id_rsa/id_rsa.G50_development
+ /var/lib/bcfg2/Cfg/home/foo/.ssh/id_rsa.pub/id_rsa.pub.G50_development
+
+``/var/lib/bcfg2/Cfg/home/foo/.ssh/id_rsa.pub`` would be created if it
+did not exist.
+
+Subsequent clients that were also members of the ``development``
+environment would get the keys that have already been generated.
+
+``pubkey.xml`` always contains a single empty tag:
+
+.. code-block:: xml
+
+ <PublicKey/>
+
+Generating ``authorized_keys``
+------------------------------
+
+``authorized_keys`` can be automatically generated from public SSH
+keys that exist in the Cfg tree. The keys in question can be
+generated from ``privkey.xml``, or they can be manually created.
+
+If a key doesn't exist when ``authorized_keys`` is generated, the key
+will only be created if ``pubkey.xml`` exists. If that is not the
+case, a warning will be produced.
+
+To generate ``authorized_keys``, create ``authorized_keys.xml``, e.g.:
+``/var/lib/bcfg2/Cfg/root/.ssh/authorized_keys/authorized_keys.xml``.
+
+``authorized_keys.xml``
+~~~~~~~~~~~~~~~~~~~~~~~
+
+``authorized_keys.xml`` is structured as follows:
+
+.. xml:element:: AuthorizedKeys
+ :linktotype:
+
+Example
+~~~~~~~
+
+.. code-block:: xml
+
+ <AuthorizedKeys>
+ <Group name="some_group">
+ <Allow from="/root/.ssh/id_rsa.pub"/>
+ <Allow from="/root/.ssh/id_rsa.pub" group="test"/>
+ </Group>
+ <Allow from="/root/.ssh/id_rsa.pub" host="foo.example.com"/>
+ <Allow from="/home/foo_user/.ssh/id_rsa.pub">
+ <Params command="/home/foo_user/.ssh/ssh_command_filter"/>
+ </Allow>
+ <Allow>
+ ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDw/rgKQeARRAHK5bQQhAAe1b+gzdtqBXWrZIQ6cIaLgxqj76TwZ3DY4A6aW9RgC4zzd0p4a9MfsScUIB4+UeZsx9GopUj4U6H8Vz7S3pXxrr4E9logVLuSfOLFbI/wMWNRuOANqquLYQ+JYWKeP4kagkVp0aAWp7mH5IOI0rp0A6qE2you4ep9N/nKvHDrtypwhYBWprsgTUXXMHnAWGmyuHGYWxNYBV9AARPdAvZfb8ggtuwibcOULlyK4DdVNbDTAN1/BDBE1ve6WZDcrc386KhqUGj/yoRyPjNZ46uZiOjRr3cdY6yUZoCwzzxvm5vle6mEbLjHgjGEMQMArzM9 vendor@example.com
+ </Allow>
+ </AuthorizedKeys>
+
+Configuration
+-------------
+
+In addition to ``privkey.xml`` and ``authorized_keys.xml``, described
+above, the behavior of the SSH key generation feature can be
+influenced by several options in ``bcfg2.conf``:
+
++----------------+---------------------------------------------------------+-----------------------+------------+
+| Option | Description | Values | Default |
++================+=========================================================+=======================+============+
+| ``passphrase`` | Use the named passphrase to encrypt private keys on the | String | None |
+| | filesystem. The passphrase must be defined in the | | |
+| | ``[encryption]`` section. See :ref:`server-encryption` | | |
+| | for more details on encryption in Bcfg2 in general. | | |
++----------------+---------------------------------------------------------+-----------------------+------------+
+| ``category`` | Generate keys specific to groups in the given category. | String | None |
+| | It is best to pick a category that all clients have a | | |
+| | group from. | | |
++----------------+---------------------------------------------------------+-----------------------+------------+
+| ``decrypt`` | If decrypt is set to ``lax``, then a key that cannot be | ``strict`` or ``lax`` | ``strict`` |
+| | decrypted will produce a warning instead of an error. | | |
++----------------+---------------------------------------------------------+-----------------------+------------+
+
Deltas
======