diff --git a/EA-MakeMeAdmin_ComplianceCheck.py b/EA-MakeMeAdmin_ComplianceCheck.py
old mode 100644
new mode 100755
index 3884b83..1ca3650
--- a/EA-MakeMeAdmin_ComplianceCheck.py
+++ b/EA-MakeMeAdmin_ComplianceCheck.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/Library/ManagedFrameworks/Python/Python3.framework/Versions/Current/bin/python3
import os, plistlib, subprocess
@@ -6,12 +6,15 @@
statusFile = 'MakeMeAdmin.Status.plist' # compliancy check plist location
if os.path.exists(workingDir + statusFile):
- status = plistlib.readPlist(workingDir + statusFile).Status
- if status == 'Compliant':
- print '' + status + ''
- else:
- newAdm = plistlib.readPlist(workingDir + statusFile).newAdmins
- orgAdm = plistlib.readPlist(workingDir + statusFile).orgAdmin
- print '' + status + ' - ' + newAdm + ' - ' + orgAdm + ''
+ with open(workingDir + statusFile, 'rb') as fp:
+ d = plistlib.load(fp)
+ status = d["Status"]
+
+ if status == 'Compliant':
+ print('' + status + '')
+ else:
+ newAdm = d["newAdmins"]
+ orgAdm = d["orgAdmin"]
+ print('' + status + ' - ' + newAdm + ' - ' + orgAdm + '')
else:
- print '' + 'Compliant' + ''
\ No newline at end of file
+ print('' + 'Compliant' + '')
diff --git a/EA-adminElevations24h.py b/EA-adminElevations24h.py
new file mode 100755
index 0000000..0e37179
--- /dev/null
+++ b/EA-adminElevations24h.py
@@ -0,0 +1,32 @@
+#!/Library/ManagedFrameworks/Python/Python3.framework/Versions/Current/bin/python3
+
+from datetime import date, timedelta, datetime
+
+workingDir = '/usr/local/jamfps/' # working directory for script
+tempAdminLog = 'tempAdmin.log' # script log file
+
+fmt = '%Y-%m-%d %H:%M:%S.%f'
+
+stop = datetime.now()
+start = stop - timedelta(days=1)
+
+elevationCount=0
+
+try:
+ with open(workingDir + tempAdminLog, 'r') as file:
+ for line in file:
+ line = line.strip()
+
+ try:
+ ts = datetime.strptime(' '.join(line.split()[:2]), fmt)
+
+ if start <= ts <= stop:
+ if "Granted" in line:
+ elevationCount=elevationCount+1
+
+ except:
+ pass
+except:
+ pass
+
+print(('' + str(elevationCount) + ''))
diff --git a/grantTempAdmin.py b/grantTempAdmin.py
index c97388e..f57c6af 100644
--- a/grantTempAdmin.py
+++ b/grantTempAdmin.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/Library/ManagedFrameworks/Python/Python3.framework/Versions/Current/bin/python3
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#
@@ -13,6 +13,7 @@
# documentation and/or other materials provided with the distribution.
# * Neither the name of the Jamf nor the names of its contributors may be
# used to endorse or promote products derived from this software without
+# used to endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY JAMF SOFTWARE, LLC "AS IS" AND ANY
@@ -55,6 +56,7 @@
# Updated On: July 26th, 2017
#
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+# Updated On: April 20th, 2022 - python3
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# IMPORTS
@@ -83,23 +85,24 @@
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# place launchd plist to call JSS policy to remove admin rights.
-print 'Creating LaunchDaemon...'
+print('Creating LaunchDaemon...')
launchDaemon = { 'Label':launchdLabel,
'LaunchOnlyOnce':True,
'ProgramArguments':['/usr/local/jamf/bin/jamf', 'policy', '-trigger', policyCustomTrigger],
'StartInterval':adminTimer,
'UserName':'root',
}
-plistlib.writePlist(launchDaemon, '/Library/LaunchDaemons/' + launchdFile)
+with open('/Library/LaunchDaemons/' + launchdFile, "wb") as fp:
+ plistlib.dump(launchDaemon, fp)
# set the permission on the file just made.
userID = pwd.getpwnam("root").pw_uid
groupID = grp.getgrnam("wheel").gr_gid
os.chown('/Library/LaunchDaemons/' + launchdFile, userID, groupID)
-os.chmod('/Library/LaunchDaemons/' + launchdFile, 0644)
+os.chmod('/Library/LaunchDaemons/' + launchdFile, 0o644)
-# load the removal plist timer.
-print 'Loading LaunchDaemon...'
+# load the removal plist timer.
+print('Loading LaunchDaemon...')
subprocess.call(["launchctl", "load", "-w", '/Library/LaunchDaemons/' + launchdFile])
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
@@ -112,12 +115,13 @@
# record user that will need to have admin rights removed
# record current existing admins
-print 'Retrieving List of Current Admins...'
+print('Retrieving List of Current Admins...')
currentAdmins = grp.getgrnam('admin').gr_mem
-print 'Updating Plist...'
+print('Updating Plist...')
plist = { 'User2Remove':userName,
'CurrentAdminUsers':currentAdmins}
-plistlib.writePlist(plist, workingDir + plistFile)
+with open(workingDir + plistFile, "wb") as fp:
+ plistlib.dump(plist, fp)
# give current logged user admin rights
subprocess.call(["dseditgroup", "-o", "edit", "-a", userName, "-t", "user", "admin"])
@@ -127,4 +131,4 @@
log.write("{} - MakeMeAdmin Granted Admin Rights for {}\r\n".format(datetime.now(), userName))
log.close()
-print 'Granted Admin Right to ' + userName
+print('Granted Admin Right to ' + userName)
diff --git a/removeTempAdmin.py b/removeTempAdmin.py
index 9598c88..f96c395 100644
--- a/removeTempAdmin.py
+++ b/removeTempAdmin.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/Library/ManagedFrameworks/Python/Python3.framework/Versions/Current/bin/python3
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#
@@ -55,6 +55,7 @@
# Updated On: July 26th, 2017
#
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+# Updated On: April 20th, 2022 - python3
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# IMPORTS
@@ -82,8 +83,8 @@
def DecryptString(inputString, salt, passphrase):
'''Usage: >>> DecryptString("Encrypted String", "Salt", "Passphrase")'''
- p = subprocess.Popen(['/usr/bin/openssl', 'enc', '-aes256', '-d', '-a', '-A', '-S', salt, '-k', passphrase], stdin = subprocess.PIPE, stdout = subprocess.PIPE)
- return p.communicate(inputString)[0]
+ p = subprocess.Popen(['/usr/bin/openssl', 'enc', '-aes256', '-d', '-md', 'md5', '-a', '-A', '-S', salt, '-k', passphrase], stdin = subprocess.PIPE, stdout = subprocess.PIPE)
+ return p.communicate(inputString.encode())[0]
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# APPLICATION
@@ -91,47 +92,51 @@ def DecryptString(inputString, salt, passphrase):
if os.path.exists(workingDir + plistFile):
# remove user admin rights
- user2Remove = plistlib.readPlist(workingDir + plistFile).User2Remove
- subprocess.call(["dseditgroup", "-o", "edit", "-d", user2Remove, "-t", "user", "admin"])
- # add log entry
- log = open(workingDir + tempAdminLog, "a+")
- log.write("{} - MakeMeAdmin Removed Admin Rights for {}\r\n".format(datetime.now(), user2Remove))
- log.close()
- print 'Revoked Admin Rights for ' + user2Remove
- # compre prior to current admin lists
- print 'Checking for newly created admin accounts...'
- priorAdmins = plistlib.readPlist(workingDir + plistFile).CurrentAdminUsers
- currentAdmins = grp.getgrnam('admin').gr_mem
- newAdmins = set(currentAdmins).difference(set(priorAdmins))
- newAdm = ''
- if not newAdmins:
- print ' No New Accounts Found!'
- # update compliancy plist
- status = { 'Status':'Compliant'}
- plistlib.writePlist(status, workingDir + statusFile)
- else:
- print ' New Admin Accounts Found!'
+ with open(workingDir + plistFile, 'rb') as fp:
+ d = plistlib.load(fp)
+ user2Remove = d["User2Remove"]
+ subprocess.call(["dseditgroup", "-o", "edit", "-d", user2Remove, "-t", "user", "admin"])
+ # add log entry
log = open(workingDir + tempAdminLog, "a+")
- log.write("{} - MakeMeAdmin Discovered New Admin Accounts: {}\r\n".format(datetime.now(), list(newAdmins)))
+ log.write("{} - MakeMeAdmin Removed Admin Rights for {}\r\n".format(datetime.now(), user2Remove))
log.close()
- # update status plist
- status = { 'Status':'Remediated',
- 'newAdmins':'newAdmin Created',
- 'orgAdmin':'orgAdmin OK'}
- plistlib.writePlist(status, workingDir + statusFile)
- newAdm = plistlib.readPlist(workingDir + statusFile).newAdmins
- # loop through new admin accounts and remove admin rights
- print ' Removing Admin Rights for New Admin Accounts...'
- for user in newAdmins:
- subprocess.call(["dseditgroup", "-o", "edit", "-d", user, "-t", "user", "admin"])
+ print('Revoked Admin Rights for ' + user2Remove)
+ # compre prior to current admin lists
+ print('Checking for newly created admin accounts...')
+ priorAdmins = d["CurrentAdminUsers"]
+ currentAdmins = grp.getgrnam('admin').gr_mem
+ newAdmins = set(currentAdmins).difference(set(priorAdmins))
+ newAdm = ''
+ if not newAdmins:
+ print(' No New Accounts Found!')
+ # update compliancy plist
+ status = { 'Status':'Compliant'}
+ with open(workingDir + statusFile, "wb") as fp2:
+ plistlib.dump(status, fp2)
+ else:
+ print(' New Admin Accounts Found!')
+ newAdm = 'newAdmin Created'
log = open(workingDir + tempAdminLog, "a+")
- log.write("{} - MakeMeAdmin Removed Admin Rights for: {}\r\n".format(datetime.now(), user))
+ log.write("{} - MakeMeAdmin Discovered New Admin Accounts: {}\r\n".format(datetime.now(), list(newAdmins)))
log.close()
- print ' Removed Admin Rights for ' + user
- time.sleep(1)
+ # update status plist
+ status = { 'Status':'Remediated',
+ 'newAdmins':newAdm,
+ 'orgAdmin':'orgAdmin OK'}
+ with open(workingDir + statusFile, "wb") as fp2:
+ plistlib.dump(status, fp2)
+ # loop through new admin accounts and remove admin rights
+ print(' Removing Admin Rights for New Admin Accounts...')
+ for user in newAdmins:
+ subprocess.call(["dseditgroup", "-o", "edit", "-d", user, "-t", "user", "admin"])
+ log = open(workingDir + tempAdminLog, "a+")
+ log.write("{} - MakeMeAdmin Removed Admin Rights for: {}\r\n".format(datetime.now(), user))
+ log.close()
+ print(' Removed Admin Rights for ' + user)
+ time.sleep(1)
# check if organization admin(s) are valid
- print 'Checking organizational admin passwords...'
- for admin, admpass in orgAdmins.iteritems():
+ print('Checking organizational admin passwords...')
+ for admin, admpass in orgAdmins.items():
# decrypt password
admpassDecrypted = DecryptString(admpass, salt, passphrase)
time.sleep(1)
@@ -141,52 +146,56 @@ def DecryptString(inputString, salt, passphrase):
log = open(workingDir + tempAdminLog, "a+")
log.write("{} - orgAdmin Password is Valid \r\n".format(datetime.now()))
log.close()
- print 'Password for orgAdmin: ' + admin + ' is valid!'
+ print('Password for orgAdmin: ' + admin + ' is valid!')
else:
log = open(workingDir + tempAdminLog, "a+")
log.write("{} - orgAdmin Password is Invalid! \r\n".format(datetime.now()))
log.close()
result = subprocess.call(["dscl", ".", "passwd", "/Users/" + admin, admpassDecrypted])
time.sleep(3)
- print 'Password for orgAdmin: ' + admin + ' was invalid!'
+ print('Password for orgAdmin: ' + admin + ' was invalid!')
if result == 0:
log = open(workingDir + tempAdminLog, "a+")
log.write("{} - orgAdmin Password Successfully Reset! \r\n".format(datetime.now()))
log.close()
- print 'Password Successfully Reset for ' + admin + "!"
+ print('Password Successfully Reset for ' + admin + "!")
if not newAdm:
# update status plist
status = { 'Status':'Remediated',
'newAdmins':'No newAdmins',
'orgAdmin':'orgAdmin OK'}
- plistlib.writePlist(status, workingDir + statusFile)
+ with open(workingDir + statusFile, "wb") as fp2:
+ plistlib.dump(status, fp2)
else:
# update status plist
status = { 'Status':'Remediated',
'newAdmins':'newAdmin Created',
'orgAdmin':'orgAdmin OK'}
- plistlib.writePlist(status, workingDir + statusFile)
+ with open(workingDir + statusFile, "wb") as fp2:
+ plistlib.dump(status, fp2)
else:
log = open(workingDir + tempAdminLog, "a+")
log.write("{} - Error Resetting orgAdmin Password! \r\n".format(datetime.now()))
log.close()
- print 'Error Resetting Password for ' + admin + "!"
+ print('Error Resetting Password for ' + admin + "!")
if not newAdm:
# update status plist
status = { 'Status':'Violation',
'newAdmins':'No newAdmins',
'orgAdmin':'orgAdmin ERROR'}
- plistlib.writePlist(status, workingDir + statusFile)
+ with open(workingDir + statusFile, "wb") as fp2:
+ plistlib.dump(status, fp2)
else:
# update status plist
status = { 'Status':'Violation',
'newAdmins':'newAdmin Created',
'orgAdmin':'orgAdmin ERROR'}
- plistlib.writePlist(status, workingDir + statusFile)
+ with open(workingDir + statusFile, "wb") as fp2:
+ plistlib.dump(status, fp2)
os.remove(workingDir + plistFile)
if os.path.exists('/Library/LaunchDaemons/' + launchdFile):
- print 'Removing LaunchDaemon...'
+ print('Removing LaunchDaemon...')
os.remove('/Library/LaunchDaemons/' + launchdFile)
# Submit Jamf Pro Inventory