summaryrefslogtreecommitdiffstats
path: root/src/lib/Bcfg2/Client/Tools/POSIX
diff options
context:
space:
mode:
authorSol Jerome <sol.jerome@gmail.com>2014-04-16 10:16:29 -0500
committerSol Jerome <sol.jerome@gmail.com>2014-04-16 10:16:29 -0500
commitd510e918e41b7b2b7b0b9351a40eab2794b49c83 (patch)
tree250715ab112c10612ee131925ad07b68591c09f3 /src/lib/Bcfg2/Client/Tools/POSIX
parent9ebdcdb2f7718ae9203b20dafea4bca9f310ed75 (diff)
parent24a261f842a4bc1d4dc125fad0f43343d5d4c9d8 (diff)
downloadbcfg2-d510e918e41b7b2b7b0b9351a40eab2794b49c83.tar.gz
bcfg2-d510e918e41b7b2b7b0b9351a40eab2794b49c83.tar.bz2
bcfg2-d510e918e41b7b2b7b0b9351a40eab2794b49c83.zip
Merge branch 'maint' into master
Signed-off-by: Sol Jerome <sol.jerome@gmail.com> Conflicts: doc/appendix/guides/import-existing-ssh-keys.txt misc/bcfg2.spec src/lib/Bcfg2/Client/Tools/VCS.py src/lib/Bcfg2/Client/Tools/YUM.py src/lib/Bcfg2/Encryption.py src/lib/Bcfg2/Reporting/Collector.py src/lib/Bcfg2/Reporting/Storage/DjangoORM.py src/lib/Bcfg2/Server/Core.py src/lib/Bcfg2/Server/FileMonitor/__init__.py src/lib/Bcfg2/Server/Lint/RequiredAttrs.py src/lib/Bcfg2/Server/Plugin/helpers.py src/lib/Bcfg2/Server/Plugins/Metadata.py src/lib/Bcfg2/Server/Plugins/Packages/Yum.py src/lib/Bcfg2/Server/Plugins/Packages/__init__.py src/lib/Bcfg2/settings.py src/sbin/bcfg2-crypt src/sbin/bcfg2-reports src/sbin/bcfg2-yum-helper testsuite/Testsrc/Testlib/TestClient/TestTools/TestPOSIX/TestAugeas.py
Diffstat (limited to 'src/lib/Bcfg2/Client/Tools/POSIX')
-rw-r--r--src/lib/Bcfg2/Client/Tools/POSIX/Augeas.py32
-rw-r--r--src/lib/Bcfg2/Client/Tools/POSIX/base.py116
2 files changed, 94 insertions, 54 deletions
diff --git a/src/lib/Bcfg2/Client/Tools/POSIX/Augeas.py b/src/lib/Bcfg2/Client/Tools/POSIX/Augeas.py
index 4f6953b2a..dc5fc6755 100644
--- a/src/lib/Bcfg2/Client/Tools/POSIX/Augeas.py
+++ b/src/lib/Bcfg2/Client/Tools/POSIX/Augeas.py
@@ -4,6 +4,7 @@ import sys
import Bcfg2.Client.XML
from augeas import Augeas
from Bcfg2.Client.Tools.POSIX.base import POSIXTool
+from Bcfg2.Client.Tools.POSIX.File import POSIXFile
class AugeasCommand(object):
@@ -187,13 +188,14 @@ class Insert(AugeasCommand):
class POSIXAugeas(POSIXTool):
""" Handle <Path type='augeas'...> entries. See
:ref:`client-tools-augeas`. """
-
- __handles__ = [('Path', 'augeas')]
- __req__ = {'Path': ['type', 'name', 'setting', 'value']}
+ __req__ = ['name', 'mode', 'owner', 'group']
def __init__(self, config):
POSIXTool.__init__(self, config)
self._augeas = dict()
+ # file tool for setting initial values of files that don't
+ # exist
+ self.filetool = POSIXFile(logger, setup, config)
def get_augeas(self, entry):
""" Get an augeas object for the given entry. """
@@ -214,9 +216,9 @@ class POSIXAugeas(POSIXTool):
return self._augeas[entry.get("name")]
def fully_specified(self, entry):
- return entry.text is not None
+ return len(entry.getchildren()) != 0
- def get_commands(self, entry, unverified=False):
+ def get_commands(self, entry):
""" Get a list of commands to verify or install.
@param entry: The entry to get commands from.
@@ -229,7 +231,7 @@ class POSIXAugeas(POSIXTool):
"""
rv = []
for cmd in entry.iterchildren():
- if unverified and cmd.get("verified", "false") != "false":
+ if cmd.tag == "Initial":
continue
if cmd.tag in globals():
rv.append(globals()[cmd.tag](cmd, self.get_augeas(entry),
@@ -266,7 +268,18 @@ class POSIXAugeas(POSIXTool):
def install(self, entry):
rv = True
- for cmd in self.get_commands(entry, unverified=True):
+ if entry.get("current_exists", "true") == "false":
+ initial = entry.find("Initial")
+ if initial is not None:
+ self.logger.debug("Augeas: Setting initial data for %s" %
+ entry.get("name"))
+ file_entry = Bcfg2.Client.XML.Element("Path",
+ **dict(entry.attrib))
+ file_entry.text = initial.text
+ self.filetool.install(file_entry)
+ # re-parse the file
+ self.get_augeas(entry).load()
+ for cmd in self.get_commands(entry):
try:
cmd.install()
except: # pylint: disable=W0702
@@ -277,8 +290,7 @@ class POSIXAugeas(POSIXTool):
try:
self.get_augeas(entry).save()
except: # pylint: disable=W0702
- self.logger.error(
- "Failure saving Augeas changes to %s: %s" %
- (entry.get("name"), sys.exc_info()[1]))
+ self.logger.error("Failure saving Augeas changes to %s: %s" %
+ (entry.get("name"), sys.exc_info()[1]))
rv = False
return POSIXTool.install(self, entry) and rv
diff --git a/src/lib/Bcfg2/Client/Tools/POSIX/base.py b/src/lib/Bcfg2/Client/Tools/POSIX/base.py
index 712620206..8895eaae1 100644
--- a/src/lib/Bcfg2/Client/Tools/POSIX/base.py
+++ b/src/lib/Bcfg2/Client/Tools/POSIX/base.py
@@ -217,18 +217,13 @@ class POSIXTool(Bcfg2.Client.Tools.Tool):
acl.delete_entry(aclentry)
if os.path.isdir(path):
defacl = posix1e.ACL(filedef=path)
- if not defacl.valid():
- # when a default ACL is queried on a directory that
- # has no default ACL entries at all, you get an empty
- # ACL, which is not valid. in this circumstance, we
- # just copy the access ACL to get a base valid ACL
- # that we can add things to.
- defacl = posix1e.ACL(acl=acl)
- else:
- for aclentry in defacl:
- if aclentry.tag_type in [posix1e.ACL_USER,
- posix1e.ACL_GROUP]:
- defacl.delete_entry(aclentry)
+ for aclentry in defacl:
+ if aclentry.tag_type in [posix1e.ACL_USER,
+ posix1e.ACL_USER_OBJ,
+ posix1e.ACL_GROUP,
+ posix1e.ACL_GROUP_OBJ,
+ posix1e.ACL_OTHER]:
+ defacl.delete_entry(aclentry)
else:
defacl = None
@@ -254,10 +249,16 @@ class POSIXTool(Bcfg2.Client.Tools.Tool):
try:
if scope == posix1e.ACL_USER:
scopename = "user"
- aclentry.qualifier = self._norm_uid(qualifier)
+ if qualifier:
+ aclentry.qualifier = self._norm_uid(qualifier)
+ else:
+ aclentry.tag_type = posix1e.ACL_USER_OBJ
elif scope == posix1e.ACL_GROUP:
scopename = "group"
- aclentry.qualifier = self._norm_gid(qualifier)
+ if qualifier:
+ aclentry.qualifier = self._norm_gid(qualifier)
+ else:
+ aclentry.tag_type = posix1e.ACL_GROUP_OBJ
except (OSError, KeyError):
err = sys.exc_info()[1]
self.logger.error("POSIX: Could not resolve %s %s: %s" %
@@ -358,7 +359,7 @@ class POSIXTool(Bcfg2.Client.Tools.Tool):
try:
# single octal digit
rv = int(perms)
- if rv > 0 and rv < 8:
+ if rv >= 0 and rv < 8:
return rv
else:
self.logger.error("POSIX: Permissions digit out of range in "
@@ -388,13 +389,17 @@ class POSIXTool(Bcfg2.Client.Tools.Tool):
""" Get a string representation of the given ACL. aclkey must
be a tuple of (<acl type>, <acl scope>, <qualifier>) """
atype, scope, qualifier = aclkey
+ if not qualifier:
+ qualifier = ''
acl_str = []
if atype == 'default':
acl_str.append(atype)
- if scope == posix1e.ACL_USER:
+ if scope == posix1e.ACL_USER or scope == posix1e.ACL_USER_OBJ:
acl_str.append("user")
- elif scope == posix1e.ACL_GROUP:
+ elif scope == posix1e.ACL_GROUP or scope == posix1e.ACL_GROUP_OBJ:
acl_str.append("group")
+ elif scope == posix1e.ACL_OTHER:
+ acl_str.append("other")
acl_str.append(qualifier)
acl_str.append(self._acl_perm2string(perms))
return ":".join(acl_str)
@@ -414,7 +419,7 @@ class POSIXTool(Bcfg2.Client.Tools.Tool):
""" Get data on the existing state of <path> -- e.g., whether
or not it exists, owner, group, permissions, etc. """
try:
- ondisk = os.stat(path)
+ ondisk = os.lstat(path)
except OSError:
self.logger.debug("POSIX: %s does not exist" % path)
return (False, None, None, None, None, None)
@@ -451,7 +456,7 @@ class POSIXTool(Bcfg2.Client.Tools.Tool):
if HAS_SELINUX:
try:
- secontext = selinux.getfilecon(path)[1].split(":")[2]
+ secontext = selinux.lgetfilecon(path)[1].split(":")[2]
except (OSError, KeyError):
err = sys.exc_info()[1]
self.logger.debug("POSIX: Could not get current SELinux "
@@ -460,7 +465,7 @@ class POSIXTool(Bcfg2.Client.Tools.Tool):
else:
secontext = None
- if HAS_ACLS:
+ if HAS_ACLS and not stat.S_ISLNK(ondisk[stat.ST_MODE]):
acls = self._list_file_acls(path)
else:
acls = None
@@ -562,9 +567,17 @@ class POSIXTool(Bcfg2.Client.Tools.Tool):
wanted = dict()
for acl in entry.findall("ACL"):
if acl.get("scope") == "user":
- scope = posix1e.ACL_USER
+ if acl.get("user"):
+ scope = posix1e.ACL_USER
+ else:
+ scope = posix1e.ACL_USER_OBJ
elif acl.get("scope") == "group":
- scope = posix1e.ACL_GROUP
+ if acl.get("group"):
+ scope = posix1e.ACL_GROUP
+ else:
+ scope = posix1e.ACL_GROUP_OBJ
+ elif acl.get("scope") == "other":
+ scope = posix1e.ACL_OTHER
else:
self.logger.error("POSIX: Unknown ACL scope %s" %
acl.get("scope"))
@@ -573,7 +586,10 @@ class POSIXTool(Bcfg2.Client.Tools.Tool):
self.logger.error("POSIX: No permissions set for ACL: %s" %
Bcfg2.Client.XML.tostring(acl))
continue
- wanted[(acl.get("type"), scope, acl.get(acl.get("scope")))] = \
+ qual = acl.get(acl.get("scope"))
+ if not qual:
+ qual = ''
+ wanted[(acl.get("type"), scope, qual)] = \
self._norm_acl_perms(acl.get('perms'))
return wanted
@@ -587,11 +603,12 @@ class POSIXTool(Bcfg2.Client.Tools.Tool):
""" Given an ACL object, process it appropriately and add
it to the return value """
try:
+ qual = ''
if acl.tag_type == posix1e.ACL_USER:
qual = pwd.getpwuid(acl.qualifier)[0]
elif acl.tag_type == posix1e.ACL_GROUP:
qual = grp.getgrgid(acl.qualifier)[0]
- else:
+ elif atype == "access" or acl.tag_type == posix1e.ACL_MASK:
return
except (OSError, KeyError):
err = sys.exc_info()[1]
@@ -621,9 +638,38 @@ class POSIXTool(Bcfg2.Client.Tools.Tool):
_process_acl(acl, "default")
return existing
- def _verify_acls(self, entry, path=None):
+ def _verify_acls(self, entry, path=None): # pylint: disable=R0912
""" verify POSIX ACLs on the given entry. return True if all
ACLS are correct, false otherwise """
+ def _verify_acl(aclkey, perms):
+ """ Given ACL data, process it appropriately and add it to
+ missing or wrong lists if appropriate """
+ if aclkey not in existing:
+ missing.append(self._acl2string(aclkey, perms))
+ elif existing[aclkey] != perms:
+ wrong.append((self._acl2string(aclkey, perms),
+ self._acl2string(aclkey, existing[aclkey])))
+ if path == entry.get("name"):
+ atype, scope, qual = aclkey
+ aclentry = Bcfg2.Client.XML.Element("ACL", type=atype,
+ perms=str(perms))
+ if (scope == posix1e.ACL_USER or
+ scope == posix1e.ACL_USER_OBJ):
+ aclentry.set("scope", "user")
+ elif (scope == posix1e.ACL_GROUP or
+ scope == posix1e.ACL_GROUP_OBJ):
+ aclentry.set("scope", "group")
+ elif scope == posix1e.ACL_OTHER:
+ aclentry.set("scope", "other")
+ else:
+ self.logger.debug("POSIX: Unknown ACL scope %s on %s" %
+ (scope, path))
+ return
+
+ if scope != posix1e.ACL_OTHER:
+ aclentry.set(aclentry.get("scope"), qual)
+ entry.append(aclentry)
+
if not HAS_ACLS:
if entry.findall("ACL"):
self.logger.debug("POSIX: ACLs listed for %s but no pylibacl "
@@ -644,25 +690,7 @@ class POSIXTool(Bcfg2.Client.Tools.Tool):
extra = []
wrong = []
for aclkey, perms in wanted.items():
- if aclkey not in existing:
- missing.append(self._acl2string(aclkey, perms))
- elif existing[aclkey] != perms:
- wrong.append((self._acl2string(aclkey, perms),
- self._acl2string(aclkey, existing[aclkey])))
- if path == entry.get("name"):
- atype, scope, qual = aclkey
- aclentry = Bcfg2.Client.XML.Element("ACL", type=atype,
- perms=str(perms))
- if scope == posix1e.ACL_USER:
- aclentry.set("scope", "user")
- elif scope == posix1e.ACL_GROUP:
- aclentry.set("scope", "group")
- else:
- self.logger.debug("POSIX: Unknown ACL scope %s on %s" %
- (scope, path))
- continue
- aclentry.set(aclentry.get("scope"), qual)
- entry.append(aclentry)
+ _verify_acl(aclkey, perms)
for aclkey, perms in existing.items():
if aclkey not in wanted: