Skip to main content
Question

Script to Prompt user for password


Forum|alt.badge.img+3

Hello All, 

    First off, I tried to find another post related to this type of thing and was not able to find on JAMF Nation so sorry if this is a duplicate post.  I also scoured the web for this and seem to find things that are older or designed for much more complex needs.

 

I am trying to come up with a script that, at least to me, should be pretty simple to do.  This will be deployed via Self Service for users to run, so not something executed from Terminal. 

At bit of back story: I am trying to deploy FileVault in our environment and we have mobile/AD Joined accounts that will be used for enabling Encryption and generating recovery keys.  My understanding is that this will require the local admin account (which does have a token verified by: sudo profiles status -type bootstraptoken) created in the Pre-Stage process on our machines to "pass" the Secure Token to these mobile accounts using the sysadminctl command.  I would like to script the process out as much as possible and I am trying to find a good/simple solution to create a pop-up box prompt for the currently logged in user to enter their password and click OK.  

 

This is what my script looks like so far.  Any suggestions or tips is greatly appreciated!

#!/bin/bash
## Get the logged in user's name
LoggedinUser=$(/usr/bin/stat -f%Su /dev/console)

## Prompt for currently logged in users password
userPass=$ ??????????????????????????

## Enable the logged in user with secure token
sudo sysadminctl -adminUser <ourlocaladminaccount> -adminPassword -<ourlocaladminpassword> -secureTokenOn "$LoggedinUser" -password -$"userPass"

 

12 replies

Hugonaut
Forum|alt.badge.img+15
  • Esteemed Contributor
  • 574 replies
  • September 16, 2021

I use applescript & prompt the end user for password & then write it to a tmp text file, /var/tmp is ideal as its wiped after restart & you can also encode the password using something like ceasar cipher / rot13 but here is a script for passing it in plain text, you will see in the scripts in the github link, the file the applescript writes to is then passed using cat to the shell script for automating filevault within a script.

 

@Schmidt  https://github.com/Hugonauts/Jamf-Filevault

 

 

#!/usr/bin/osascript set myupname to do shell script "echo $USER" set questionadmin to "*EDITHERE* Account Setup Requires Encryption. Please enter your Password " & myupname & "" repeat try set init_pass to text returned of (display dialog questionadmin default answer "" buttons {"OK", "Cancel"} default button 1 with hidden answer) set final_pass to text returned of (display dialog "Please verify and re-type your password" buttons {"OK", "Cancel"} default button 1 default answer "" with hidden answer) if (final_pass is not equal to init_pass) then display dialog "Password Incorrect. Please Try Again." with icon stop else try do shell script "ls" user name myupname password init_pass with administrator privileges set admin_passwd to final_pass exit repeat on error err display dialog "Password Incorrect. Please Try Again." end try end if on error number -128 set canceldialog to display dialog "Cancel was Selected, " & myupname & " is Not Enabled for Filevault 2. You must Enable " & myupname & " for Filevault 2 in Order to Login at Startup." buttons {"OK"} default button 1 with icon stop try if button returned of canceldialog is "OK" then return end if end try end try end repeat do shell script "touch /Library/Scripts/TempFVPassword.txt" do shell script "echo " & init_pass & "> " & "/Library/Scripts/TempFVPassword.txt"

 

 


AJPinto
Forum|alt.badge.img+26
  • Legendary Contributor
  • 2725 replies
  • September 16, 2021

Unfortunately as with most things involving macOS, nothing is simple. You are on the right path in needing to prompt the users to enter credentials, however I have found the most straight forward commands to use are fdesetup for provisioning access. I can see needing a users authentication to remove filevault access, but granting it should be a much simpler process. Either way this is what we use, it could be cleaned up a bit but it works. I have not finished the end of it to run an if statement to exit correctly (or fail) if FV access was not provisioned, I just noticed that lol.

 

 

 

#!/bin/bash echo "Begin script" ###################### # Gather and verify local admin account # Password is salted lines 13-19 can be removed, and the password can be hard coded in line 19 ###################### #*------------------------ STRING DECRYPTION ------------------------*# function DecryptString() { echo "${1}" | /usr/bin/openssl enc -aes256 -d -a -A -S "${2}" -k "${3}" } Pass="" Salt="" DecryptString=$(DecryptString "$5" "$Salt" "$Pass") adminUser="$4" adminPass="$DecryptString" osvers=$(sw_vers -productVersion | awk -F. '{print $2}') check4AD=`/usr/bin/dscl localhost -list . | grep "Active Directory"` ## verify that adminuser and pass variables are both passed to the user if [[ -z "$adminUser" ]] || [[ -z "$adminPass" ]] ; then dialog="either Admin User or Password is missing" echo "$dialog" cmd="Tell app \\"System Events\\" to display dialog \\"$dialog\\"" /usr/bin/osascript -e "$cmd" exit 1 fi ## check the admin password adminCheck=$(/usr/bin/dscl /Local/Default -authonly "$adminUser" "$adminPass") if [[ -z "$adminCheck" ]] ; then echo "Admin password is verified" else echo "Admin Password not working" exit 1 fi ###################### # Check for domain bind, fails out of not bound ###################### echo "Checking for Domain Bind" if [ "${check4AD}" != "Active Directory" ]; then dialog="This machine is not bound to Active Directory.\\nPlease bind to AD first. " echo "$dialog" cmd="Tell app \\"System Events\\" to display dialog \\"$dialog\\"" /usr/bin/osascript -e "$cmd" exit 2 fi ###################### # Popups asking for user to ender userID and Password ###################### echo "Prompting for userToAdd credentials." ## Prompt for Username userToAdd=$(/usr/bin/osascript<<END tell application "System Events" activate set the answer to text returned of (display dialog "Enter your userID:" default answer "" buttons {"Continue"} default button 1) end tell END ) ## Prompt for Password userPass=$(/usr/bin/osascript<<END tell application "System Events" activate set the answer to text returned of (display dialog "Enter your Password:" default answer "" with hidden answer buttons {"Continue"} default button 1) end tell END ) loopCount=0 while [ "$loopCount" -lt 3 ]; do # Refresh Directory Services if [[ ${osvers} -ge 7 ]]; then /usr/bin/killall opendirectoryd else /usr/bin/killall DirectoryService fi sleep 15 ## try to auth the user in advance. this seems to increase the success of the ID command. /usr/bin/dscl /Search -authonly "$userToAdd" "$userPass" adCheck=`id $userToAdd` echo "AD Check is: $adCheck" if [[ -z "$adCheck" ]] ; then ((loopCount++)) else echo "AD Check successful" break fi done ###################### # Fails script if user account is not found on domain controller # Commented out as this function is error prone if the domain controller takes too long to respond. ###################### # #if [[ -z "$adCheck" ]] ; then # dialog="AD User Not found. Please contact the support center at 205.261.4357" # echo "$dialog" # cmd="Tell app \\"System Events\\" to display dialog \\"$dialog\\"" # /usr/bin/osascript -e "$cmd" # exit 3 #fi # #sleep 2 # ###################### # Remove FV Access if existing ###################### sleep 2 sudo fdesetup remove -user $userToAdd ###################### # Provision Admin Access # Comment this function out if admin access is not desired ###################### dscl . -append /groups/admin GroupMembership $userToAdd echo "Provisioning admin access for $userToAdd." ###################### # Provision FileVault Access # Filevault encryption status currently commented out as its not needed at this time ###################### ## Check to see if the encryption process is complete #encryptCheck=fdesetup status\\ #statusCheck=$(echo "${encryptCheck}" | grep "FileVault is On.") #expectedStatus="FileVault is On." # if [ "${statusCheck}" != "${expectedStatus}" ]; then # echo "The encryption process has not completed, unable to add user at this time." echo "${encryptCheck}" exit 4 # else # echo "Adding $userToAdd to FileVault 2 list." # fi # #sleep 5 ## Get the user to be added to FV userName=$userToAdd ## This "expect" block will populate answers for the sysadminctl variables. sysadminctl -adminUser "$adminUser" -adminPassword "$adminPass" -secureTokenOn "$userName" -password "$userPass" echo "${userName} has been added to the FileVault 2 list." ###################### # Runs JAMF Recon to assign Mac to $userToAdd ###################### jamf recon -endUsername $userToAdd ###################### # Clean up ###################### echo "Script completed" exit 0

 

 

 


beeboo
Forum|alt.badge.img+7
  • Contributor
  • 119 replies
  • September 17, 2021

I had the same problem as you, and this was my resolution, using osascript

 

CurrentUser=$(stat -f%Su /dev/console) UIDCurrentUser=$(id -u "$CurrentUser") adminPASS="" jamfHELPERbody="" jamfHELPERHEADER="" jamfHELPERicon="" jamfHELPERbody2="" popup=`/Library/Application\\ Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper -windowType utility -description "$jamfHELPERbody" -heading "$jamfHELPERHEADER" -icon "$jamfHELPERicon" -button1 "Continue" -defaultButton 1` #popup=`/Library/Application\\ Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper -windowType utility -description "$description" -heading "{VALUE}" -icon "$logo" -button1 "Update Now" -defaultButton 1 -countdown 1800 -countdown -alignCountdown center` if [[ "$popup" == "0" ]]; then] #Ask User Password userPassword=$(/bin/launchctl asuser "$UIDCurrentUser" sudo -iu "$CurrentUser" /usr/bin/osascript -e 'Tell application "System Events" to display dialog "Password for user: '${CurrentUser}'" default answer "" with title "{VALUE}" with text buttons {"Ok"} default button 1 with hidden answer' -e 'text returned of result') #Enable SecureToken for the CurrentUser and adminUser sysadminctl -adminUser {admin account} -adminPassword $adminPASS -secureTokenOn $CurrentUser -password $userPassword #Notification /Library/Application\\ Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper -windowType utility -description "$jamfHELPERbody2" -button1 "Ok" -icon "$jamfHELPERicon" fi exit 0

Forum|alt.badge.img+31
  • Honored Contributor
  • 2721 replies
  • September 18, 2021

Just a heads up, and I totally understand this may be your only option, but prompting a user for their password in any language that doesn't use some sort of secure auth hook/API, or something like say a password vault, that password will be stored in clear text in memory and possibly elsewhere.  I am only pointing this out from a security perspective so you are aware, and not really telling anyone how to do their job.


Forum|alt.badge.img+3
  • Author
  • New Contributor
  • 8 replies
  • September 21, 2021
tlarkin wrote:

Just a heads up, and I totally understand this may be your only option, but prompting a user for their password in any language that doesn't use some sort of secure auth hook/API, or something like say a password vault, that password will be stored in clear text in memory and possibly elsewhere.  I am only pointing this out from a security perspective so you are aware, and not really telling anyone how to do their job.


Hey tlarkin,

    Thanks for the advice.  I am still new to JAMF/MacOS administration so if you have any tips for how to secure this information, or if you know of ways that using a script like this can exploit and/or extract the users password, I would like to learn more.


Forum|alt.badge.img+3
  • Author
  • New Contributor
  • 8 replies
  • September 21, 2021
AJPinto wrote:

Unfortunately as with most things involving macOS, nothing is simple. You are on the right path in needing to prompt the users to enter credentials, however I have found the most straight forward commands to use are fdesetup for provisioning access. I can see needing a users authentication to remove filevault access, but granting it should be a much simpler process. Either way this is what we use, it could be cleaned up a bit but it works. I have not finished the end of it to run an if statement to exit correctly (or fail) if FV access was not provisioned, I just noticed that lol.

 

 

 

#!/bin/bash echo "Begin script" ###################### # Gather and verify local admin account # Password is salted lines 13-19 can be removed, and the password can be hard coded in line 19 ###################### #*------------------------ STRING DECRYPTION ------------------------*# function DecryptString() { echo "${1}" | /usr/bin/openssl enc -aes256 -d -a -A -S "${2}" -k "${3}" } Pass="" Salt="" DecryptString=$(DecryptString "$5" "$Salt" "$Pass") adminUser="$4" adminPass="$DecryptString" osvers=$(sw_vers -productVersion | awk -F. '{print $2}') check4AD=`/usr/bin/dscl localhost -list . | grep "Active Directory"` ## verify that adminuser and pass variables are both passed to the user if [[ -z "$adminUser" ]] || [[ -z "$adminPass" ]] ; then dialog="either Admin User or Password is missing" echo "$dialog" cmd="Tell app \\"System Events\\" to display dialog \\"$dialog\\"" /usr/bin/osascript -e "$cmd" exit 1 fi ## check the admin password adminCheck=$(/usr/bin/dscl /Local/Default -authonly "$adminUser" "$adminPass") if [[ -z "$adminCheck" ]] ; then echo "Admin password is verified" else echo "Admin Password not working" exit 1 fi ###################### # Check for domain bind, fails out of not bound ###################### echo "Checking for Domain Bind" if [ "${check4AD}" != "Active Directory" ]; then dialog="This machine is not bound to Active Directory.\\nPlease bind to AD first. " echo "$dialog" cmd="Tell app \\"System Events\\" to display dialog \\"$dialog\\"" /usr/bin/osascript -e "$cmd" exit 2 fi ###################### # Popups asking for user to ender userID and Password ###################### echo "Prompting for userToAdd credentials." ## Prompt for Username userToAdd=$(/usr/bin/osascript<<END tell application "System Events" activate set the answer to text returned of (display dialog "Enter your userID:" default answer "" buttons {"Continue"} default button 1) end tell END ) ## Prompt for Password userPass=$(/usr/bin/osascript<<END tell application "System Events" activate set the answer to text returned of (display dialog "Enter your Password:" default answer "" with hidden answer buttons {"Continue"} default button 1) end tell END ) loopCount=0 while [ "$loopCount" -lt 3 ]; do # Refresh Directory Services if [[ ${osvers} -ge 7 ]]; then /usr/bin/killall opendirectoryd else /usr/bin/killall DirectoryService fi sleep 15 ## try to auth the user in advance. this seems to increase the success of the ID command. /usr/bin/dscl /Search -authonly "$userToAdd" "$userPass" adCheck=`id $userToAdd` echo "AD Check is: $adCheck" if [[ -z "$adCheck" ]] ; then ((loopCount++)) else echo "AD Check successful" break fi done ###################### # Fails script if user account is not found on domain controller # Commented out as this function is error prone if the domain controller takes too long to respond. ###################### # #if [[ -z "$adCheck" ]] ; then # dialog="AD User Not found. Please contact the support center at 205.261.4357" # echo "$dialog" # cmd="Tell app \\"System Events\\" to display dialog \\"$dialog\\"" # /usr/bin/osascript -e "$cmd" # exit 3 #fi # #sleep 2 # ###################### # Remove FV Access if existing ###################### sleep 2 sudo fdesetup remove -user $userToAdd ###################### # Provision Admin Access # Comment this function out if admin access is not desired ###################### dscl . -append /groups/admin GroupMembership $userToAdd echo "Provisioning admin access for $userToAdd." ###################### # Provision FileVault Access # Filevault encryption status currently commented out as its not needed at this time ###################### ## Check to see if the encryption process is complete #encryptCheck=fdesetup status\\ #statusCheck=$(echo "${encryptCheck}" | grep "FileVault is On.") #expectedStatus="FileVault is On." # if [ "${statusCheck}" != "${expectedStatus}" ]; then # echo "The encryption process has not completed, unable to add user at this time." echo "${encryptCheck}" exit 4 # else # echo "Adding $userToAdd to FileVault 2 list." # fi # #sleep 5 ## Get the user to be added to FV userName=$userToAdd ## This "expect" block will populate answers for the sysadminctl variables. sysadminctl -adminUser "$adminUser" -adminPassword "$adminPass" -secureTokenOn "$userName" -password "$userPass" echo "${userName} has been added to the FileVault 2 list." ###################### # Runs JAMF Recon to assign Mac to $userToAdd ###################### jamf recon -endUsername $userToAdd ###################### # Clean up ###################### echo "Script completed" exit 0

 

 

 


I was able to create a simple script below using the method you provided.  Nothing fancy but at least for initial testing, seems to get the job done.  One thing I did tweak was remove the "Tell" potion of the prompt as it removes the need for users to accept the prompt of "JAMF wants access to control system events", which I could not seem to remove using PPPCP, although we already have JAMF PPPCP setup.

 

#!/bin/bash ## Get the logged in user's name LoggedinUser=$(/usr/bin/stat -f%Su /dev/console) ## Prompt for Password userPass=$(/usr/bin/osascript<<END application "System Events" activate set the answer to text returned of (display dialog "IT needs to Activate Encryption, Please Enter your Password:" default answer "" with hidden answer buttons {"Continue"} default button 1) END ) ## Enable the logged in user with secure token sudo sysadminctl -adminUser <localmacaccount>-adminPassword -<localmacpassword> -secureTokenOn "$LoggedinUser" -password -$"userPass"

 

 

 


Hugonaut
Forum|alt.badge.img+15
  • Esteemed Contributor
  • 574 replies
  • September 22, 2021
tlarkin wrote:

Just a heads up, and I totally understand this may be your only option, but prompting a user for their password in any language that doesn't use some sort of secure auth hook/API, or something like say a password vault, that password will be stored in clear text in memory and possibly elsewhere.  I am only pointing this out from a security perspective so you are aware, and not really telling anyone how to do their job.


An API Hook is absolutely the way to go. +1


beeboo
Forum|alt.badge.img+7
  • Contributor
  • 119 replies
  • September 22, 2021
Hugonaut wrote:

An API Hook is absolutely the way to go. +1


API hook as in this right?

https://{{url}}/JSSResource/computercommands/command/ScheduleOSUpdate/action/install/id/136,326,332

 

I run that in postman at night after hours, but not sure if that should be in a script or if you have yours as part of a script @Hugonaut 


Hugonaut
Forum|alt.badge.img+15
  • Esteemed Contributor
  • 574 replies
  • September 22, 2021
beeboo wrote:

API hook as in this right?

https://{{url}}/JSSResource/computercommands/command/ScheduleOSUpdate/action/install/id/136,326,332

 

I run that in postman at night after hours, but not sure if that should be in a script or if you have yours as part of a script @Hugonaut 


@beebooI am referring to an Api call in the sense of scripting the following (all without writing anywhere on the system),

 

Prompt End user for Password -> Encode Password -> Pass encoded password via api to say Jamf Dashboard via Extension attribute -> Pass Extension Attribute of Encoded Password to script in Jamf Dash as Variable & have another variable that decodes pass & used as the password flag for the startoscommand for M1s to authenticate end user & upgrade OS.

 

this will all be fixed in Monterey though


beeboo
Forum|alt.badge.img+7
  • Contributor
  • 119 replies
  • September 22, 2021
Hugonaut wrote:

@beebooI am referring to an Api call in the sense of scripting the following (all without writing anywhere on the system),

 

Prompt End user for Password -> Encode Password -> Pass encoded password via api to say Jamf Dashboard via Extension attribute -> Pass Extension Attribute of Encoded Password to script in Jamf Dash as Variable & have another variable that decodes pass & used as the password flag for the startoscommand for M1s to authenticate end user & upgrade OS.

 

this will all be fixed in Monterey though


Do you mind sharing the workflow?

I didnt think there was an alternative method til you brought up yours.

And when you say itll be fixed in monterey, what do you? that wont be possible anymore?

Thanks!


Hugonaut
Forum|alt.badge.img+15
  • Esteemed Contributor
  • 574 replies
  • September 22, 2021

It was just a thought pertaining to what tlarkin stated, I don't have this built out to share, Monterey will introduce an easier workflow for us


Forum|alt.badge.img+31
  • Honored Contributor
  • 2721 replies
  • September 22, 2021
beeboo wrote:

Do you mind sharing the workflow?

I didnt think there was an alternative method til you brought up yours.

And when you say itll be fixed in monterey, what do you? that wont be possible anymore?

Thanks!


Yeah there is a secure prompt API in macOS (swift or objc) which one can invoke to pop up a dialog box or prompt for touch ID or what not. AFAIK there is no way to do this in scripting languages like the shells or AppleScript.  I do know AppleScript will store creds in clear text.  I am not here to accept any risks for any other Orgs, but simply pointing this out. It is up to the Org to accept those risks. Sometimes the risk is wroth the acceptance, sometimes it is not, but that highly depends on your threat models


Reply


Cookie policy

We use cookies to enhance and personalize your experience. If you accept you agree to our full cookie policy. Learn more about our cookies.

 
Cookie settings