From eac71fc1109f2edc6b71e62a6cff38d762bebe63 Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Tue, 25 Sep 2012 11:49:15 -0400 Subject: expanded pylint coverage --- src/sbin/bcfg2-crypt | 100 +++++++++++++++++++++++++++------------------------ 1 file changed, 54 insertions(+), 46 deletions(-) (limited to 'src/sbin/bcfg2-crypt') diff --git a/src/sbin/bcfg2-crypt b/src/sbin/bcfg2-crypt index bae4ad8ef..904f77611 100755 --- a/src/sbin/bcfg2-crypt +++ b/src/sbin/bcfg2-crypt @@ -9,59 +9,48 @@ import lxml.etree import Bcfg2.Logger import Bcfg2.Options from Bcfg2.Server import XMLParser -from Bcfg2.Compat import input +from Bcfg2.Compat import input # pylint: disable=W0622 try: import Bcfg2.Encryption except ImportError: - err = sys.exc_info()[1] - print("Could not import %s. Is M2Crypto installed?" % err) + print("Could not import %s. Is M2Crypto installed?" % sys.exc_info()[1]) raise SystemExit(1) -LOGGER = None - -def get_logger(verbose=0): - """ set up logging according to the verbose level given on the - command line """ - global LOGGER - if LOGGER is None: - LOGGER = logging.getLogger(sys.argv[0]) - stderr = logging.StreamHandler() - if verbose: - level = logging.DEBUG - else: - level = logging.WARNING - LOGGER.setLevel(level) - LOGGER.addHandler(stderr) - syslog = logging.handlers.SysLogHandler("/dev/log") - syslog.setFormatter(logging.Formatter("%(name)s: %(message)s")) - LOGGER.addHandler(syslog) - return LOGGER - class EncryptionChunkingError(Exception): + """ error raised when Encryptor cannot break a file up into chunks + to be encrypted, or cannot reassemble the chunks """ pass class Encryptor(object): + """ Generic encryptor for all files """ + def __init__(self, setup): self.setup = setup - self.logger = get_logger() self.passphrase = None self.pname = None + self.logger = logging.getLogger(self.__class__.__name__) def get_encrypted_filename(self, plaintext_filename): + """ get the name of the file encrypted data should be written to """ return plaintext_filename def get_plaintext_filename(self, encrypted_filename): + """ get the name of the file decrypted data should be written to """ return encrypted_filename def chunk(self, data): + """ generator to break the file up into smaller chunks that + will each be individually encrypted or decrypted """ yield data - def unchunk(self, data, original): + def unchunk(self, data, original): # pylint: disable=W0613 + """ given chunks of a file, reassemble then into the whole file """ return data[0] def set_passphrase(self): + """ set the passphrase for the current file """ if (not self.setup.cfp.has_section("encryption") or self.setup.cfp.options("encryption") == 0): self.logger.error("No passphrases available in %s" % @@ -98,6 +87,7 @@ class Encryptor(object): return False def encrypt(self, fname): + """ encrypt the given file, returning the encrypted data """ try: plaintext = open(fname).read() except IOError: @@ -124,12 +114,16 @@ class Encryptor(object): return False return self.unchunk(crypted, plaintext) + # pylint: disable=W0613 def _encrypt(self, plaintext, passphrase, name=None): + """ encrypt a single chunk of a file """ return Bcfg2.Encryption.ssl_encrypt( plaintext, passphrase, Bcfg2.Encryption.get_algorithm(self.setup)) + # pylint: enable=W0613 def decrypt(self, fname): + """ decrypt the given file, returning the plaintext data """ try: crypted = open(fname).read() except IOError: @@ -149,12 +143,12 @@ class Encryptor(object): except Bcfg2.Encryption.EVPError: self.logger.info("Could not decrypt %s with the " "specified passphrase" % fname) - return False + continue except: err = sys.exc_info()[1] self.logger.error("Error decrypting %s: %s" % (fname, err)) - return False + continue except TypeError: pchunk = None for pname in self.setup.cfp.options('encryption'): @@ -175,7 +169,7 @@ class Encryptor(object): self.logger.error("Could not decrypt %s with any " "passphrase in %s" % (fname, self.setup['configfile'])) - return False + continue except EncryptionChunkingError: err = sys.exc_info()[1] self.logger.error("Error getting encrypted data from %s: %s" % @@ -190,7 +184,14 @@ class Encryptor(object): (fname, err)) return False + def _decrypt(self, crypted, passphrase): + """ decrypt a single chunk """ + return Bcfg2.Encryption.ssl_decrypt( + crypted, passphrase, + Bcfg2.Encryption.get_algorithm(self.setup)) + def write_encrypted(self, fname, data=None): + """ write encrypted data to disk """ if data is None: data = self.decrypt(fname) new_fname = self.get_encrypted_filename(fname) @@ -210,6 +211,7 @@ class Encryptor(object): return False def write_decrypted(self, fname, data=None): + """ write decrypted data to disk """ if data is None: data = self.decrypt(fname) new_fname = self.get_plaintext_filename(fname) @@ -224,6 +226,7 @@ class Encryptor(object): return False def get_passphrase(self, chunk): + """ get the passphrase for a chunk of a file """ pname = self._get_passphrase(chunk) if not self.pname: if not pname: @@ -246,16 +249,14 @@ class Encryptor(object): (self.pname, pname)) return (passphrase, pname) - def _get_passphrase(self, chunk): + def _get_passphrase(self, chunk): # pylint: disable=W0613 + """ get the passphrase for a chunk of a file """ return None - def _decrypt(self, crypted, passphrase): - return Bcfg2.Encryption.ssl_decrypt( - crypted, passphrase, - Bcfg2.Encryption.get_algorithm(self.setup)) - class CfgEncryptor(Encryptor): + """ encryptor class for Cfg files """ + def get_encrypted_filename(self, plaintext_filename): return plaintext_filename + ".crypt" @@ -267,6 +268,8 @@ class CfgEncryptor(Encryptor): class PropertiesEncryptor(Encryptor): + """ encryptor class for Properties files """ + def _encrypt(self, plaintext, passphrase, name=None): # plaintext is an lxml.etree._Element if name is None: @@ -347,7 +350,7 @@ class PropertiesEncryptor(Encryptor): return crypted -def main(): +def main(): # pylint: disable=R0912,R0915 optinfo = dict(interactive=Bcfg2.Options.INTERACTIVE) optinfo.update(Bcfg2.Options.CRYPT_OPTIONS) optinfo.update(Bcfg2.Options.CLI_COMMON_OPTIONS) @@ -360,35 +363,40 @@ def main(): print(setup.hm) raise SystemExit(1) + log_args = dict(to_syslog=setup['syslog'], to_console=logging.WARNING) + if setup['verbose']: + log_args['to_console'] = logging.DEBUG + Bcfg2.Logger.setup_logging('bcfg2-crypt', **log_args) + logger = logging.getLogger('bcfg2-crypt') + if setup['decrypt']: if setup['encrypt']: - print("You cannot specify both --encrypt and --decrypt") + logger.error("You cannot specify both --encrypt and --decrypt") raise SystemExit(1) elif setup['remove']: - print("--remove cannot be used with --decrypt, ignoring") + logger.error("--remove cannot be used with --decrypt, ignoring") setup['remove'] = Bcfg2.Options.CRYPT_REMOVE.default elif setup['interactive']: - print("Cannot decrypt interactively") + logger.error("Cannot decrypt interactively") setup['interactive'] = False if setup['cfg']: if setup['properties']: - print("You cannot specify both --cfg and --properties") + logger.error("You cannot specify both --cfg and --properties") raise SystemExit(1) if setup['xpath']: - print("Specifying --xpath with --cfg is nonsensical, ignoring " - "--xpath") + logger.error("Specifying --xpath with --cfg is nonsensical, " + "ignoring --xpath") setup['xpath'] = Bcfg2.Options.CRYPT_XPATH.default if setup['interactive']: - print("You cannot use interactive mode with --cfg, ignoring -I") + logger.error("You cannot use interactive mode with --cfg, " + "ignoring -I") setup['interactive'] = False elif setup['properties']: if setup['remove']: - print("--remove cannot be used with --properties, ignoring") + logger.error("--remove cannot be used with --properties, ignoring") setup['remove'] = Bcfg2.Options.CRYPT_REMOVE.default - logger = get_logger(setup['verbose']) - props_crypt = PropertiesEncryptor(setup) cfg_crypt = CfgEncryptor(setup) @@ -456,7 +464,7 @@ def main(): if data is None: data = xform(fname) if not data: - print("Failed to %s %s, skipping" % (xform.__name__, fname)) + logger.error("Failed to %s %s, skipping" % (xform.__name__, fname)) continue if setup['crypt_stdout']: if len(setup['args']) > 1: -- cgit v1.2.3-1-g7c22