[PATCH 12/18] gpo: Added the cases where GPO is deleted from OU or altogether, modularized, and fine tuned hierarchy order
David Mulder
dmulder at suse.com
Thu Feb 23 20:22:04 UTC 2017
From: Luke Morrison <luc785 at hotmail.com>
Signed-off-by: Garming Sam <garming at catalyst.net.nz>
Signed-off-by: Luke Morrison <luke at hubtrek.com>
---
python/samba/gpclass.py | 38 +++++++++++++++++++++----
source4/scripting/bin/samba_gpoupdate | 52 ++++++++++++++++++++++-------------
2 files changed, 65 insertions(+), 25 deletions(-)
diff --git a/python/samba/gpclass.py b/python/samba/gpclass.py
index adebcb5..0b2159b 100755
--- a/python/samba/gpclass.py
+++ b/python/samba/gpclass.py
@@ -118,10 +118,11 @@ class gp_sec_ext(gp_ext):
"PasswordComplexity": ("pwdProperties", inf_to_ldb),
}
}
-#FIXME. EACH gpo should have a parser, and a creater. Essentially a gpo is just a file. Possibly a method and class to link it to organization unit (if that already does not exist) so that GPO's can be created arithmetically, possibly with a hashtable for certain GPO, then linked if desired. Also could store a backup folder of gpo's and then configure them without necessarily deploying it.
def read_inf(self, path, conn, attr_log):
+ ret = False
inftable = self.populate_inf()
+
try:
policy = conn.loadfile(path).decode('utf-16')
except:
@@ -129,6 +130,13 @@ class gp_sec_ext(gp_ext):
current_section = None
LOG = open(attr_log, "a")
LOG.write(str(path.split('/')[2]) + '\n')
+
+ # So here we would declare a boolean,
+ # that would get changed to TRUE.
+ #
+ # If at any point in time a GPO was applied,
+ # then we return that boolean at the end.
+
for line in policy.splitlines():
line = line.strip()
if line[0] == '[':
@@ -144,10 +152,9 @@ class gp_sec_ext(gp_ext):
if current_section.get(key):
(att, setter) = current_section.get(key)
value = value.encode('ascii', 'ignore')
- # so value is the value that it contains, and the att is the attribute
- LOG.write(att + ' ' + value + '\n')
- # copy and paste this logic to backwalk deleted GPO
+ ret = True
setter(self.ldb, self.dn, att, value).update_samba()
+ return ret
def parse(self, afile, ldb, conn, attr_log):
self.ldb = ldb
@@ -165,6 +172,23 @@ def scan_log(sysvol_path):
data[guid] = int(version)
return data
+
+def Reset_Defaults(test_ldb):
+ test_ldb.set_minPwdAge(str(-25920000000000))
+ test_ldb.set_maxPwdAge(str(-38016000000000))
+ test_ldb.set_minPwdLength(str(7))
+ test_ldb.set_pwdProperties(str(1))
+
+
+def check_deleted(guid_list, backloggpo):
+ if backloggpo is None:
+ return False
+ for guid in backloggpo:
+ if guid not in guid_list:
+ return True
+ return False
+
+
# The hierarchy is as per MS http://msdn.microsoft.com/en-us/library/windows/desktop/aa374155%28v=vs.85%29.aspx
#
# It does not care about local GPO, because GPO and snap-ins are not made in Linux yet.
@@ -265,8 +289,9 @@ def establish_hierarchy(SamDB, GUID_LIST, DC_OU, global_dn):
unapplied_gpo = []
# Sorted by container
sorted_gpo_list = []
- '''Since the unapplied GPO are put at the front of the list, just once again append them to the linked container sorted list'''
- while count < indexed_places[0]:
+
+ # Unapplied GPO live at start of list, append them to final list
+ while final_list[0][1] == False:
unapplied_gpo.append(final_list[count])
count += 1
count = 0
@@ -274,6 +299,7 @@ def establish_hierarchy(SamDB, GUID_LIST, DC_OU, global_dn):
# A single container call gets the linked order for all GPO in container.
# So we need one call per container - > index of the Original list
+ indexed_places.insert(0, 0)
while count < (len(indexed_places)-1):
sorted_gpo_list += (sort_linked(SamDB, final_list, indexed_places[count], indexed_places[count+1]))
count += 1
diff --git a/source4/scripting/bin/samba_gpoupdate b/source4/scripting/bin/samba_gpoupdate
index 1388bf7..e0337f4 100755
--- a/source4/scripting/bin/samba_gpoupdate
+++ b/source4/scripting/bin/samba_gpoupdate
@@ -24,6 +24,7 @@ from samba.net import Net
from samba.dcerpc import nbt
from samba import smb
+
# Finds all GPO Files ending in inf
def gp_path_list(path):
@@ -32,6 +33,7 @@ def gp_path_list(path):
GPO_LIST.append((ext, ext.list(path)))
return GPO_LIST
+
def gpo_parser(GPO_LIST, ldb, conn, attr_log):
'''The API method to parse the GPO
:param GPO_LIST:
@@ -41,9 +43,14 @@ def gpo_parser(GPO_LIST, ldb, conn, attr_log):
no return except a newly updated Samba
'''
+ ret = False
for entry in GPO_LIST:
(ext, thefile) = entry
- ext.parse(thefile, ldb, conn, attr_log)
+ if ret == False:
+ ret = ext.parse(thefile, ldb, conn, attr_log)
+ else:
+ temp = ext.parse(thefile, ldb, conn, attr_log)
+ return ret
class GPOServiceSetup:
@@ -152,6 +159,8 @@ BackLoggedGPO = None
sys_log = '%s/%s' % (lp.get("path", "sysvol"), 'syslog.txt')
attr_log = '%s/%s' % (lp.get("path", "sysvol"), 'attrlog.txt')
BackLoggedGPO = GetBackLog(sys_log)
+
+
BackLog = open(sys_log, "w")
@@ -173,38 +182,43 @@ DC_OU = "OU=Domain Controllers" + ',' + global_dn
# Set up a List of the GUID for all GPO's
guid_list = [x['name'] for x in conn.list('%s/Policies' % lp.get("realm").lower())]
+SYSV_PATH = '%s/%s/%s' % (lp.get("path", "sysvol"), lp.get("realm"), 'Policies')
-#Power through the Microsoft Hierarchy with Linking Order included
-#FIXME could be SO much more efficient if we get the dn if the DC, then use that to get all its containers
-#Then use the acquired containers of DC dn, to get all GPO in a convenient linking order with linking order already taken into account
hierarchy_gpos = establish_hierarchy(test_ldb, guid_list, DC_OU, global_dn)
-
-#At this point we have a list of hierarchically applied GPOS
-#Say for example a GPO was deleted, we can either
-#1)Reset ALL Defaults and then call script to apply all GPO
-#2)Find which attribute, fall back on previous attribute. THat way when we call this script, it only still applies the GPO that has changed
-#2 is more favorable because we are minimally changing Samba
+change_backlog = False
+
+# Take a local list of all current GPO list and run it against previous GPO's
+# to see if something has changed. If so reset default and re-apply GPO.
+Applicable_GPO = []
+for i in hierarchy_gpos:
+ Applicable_GPO += i
+
+# Flag gets set when
+GPO_Changed = False
+GPO_Deleted = check_deleted(Applicable_GPO, BackLoggedGPO)
+if (GPO_Deleted):
+ # Null the backlog
+ BackLoggedGPO = {}
+ # Reset defaults then overwrite them
+ Reset_Defaults(test_ldb)
+ GPO_Changed = False
for guid_eval in hierarchy_gpos:
guid = guid_eval[0]
gp_extensions = [gp_sec_ext()]
local_path = '%s/Policies' % lp.get("realm").lower() + '/' + guid + '/'
version = gpo.gpo_get_sysvol_gpt_version(lp.get("path", "sysvol") + '/' + local_path)[1]
-
gpolist = gp_path_list(local_path)
-
-
- '''If an important GPO parse it. Will not parse if it has not changed, is empty, or is not in the right container'''
+ if(version != BackLoggedGPO.get(guid)):
+ GPO_Changed = True
# If the GPO has a dn that is applicable to Samba
if guid_eval[1]:
# If it has a GPO file that could apply to Samba
if gpolist[0][1]:
# If it we have not read it before and is not empty
- #We need to rewrite
- if (version != BackLoggedGPO.get(guid)) and (version != 0):
- print ('GPO %s has changed' % guid)
- #Apply to Samba
- gpo_parser(gpolist, test_ldb, conn, attr_log)
+ # Rewrite entire logfile here
+ if (version != 0) and GPO_Changed == True:
+ change_backlog = gpo_parser(gpolist, test_ldb, conn, attr_log)
BackLog.write('%s %i\n' % (guid, version))
--
2.10.2
More information about the samba-technical
mailing list