├── EA-MakeMeAdmin_ComplianceCheck.py
├── LICENSE.md
├── README.md
├── grantTempAdmin.py
└── removeTempAdmin.py
/EA-MakeMeAdmin_ComplianceCheck.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | import os, plistlib, subprocess
4 |
5 | workingDir = '/usr/local/jamfps/' # working directory for script
6 | statusFile = 'MakeMeAdmin.Status.plist' # compliancy check plist location
7 |
8 | if os.path.exists(workingDir + statusFile):
9 | status = plistlib.readPlist(workingDir + statusFile).Status
10 | if status == 'Compliant':
11 | print '' + status + ''
12 | else:
13 | newAdm = plistlib.readPlist(workingDir + statusFile).newAdmins
14 | orgAdm = plistlib.readPlist(workingDir + statusFile).orgAdmin
15 | print '' + status + ' - ' + newAdm + ' - ' + orgAdm + ''
16 | else:
17 | print '' + 'Compliant' + ''
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | **Copyright (c) 2017, Jamf. All rights reserved.**
2 |
3 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
4 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
5 | * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
6 | * 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 specific prior written permission.
7 |
8 | THIS SOFTWARE IS PROVIDED BY JAMF SOFTWARE, LLC "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JAMF SOFTWARE, LLC BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
9 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # MakeMeAdminPy
2 | ###### Updated MakeMeAdmin workflow from Andrina Kelly's JNUC2013 presentation now converted to Python with violation checking and remediation if additional accounts get created during the users time as a temporary admin.
3 | ___
4 | This script was designed to be used in a Self Service policy to allow users to become temporary administrators on their system for the time specifed as 'adminTimer'. Once the timer reaches zero, the users admin rights will be revoked and the system will be checked for any admin accounts that may have been created during the 'adminTimer'. If a user created an admin account it will be logged and reported back to Jamf Pro and then the admin rights will be revoked for those newly created accounts. We've also added the ability to enter your orgAdmin account(s) and verify those accounts are still valid and haven't been changed.
5 |
6 | Requirements:
7 | * Jamf Pro
8 | * Policy for enabling tempAdmin via Self Service
9 | * Policy to remove tempAdmin via custom trigger
10 | * Scripts: grantTempAdmin.py & removeTempAdmin.py
11 | * EA's: EA-MakeMeAdmin_ComplianceCheck.py
12 |
13 | Please reference https://github.com/brysontyrrell/EncryptedStrings for generating the encrypting password, salt, and passphrase strings.
14 |
15 |
16 | Written By: Joshua Roskos | Professional Services Engineer | Jamf
17 |
18 | Created On: June 20th, 2017 | Updated On: July 26th, 2017
19 | ___
20 |
21 | ### Why is this needed?
22 |
23 | This workflow has long been used by many organizations, however one issue always remained..."What if the user creates another admin account while they have admin rights?" Well, fear no more, as this script will capture the current admin users before granting temporary admin rights and then after it revokes the rights, it will check again and compare to see if any new accounts were created. If so, the status will be written to a plist and can then be captured via the EA (Extension Attribute) which can then be scoped via a Smart Computer Group.
24 |
25 |
26 | ### Implementation
27 |
28 | **Step 1 - Configure the Scripts**
29 |
30 | When you open the scripts you will find some user variables that will need to be defined as specified below:
31 | * grantTempAdmin.py - Lines 72-79
32 | * removeTempAdmin.py - Lines 70-77
33 | * EA-MakeMeAdmin_ComplianceCheck.py - Lines 5-6
34 |
35 | **Step 2 - Upload the EA**
36 |
37 | * Display Name: MakeMeAdmin - Compliance Status
38 | * Data Type: String
39 | * Inventory Display: {Your Choice}
40 | * Input Type: Script
41 | * Script: {Paste Contents of EA-MakeMeAdmin_ComplianceCheck.py}
42 |
43 | **Step 3 - Configure the Smart Group**
44 |
45 | *Create a Smart Group named "MakeMeAdmin - Violations" and ensure "Send email notification on membership change" is enabled.*
46 |
47 | | And/Or | Criteria | Operator | Value |
48 | | :---: | :---: | :---: | :---: |
49 | | | MakeMeAdmin - Compliance Status | Like | Remediated |
50 | | Or | MakeMeAdmin - Compliance Status | Like | Violation |
51 |
52 | **Step 4 - Create your policies**
53 |
54 | * Policy: MakeMeAdmin
55 | * Payload - General
56 | * Display Name: *MakeMeAdmin*
57 | * Enabled: *Checked*
58 | * Category: {Your Choice}
59 | * Trigger(s): *None*
60 | * Execution Frequency: *Once every day (recommended)*
61 | * Payload - Scripts
62 | * Scripts: *grantTempAdmin.py*
63 | * Scope
64 | * *Configure to your requirements*
65 | * Self Service
66 | * *Configure to your requirements*
67 | * User Interaction
68 | * Complete Message: *You have been granted admin rights for the next 30 minutes.*
69 | * Policy: MakeMeAdmin - Remove Admin Rights
70 | * Payload - General
71 | * Display Name: *MakeMeAdmin - Remove Admin Rights*
72 | * Enabled: *Checked*
73 | * Category: {Your Choice}
74 | * Trigger(s): Custom w/ Event *adminremove*
75 | * Execution Frequency: *Ongoing*
76 | * Payload - Scripts
77 | * Scripts: *removeTempAdmin.py*
78 | * Parameter 4: *Your orgAdmin password encrypted*
79 | * Scope
80 | * Targets: *All Computers*
81 | * User Interaction
82 | * Complete Message: *Time up! Your admin rights have been revoked.*
83 |
84 |
--------------------------------------------------------------------------------
/grantTempAdmin.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
4 | #
5 | # Copyright (c) 2017 Jamf. All rights reserved.
6 | #
7 | # Redistribution and use in source and binary forms, with or without
8 | # modification, are permitted provided that the following conditions are met:
9 | # * Redistributions of source code must retain the above copyright
10 | # notice, this list of conditions and the following disclaimer.
11 | # * Redistributions in binary form must reproduce the above copyright
12 | # notice, this list of conditions and the following disclaimer in the
13 | # documentation and/or other materials provided with the distribution.
14 | # * Neither the name of the Jamf nor the names of its contributors may be
15 | # used to endorse or promote products derived from this software without
16 | # specific prior written permission.
17 | #
18 | # THIS SOFTWARE IS PROVIDED BY JAMF SOFTWARE, LLC "AS IS" AND ANY
19 | # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 | # DISCLAIMED. IN NO EVENT SHALL JAMF SOFTWARE, LLC BE LIABLE FOR ANY
22 | # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 | #
29 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
30 |
31 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
32 | #
33 | # This script was modified from Andrina Kelly's version presented at JNUC2013 for allowing
34 | # a user to elevate their privelages to administrator once per day for 30 minutes. After
35 | # the 30 minutes if a user created a new admin account that account will have admin rights
36 | # also revoked. If the user changed the organization admin account password, that will also
37 | # be reset.
38 | #
39 | # To accomplish this the following will be performed:
40 | # - A launch daemon will be put in place in order to remove admin rights
41 | # - Log will be written to tempAdmin.log
42 | # - This policy in Jamf will be set to only be allowed once per day
43 | #
44 | # REQUIREMENTS:
45 | # - Jamf Pro
46 | # - Policy for enabling tempAdmin via Self Service
47 | # - Policy to remove tempAdmin via custom trigger
48 | # - tempAdmin.sh & removeTempAdmin.sh Scripts
49 | # - orgAdmin encrypted password specified in Jamf Pro parameter #4
50 | #
51 | #
52 | # Written by: Joshua Roskos | Professional Services Engineer | Jamf
53 | #
54 | # Created On: June 20th, 2017
55 | # Updated On: July 26th, 2017
56 | #
57 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
58 |
59 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
60 | # IMPORTS
61 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
62 |
63 | import os, plistlib, pwd, grp, subprocess, sys
64 | from SystemConfiguration import SCDynamicStoreCopyConsoleUser
65 | from datetime import datetime
66 |
67 |
68 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
69 | # VARIABLES
70 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
71 |
72 | userName = (SCDynamicStoreCopyConsoleUser(None, None, None) or [None])[0] # get the logged in user's name
73 | workingDir = '/usr/local/jamfps/' # working directory for script
74 | launchdFile = 'com.jamfps.adminremove.plist' # launch daemon file name
75 | launchdLabel = launchdFile.replace('.plist', '') # launch daemon label
76 | plistFile = 'MakeMeAdmin.plist' # settings file name
77 | tempAdminLog = 'tempAdmin.log' # script log file
78 | adminTimer = 1800 # how long should they have admin rights for (in seconds)
79 | policyCustomTrigger = 'adminremove' # custom trigger specified for removeTempAdmin.py policy
80 |
81 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
82 | # LAUNCH DAEMON
83 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
84 |
85 | # place launchd plist to call JSS policy to remove admin rights.
86 | print 'Creating LaunchDaemon...'
87 | launchDaemon = { 'Label':launchdLabel,
88 | 'LaunchOnlyOnce':True,
89 | 'ProgramArguments':['/usr/local/jamf/bin/jamf', 'policy', '-trigger', policyCustomTrigger],
90 | 'StartInterval':adminTimer,
91 | 'UserName':'root',
92 | }
93 | plistlib.writePlist(launchDaemon, '/Library/LaunchDaemons/' + launchdFile)
94 |
95 | # set the permission on the file just made.
96 | userID = pwd.getpwnam("root").pw_uid
97 | groupID = grp.getgrnam("wheel").gr_gid
98 | os.chown('/Library/LaunchDaemons/' + launchdFile, userID, groupID)
99 | os.chmod('/Library/LaunchDaemons/' + launchdFile, 0644)
100 |
101 | # load the removal plist timer.
102 | print 'Loading LaunchDaemon...'
103 | subprocess.call(["launchctl", "load", "-w", '/Library/LaunchDaemons/' + launchdFile])
104 |
105 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
106 | # APPLICATION
107 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
108 |
109 | # build log files
110 | if not os.path.exists(workingDir):
111 | os.makedirs(workingDir)
112 |
113 | # record user that will need to have admin rights removed
114 | # record current existing admins
115 | print 'Retrieving List of Current Admins...'
116 | currentAdmins = grp.getgrnam('admin').gr_mem
117 | print 'Updating Plist...'
118 | plist = { 'User2Remove':userName,
119 | 'CurrentAdminUsers':currentAdmins}
120 | plistlib.writePlist(plist, workingDir + plistFile)
121 |
122 | # give current logged user admin rights
123 | subprocess.call(["dseditgroup", "-o", "edit", "-a", userName, "-t", "user", "admin"])
124 |
125 | # add log entry
126 | log = open(workingDir + tempAdminLog, "a+")
127 | log.write("{} - MakeMeAdmin Granted Admin Rights for {}\r\n".format(datetime.now(), userName))
128 | log.close()
129 |
130 | print 'Granted Admin Right to ' + userName
131 |
--------------------------------------------------------------------------------
/removeTempAdmin.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
4 | #
5 | # Copyright (c) 2017 Jamf. All rights reserved.
6 | #
7 | # Redistribution and use in source and binary forms, with or without
8 | # modification, are permitted provided that the following conditions are met:
9 | # * Redistributions of source code must retain the above copyright
10 | # notice, this list of conditions and the following disclaimer.
11 | # * Redistributions in binary form must reproduce the above copyright
12 | # notice, this list of conditions and the following disclaimer in the
13 | # documentation and/or other materials provided with the distribution.
14 | # * Neither the name of the Jamf nor the names of its contributors may be
15 | # used to endorse or promote products derived from this software without
16 | # specific prior written permission.
17 | #
18 | # THIS SOFTWARE IS PROVIDED BY JAMF SOFTWARE, LLC "AS IS" AND ANY
19 | # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 | # DISCLAIMED. IN NO EVENT SHALL JAMF SOFTWARE, LLC BE LIABLE FOR ANY
22 | # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 | #
29 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
30 |
31 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
32 | #
33 | # This script was modified from Andrina Kelly's version presented at JNUC2013 for allowing
34 | # a user to elevate their privelages to administrator once per day for 30 minutes. After
35 | # the 30 minutes if a user created a new admin account that account will have admin rights
36 | # also revoked. If the user changed the organization admin account password, that will also
37 | # be reset.
38 | #
39 | # To accomplish this the following will be performed:
40 | # - A launch daemon will be put in place in order to remove admin rights
41 | # - Log will be written to tempAdmin.log
42 | # - This policy in Jamf will be set to only be allowed once per day
43 | #
44 | # REQUIREMENTS:
45 | # - Jamf Pro
46 | # - Policy for enabling tempAdmin via Self Service
47 | # - Policy to remove tempAdmin via custom trigger (adminremove)
48 | # - tempAdmin.sh & removeTempAdmin.sh Scripts
49 | # - orgAdmin encrypted password specified in Jamf Pro parameter #4
50 | #
51 | #
52 | # Written by: Joshua Roskos | Professional Services Engineer | Jamf
53 | #
54 | # Created On: June 20th, 2017
55 | # Updated On: July 26th, 2017
56 | #
57 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
58 |
59 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
60 | # IMPORTS
61 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
62 |
63 | import os, plistlib, grp, subprocess, time, sys
64 | from datetime import datetime
65 |
66 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
67 | # VARIABLES
68 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
69 |
70 | workingDir = '/usr/local/jamfps/' # working directory for script
71 | launchdFile = 'com.jamfps.adminremove.plist' # launch daemon file location
72 | plistFile = 'MakeMeAdmin.plist' # working plist location
73 | statusFile = 'MakeMeAdmin.Status.plist' # compliancy check plist location
74 | tempAdminLog = 'tempAdmin.log' # script log file
75 | orgAdmins = {'orgadmin': sys.argv[4]} # replace orgAdmin with your organizational admin / password passed via Jamf Pro Parameter #4
76 | salt = '34599b64b8d44a7e' # decrypt salt
77 | passphrase = 'c0495bebbed8ce26115d66a2' # decrypt passphrase
78 |
79 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
80 | # FUNCTIONS
81 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
82 |
83 | def DecryptString(inputString, salt, passphrase):
84 | '''Usage: >>> DecryptString("Encrypted String", "Salt", "Passphrase")'''
85 | p = subprocess.Popen(['/usr/bin/openssl', 'enc', '-aes256', '-d', '-a', '-A', '-S', salt, '-k', passphrase], stdin = subprocess.PIPE, stdout = subprocess.PIPE)
86 | return p.communicate(inputString)[0]
87 |
88 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
89 | # APPLICATION
90 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
91 |
92 | if os.path.exists(workingDir + plistFile):
93 | # remove user admin rights
94 | user2Remove = plistlib.readPlist(workingDir + plistFile).User2Remove
95 | subprocess.call(["dseditgroup", "-o", "edit", "-d", user2Remove, "-t", "user", "admin"])
96 | # add log entry
97 | log = open(workingDir + tempAdminLog, "a+")
98 | log.write("{} - MakeMeAdmin Removed Admin Rights for {}\r\n".format(datetime.now(), user2Remove))
99 | log.close()
100 | print 'Revoked Admin Rights for ' + user2Remove
101 | # compre prior to current admin lists
102 | print 'Checking for newly created admin accounts...'
103 | priorAdmins = plistlib.readPlist(workingDir + plistFile).CurrentAdminUsers
104 | currentAdmins = grp.getgrnam('admin').gr_mem
105 | newAdmins = set(currentAdmins).difference(set(priorAdmins))
106 | newAdm = ''
107 | if not newAdmins:
108 | print ' No New Accounts Found!'
109 | # update compliancy plist
110 | status = { 'Status':'Compliant'}
111 | plistlib.writePlist(status, workingDir + statusFile)
112 | else:
113 | print ' New Admin Accounts Found!'
114 | log = open(workingDir + tempAdminLog, "a+")
115 | log.write("{} - MakeMeAdmin Discovered New Admin Accounts: {}\r\n".format(datetime.now(), list(newAdmins)))
116 | log.close()
117 | # update status plist
118 | status = { 'Status':'Remediated',
119 | 'newAdmins':'newAdmin Created',
120 | 'orgAdmin':'orgAdmin OK'}
121 | plistlib.writePlist(status, workingDir + statusFile)
122 | newAdm = plistlib.readPlist(workingDir + statusFile).newAdmins
123 | # loop through new admin accounts and remove admin rights
124 | print ' Removing Admin Rights for New Admin Accounts...'
125 | for user in newAdmins:
126 | subprocess.call(["dseditgroup", "-o", "edit", "-d", user, "-t", "user", "admin"])
127 | log = open(workingDir + tempAdminLog, "a+")
128 | log.write("{} - MakeMeAdmin Removed Admin Rights for: {}\r\n".format(datetime.now(), user))
129 | log.close()
130 | print ' Removed Admin Rights for ' + user
131 | time.sleep(1)
132 | # check if organization admin(s) are valid
133 | print 'Checking organizational admin passwords...'
134 | for admin, admpass in orgAdmins.iteritems():
135 | # decrypt password
136 | admpassDecrypted = DecryptString(admpass, salt, passphrase)
137 | time.sleep(1)
138 | valid = subprocess.call(["dscl", "/Local/Default", "-authonly", admin, admpassDecrypted])
139 | time.sleep(1)
140 | if valid == 0:
141 | log = open(workingDir + tempAdminLog, "a+")
142 | log.write("{} - orgAdmin Password is Valid \r\n".format(datetime.now()))
143 | log.close()
144 | print 'Password for orgAdmin: ' + admin + ' is valid!'
145 | else:
146 | log = open(workingDir + tempAdminLog, "a+")
147 | log.write("{} - orgAdmin Password is Invalid! \r\n".format(datetime.now()))
148 | log.close()
149 | result = subprocess.call(["dscl", ".", "passwd", "/Users/" + admin, admpassDecrypted])
150 | time.sleep(3)
151 | print 'Password for orgAdmin: ' + admin + ' was invalid!'
152 | if result == 0:
153 | log = open(workingDir + tempAdminLog, "a+")
154 | log.write("{} - orgAdmin Password Successfully Reset! \r\n".format(datetime.now()))
155 | log.close()
156 | print 'Password Successfully Reset for ' + admin + "!"
157 | if not newAdm:
158 | # update status plist
159 | status = { 'Status':'Remediated',
160 | 'newAdmins':'No newAdmins',
161 | 'orgAdmin':'orgAdmin OK'}
162 | plistlib.writePlist(status, workingDir + statusFile)
163 | else:
164 | # update status plist
165 | status = { 'Status':'Remediated',
166 | 'newAdmins':'newAdmin Created',
167 | 'orgAdmin':'orgAdmin OK'}
168 | plistlib.writePlist(status, workingDir + statusFile)
169 | else:
170 | log = open(workingDir + tempAdminLog, "a+")
171 | log.write("{} - Error Resetting orgAdmin Password! \r\n".format(datetime.now()))
172 | log.close()
173 | print 'Error Resetting Password for ' + admin + "!"
174 | if not newAdm:
175 | # update status plist
176 | status = { 'Status':'Violation',
177 | 'newAdmins':'No newAdmins',
178 | 'orgAdmin':'orgAdmin ERROR'}
179 | plistlib.writePlist(status, workingDir + statusFile)
180 | else:
181 | # update status plist
182 | status = { 'Status':'Violation',
183 | 'newAdmins':'newAdmin Created',
184 | 'orgAdmin':'orgAdmin ERROR'}
185 | plistlib.writePlist(status, workingDir + statusFile)
186 | os.remove(workingDir + plistFile)
187 |
188 | if os.path.exists('/Library/LaunchDaemons/' + launchdFile):
189 | print 'Removing LaunchDaemon...'
190 | os.remove('/Library/LaunchDaemons/' + launchdFile)
191 |
192 | # Submit Jamf Pro Inventory
193 | subprocess.call(["/usr/local/jamf/bin/jamf", "recon"])
194 |
--------------------------------------------------------------------------------