Skip to content

Instantly share code, notes, and snippets.

@adriannier
Last active November 23, 2017 12:40
Show Gist options
  • Save adriannier/e4663482d5d3e7f9e91302f998344f86 to your computer and use it in GitHub Desktop.
Save adriannier/e4663482d5d3e7f9e91302f998344f86 to your computer and use it in GitHub Desktop.
Adds standard user temporarily to admin group, launches Console.app, and removes user from admin group right away.
global gADMIN_USER
global gADMIN_PASSWORD
on run
try
-- Check system requirements
if requireMinimumSystemVersion("10.12.4") is false then return
-- Get current user
set standardUser to currentUser()
-- Make sure current user is not in admin group already
if standardUser is in adminUsers() then
error "This user is already an administrator." number 1
end if
-- Prompt the user to select an administrator account
set gADMIN_USER to selectAdmin()
-- Ask for the admin password
askForAdminPassword()
-- Quit Console if running
quitConsoleApp()
-- Add current user to admin group
addToAdminGroup(standardUser)
try
-- Launch Console and bring to front
activateConsoleApp()
on error eMsg number eNum
-- Before raising error, clean up by removing user from admin group
removeFromAdminGroup(standardUser)
error eMsg number eNum
end try
-- Remove user from admin group
removeFromAdminGroup(standardUser)
on error eMsg number eNum
if eNum = -128 then return
activate
if eNum = -2700 then
display alert "Something went wrong" message eMsg
else
display alert "Something went wrong" message eMsg & " (" & (eNum as text) & ")"
end if
end try
end run
on currentUser()
try
return do shell script "whoami"
on error eMsg number eNum
error "Could not get name of current user. " & eMsg number eNum
end try
end currentUser
on adminUsers()
try
set theOutput to do shell script "dscl . -read /Groups/admin GroupMembership"
set o to offset of ": " in theOutput
set theOutput to text (o + 2) thru -1 of theOutput
set userNames to words of theOutput
set filteredUserNames to {}
repeat with i from 1 to count of userNames
if item i of userNames is not "root" then
set end of filteredUserNames to item i of userNames
end if
end repeat
return filteredUserNames
on error eMsg number eNum
error "Could not get list of administrators. " & eMsg number eNum
end try
end adminUsers
on selectAdmin()
set allAdmins to adminUsers()
if (count of allAdmins) is 1 then return item 1 of allAdmins
set chosenAdmins to choose from list allAdmins default items {item 1 of allAdmins}
if chosenAdmins is false then error "User cancelled." number -128
return item 1 of chosenAdmins
end selectAdmin
on askForAdminPassword()
try
repeat with i from 1 to 10
set gADMIN_PASSWORD to text returned of (display dialog "Enter password for " & gADMIN_USER & ":" default answer "" with hidden answer)
if gADMIN_PASSWORD is not "" then
if testUserPassword(gADMIN_USER, gADMIN_PASSWORD) then exit repeat
end if
-- Throttle subsequent attempts
if i < 10 then delay (i * 0.3)
end repeat
if testUserPassword(gADMIN_USER, gADMIN_PASSWORD) is false then error "Could not authenticate as administrator." number 2
on error eMsg number eNum
if eNum is not 1 then
error "Could not test admin password. " & eMsg number eNum
else
error eMsg number eNum
end if
end try
end askForAdminPassword
on testUserPassword(theUser, thePassword)
try
set theOutput to do shell script "/usr/bin/expect -f - <<EOD
spawn su " & theUser & "
expect \"Password:\"
send \"" & thePassword & "\\r\"
expect \"$ \"
send \"whoami\\r\"
expect \"$ \"
send \"exit\\r\"
EOD"
set nl to (ASCII character 13)
set testString to "whoami" & nl & theUser & nl
if theOutput does not contain testString then
return false
else
return true
end if
on error eMsg number eNum
if eMsg contains "not open" then
return false
else
error "Could not test user password. " & eMsg number eNum
end if
end try
end testUserPassword
on addToAdminGroup(userName)
try
repeat with i from 1 to 3
try
-- Make sure current user is not in admin group
if userName is in adminUsers() then return
-- Run an expect script to switch to the admintrative user and add standard user to admin group
do shell script "/usr/bin/expect -f - <<EOD
spawn su " & gADMIN_USER & "
expect \"Password:\"
send \"" & gADMIN_PASSWORD & "\\r\"
expect \"$ \"
send \"sudo dscl . -append /Groups/admin GroupMembership " & userName & "\\r\"
expect \"Password:\"
send \"" & gADMIN_PASSWORD & "\\r\"
expect \"$ \"
send \"exit\\r\"
EOD"
delay 0.3
-- Check to see if user has been added (in testing sometimes the dscl command was ineffective)
if userName is in adminUsers() then return
on error eMsg number eNum
-- Save error for raising it after the loop
end try
if i < 3 then delay 1
end repeat
error eMsg number eNum
on error eMsg number eNum
error "Could not remove " & userName & " from the list of administrators. Please do so manually. Error: " & eMsg number eNum
end try
end addToAdminGroup
on removeFromAdminGroup(userName)
try
repeat with i from 1 to 3
try
-- Make sure current user is still in admin group
if userName is not in adminUsers() then return
-- Run an expect script to switch to the admintrative user and remove standard user from admin group
do shell script "/usr/bin/expect -f - <<EOD
spawn su " & gADMIN_USER & "
expect \"Password:\"
send \"" & gADMIN_PASSWORD & "\\r\"
expect \"$ \"
send \"sudo dscl . -delete /Groups/admin GroupMembership " & userName & "\\r\"
expect \"Password:\"
send \"" & gADMIN_PASSWORD & "\\r\"
expect \"$ \"
send \"exit\\r\"
EOD"
delay 0.3
-- Check to see if user is removed (in testing sometimes the dscl command was ineffective)
if userName is not in adminUsers() then return
on error eMsg number eNum
-- Save error for raising it after the loop
end try
if i < 3 then delay 1
end repeat
error eMsg number eNum
on error eMsg number eNum
error "Could not remove " & userName & " from the list of administrators. Please do so manually. Error: " & eMsg number eNum
end try
end removeFromAdminGroup
on activateConsoleApp()
repeat with i from 1 to 3
if consoleAppRunning() is false then
tell application "Console" to activate
delay 1
else
return
end if
end repeat
if consoleAppRunning() is false then error "Could not launch Console.app." number 3
end activateConsoleApp
on consoleAppRunning()
try
do shell script "pgrep -u `whoami` -f /Applications/Utilities/Console.app"
return true
on error
return false
end try
end consoleAppRunning
on quitConsoleApp()
repeat with i from 1 to 3
if consoleAppRunning() then
tell application "Console" to quit
delay 1
else
return
end if
end repeat
if consoleAppRunning() then error "Could not quit Console.app." number 4
end quitConsoleApp
on requireMinimumSystemVersion(minimumSystemVersion)
set currentVersion to parseVersionString(do shell script "sw_vers -productVersion")
set requiredVersion to parseVersionString(minimumSystemVersion)
if (majorVersion of currentVersion) < (majorVersion of requiredVersion) then
set requirementsMet to false
else if (majorVersion of currentVersion) = (majorVersion of requiredVersion) then
if (minorVersion of currentVersion) < (minorVersion of requiredVersion) then
set requirementsMet to false
else if (minorVersion of currentVersion) = (minorVersion of requiredVersion) then
if (theRevision of currentVersion) < (theRevision of requiredVersion) then
set requirementsMet to false
else
set requirementsMet to true
end if
else
set requirementsMet to true
end if
else
set requirementsMet to true
end if
if requirementsMet then return true
-- Display a dialog if requirements are not met
try
set targetLanguage to first word of (do shell script "defaults read NSGlobalDomain AppleLanguages")
on error
set targetLanguage to "en"
end try
if targetLanguage is "de" then
set dialogTitle to "Nicht unterst" & (ASCII character 159) & "tztes System"
set dialogMessage to "Dieses Skript erfordert mindestens die Systemversion " & minimumSystemVersion & ". "
else
set dialogTitle to "System not supported"
set dialogMessage to "This script requires at least system version " & minimumSystemVersion & ". "
end if
activate
if (majorVersion of currentVersion) ≥ 10 and (minorVersion of currentVersion) ≥ 4 then
display alert dialogTitle message dialogMessage buttons {"OK"} default button "OK" as warning
else
display dialog dialogTitle & return & return & dialogMessage buttons {"OK"} default button "OK" with icon 2
end if
return false
end requireMinimumSystemVersion
on parseVersionString(versionString)
set prvDlmt to text item delimiters
set text item delimiters to "."
try
set majorVersion to (text item 1 of versionString) as integer
on error
set majorVersion to 0
end try
try
set minorVersion to (text item 2 of versionString) as integer
on error
set minorVersion to 0
end try
try
set theRevision to (text item 3 of versionString) as integer
on error
set theRevision to 0
end try
set text item delimiters to prvDlmt
return {majorVersion:majorVersion, minorVersion:minorVersion, theRevision:theRevision}
end parseVersionString
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment