summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris St. Pierre <chris.a.st.pierre@gmail.com>2013-01-17 09:20:37 -0500
committerChris St. Pierre <chris.a.st.pierre@gmail.com>2013-01-17 09:20:37 -0500
commitae58c24f72a8ed72327fbc3f7305bd69ec6a13db (patch)
treee8614b54239161156d76424251cfc868643488a0
parent873a373c7eda0ba523ea8b78c3c45d7e8f189628 (diff)
downloadbcfg2-ae58c24f72a8ed72327fbc3f7305bd69ec6a13db.tar.gz
bcfg2-ae58c24f72a8ed72327fbc3f7305bd69ec6a13db.tar.bz2
bcfg2-ae58c24f72a8ed72327fbc3f7305bd69ec6a13db.zip
Made a few encryption things simpler:
* Only one strict/lax setting, in [encryption], rather than separate settings in [properties] and [sshkeys] * No longer necessary to enable encryption on each Properties file
-rw-r--r--doc/server/encryption.txt20
-rw-r--r--doc/server/plugins/connectors/properties.txt5
-rw-r--r--doc/server/plugins/generators/cfg.txt6
-rw-r--r--schemas/privkey.xsd17
-rw-r--r--schemas/types.xsd7
-rw-r--r--src/lib/Bcfg2/Server/Plugins/Cfg/CfgPrivateKeyCreator.py6
-rw-r--r--src/lib/Bcfg2/Server/Plugins/Properties.py37
-rwxr-xr-xsrc/sbin/bcfg2-crypt19
-rw-r--r--testsuite/Testsrc/Testlib/TestEncryption.py5
-rw-r--r--testsuite/Testsrc/Testlib/TestServer/TestPlugins/TestProperties.py14
10 files changed, 92 insertions, 44 deletions
diff --git a/doc/server/encryption.txt b/doc/server/encryption.txt
index bc18e140c..e84b9fb31 100644
--- a/doc/server/encryption.txt
+++ b/doc/server/encryption.txt
@@ -203,6 +203,26 @@ get a list of valid algorithms, you can run::
openssl list-cipher-algorithms | grep -v ' => ' | \
tr 'A-Z-' 'a-z_' | sort -u
+Lax vs. Strict decryption
+-------------------------
+
+By default, Bcfg2 expects to be able to decrypt every encrypted
+datum. Depending on how encryption is implemented at your site,
+though, that may not be possible. (For instance, if you use
+encryption to protect data for your production environment from your
+staging Bcfg2 server, then you would not expect the staging server to
+be able to decrypt everything.) In this case, you want to enable lax
+decryption in the ``[encryption]`` section of ``bcfg2.conf``:
+
+ [encryption]
+ decrypt = lax
+
+This causes a failed decrypt to produce a warning only, not an error.
+
+This can be overridden by individual XML files by setting
+``decrypt="strict"`` on the top-level tag (or, vice-versa; if strict
+is the default an XML file can specify ``decrypt="lax"``.
+
Encryption API
==============
diff --git a/doc/server/plugins/connectors/properties.txt b/doc/server/plugins/connectors/properties.txt
index 1d276697a..da511736d 100644
--- a/doc/server/plugins/connectors/properties.txt
+++ b/doc/server/plugins/connectors/properties.txt
@@ -290,9 +290,8 @@ 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 ``[properties]`` section of
- ``bcfg2.conf`` to set lax decryption on all Properties files by
- default; or
+* 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.
diff --git a/doc/server/plugins/generators/cfg.txt b/doc/server/plugins/generators/cfg.txt
index dcaeef4f8..e843b1d2d 100644
--- a/doc/server/plugins/generators/cfg.txt
+++ b/doc/server/plugins/generators/cfg.txt
@@ -411,6 +411,9 @@ structured as follows:
.. xml:element:: PrivateKey
:linktotype:
+See :ref:`server-encryption` for more details on encryption in Bcfg2
+in general.
+
``pubkey.xml``
~~~~~~~~~~~~~~~
@@ -579,9 +582,6 @@ influenced by several options in the ``[sshkeys]`` section of
| | 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
======
diff --git a/schemas/privkey.xsd b/schemas/privkey.xsd
index b8d9e317d..f6de534c1 100644
--- a/schemas/privkey.xsd
+++ b/schemas/privkey.xsd
@@ -5,6 +5,8 @@
</xsd:documentation>
</xsd:annotation>
+ <xsd:include schemaLocation="types.xsd"/>
+
<xsd:complexType name="PrivateKeyGroupType">
<xsd:annotation>
<xsd:documentation>
@@ -133,6 +135,21 @@
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
+ <xsd:attribute name="priority" type="xsd:positiveInteger" default="50">
+ <xsd:annotation>
+ <xsd:documentation>
+ Create group-specific keys with the given priority.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ <xsd:attribute name="decrypt" type="EncryptStrictnessEnum">
+ <xsd:annotation>
+ <xsd:documentation>
+ Override the global strict/lax decryption setting in
+ ``bcfg2.conf``.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
</xsd:complexType>
</xsd:element>
</xsd:schema>
diff --git a/schemas/types.xsd b/schemas/types.xsd
index a6070279a..524b327c5 100644
--- a/schemas/types.xsd
+++ b/schemas/types.xsd
@@ -96,6 +96,13 @@
</xsd:restriction>
</xsd:simpleType>
+ <xsd:simpleType name="EncryptStrictnessEnum">
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="strict"/>
+ <xsd:enumeration value="lax"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+
<xsd:complexType name='ActionType'>
<xsd:annotation>
<xsd:documentation>
diff --git a/src/lib/Bcfg2/Server/Plugins/Cfg/CfgPrivateKeyCreator.py b/src/lib/Bcfg2/Server/Plugins/Cfg/CfgPrivateKeyCreator.py
index 597f8f57b..aaeb65cd6 100644
--- a/src/lib/Bcfg2/Server/Plugins/Cfg/CfgPrivateKeyCreator.py
+++ b/src/lib/Bcfg2/Server/Plugins/Cfg/CfgPrivateKeyCreator.py
@@ -215,8 +215,10 @@ class CfgPrivateKeyCreator(CfgCreator, StructFile):
def Index(self):
StructFile.Index(self)
if HAS_CRYPTO:
- strict = SETUP.cfp.get("sshkeys", "decrypt",
- default="strict") == "strict"
+ strict = self.xdata.get(
+ "decrypt",
+ SETUP.cfp.get(Bcfg2.Encryption.CFG_SECTION, "decrypt",
+ default="strict")) == "strict"
for el in self.xdata.xpath("//*[@encrypted]"):
try:
el.text = self._decrypt(el).encode('ascii',
diff --git a/src/lib/Bcfg2/Server/Plugins/Properties.py b/src/lib/Bcfg2/Server/Plugins/Properties.py
index b3c0a6ae5..a51dd8adc 100644
--- a/src/lib/Bcfg2/Server/Plugins/Properties.py
+++ b/src/lib/Bcfg2/Server/Plugins/Properties.py
@@ -205,28 +205,27 @@ class XMLPropertyFile(Bcfg2.Server.Plugin.StructFile, PropertyFile):
def Index(self):
Bcfg2.Server.Plugin.StructFile.Index(self)
- if self.xdata.get("encryption", "false").lower() != "false":
+ strict = self.xdata.get(
+ "decrypt",
+ SETUP.cfp.get(Bcfg2.Encryption.CFG_SECTION, "decrypt",
+ default="strict")) == "strict"
+ for el in self.xdata.xpath("//*[@encrypted]"):
if not HAS_CRYPTO:
raise PluginExecutionError("Properties: M2Crypto is not "
"available: %s" % self.name)
- strict = self.xdata.get(
- "decrypt",
- SETUP.cfp.get("properties", "decrypt",
- default="strict")) == "strict"
- for el in self.xdata.xpath("//*[@encrypted]"):
- try:
- el.text = self._decrypt(el).encode('ascii',
- 'xmlcharrefreplace')
- except UnicodeDecodeError:
- LOGGER.info("Properties: Decrypted %s to gibberish, "
- "skipping" % el.tag)
- except Bcfg2.Encryption.EVPError:
- msg = "Properties: Failed to decrypt %s element in %s" % \
- (el.tag, self.name)
- if strict:
- raise PluginExecutionError(msg)
- else:
- LOGGER.warning(msg)
+ try:
+ el.text = self._decrypt(el).encode('ascii',
+ 'xmlcharrefreplace')
+ except UnicodeDecodeError:
+ LOGGER.info("Properties: Decrypted %s to gibberish, "
+ "skipping" % el.tag)
+ except Bcfg2.Encryption.EVPError:
+ msg = "Properties: Failed to decrypt %s element in %s" % \
+ (el.tag, self.name)
+ if strict:
+ raise PluginExecutionError(msg)
+ else:
+ LOGGER.warning(msg)
Index.__doc__ = Bcfg2.Server.Plugin.StructFile.Index.__doc__
def _decrypt(self, element):
diff --git a/src/sbin/bcfg2-crypt b/src/sbin/bcfg2-crypt
index 9eab7bd29..fde6af582 100755
--- a/src/sbin/bcfg2-crypt
+++ b/src/sbin/bcfg2-crypt
@@ -55,7 +55,7 @@ class Encryptor(object):
def set_passphrase(self):
""" set the passphrase for the current file """
- if (not self.setup.cfp.has_section("encryption") or
+ if (not self.setup.cfp.has_section(Bcfg2.Encryption.CFG_SECTION) or
len(Bcfg2.Encryption.get_passphrases(self.setup)) == 0):
self.logger.error("No passphrases available in %s" %
self.setup['configfile'])
@@ -70,9 +70,11 @@ class Encryptor(object):
self.pname = self.setup['passphrase']
if self.pname:
- if self.setup.cfp.has_option("encryption", self.pname):
- self.passphrase = self.setup.cfp.get("encryption",
- self.pname)
+ if self.setup.cfp.has_option(Bcfg2.Encryption.CFG_SECTION,
+ self.pname):
+ self.passphrase = \
+ self.setup.cfp.get(Bcfg2.Encryption.CFG_SECTION,
+ self.pname)
self.logger.debug("Using passphrase %s specified on command "
"line" % self.pname)
return True
@@ -241,8 +243,10 @@ class Encryptor(object):
self.logger.info("No passphrase given on command line or "
"found in file")
return False
- elif self.setup.cfp.has_option("encryption", pname):
- passphrase = self.setup.cfp.get("encryption", pname)
+ elif self.setup.cfp.has_option(Bcfg2.Encryption.CFG_SECTION,
+ pname):
+ passphrase = self.setup.cfp.get(Bcfg2.Encryption.CFG_SECTION,
+ pname)
else:
self.logger.error("Could not find passphrase %s in %s" %
(pname, self.setup['configfile']))
@@ -339,13 +343,12 @@ class PropertiesEncryptor(Encryptor):
# find root element
while xdata.getparent() != None:
xdata = xdata.getparent()
- xdata.set("encryption", "true")
return lxml.etree.tostring(xdata,
xml_declaration=False,
pretty_print=True).decode('UTF-8')
def _get_passphrase(self, chunk):
- pname = chunk.get("encrypted") or chunk.get("encryption")
+ pname = chunk.get("encrypted")
if pname and pname.lower() != "true":
return pname
return None
diff --git a/testsuite/Testsrc/Testlib/TestEncryption.py b/testsuite/Testsrc/Testlib/TestEncryption.py
index 778d5b963..c03aa66e1 100644
--- a/testsuite/Testsrc/Testlib/TestEncryption.py
+++ b/testsuite/Testsrc/Testlib/TestEncryption.py
@@ -193,11 +193,6 @@ baz
# test that different algorithms are used
mock_passphrases.reset_mock()
- self.assertRaises(EVPError,
- bruteforce_decrypt,
- crypted, setup=setup, algorithm=self.algo)
-
- mock_passphrases.reset_mock()
crypted = ssl_encrypt(self.plaintext, passwd, algorithm=self.algo)
self.assertEqual(self.plaintext,
bruteforce_decrypt(crypted, setup=setup,
diff --git a/testsuite/Testsrc/Testlib/TestServer/TestPlugins/TestProperties.py b/testsuite/Testsrc/Testlib/TestServer/TestPlugins/TestProperties.py
index 1a8619097..d66780a20 100644
--- a/testsuite/Testsrc/Testlib/TestServer/TestPlugins/TestProperties.py
+++ b/testsuite/Testsrc/Testlib/TestServer/TestPlugins/TestProperties.py
@@ -247,14 +247,17 @@ class TestXMLPropertyFile(TestPropertyFile, TestStructFile):
TestStructFile.test_Index(self)
pf = self.get_obj()
- pf.xdata = lxml.etree.Element("Properties", encryption="true")
+ pf.xdata = lxml.etree.Element("Properties")
+ lxml.etree.SubElement(pf.xdata, "Crypted", encrypted="foo")
pf.data = lxml.etree.tostring(pf.xdata)
# extra test: crypto is not available, but properties file is
# encrypted
has_crypto = Bcfg2.Server.Plugins.Properties.HAS_CRYPTO
Bcfg2.Server.Plugins.Properties.HAS_CRYPTO = False
- self.assertRaises(PluginExecutionError, pf.Index)
- Bcfg2.Server.Plugins.Properties.HAS_CRYPTO = has_crypto
+ try:
+ self.assertRaises(PluginExecutionError, pf.Index)
+ finally:
+ Bcfg2.Server.Plugins.Properties.HAS_CRYPTO = has_crypto
@skipUnless(HAS_CRYPTO, "No crypto libraries found, skipping")
def test_Index_crypto(self):
@@ -262,7 +265,7 @@ class TestXMLPropertyFile(TestPropertyFile, TestStructFile):
pf._decrypt = Mock()
pf._decrypt.return_value = 'plaintext'
pf.data = '''
-<Properties encryption="true" decrypt="strict">
+<Properties decrypt="strict">
<Crypted encrypted="foo">
crypted
<Plain foo="bar">plain</Plain>
@@ -274,6 +277,9 @@ class TestXMLPropertyFile(TestPropertyFile, TestStructFile):
</Plain>
</Properties>'''
+ print "HAS_CRYPTO: %s" % HAS_CRYPTO
+ print "Properties HAS_CRYPTO: %s" % Bcfg2.Server.Plugins.Properties.HAS_CRYPTO
+
# test successful decryption
pf.Index()
self.assertItemsEqual(pf._decrypt.call_args_list,