Permalink
Browse files

Updated docs for fedmsg.crypto.

  • Loading branch information...
ralphbean committed Sep 6, 2012
1 parent 11460bb commit b39e6cfe1857487ddf975413db4d64fb8d0be70c
Showing with 169 additions and 24 deletions.
  1. +1 −0 .gitignore
  2. +87 −0 doc/config.rst
  3. +6 −8 doc/crypto.rst
  4. +4 −2 doc/index.rst
  5. +71 −14 fedmsg/crypto.py
View
@@ -7,3 +7,4 @@ dist
*.pdf
_build
html-output
+htmldoc
View
@@ -0,0 +1,87 @@
+Configuration
+=============
+
+.. automodule:: fedmsg.config
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+Glossary of Configuration Values
+--------------------------------
+
+.. glossary::
+
+ sign_messages
+ ``bool`` - If set to true, then :mod:`fedmsg.core` will try to sign
+ every message sent using the machinery from :mod:`fedmsg.crypto`.
+
+ It is often useful to set this to `False` when developing. You may not
+ have X509 certs or the tools to generate them just laying around. If
+ disabled, you will likely want to also disable
+ :term:`validate_signatures`.
+
+ validate_signatures
+ ``bool`` - If set to true, then the base class
+ :class:`fedmsg.consumers.FedmsgConsumer` will try to use
+ :func:`fedmsg.crypto.validate` to validate messages before handing
+ them off to the particular consumer for which the message is bound.
+
+ This is also used by :mod:`fedmsg.text` to denote trustworthiness
+ in the natural language representations produced by that module.
+
+ ssldir
+ ``str`` - This should be directory on the filesystem
+ where the certificates used by :mod:`fedmsg.crypto` can be found.
+ Typically ``/etc/pki/fedmsg/``.
+
+ crl_location
+ ``str`` - This should be a URL where the certificate revocation list can
+ be found. This is checked by :function:`fedmsg.crypto.validate` and
+ cached on disk.
+
+ crl_cache
+ ``str`` - This should be the path to a filename on the filesystem where
+ the CRL downloaded from :term:`crl_location` can be saved. The python
+ process should have write access there.
+
+ crl_cache_expiry
+ ``int`` - Number of seconds to keep the CRL cached before checking
+ :term:`crl_location` for a new one.
+
+ certnames
+ ``dict`` - This should be a mapping of certnames to cert prefixes.
+
+ The keys should be of the form ``<service>.<host>``. For example:
+ ``bodhi.app01``.
+
+ The values should be the prefixes of cert/key pairs to be found in
+ :term:`ssldir`. For example, if
+ ``bodhi-app01.stg.phx2.fedoraproject.org.crt`` and
+ ``bodhi-app01.stg.phx2.fedoraproject.org.key`` are to be found in
+ :term:`ssldir`, then the value
+ ``bodhi-app01.stg.phx2.fedoraproject.org`` should appear in the
+ :term:`certnames` dict.
+
+ Putting it all together, this value could be specified as follows::
+
+ certnames={
+ "bodhi.app01": "bodhi-app01.stg.phx2.fedoraproject.org",
+ # ... other certname mappings may follow here.
+ }
+
+ .. note::
+
+ This is one of the most cumbersome parts of fedmsg. The reason we
+ have to enumerate all these redundant mappings between
+ "service.hostname" and "service-fqdn" has to do with the limitations
+ of reverse dns lookup. Case in point, try running the following on
+ app01.stg inside Fedora Infrastructure's environment.
+
+ >>> import socket
+ >>> print socket.getfqdn()
+
+ You might expect it to print "app01.stg.phx2.fedoraproject.org", but
+ it doesn't. It prints "memcached04.phx2.fedoraproject.org". Since
+ we can't rely on programatically extracting the fully qualified
+ domain names of the host machine during runtime, we need to
+ explicitly list all of the certs in the config.
View
@@ -1,9 +1,7 @@
-Use of X509 Certs
-=================
+Cryptography and Message Signing
+================================
-TODO - this has yet to be written.
-
-For now, check out the doc strings at
-https://github.com/ralphbean/fedmsg/blob/develop/fedmsg/crypto.py
-
-They're actually pretty good. :)
+.. automodule:: fedmsg.crypto
+ :members:
+ :undoc-members:
+ :show-inheritance:
View
@@ -7,9 +7,11 @@ Fedora Infrastructure to send and receive messages to and from applications.
You can find the source at http://github.com/ralphbean/fedmsg
- :doc:`overview`
- - :doc:`status`
- - :doc:`services`
- :doc:`topology`
+ - :doc:`status`
+ - :doc:`commands`
+ - :doc:`config`
+ - :doc:`encoding`
- :doc:`sending`
- :doc:`receiving`
- :doc:`crypto`
View
@@ -17,17 +17,21 @@
#
# Authors: Ralph Bean <rbean@redhat.com>
#
-""" Cryptographic component of fedmsg.
+""" ``fedmsg.crypto`` - Cryptographic component of fedmsg.
+
+Introduction
+------------
In general, we assume that 'everything on the bus is public'. Even though all
the zmq endpoints are firewalled off from the outside world with iptables, we
-intend to someday have a forwarding service setup that will indiscriminantly
-forward all messages to anyone who wants them. So, the issue is not encrypting
-messages so they can't be read. It is up to sensitive services like FAS to
-*not send* sensitive information in the first place (like passwords, for
-instance).
-
-Since at some point, some services will respond to and act on messages that
+do have a forwarding service setup that indiscriminantly
+forwards all messages to anyone who wants them.
+(See :mod:`fedmsg.commands.gateway` for that service.)
+So, the issue is not encrypting messages so they can't be read. It is up to
+sensitive services like FAS to *not send* sensitive information in the first
+place (like passwords, for instance).
+
+However, since at some point, services will respond to and act on messages that
come across the bus, we need facilities for guaranteeing a message comes from
where it *ought* to come from. (Tangentially, message consumers need a simple
way to declare where they expect their messages to come from and have
@@ -40,13 +44,60 @@
difficult to sign messages. A consumer of those messages should be allowed
to ignore validation for those and only those expected unsigned messages
-This module encapsulates standalone functions for:
+Certificates
+------------
+
+To accomplish message signing, fedmsg must be able to read certificates and a
+private key on disk. For message validation, it only need be able to read the
+certificate. Exactly *which* certificates are used are determined by looking up
+the ``certname`` in the ``certnames`` config dict.
+
+We use a large number of certs for the deployment of fedmsg. We have one cert
+per `service-host`. For example, if we have 3 fedmsg-enabled services and each
+service runs on 10 hosts, then we have 30 unique certificate/key pairs in all.
+
+The intent is to create difficulty for attackers. If a low-security service on
+a particular box is compromised, we don't want the attacker automatically have
+access to the same certificate used for signing high-security service messages.
+
+Furthermore, attempts are made at the sysadmin-level to ensure that
+fedmsg-enabled services run as users that have exclusive read access to their
+own keys. See the `Fedora Infrastructure SOP
+<http://infrastructure.fedoraproject.org/infra/docs/fedmsg-certs.txt>`_ for more
+information (including how to generate new certs/bring up new services).
+
+Configuration
+-------------
+
+By convention, configuration values for :mod:`fedmsg.crypto` are kept in
+``/etc/fedmsg.d/ssl.py``, although technically they can be kept in any
+config ``dict`` in ``/etc/fedmsg.d`` (or in any of the config locations checked
+by :mod:`fedmsg.config`).
+
+The cryptography routines expect the following values to be defined:
+
+ - :term:`sign_messages`
+ - :term:`validate_signatures`
+ - :term:`ssldir`
+ - :term:`crl_location`
+ - :term:`crl_cache`
+ - :term:`crl_cache_expiry`
+ - :term:`certnames`
+
+For general information on configuration, see :mod:`fedmsg.config`.
+
+Module Contents
+---------------
+
+:mod:`fedmsg.crypto` encapsulates standalone functions for:
- Message signing.
- Signature validation.
+ - Stripping crypto information for view.
+
+It also contains some hidden/private machinery to handle refreshing a cached
+CRL.
-To accomplish this, we'll use puppet's already in place PKI involving X509
-certificates and RSA signatures.
"""
@@ -72,8 +123,10 @@
def sign(message, ssldir, certname, **config):
""" Insert two new fields into the message dict and return it.
- 'signature' - the computed RSA message digest of the JSON repr.
- 'certificate' - the base64 X509 certificate of the sending host.
+ Those fields are:
+
+ - 'signature' - the computed RSA message digest of the JSON repr.
+ - 'certificate' - the base64 X509 certificate of the sending host.
"""
certificate = M2Crypto.X509.load_cert(
@@ -172,7 +225,11 @@ def fail(reason):
def strip_credentials(message):
- """ Strip credentials from a message dict. """
+ """ Strip credentials from a message dict.
+
+ A new dict is returned without either `signature` or `certificate` keys.
+ This method can be called safely; the original dict is not modified.
+ """
message = copy.deepcopy(message)
for field in ['signature', 'certificate']:
if field in message:

0 comments on commit b39e6cf

Please sign in to comment.