summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--man/bcfg2-admin.82
-rw-r--r--man/bcfg2-build-reports.82
-rw-r--r--man/bcfg2-crypt.812
-rw-r--r--man/bcfg2-info.82
-rw-r--r--man/bcfg2-lint.82
-rw-r--r--man/bcfg2-lint.conf.52
-rw-r--r--man/bcfg2-reports.82
-rw-r--r--man/bcfg2-server.82
-rw-r--r--man/bcfg2.12
-rw-r--r--man/bcfg2.conf.52
-rw-r--r--src/lib/Bcfg2/Client/Frame.py8
-rw-r--r--src/lib/Bcfg2/Options.py17
-rwxr-xr-xsrc/sbin/bcfg2-crypt174
-rw-r--r--tools/manpagegen/bcfg2-crypt.8.ronn10
14 files changed, 157 insertions, 82 deletions
diff --git a/man/bcfg2-admin.8 b/man/bcfg2-admin.8
index bed51ff9a..e5bcc55f3 100644
--- a/man/bcfg2-admin.8
+++ b/man/bcfg2-admin.8
@@ -1,5 +1,5 @@
.
-.TH "BCFG2\-ADMIN" "8" "August 2012" "" ""
+.TH "BCFG2\-ADMIN" "8" "September 2012" "" ""
.
.SH "NAME"
\fBbcfg2\-admin\fR \- Perform repository administration tasks
diff --git a/man/bcfg2-build-reports.8 b/man/bcfg2-build-reports.8
index 3c61e8356..55aff8b31 100644
--- a/man/bcfg2-build-reports.8
+++ b/man/bcfg2-build-reports.8
@@ -1,5 +1,5 @@
.
-.TH "BCFG2\-BUILD\-REPORTS" "8" "August 2012" "" ""
+.TH "BCFG2\-BUILD\-REPORTS" "8" "September 2012" "" ""
.
.SH "NAME"
\fBbcfg2\-build\-reports\fR \- Generate state reports for Bcfg2 clients
diff --git a/man/bcfg2-crypt.8 b/man/bcfg2-crypt.8
index a73f3e066..64c10a902 100644
--- a/man/bcfg2-crypt.8
+++ b/man/bcfg2-crypt.8
@@ -1,11 +1,11 @@
.
-.TH "BCFG2\-CRYPT" "8" "August 2012" "" ""
+.TH "BCFG2\-CRYPT" "8" "September 2012" "" ""
.
.SH "NAME"
\fBbcfg2\-crypt\fR \- Bcfg2 encryption and decryption utility
.
.SH "SYNOPSIS"
-\fBbcfg2\-crypt\fR [\fI\-C configfile\fR] [\-\-decrypt|\-\-encrypt] [\-\-cfg|\-\-properties] [\-\-remove] [\-\-xpath \fIxpath\fR] [\-p \fIpassphrase\-or\-name\fR] [\-v] \fIfilename\fR [\fIfilename\fR\.\.\.]
+\fBbcfg2\-crypt\fR [\fI\-C configfile\fR] [\-\-decrypt|\-\-encrypt] [\-\-cfg|\-\-properties] [\-\-stdout] [\-\-remove] [\-\-xpath \fIxpath\fR] [\-p \fIpassphrase\-or\-name\fR] [\-v] [\-I] \fIfilename\fR [\fIfilename\fR\.\.\.]
.
.SH "DESCRIPTION"
\fBbcfg2\-crypt\fR performs encryption and decryption of Cfg and Properties files\. It\'s often sufficient to run \fBbcfg2\-crypt\fR with only the name of the file you wish to encrypt or decrypt; it can usually figure out what to do\.
@@ -29,6 +29,10 @@ Tell \fBbcfg2\-crypt\fR that an XML file should be encrypted in its entirety rat
Tell \fBbcfg2\-crypt\fR to process a file as an XML Properties file, and encrypt the text of each element separately\. This is necessary if, for example, you\'ve used a different top\-level tag than \fB<Properties>\fR in your Properties files\. See \fIMODES\fR below for details\.
.
.TP
+\fB\-\-stdout\fR
+Print the resulting file to stdout instead of writing it to a file\.
+.
+.TP
\fB\-\-remove\fR
Remove the plaintext file after it has been encrypted\. Only meaningful for Cfg files\.
.
@@ -45,6 +49,10 @@ Specify the name of a passphrase specified in the \fB[encryption]\fR section of
Be verbose\.
.
.TP
+\fB\-I\fR
+When encrypting a Properties file, interactively select the elements whose data should be encrypted\.
+.
+.TP
\fB\-h\fR
Display help and exit\.
.
diff --git a/man/bcfg2-info.8 b/man/bcfg2-info.8
index bb515079f..9362776a1 100644
--- a/man/bcfg2-info.8
+++ b/man/bcfg2-info.8
@@ -1,5 +1,5 @@
.
-.TH "BCFG2\-INFO" "8" "August 2012" "" ""
+.TH "BCFG2\-INFO" "8" "September 2012" "" ""
.
.SH "NAME"
\fBbcfg2\-info\fR \- Creates a local version of the Bcfg2 server core for state observation
diff --git a/man/bcfg2-lint.8 b/man/bcfg2-lint.8
index 7a5a69b7a..a6bfffb8a 100644
--- a/man/bcfg2-lint.8
+++ b/man/bcfg2-lint.8
@@ -1,5 +1,5 @@
.
-.TH "BCFG2\-LINT" "8" "August 2012" "" ""
+.TH "BCFG2\-LINT" "8" "September 2012" "" ""
.
.SH "NAME"
\fBbcfg2\-lint\fR \- Check Bcfg2 specification for validity, common mistakes, and style
diff --git a/man/bcfg2-lint.conf.5 b/man/bcfg2-lint.conf.5
index d23afa8dc..55dfa5cc2 100644
--- a/man/bcfg2-lint.conf.5
+++ b/man/bcfg2-lint.conf.5
@@ -1,5 +1,5 @@
.
-.TH "BCFG2\-LINT\.CONF" "5" "August 2012" "" ""
+.TH "BCFG2\-LINT\.CONF" "5" "September 2012" "" ""
.
.SH "NAME"
\fBbcfg2\-lint\.conf\fR \- configuration parameters for bcfg2\-lint
diff --git a/man/bcfg2-reports.8 b/man/bcfg2-reports.8
index b2c0cad43..78b594047 100644
--- a/man/bcfg2-reports.8
+++ b/man/bcfg2-reports.8
@@ -1,5 +1,5 @@
.
-.TH "BCFG2\-REPORTS" "8" "August 2012" "" ""
+.TH "BCFG2\-REPORTS" "8" "September 2012" "" ""
.
.SH "NAME"
\fBbcfg2\-reports\fR \- Query reporting system for client status
diff --git a/man/bcfg2-server.8 b/man/bcfg2-server.8
index 955f541c9..7bbfb87c3 100644
--- a/man/bcfg2-server.8
+++ b/man/bcfg2-server.8
@@ -1,5 +1,5 @@
.
-.TH "BCFG2\-SERVER" "8" "August 2012" "" ""
+.TH "BCFG2\-SERVER" "8" "September 2012" "" ""
.
.SH "NAME"
\fBbcfg2\-server\fR \- Server for client configuration specifications
diff --git a/man/bcfg2.1 b/man/bcfg2.1
index 2aa219756..231155797 100644
--- a/man/bcfg2.1
+++ b/man/bcfg2.1
@@ -1,5 +1,5 @@
.
-.TH "BCFG2" "1" "August 2012" "" ""
+.TH "BCFG2" "1" "September 2012" "" ""
.
.SH "NAME"
\fBbcfg2\fR \- Bcfg2 client tool
diff --git a/man/bcfg2.conf.5 b/man/bcfg2.conf.5
index b62d223c9..c7f8bf4ed 100644
--- a/man/bcfg2.conf.5
+++ b/man/bcfg2.conf.5
@@ -1,5 +1,5 @@
.
-.TH "BCFG2\.CONF" "5" "August 2012" "" ""
+.TH "BCFG2\.CONF" "5" "September 2012" "" ""
.
.SH "NAME"
\fBbcfg2\.conf\fR \- configuration parameters for Bcfg2
diff --git a/src/lib/Bcfg2/Client/Frame.py b/src/lib/Bcfg2/Client/Frame.py
index 508e3b616..2fb81d6ba 100644
--- a/src/lib/Bcfg2/Client/Frame.py
+++ b/src/lib/Bcfg2/Client/Frame.py
@@ -7,6 +7,7 @@ import logging
import sys
import time
import Bcfg2.Client.Tools
+from Bcfg2.Compat import input
def cmpent(ent1, ent2):
@@ -150,12 +151,7 @@ class Frame(object):
else:
iprompt = prompt % (entry.tag, entry.get('name'))
try:
- # py3k compatibility
- try:
- ans = raw_input(iprompt.encode(sys.stdout.encoding,
- 'replace'))
- except NameError:
- ans = input(iprompt)
+ ans = input(iprompt.encode(sys.stdout.encoding, 'replace'))
if ans in ['y', 'Y']:
ret.append(entry)
except EOFError:
diff --git a/src/lib/Bcfg2/Options.py b/src/lib/Bcfg2/Options.py
index 34f4b2bc6..6ac9cafb1 100644
--- a/src/lib/Bcfg2/Options.py
+++ b/src/lib/Bcfg2/Options.py
@@ -21,9 +21,9 @@ DEFAULT_INSTALL_PREFIX = '/usr'
class DefaultConfigParser(ConfigParser.ConfigParser):
- def __init__(self,*args,**kwargs):
+ def __init__(self, *args, **kwargs):
"""Make configuration options case sensitive"""
- ConfigParser.ConfigParser.__init__(self,*args,**kwargs)
+ ConfigParser.ConfigParser.__init__(self, *args, **kwargs)
self.optionxform = str
def get(self, section, option, **kwargs):
@@ -100,7 +100,7 @@ class Option(object):
rv.append("%s %s" % (self.cmd, self.odesc))
else:
rv.append("%s" % self.cmd)
-
+
if self.cf:
if self.cmd:
rv.append("; ")
@@ -175,9 +175,10 @@ class Option(object):
% (self.deprecated_cf[0], self.deprecated_cf[1],
self.cf[0], self.cf[1]))
return
- except (ConfigParser.NoSectionError, ConfigParser.NoOptionError):
+ except (ConfigParser.NoSectionError,
+ ConfigParser.NoOptionError):
pass
-
+
# Default value not cooked
self.value = self.default
@@ -907,8 +908,8 @@ DECRYPT = \
default=False,
cmd='--decrypt',
long_arg=True)
-DECRYPT_STDOUT = \
- Option('Decrypt the specified file to stdout',
+CRYPT_STDOUT = \
+ Option('Decrypt or encrypt the specified file to stdout',
default=False,
cmd='--stdout',
long_arg=True)
@@ -968,7 +969,7 @@ SERVER_COMMON_OPTIONS = dict(repo=SERVER_REPOSITORY,
CRYPT_OPTIONS = dict(encrypt=ENCRYPT,
decrypt=DECRYPT,
- decrypt_stdout=DECRYPT_STDOUT,
+ crypt_stdout=CRYPT_STDOUT,
passphrase=CRYPT_PASSPHRASE,
xpath=CRYPT_XPATH,
properties=CRYPT_PROPERTIES,
diff --git a/src/sbin/bcfg2-crypt b/src/sbin/bcfg2-crypt
index cb1b956fb..1af1771cf 100755
--- a/src/sbin/bcfg2-crypt
+++ b/src/sbin/bcfg2-crypt
@@ -3,16 +3,18 @@
import os
import sys
+import copy
import logging
import lxml.etree
import Bcfg2.Logger
import Bcfg2.Options
+from Bcfg2.Server import XMLParser
+from Bcfg2.Compat import input
try:
import Bcfg2.Encryption
except ImportError:
err = sys.exc_info()[1]
- print("Import failed '%s'. Is M2Crypto installed?" %
- err)
+ print("Could not import %s. Is M2Crypto installed?" % err)
raise SystemExit(1)
LOGGER = None
@@ -103,7 +105,8 @@ class Encryptor(object):
self.logger.error("Error reading %s, skipping: %s" % (fname, err))
return False
- self.set_passphrase()
+ if not self.set_passphrase():
+ return False
crypted = []
try:
@@ -119,22 +122,7 @@ class Encryptor(object):
self.logger.error("Error getting data to encrypt from %s: %s" %
(fname, err))
return False
-
- new_fname = self.get_encrypted_filename(fname)
- try:
- open(new_fname, "wb").write(self.unchunk(crypted, plaintext))
- self.logger.info("Wrote encrypted data to %s" % new_fname)
- return True
- except IOError:
- err = sys.exc_info()[1]
- self.logger.error("Error writing encrypted data from %s to %s: %s" %
- (fname, new_fname, err))
- return False
- except EncryptionChunkingError:
- err = sys.exc_info()[1]
- self.logger.error("Error assembling encrypted data from %s: %s" %
- (fname, err))
- return False
+ return self.unchunk(crypted, plaintext)
def _encrypt(self, plaintext, passphrase, name=None):
return Bcfg2.Encryption.ssl_encrypt(plaintext, passphrase)
@@ -200,6 +188,25 @@ class Encryptor(object):
(fname, err))
return False
+ def write_encrypted(self, fname, data=None):
+ if data is None:
+ data = self.decrypt(fname)
+ new_fname = self.get_encrypted_filename(fname)
+ try:
+ open(new_fname, "wb").write(data)
+ self.logger.info("Wrote encrypted data to %s" % new_fname)
+ return True
+ except IOError:
+ err = sys.exc_info()[1]
+ self.logger.error("Error writing encrypted data from %s to %s: %s" %
+ (fname, new_fname, err))
+ return False
+ except EncryptionChunkingError:
+ err = sys.exc_info()[1]
+ self.logger.error("Error assembling encrypted data from %s: %s" %
+ (fname, err))
+ return False
+
def write_decrypted(self, fname, data=None):
if data is None:
data = self.decrypt(fname)
@@ -262,12 +269,12 @@ class PropertiesEncryptor(Encryptor):
name = "true"
if plaintext.text and plaintext.text.strip():
plaintext.text = Bcfg2.Encryption.ssl_encrypt(plaintext.text,
- passphrase)
+ passphrase).strip()
plaintext.set("encrypted", name)
return plaintext
def chunk(self, data):
- xdata = lxml.etree.XML(data)
+ xdata = lxml.etree.XML(data, parser=XMLParser)
if self.setup['xpath']:
elements = xdata.xpath(self.setup['xpath'])
if not elements:
@@ -276,7 +283,28 @@ class PropertiesEncryptor(Encryptor):
else:
elements = xdata.xpath('//*[@encrypted]')
if not elements:
- elements = list(xdata.getiterator())
+ elements = list(xdata.getiterator(tag=lxml.etree.Element))
+
+ # filter out elements without text data
+ for el in elements[:]:
+ if not el.text:
+ elements.remove(el)
+
+ if self.setup['interactive']:
+ for element in elements[:]:
+ if len(element):
+ elt = copy.copy(element)
+ for child in elt.iterchildren():
+ elt.remove(child)
+ else:
+ elt = element
+ print(lxml.etree.tostring(
+ elt,
+ xml_declaration=False).decode("UTF-8").strip())
+ ans = input("Encrypt this element? [y/N] ")
+ if not ans.lower().startswith("y"):
+ elements.remove(element)
+
# this is not a good use of a generator, but we need to
# generate the full list of elements in order to ensure that
# some exist before we know what to return
@@ -291,7 +319,9 @@ class PropertiesEncryptor(Encryptor):
while xdata.getparent() != None:
xdata = xdata.getparent()
xdata.set("encryption", "true")
- return lxml.etree.tostring(xdata, xml_declaration=False).decode('UTF-8')
+ 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")
@@ -304,13 +334,13 @@ class PropertiesEncryptor(Encryptor):
if not crypted.text or not crypted.text.strip():
self.logger.warning("Skipping empty element %s" % crypted.tag)
return crypted
- rv = Bcfg2.Encryption.ssl_decrypt(crypted.text, passphrase)
- crypted.text = rv
+ crypted.text = Bcfg2.Encryption.ssl_decrypt(crypted.text,
+ passphrase).strip()
return crypted
def main():
- optinfo = dict()
+ optinfo = dict(interactive=Bcfg2.Options.INTERACTIVE)
optinfo.update(Bcfg2.Options.CRYPT_OPTIONS)
optinfo.update(Bcfg2.Options.CLI_COMMON_OPTIONS)
setup = Bcfg2.Options.OptionParser(optinfo)
@@ -321,18 +351,33 @@ def main():
if not setup['args']:
print(setup.hm)
raise SystemExit(1)
- elif setup['encrypt'] and (setup['decrypt_stdout'] or setup['decrypt']):
- print("You cannot specify both --encrypt and --decrypt or --stdout")
- raise SystemExit(1)
- elif setup['cfg'] and setup['properties']:
- print("You cannot specify both --cfg and --properties")
- raise SystemExit(1)
- elif setup['cfg'] and setup['properties']:
- print("Specifying --xpath with --cfg is nonsensical, ignoring --xpath")
- setup['xpath'] = Bcfg2.Options.CRYPT_XPATH.default
- elif setup['decrypt'] and setup['remove']:
- print("--remove cannot be used with --decrypt, ignoring")
- setup['remove'] = Bcfg2.Options.CRYPT_REMOVE.default
+
+ if setup['decrypt']:
+ if setup['encrypt']:
+ print("You cannot specify both --encrypt and --decrypt")
+ raise SystemExit(1)
+ elif setup['remove']:
+ print("--remove cannot be used with --decrypt, ignoring")
+ setup['remove'] = Bcfg2.Options.CRYPT_REMOVE.default
+ elif setup['interactive']:
+ print("Cannot decrypt interactively")
+ setup['interactive'] = False
+
+ if setup['cfg']:
+ if setup['properties']:
+ print("You cannot specify both --cfg and --properties")
+ raise SystemExit(1)
+ if setup['xpath']:
+ print("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")
+ setup['interactive'] = False
+ elif setup['properties']:
+ if setup['remove']:
+ print("--remove cannot be used with --properties, ignoring")
+ setup['remove'] = Bcfg2.Options.CRYPT_REMOVE.default
logger = get_logger(setup['verbose'])
@@ -369,32 +414,49 @@ def main():
if props:
encryptor = props_crypt
+ if setup['remove']:
+ logger.info("Cannot use --remove with Properties file %s, "
+ "ignoring for this file" % fname)
else:
+ if setup['xpath']:
+ logger.info("Cannot use xpath with Cfg file %s, ignoring xpath "
+ "for this file" % fname)
+ if setup['interactive']:
+ logger.info("Cannot use interactive mode with Cfg file %s, "
+ "ignoring -I for this file" % fname)
encryptor = cfg_crypt
+ data = None
if setup['encrypt']:
- if not encryptor.encrypt(fname):
- print("Failed to encrypt %s, skipping" % fname)
- elif setup['decrypt'] or setup['decrypt_stdout']:
- data = encryptor.decrypt(fname)
- if not data:
- print("Failed to decrypt %s, skipping" % fname)
- continue
- if setup['decrypt_stdout']:
- if len(setup['args']) > 1:
- print("----- %s -----" % fname)
- print(data)
- if len(setup['args']) > 1:
- print("")
- else:
- encryptor.write_decrypted(fname, data=data)
+ xform = encryptor.encrypt
+ write = encryptor.write_encrypted
+ elif setup['decrypt']:
+ xform = encryptor.decrypt
+ write = encryptor.write_decrypted
else:
logger.info("Neither --encrypt nor --decrypt specified, "
"determining mode")
- if not encryptor.decrypt(fname):
+ data = encryptor.decrypt(fname)
+ if data:
+ write = encryptor.write_decrypted
+ else:
logger.info("Failed to decrypt %s, trying encryption" % fname)
- if not encryptor.encrypt(fname):
- print("Failed to encrypt %s, skipping" % fname)
+ data = None
+ xform = encryptor.encrypt
+ write = encryptor.write_encrypted
+
+ if data is None:
+ data = xform(fname)
+ if not data:
+ print("Failed to %s %s, skipping" % (xform.__name__, fname))
+ if setup['crypt_stdout']:
+ if len(setup['args']) > 1:
+ print("----- %s -----" % fname)
+ print(data)
+ if len(setup['args']) > 1:
+ print("")
+ else:
+ write(fname, data=data)
if setup['remove'] and encryptor.get_encrypted_filename(fname) != fname:
try:
diff --git a/tools/manpagegen/bcfg2-crypt.8.ronn b/tools/manpagegen/bcfg2-crypt.8.ronn
index a164d47f1..64077ec3b 100644
--- a/tools/manpagegen/bcfg2-crypt.8.ronn
+++ b/tools/manpagegen/bcfg2-crypt.8.ronn
@@ -3,7 +3,7 @@ bcfg2-crypt(8) -- Bcfg2 encryption and decryption utility
## SYNOPSIS
-`bcfg2-crypt` [<-C configfile>] [--decrypt|--encrypt] [--cfg|--properties] [--remove] [--xpath <xpath>] [-p <passphrase-or-name>] [-v] <filename> [<filename>...]
+`bcfg2-crypt` [<-C configfile>] [--decrypt|--encrypt] [--cfg|--properties] [--stdout] [--remove] [--xpath <xpath>] [-p <passphrase-or-name>] [-v] [-I] <filename> [<filename>...]
## DESCRIPTION
@@ -35,6 +35,10 @@ what to do.
than `<Properties>` in your Properties files. See [MODES] below
for details.
+ * `--stdout`:
+ Print the resulting file to stdout instead of writing it to a
+ file.
+
* `--remove`:
Remove the plaintext file after it has been encrypted. Only
meaningful for Cfg files.
@@ -53,6 +57,10 @@ what to do.
* `-v`:
Be verbose.
+ * `-I`:
+ When encrypting a Properties file, interactively select the
+ elements whose data should be encrypted.
+
* `-h`:
Display help and exit.