summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorChris St. Pierre <chris.a.st.pierre@gmail.com>2013-09-13 15:19:56 -0400
committerChris St. Pierre <chris.a.st.pierre@gmail.com>2013-09-16 11:41:34 -0400
commitb03e1e47c9805332cd83dcc5cf3e68e0b3c8175a (patch)
treed3d6554dbf29b917c194a6fb936962e1d5987e78 /src
parent5f98fa9d7cf175d565905189018a758adc1431b5 (diff)
downloadbcfg2-b03e1e47c9805332cd83dcc5cf3e68e0b3c8175a.tar.gz
bcfg2-b03e1e47c9805332cd83dcc5cf3e68e0b3c8175a.tar.bz2
bcfg2-b03e1e47c9805332cd83dcc5cf3e68e0b3c8175a.zip
CfgPublicKeyCreator: properly handle case where only private key has been created
Previously, only two cases were handled properly: both public and private keys had been created; or neither had been created. If the private key had been created (e.g., manually added to the repo), the public key would not be created from it. This fixes that.
Diffstat (limited to 'src')
-rw-r--r--src/lib/Bcfg2/Server/Plugins/Cfg/CfgPrivateKeyCreator.py16
-rw-r--r--src/lib/Bcfg2/Server/Plugins/Cfg/CfgPublicKeyCreator.py53
2 files changed, 44 insertions, 25 deletions
diff --git a/src/lib/Bcfg2/Server/Plugins/Cfg/CfgPrivateKeyCreator.py b/src/lib/Bcfg2/Server/Plugins/Cfg/CfgPrivateKeyCreator.py
index c0a3036a9..e890fdecb 100644
--- a/src/lib/Bcfg2/Server/Plugins/Cfg/CfgPrivateKeyCreator.py
+++ b/src/lib/Bcfg2/Server/Plugins/Cfg/CfgPrivateKeyCreator.py
@@ -159,7 +159,7 @@ class CfgPrivateKeyCreator(CfgCreator, StructFile):
return specificity
# pylint: disable=W0221
- def create_data(self, entry, metadata, return_pair=False):
+ def create_data(self, entry, metadata):
""" Create data for the given entry on the given client
:param entry: The abstract entry to create data for. This
@@ -167,15 +167,7 @@ class CfgPrivateKeyCreator(CfgCreator, StructFile):
:type entry: lxml.etree._Element
:param metadata: The client metadata to create data for
:type metadata: Bcfg2.Server.Plugins.Metadata.ClientMetadata
- :param return_pair: Return a tuple of ``(public key, private
- key)`` instead of just the private key.
- This is used by
- :class:`Bcfg2.Server.Plugins.Cfg.CfgPublicKeyCreator.CfgPublicKeyCreator`
- to create public keys as requested.
- :type return_pair: bool
:returns: string - The private key data
- :returns: tuple - Tuple of ``(public key, private key)``, if
- ``return_pair`` is set to True
"""
spec = self.XMLMatch(metadata)
specificity = self.get_specificity(metadata, spec)
@@ -201,11 +193,7 @@ class CfgPrivateKeyCreator(CfgCreator, StructFile):
specificity['ext'] = '.crypt'
self.write_data(privkey, **specificity)
-
- if return_pair:
- return (pubkey, privkey)
- else:
- return privkey
+ return privkey
finally:
shutil.rmtree(os.path.dirname(filename))
# pylint: enable=W0221
diff --git a/src/lib/Bcfg2/Server/Plugins/Cfg/CfgPublicKeyCreator.py b/src/lib/Bcfg2/Server/Plugins/Cfg/CfgPublicKeyCreator.py
index 6be438462..4bd8690ed 100644
--- a/src/lib/Bcfg2/Server/Plugins/Cfg/CfgPublicKeyCreator.py
+++ b/src/lib/Bcfg2/Server/Plugins/Cfg/CfgPublicKeyCreator.py
@@ -2,7 +2,11 @@
:class:`Bcfg2.Server.Plugins.Cfg.CfgPrivateKeyCreator.CfgPrivateKeyCreator`
to create SSH keys on the fly. """
+import os
+import sys
+import tempfile
import lxml.etree
+from Bcfg2.Utils import Executor
from Bcfg2.Server.Plugin import StructFile, PluginExecutionError
from Bcfg2.Server.Plugins.Cfg import CfgCreator, CfgCreationError, CFG
@@ -27,7 +31,8 @@ class CfgPublicKeyCreator(CfgCreator, StructFile):
CfgCreator.__init__(self, fname)
StructFile.__init__(self, fname)
self.cfg = CFG
- __init__.__doc__ = CfgCreator.__init__.__doc__
+ self.core = CFG.core
+ self.cmd = Executor()
def create_data(self, entry, metadata):
if entry.get("name").endswith(".pub"):
@@ -37,25 +42,51 @@ class CfgPublicKeyCreator(CfgCreator, StructFile):
"%s: Filename does not end in .pub" %
entry.get("name"))
- if privkey not in self.cfg.entries:
- raise CfgCreationError("Cfg: Could not find Cfg entry for %s "
- "(private key for %s)" % (privkey,
- self.name))
- eset = self.cfg.entries[privkey]
+ privkey_entry = lxml.etree.Element("Path", name=privkey)
try:
+ self.core.Bind(privkey_entry, metadata)
+ except PluginExecutionError:
+ raise CfgCreationError("Cfg: Could not bind %s (private key for "
+ "%s): %s" % (privkey, self.name,
+ sys.exc_info()[1]))
+
+ try:
+ eset = self.cfg.entries[privkey]
creator = eset.best_matching(metadata,
eset.get_handlers(metadata,
CfgCreator))
+ except KeyError:
+ raise CfgCreationError("Cfg: No private key defined for %s (%s)" %
+ (self.name, privkey))
except PluginExecutionError:
raise CfgCreationError("Cfg: No privkey.xml defined for %s "
"(private key for %s)" % (privkey,
self.name))
- privkey_entry = lxml.etree.Element("Path", name=privkey)
- pubkey = creator.create_data(privkey_entry, metadata,
- return_pair=True)[0]
- return pubkey
- create_data.__doc__ = CfgCreator.create_data.__doc__
+ specificity = creator.get_specificity(metadata)
+ fname = self.get_filename(**specificity)
+
+ # if the private key didn't exist, then creating it may have
+ # created the private key, too. check for it first.
+ if os.path.exists(fname):
+ return open(fname).read()
+ else:
+ # generate public key from private key
+ fd, privfile = tempfile.mkstemp()
+ try:
+ os.fdopen(fd, 'w').write(privkey_entry.text)
+ cmd = ["ssh-keygen", "-y", "-f", privfile]
+ self.debug_log("Cfg: Extracting SSH public key from %s: %s" %
+ (privkey, " ".join(cmd)))
+ result = self.cmd.run(cmd)
+ if not result.success:
+ raise CfgCreationError("Cfg: Failed to extract public key "
+ "from %s: %s" % (privkey,
+ result.error))
+ self.write_data(result.stdout, **specificity)
+ return result.stdout
+ finally:
+ os.unlink(privfile)
def handle_event(self, event):
CfgCreator.handle_event(self, event)