Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 12 additions & 9 deletions EA-MakeMeAdmin_ComplianceCheck.py
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
#!/usr/bin/env python
#!/Library/ManagedFrameworks/Python/Python3.framework/Versions/Current/bin/python3

import os, plistlib, subprocess

workingDir = '/usr/local/jamfps/' # working directory for script
statusFile = 'MakeMeAdmin.Status.plist' # compliancy check plist location

if os.path.exists(workingDir + statusFile):
status = plistlib.readPlist(workingDir + statusFile).Status
if status == 'Compliant':
print '<result>' + status + '</result>'
else:
newAdm = plistlib.readPlist(workingDir + statusFile).newAdmins
orgAdm = plistlib.readPlist(workingDir + statusFile).orgAdmin
print '<result>' + status + ' - ' + newAdm + ' - ' + orgAdm + '</result>'
with open(workingDir + statusFile, 'rb') as fp:
d = plistlib.load(fp)
status = d["Status"]

if status == 'Compliant':
print('<result>' + status + '</result>')
else:
newAdm = d["newAdmins"]
orgAdm = d["orgAdmin"]
print('<result>' + status + ' - ' + newAdm + ' - ' + orgAdm + '</result>')
else:
print '<result>' + 'Compliant' + '</result>'
print('<result>' + 'Compliant' + '</result>')
32 changes: 32 additions & 0 deletions EA-adminElevations24h.py
Original file line number Diff line number Diff line change
@@ -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(('<result>' + str(elevationCount) + '</result>'))
24 changes: 14 additions & 10 deletions grantTempAdmin.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/Library/ManagedFrameworks/Python/Python3.framework/Versions/Current/bin/python3

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#
Expand All @@ -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
Expand Down Expand Up @@ -55,6 +56,7 @@
# Updated On: July 26th, 2017
#
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Updated On: April 20th, 2022 - python3

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# IMPORTS
Expand Down Expand Up @@ -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])

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
Expand All @@ -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"])
Expand All @@ -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)
105 changes: 57 additions & 48 deletions removeTempAdmin.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/Library/ManagedFrameworks/Python/Python3.framework/Versions/Current/bin/python3

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#
Expand Down Expand Up @@ -55,6 +55,7 @@
# Updated On: July 26th, 2017
#
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Updated On: April 20th, 2022 - python3

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# IMPORTS
Expand Down Expand Up @@ -82,56 +83,60 @@

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
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

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)
Expand All @@ -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
Expand Down