Source code for Bcfg2.Server.Plugins.Cfg.CfgPublicKeyCreator
""" The CfgPublicKeyCreator invokes
: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, get_cfg
[docs]class CfgPublicKeyCreator(CfgCreator, StructFile):
""" .. currentmodule:: Bcfg2.Server.Plugins.Cfg
The CfgPublicKeyCreator creates SSH public keys on the fly. It is
invoked by :class:`CfgPrivateKeyCreator.CfgPrivateKeyCreator` to
handle the creation of the public key, and can also call
:class:`CfgPrivateKeyCreator.CfgPrivateKeyCreator` to trigger the
creation of a keypair when a public key is created. """
#: Different configurations for different clients/groups can be
#: handled with Client and Group tags within pubkey.xml
__specific__ = False
#: Handle XML specifications of private keys
__basenames__ = ['pubkey.xml']
#: No text content on any tags, so encryption support disabled
encryption = False
def __init__(self, fname):
CfgCreator.__init__(self, fname)
StructFile.__init__(self, fname)
self.cfg = get_cfg()
self.core = self.cfg.core
self.cmd = Executor()
[docs] def create_data(self, entry, metadata):
if entry.get("name").endswith(".pub"):
privkey = entry.get("name")[:-4]
else:
raise CfgCreationError("Cfg: Could not determine private key for "
"%s: Filename does not end in .pub" %
entry.get("name"))
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))
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)
[docs] def handle_event(self, event):
CfgCreator.handle_event(self, event)
StructFile.HandleEvent(self, event)
handle_event.__doc__ = CfgCreator.handle_event.__doc__