summaryrefslogtreecommitdiffstats
path: root/doc/server/plugins/generators/cfg.txt
blob: 7e7a7c72e5080f58b2c87940f16e3b64a3b1e544 (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
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
.. -*- mode: rst -*-
.. vim: ft=rst

.. _server-plugins-generators-cfg:

===
Cfg
===

The Cfg plugin provides a repository to describe configuration file
contents for clients. In its simplest form, the Cfg repository is just a
directory tree modeled off of the directory tree on your client machines.

The Cfg Repository
==================

The Cfg plugin is enabled by including **Cfg** on the **plugins** line of
the **[server]** section of your Bcfg2 server config file. The repository
itself lives in ``/var/lib/bcfg2/Cfg``, assuming you are using the default
repository location of ``/var/lib/bcfg2``. The contents of this directory
are a series of directories corresponding to the real-life locations of
the files on your clients, starting at the root level. For example::

    % ls Cfg
    bin/  boot/  etc/  opt/  root/  usr/  var/

Specific config files go in like-named directories in this
heirarchy.  For example the password file, ``/etc/passwd``, goes
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 templates -- see 
below).

Group-Specific Files
====================

It is often the case that you want one version of a config file for
all of your machines except those in a particular group. For example,
``/etc/fstab`` should look alike on all of your desktop machines, but
should be different on your file servers. Bcfg2 can handle this case
through use of group-specific files.

As mentioned above, all Cfg entries live in like-named directories
at the end of their directory tree. In the case of fstab, the file at
``Cfg/etc/fstab/fstab`` will be handed out by default to any client that
asks for a copy of ``/etc/fstab``. Group-specific files are located in
the same directory and are named with the following syntax::

    /path/to/filename/filename.GNN_groupname

**NN** is a priority number where **00** is lowest and **99**
is highest, and **groupname** is the name of a group defined in
``Metadata/groups.xml``. Back to our fstab example, we might have a
``Cfg/etc/fstab/`` directory that looks like this::

    fstab
    fstab.G50_server
    fstab.G99_fileserver

By default, clients will receive the plain fstab file when they request
``/etc/fstab``. Any machine that is in the **server** group, however, will
instead receive the ``fstab.G50_server`` file. Finally, any machine that
is in the **fileserver** group will receive the ``fstab.G99_fileserver``
file, even if they are also in the **server** group.

Host-Specific Files
===================

Similar to the case with group-specific files, there are cases where
a specific machine should have a different version of a file than all
others. This can be accomplished with host-specific files. The format
of a host-specific file name is::

    /path/to/filename/filename.H_host.example.com

Host-specific files have a higher priority than group specific
files. Again, the fstab example::

    fstab
    fstab.G50_server
    fstab.G99_fileserver
    fstab.H_host.example.com

In this case, *host.example.com* will always get the host-specific
version, even if it is part of the **server** or **fileserver** (or both)
classes.

.. note::

    If you have the ability to choose between using a group-specific and a
    host-specific file, it is almost always best to use a group-specific
    one. That way if a hostname changes or an extra copy of a particular
    client is built, it will get the same changes as the original.

Templates
=========

.. _server-plugins-generators-cfg-genshi:

Genshi Templates
----------------

Genshi templates allow you to use the `Genshi
<http://genshi.edgewall.org>`_ templating system.  Genshi templates
should be named with a ``.genshi`` extension, e.g.::

    % ls Cfg/etc/motd
    info.xml  motd.genshi

See the genshi `documentation
<http://genshi.edgewall.org/wiki/Documentation>`_ for examples of
Genshi syntax.

Troubleshooting
~~~~~~~~~~~~~~~

When developing a template, you can see what the template would
generate on a client with :ref:`bcfg2-info <server-bcfg2-info>`::

    bcfg2-info buildfile <path> <hostname>

E.g.::

    bcfg2-info buildfile /etc/foo.conf foo.example.com

To generate a file with an :ref:`altsrc
<server-plugins-structures-altsrc>` attribute, you can run::

    bcfg2-info buildfile /etc/foo/foo.conf --altsrc=/etc/foo.conf \
        foo.example.com

Sometimes, it's useful to be able to do more in-depth troubleshooting
by running the template manually. To do this, run ``bcfg2-info
debug``, and, once in the Python interpreter, run::

    metadata = self.build_metadata("<hostname>")
    source_path = "<full path to template>"
    name = source_path[len(self.setup['repo']):]

Then, run::

    import os
    from genshi.template import TemplateLoader, NewTextTemplate
    template = TemplateLoader().load(source_path, cls=NewTextTemplate)
    data = dict(metadata=metadata,
                source_path=source_path,
                path=source_path,
                name=name,
                repo=self.setup['repo'])
    print(template.generate(**data).render())

This gives you more fine-grained control over how your template is
rendered.  E.g., you can tweak the values of the variables passed to
the template, or evaluate the template manually, line-by-line, and so
on.

You can also use this approach to render templates that depend on
:ref:`altsrc <server-plugins-structures-altsrc>` tags by setting
``source_path`` to the path to the template, and setting ``name`` to the path
to the file to be generated, e.g.::

    metadata = self.build_metadata("foo.example.com")
    source_path = "/Cfg/etc/sysconfig/network-scripts/ifcfg-template/ifcfg-template.genshi"
    name = "/etc/sysconfig/network-scripts/ifcfg-bond0"

Error handling
~~~~~~~~~~~~~~

Situations may arise where a templated file cannot be generated due to
missing or incomplete information.  A TemplateError can be raised to
force a bind failure and prevent sending an incomplete file to the
client.  For example, this template::

    {% python
        from genshi.template import TemplateError
        grp = None
        for g in metadata.groups:
            if g.startswith('ganglia-gmond-'):
                grp = g
                break
        else:
            raise TemplateError, "Missing group"
    %}\

will fail to bind if the client is not a member of a group starting with
"ganglia-gmond-".  The syslogs on the server will contain this message::

    bcfg2-server[5957]: Genshi template error: Missing group
    bcfg2-server[5957]: Failed to bind entry: Path /etc/ganglia/gmond.conf

...indicating the bind failure and message raised with the TemplateError.

Handling Dollar Signs
~~~~~~~~~~~~~~~~~~~~~

In a Genshi template, ``$`` is a special character and must be escaped
by doubling, i.e., ``$$``.  For instance, to embed the Subversion
``$Id$`` keyword in a Genshi template, you would have to do ``$$Id$$``.

Examples
~~~~~~~~

.. toctree::
   :glob:
   :maxdepth: 1

   examples/genshi/*

.. _server-plugins-generators-cfg-cheetah:

Cheetah Templates
-----------------

Cheetah templates allow you to use the `cheetah templating system
<http://www.cheetahtemplate.org/>`_.  Cheetah templates should be
named with a ``.cheetah`` extension, e.g.::

    % ls Cfg/etc/motd
    info.xml  motd.cheetah

Examples
~~~~~~~~

.. toctree::
   :glob:
   :maxdepth: 1

   examples/cheetah/*

Comments and Cheetah
~~~~~~~~~~~~~~~~~~~~

As Cheetah processes your templates it will consider hash "#" style
comments to be actual comments in the template and will strip them
from the final config file.  If you would like to preserve the comment
in the final config file you need to escape the hash character '\#'
which will tell Cheetah (and Python) that you do in fact want the
comment to appear in the final config file.::

    # This is a comment in my template which will be stripped when it's processed through Cheetah
    \# This comment will appear in the generated config file.

.. _server-plugins-generators-cfg-jinja2:

Jinja2 Templates
-----------------

Jinja2 templates allow you to use the `jinja2 templating system
<http://jinja.pocoo.org/>`_.  Jinja2 templates should be
named with a ``.jinja2`` extension, e.g.::

    % ls Cfg/etc/motd
    info.xml  motd.jinja2

Examples
~~~~~~~~

.. toctree::
   :glob:
   :maxdepth: 1

   examples/jinja2/*

Inside Templates
----------------

Several variables are pre-defined inside templates:

+-------------+--------------------------------------------------------+
| Name        | Description                                            |
+=============+========================================================+
| metadata    | :ref:`Client metadata                                  |
|             | <server-plugins-grouping-metadata-clientmetadata>`     |
+-------------+--------------------------------------------------------+
| name        | The value of the ``name`` attribute as specified in    |
|             | the Path entry in Bcfg2.                               |
+-------------+--------------------------------------------------------+
| source_path | The path to the template file on the filesystem        |
+-------------+--------------------------------------------------------+
| repo        | The path to the Bcfg2 repository on the filesystem     |
+-------------+--------------------------------------------------------+
| path        | In Genshi templates, ``path`` is a synonym for         |
|             | ``source_path``.  In Cheetah templates and Jinja2      |
|             | templates, it's a synonym for ``name``.  For this      |
|             | reason, use of ``path`` is discouraged, and it may be  |
|             | deprecated in a future release.                        |
+-------------+--------------------------------------------------------+

To access these variables in a Genshi template, you can simply use the
name, e.g.::

    Path to this file: ${name}

Similarly, in a Jinja2 template::

	Path to this file: {{ name }}

In a Cheetah template, the variables are properties of ``self``,
e.g.::

    Path to this file: $self.name

Notes on Using Templates
------------------------

Templates can be host and group specific as well.  Deltas will not be
processed for any Genshi, Cheetah, or Jinja2 base file.

.. note::

    If you are using templating in combination with host-specific
    or group-specific files, you will need to ensure that the ``.genshi``
    ``.cheetah`` or ``.jinja2`` extension is at the **end** of the filename. 
    Using the examples from above for *host.example.com* and group *server*
    you would have the following::

        Cfg/etc/fstab/fstab.H_host.example.com.genshi
        Cfg/etc/fstab/fstab.G50_server.cheetah

You can mix Genshi and Cheetah when using different host-specific or
group-specific files.  For example::

    Cfg/etc/fstab/fstab.H_host.example.com.genshi
    Cfg/etc/fstab/fstab.G50_server.cheetah

.. _server-plugins-generators-cfg-encryption:

Encrypted Files
===============

.. versionadded:: 1.3.0

Bcfg2 allows you to encrypt files stored in ``Cfg/`` to protect the
data in them from other people who need access to the repository.  See
also :ref:`server-plugins-connectors-properties-encryption` for
information on encrypting elements in Properties files, which is often
more friendly for tracking changes in a VCS.

.. 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.

See :ref:`server-encryption` for more details on encryption in Bcfg2
in general.

Encrypting Files
----------------

An encrypted file should end with ``.crypt``, e.g.::

    Cfg/etc/foo.conf
    Cfg/etc/foo.conf/foo.conf.crypt
    Cfg/etc/foo.conf/foo.conf.G10_foo.crypt

Encrypted Genshi, Cheetah, and Jinja2 templates can have the extensions in
either order, e.g.::

    Cfg/etc/foo.conf/foo.conf.crypt.genshi
    Cfg/etc/foo.conf/foo.conf.G10_foo.genshi.crypt
    Cfg/etc/foo.conf/foo.conf.H_bar.example.com.crypt.cheetah

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:

See :ref:`server-encryption` for more details on encryption in Bcfg2
in general.

``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">
        <Option name="command" value="/home/foo_user/.ssh/ssh_command_filter"/>
        <Option name="no-X11-forwarding"/>
      </Allow>
      <Allow>
        ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDw/rgKQeARRAHK5bQQhAAe1b+gzdtqBXWrZIQ6cIaLgxqj76TwZ3DY4A6aW9RgC4zzd0p4a9MfsScUIB4+UeZsx9GopUj4U6H8Vz7S3pXxrr4E9logVLuSfOLFbI/wMWNRuOANqquLYQ+JYWKeP4kagkVp0aAWp7mH5IOI0rp0A6qE2you4ep9N/nKvHDrtypwhYBWprsgTUXXMHnAWGmyuHGYWxNYBV9AARPdAvZfb8ggtuwibcOULlyK4DdVNbDTAN1/BDBE1ve6WZDcrc386KhqUGj/yoRyPjNZ46uZiOjRr3cdY6yUZoCwzzxvm5vle6mEbLjHgjGEMQMArzM9 vendor@example.com
      </Allow>
    </AuthorizedKeys>

.. note::

    ``authorized_keys.xml`` allows you to specify the group whose
    public key should be allowed.  This retrieves the public key
    specific to that group (if it exists), *not* the public key for
    all hosts in that group.  This is due to the performance penalties
    that would be imposed by that approach.

    Similarly, it is not possible to allow access from all keys for a
    given user (i.e., at a given path).

    Hopefully, the performance concerns can be resolved in a future
    release and these features can be added.

.. _server-plugins-generators-cfg-ssl-certificates:

SSL Keys and Certificates
=========================

Cfg can also create SSL keys and certs on the fly, and store the
generated data in the repo so that subsequent requests do not result
in repeated key/cert recreation.  In the event that a new key or cert
is needed, the old file can simply be removed from the
repository, and the next time that host checks in, a new file will be
created.  If that file happens to be the key, any dependent
certificates will also be regenerated.

See also :ref:`appendix-guides-sslca_howto` for a detailed example
that uses the SSL key management feature to automate Bcfg2 certificate
authentication.

Getting started
---------------

In order to use the SSL certificate generation feature, you must first
have at least one CA configured on your system.  For details on
setting up your own OpenSSL based CA, please see
http://www.openssl.org/docs/apps/ca.html for details of the suggested
directory layout and configuration directives.

For SSL cert generation to work, the openssl.cnf (or other
configuration file) for that CA must contain full (not relative)
paths.

#. Add a section to your ``/etc/bcfg2.conf`` called ``sslca_foo``,
   replacing foo with the name you wish to give your CA so you can
   reference it in certificate definitions.  (If you only have one CA,
   you can name it ``sslca_default``, and it will be the default CA
   for all other operations.)

#. Under that section, add a ``config`` option that gives the location
   of the ``openssl.cnf`` file for your CA.

#. If necessary, add a ``passphrase`` option containing the passphrase
   for the CA's private key.  If no passphrase is entry exists, it is
   assumed that the private key is stored unencrypted.

#. Optionally, add a ``chaincert`` option that points to the location
   of your ssl chaining certificate.  This is used when preexisting
   certificate hostfiles are found, so that they can be validated and
   only regenerated if they no longer meet the specification. If
   you're using a self signing CA this would be the CA cert that you
   generated.  If the chain cert is a root CA cert (e.g., if it is a
   self-signing CA), also add an entry ``root_ca = true``.  If
   ``chaincert`` is omitted, certificate verification will not be
   performed.

#. Once all this is done, you should have a section in your
   ``/etc/bcfg2.conf`` that looks similar to the following::

       [sslca_default]
       config = /etc/pki/CA/openssl.cnf
       passphrase = youReallyThinkIdShareThis?
       chaincert = /etc/pki/CA/chaincert.crt
       root_ca = true

#. You are now ready to create key and certificate definitions.  For
   this example we'll assume you've added Path entries for the key,
   ``/etc/pki/tls/private/localhost.key``, and the certificate,
   ``/etc/pki/tls/certs/localhost.crt`` to a bundle.

#. Within the ``Cfg/etc/pki/tls/private/localhost.key`` directory,
   create a `sslkey.xml`_ file containing the following:

   .. code-block:: xml

       <KeyInfo/>

#. This will cause the generation of an SSL key when a client requests
   that Path.  (By default, it will be a 2048-bit RSA key; see
   `sslkey.xml`_ for details on how to change the key type and size.)

#. Similarly, create `sslcert.xml`_ in
   ``Cfg/etc/pki/tls/certs/localhost.cfg/``, containing the following:

   .. code-block:: xml

       <CertInfo>
         <Cert key="/etc/pki/tls/private/localhost.key" ca="foo"/>
       </CertInfo>

#. When a client requests the cert path, a certificate will be
   generated using the key hostfile at the specified key location,
   using the CA matching the ``ca`` attribute. ie. ``ca="foo"`` will
   match ``[sslca_default]`` in your ``/etc/bcfg2.conf``

The :ref:`Bcfg2 bundle example
<server-plugins-structures-bundler-bcfg2-server>` contains entries to
automate the process of setting up a CA.

Configuration
-------------

``bcfg2.conf``
~~~~~~~~~~~~~~

In ``bcfg2.conf``, you must declare your CA(s) in ``[sslca_<name>]``
sections.  At least one is required.  Valid options are detailed
below, in `Cfg Configuration`_.

Only the ``config`` option is required; i.e., the simplest possible CA
section is::

    [sslca_default]
    config = /etc/pki/CA/openssl.cnf

``sslcert.xml``
~~~~~~~~~~~~~~~

.. xml:schema:: sslca-cert.xsd
   :linktotype:
   :inlinetypes: CertType

Example
^^^^^^^

.. code-block:: xml

    <CertInfo>
      <subjectAltName>test.example.com</subjectAltName>
      <Group name="apache">
        <Cert key="/etc/pki/tls/private/foo.key" days="730"/>
      </Group>
      <Group name="nginx">
        <Cert key="/etc/pki/tls/private/foo.key" days="730"
              append_chain="true"/>
      </Group>
    </CertInfo>

``sslkey.xml``
~~~~~~~~~~~~~~

.. xml:schema:: sslca-key.xsd
   :linktotype:
   :inlinetypes: KeyType

Example
^^^^^^^

.. code-block:: xml

    <KeyInfo>
      <Group name="fast">
        <Key type="rsa" bits="1024"/>
      </Group>
      <Group name="secure">
        <Key type="rsa" bits="4096"/>
      </Group>
    </KeyInfo>


.. _server-plugins-generators-cfg-validation:

Content Validation
==================

To ensure that files with invalid content are not pushed out, you can
provide a content validation script that will be run against each
file.  Create a file called ``:test`` inside the directory for the
file you want to test.  For example::

  Cfg/etc/sudoers/:test

You can also create host- and group-specific validators::

  Cfg/etc/sudoers/:test.G80_foogroup
  Cfg/etc/sudoers/:test.H_bar.example.com

A validator script has the following attributes:

* It must be executable, or specify a valid bangpath;
* The entire content of the file is passed to the validator on
  stdin;
* The validator is not called with any flags or arguments;
* The validator must return 0 on success and non-zero on failure; and
* The validator must output a sensible error message on failure.

For ``sudoers``, a very simple validator is::

  #!/bin/sh
  visudo -cf -

This uses the ``visudo`` command's built-in validation.

If you wish to disable validation, this can be done with the following
setting in ``bcfg2.conf``::

  [cfg]
  validation=no

If you have a very large number of validators, you may wish to disable
validation by default to avoid slowing down the generation of
configurations on the server, and use ``bcfg2-test`` (for instance, as
a post-commit hook or as part of a code review process) to run
validation.  You can do this by setting ``validation=no`` in
``bcfg2.conf`` as described above, and then calling ``bcfg2-test``
with the ``--cfg-validation`` flag.

File permissions
================

File permissions for entries handled by Cfg are controlled via the use
of :ref:`server-info` files. Note that you **cannot** use both a
Permissions entry and a Path entry to handle the same file.

.. _server-plugins-generators-cfg-configuration:

Cfg Configuration
=================

The behavior of many bits of the Cfg plugin can be configured in
``bcfg2.conf`` with the following options.

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 the ``[sshkeys]`` section of
``bcfg2.conf``:

+-------------+----------------+---------------------------------------------------------+-----------------------+------------+
| Section     | Option         | Description                                             | Values                | Default    |
+=============+================+=========================================================+=======================+============+
| ``cfg``     | ``passphrase`` | Use the named passphrase to encrypt created data on the | String                | None       |
|             |                | filesystem. (E.g., SSH and SSL keys.) The passphrase    |                       |            |
|             |                | must be defined in the ``[encryption]`` section.        |                       |            |
+-------------+----------------+---------------------------------------------------------+-----------------------+------------+
| ``cfg``     | ``category``   | Generate data (e.g., SSH keys, SSL keys and certs)      | String                | None       |
|             |                | specific to groups in the given category. It is best to |                       |            |
|             |                | pick a category that all clients have a group from.     |                       |            |
+-------------+----------------+---------------------------------------------------------+-----------------------+------------+
| ``cfg``     | ``validation`` | Whether or not to perform `Content Validation`_         | Boolean               | True       |
|             |                | specific to groups in the given category. It is best to |                       |            |
|             |                | pick a category that all clients have a group from.     |                       |            |
+-------------+----------------+---------------------------------------------------------+-----------------------+------------+
| ``sshkeys`` | ``passphrase`` | Override the global Cfg passphrase with a specific      | String                | None       |
|             |                | passphrase for encrypting created SSH private keys.     |                       |            |
+-------------+----------------+---------------------------------------------------------+-----------------------+------------+
| ``sshkeys`` | ``category``   | Override the global Cfg category with a specific        | String                | None       |
|             |                | category for created SSH keys.                          |                       |            |
+-------------+----------------+---------------------------------------------------------+-----------------------+------------+
| ``sslca``   | ``passphrase`` | Override the global Cfg passphrase with a specific      | String                | None       |
|             |                | passphrase for encrypting created SSL keys.             |                       |            |
+-------------+----------------+---------------------------------------------------------+-----------------------+------------+
| ``sslca``   | ``category``   | Override the global Cfg category with a specific        | String                | None       |
|             |                | category for created SSL keys and certs.                |                       |            |
+-------------+----------------+---------------------------------------------------------+-----------------------+------------+
| ``sslca_*`` | ``config``     | Path to the openssl config for the CA                   | String                | None       |
+-------------+----------------+---------------------------------------------------------+-----------------------+------------+
| ``sslca_*`` | ``passphrase`` | Passphrase for the CA private key                       | String                | None       |
+-------------+----------------+---------------------------------------------------------+-----------------------+------------+
| ``sslca_*`` | ``chaincert``  | Path to the SSL chaining certificate for verification   | String                | None       |
+-------------+----------------+---------------------------------------------------------+-----------------------+------------+
| ``sslca_*`` | ``root_ca``    | Whether or not ``<chaincert>`` is a root CA (as         | Boolean               | False      |
|             |                | opposed to an intermediate cert)                        |                       |            |
+-------------+----------------+---------------------------------------------------------+-----------------------+------------+

See :ref:`server-encryption` for more details on encryption in Bcfg2
in general.