Does anyone have any experience utilizing Jamf Connect login LAPS functionality? https://travellingtechguy.blog/jamf-connect-and-laps/ Following this link there is specific plist config info called out for LAPS control built into Jamf Connect, our intended use case would be finding something that can manage our local admin passwords without being AD bound and securely using the FV2 escrow key seems like an interesting idea. Any thoughts on best practice?
@mks007 the github repository is back up now you can check it here https://github.com/PezzaD84/macOSLAPS
@mks007 the github repository is back up now you can check it here https://github.com/PezzaD84/macOSLAPS
@perryd84 , good afternoon.
For me, it was not clear, which user I use in the API credential?
@perryd84 , good afternoon.
For me, it was not clear, which user I use in the API credential?
The credentials should be your encoded api account. There is a small script in the github which can do this for you.
Hi @perryd84,
very nice work.
Do you have a recommendation for the rights of the API user?
This one I think don´t need full admin rights.
Do you use an extra user only for the LAPS function?
How you are build the LAPS.pkg?
The 10 seconds time is not set by a variable or?
Best regards
Hi @perryd84,
very nice work.
Do you have a recommendation for the rights of the API user?
This one I think don´t need full admin rights.
Do you use an extra user only for the LAPS function?
How you are build the LAPS.pkg?
The 10 seconds time is not set by a variable or?
Best regards
Hi @snowwalker1988
You can find permissions for the API account here https://github.com/PezzaD84/macOSLAPS/issues/2
The LAPS account created can be an additional admin account or just replace your local admin account it's up to you. If the same account exists before the LAPS Creation runs then it will conflict with the existing account. Best practice is to have this set up a brand new account not the same as anything else already existing.
The pkg was created in Composer. You can download the LAPS.pkg from here https://github.com/PezzaD84/macOSLAPS/raw/main/LAPS.pkg
The 10 second timer is just a default timer setting in the script. It can be changed if you want by editing the --timer key followed by a custom seconds time.
Feel free to message me if you need any more help with it.
Hi @snowwalker1988
You can find permissions for the API account here https://github.com/PezzaD84/macOSLAPS/issues/2
The LAPS account created can be an additional admin account or just replace your local admin account it's up to you. If the same account exists before the LAPS Creation runs then it will conflict with the existing account. Best practice is to have this set up a brand new account not the same as anything else already existing.
The pkg was created in Composer. You can download the LAPS.pkg from here https://github.com/PezzaD84/macOSLAPS/raw/main/LAPS.pkg
The 10 second timer is just a default timer setting in the script. It can be changed if you want by editing the --timer key followed by a custom seconds time.
Feel free to message me if you need any more help with it.
First of thanks @perryd84 for putting this together. It looks excellent and it pretty much exactly what I'm after.
I'm hoping could give me some pointers since I think I'm almost there.
I've set everything up and now have a new local laps account on my test Mac and the extension attributes are populated in the Jamf inventory. My problem is that the password generated from 'Decrypt' doesn't work with the newly created laps admin account. This is what I got in the policy install logs (running it on MacOS 13.2.1):
admin has already been created and is a local admin. Resetting local admin password....
2023-02-16 15:06:40.790 sysadminctl[70436:2815752] ### Error:-14090 File:/AppleInternal/Library/BuildRoots/9e200cfa-7d96-11ed-886f-a23c4f261b56/Library/Caches/com.apple.xbs/Sources/Admin_sysadminctl/addremoveuser/main.m Line:378
2023-02-16 15:06:40.791 sysadminctl[70436:2815752] Operation is not permitted without secure token unlock.
<dscl_cmd> DS Error: -14090 (eDSAuthFailed)
Authentication for node /Local/Default failed. (-14090, eDSAuthFailed)
LAPS Password has been reset. Resetting EA to default value
<?xml version="1.0" encoding="UTF-8"?><computer><id>2641</id></computer><?xml version="1.0" encoding="UTF-8"?><computer><id>2641</id></computer><?xml version="1.0" encoding="UTF-8"?><computer><id>2641</id></computer>CryptKey and SecretKey Escrowed to Jamf successfully
The decrypt log looks fine from what I can tell: Script result: Log already exists. Continuing setup.....
***** LAPS Decryption 16/02/2023 15:21:03 The LAPS Password for ******* was viewed by ****** on ****** Reason for viewing password: TEST No slack URL configured
First of thanks @perryd84 for putting this together. It looks excellent and it pretty much exactly what I'm after.
I'm hoping could give me some pointers since I think I'm almost there.
I've set everything up and now have a new local laps account on my test Mac and the extension attributes are populated in the Jamf inventory. My problem is that the password generated from 'Decrypt' doesn't work with the newly created laps admin account. This is what I got in the policy install logs (running it on MacOS 13.2.1):
admin has already been created and is a local admin. Resetting local admin password....
2023-02-16 15:06:40.790 sysadminctl[70436:2815752] ### Error:-14090 File:/AppleInternal/Library/BuildRoots/9e200cfa-7d96-11ed-886f-a23c4f261b56/Library/Caches/com.apple.xbs/Sources/Admin_sysadminctl/addremoveuser/main.m Line:378
2023-02-16 15:06:40.791 sysadminctl[70436:2815752] Operation is not permitted without secure token unlock.
<dscl_cmd> DS Error: -14090 (eDSAuthFailed)
Authentication for node /Local/Default failed. (-14090, eDSAuthFailed)
LAPS Password has been reset. Resetting EA to default value
<?xml version="1.0" encoding="UTF-8"?><computer><id>2641</id></computer><?xml version="1.0" encoding="UTF-8"?><computer><id>2641</id></computer><?xml version="1.0" encoding="UTF-8"?><computer><id>2641</id></computer>CryptKey and SecretKey Escrowed to Jamf successfully
The decrypt log looks fine from what I can tell: Script result: Log already exists. Continuing setup.....
***** LAPS Decryption 16/02/2023 15:21:03 The LAPS Password for ******* was viewed by ****** on ****** Reason for viewing password: TEST No slack URL configured
Hi @tjhall
From a quick look, this error usually happens when an existing local admin account exists before running LAPS for the first time. For example if you have a local admin called "admin" and then run LAPS to create an account called "admin", it will see this and attempt to reset that account but the passwords will fail.
As I don't know whats been done initially I would recommend setting LAPS to create a brand new local admin account which doesn't share a name with a potential existing account.
This line here, "2023-02-16 15:06:40.791 sysadminctl[70436:2815752] Operation is not permitted without secure token unlock.", would be where it has failed to authenticate to reset the password.
Hope that helps a little? Feel free to message me if you are still stuck👍
Hi @tjhall
From a quick look, this error usually happens when an existing local admin account exists before running LAPS for the first time. For example if you have a local admin called "admin" and then run LAPS to create an account called "admin", it will see this and attempt to reset that account but the passwords will fail.
As I don't know whats been done initially I would recommend setting LAPS to create a brand new local admin account which doesn't share a name with a potential existing account.
This line here, "2023-02-16 15:06:40.791 sysadminctl[70436:2815752] Operation is not permitted without secure token unlock.", would be where it has failed to authenticate to reset the password.
Hope that helps a little? Feel free to message me if you are still stuck👍
Just to add I've updated the script in my github with a version which includes a password validation check. Basically the script will now bomb out if the password is incorrect. This would usually point to a duplicate local admin account with the same name already existing before the LAPS account is created.
Just to add I've updated the script in my github with a version which includes a password validation check. Basically the script will now bomb out if the password is incorrect. This would usually point to a duplicate local admin account with the same name already existing before the LAPS account is created.
One other thing, do you have the LAPS.log to share? If this is the first time its ran and its reporting that "admin has already been created" then that would also indicate that the account existed before LAPS was run.
One other thing, do you have the LAPS.log to share? If this is the first time its ran and its reporting that "admin has already been created" then that would also indicate that the account existed before LAPS was run.
Hi Perry
Thanks for replying so quickly.
I had a look at the log and I suspect I set it up wrong the first time which presumably meant the local laps admin got created with the incorrect password/API details.
I setup a new user and password (and used your new script), flushed the policies and it now works.
Thanks a million for your help!
Hi Perry
Thanks for replying so quickly.
I had a look at the log and I suspect I set it up wrong the first time which presumably meant the local laps admin got created with the incorrect password/API details.
I setup a new user and password (and used your new script), flushed the policies and it now works.
Thanks a million for your help!
No problem at all!
Glad to hear it's working now😃
I've been working on a LAPS solution for macs and have created a couple of scripts to manage the cycle of the password and account creation and an app to show the password when it's needed.
Some other LAPS for mac solutions display the admin password in plain text in Jamf which is a massive security risk. My script encrypts it all and never displays the password unless you use the decryption script which you can scope to just admin users.
I've detailed the setup on my github and the scripts are there as well.
https://github.com/PezzaD84/macOSLAPS
Check it out to see if it does what you need.
I like you article but your script LAPS Create Cycel Password is failing with the error message unknow command. Can you help me with this
I like you article but your script LAPS Create Cycel Password is failing with the error message unknow command. Can you help me with this
Hi @Evinrude
Do you have a log from jamf or the local Lapslog? If you can share this I can take a look.
Hi @Evinrude
Do you have a log from jamf or the local Lapslog? If you can share this I can take a look.
LAPS Logs
LAPS Configuration has failed
Cryptkey has not been successfully configured
SecretKey has not been successfully configured
***** LAPS Account cycled 16/02/2023 13:32:40
Password length has been set to characters
does not exist. Creating local admin now
Device serial is C02G71K3ML7H
JAMF ID is
LAPS Configuration has failed
Cryptkey has not been successfully configured
SecretKey has not been successfully configured
-------------------------------------------------------------------------------
script MacOS - LAPS - Create Admin & Cycle Password...
Script exit code: 0
Script result: Log already exists. Continuing setup.....
***** LAPS Account cycled 16/02/2023 15:59:34
Password length has been set to characters
/Library/Application Support/JAMF/tmp/MacOS - LAPS - Create Admin & Cycle Password: line 58: ==: command not found
cut: [-bcf] list: values may not include zero
usage: grep [-abcdDEFGHhIiJLlMmnOopqRSsUVvwXxZz] [-A num] [-B num] [-C[num]]
[-e pattern] [-f file] [--binary-files=value] [--color=when]
[--context[=num]] [--directories=action] [--label] [--line-buffered]
[--null] [pattern] [file ...]
does not exist. Creating local admin now
2023-02-16 15:59:34.713 sysadminctl[36742:231693] Usage: sysadminctl
-deleteUser <user name> [-secure || -keepHome] (interactive || -adminUser <administrator user name> -adminPassword <administrator password>)
-newPassword <new password> -oldPassword <old password> [-passwordHint <password hint>]
-resetPasswordFor <local user name> -newPassword <new password> [-passwordHint <password hint>] (interactive] || -adminUser <administrator user name> -adminPassword <administrator password>)
-addUser <user name> [-fullName <full name>] [-UID <user ID>] [-GID <group ID>] [-shell <path to shell>] [-password <user password>] [-hint <user hint>] [-home <full path to home>] [-admin] [-roleAccount] [-picture <full path to user image>] (interactive] || -adminUser <administrator user name> -adminPassword <administrator password>)
-secureTokenStatus <user name>
-secureTokenOn <user name> -password <password> (interactive || -adminUser <administrator user name> -adminPassword <administrator password>)
-secureTokenOff <user name> -password <password> (interactive || -adminUser <administrator user name> -adminPassword <administrator password>)
-guestAccount <on || off || status>
-afpGuestAccess <on || off || status>
-smbGuestAccess <on || off || status>
-automaticTime <on || off || status>
-filesystem status
-screenLock <status || immediate || off || seconds> -password <password>
Pass '-' instead of password in commands above to request prompt.
'-adminPassword' used mostly for scripted operation. Use '-' or 'interactive' to get the authentication string interactively. This preferred for security reasons
*Role accounts require name starting with _ and UID in 200-400 range.
usage: grep [-abcdDEFGHhIiJLlMmnOopqRSsUVvwXxZz] [-A num] [-B num] [-C[num]]
[-e pattern] [-f file] [--binary-files=value] [--color=when]
[--context[=num]] [--directories=action] [--label] [--line-buffered]
[--null] [pattern] [file ...]
/Library/Application Support/JAMF/tmp/MacOS - LAPS - Create Admin & Cycle Password: line 140: /Users//Library/Preferences/com.apple.SetupAssistant.plist: No such file or directory
chown: /Users//Library/Preferences/com.apple.SetupAssistant.plist: No such file or directory
chmod: /Users//Library/Preferences/com.apple.SetupAssistant.plist: No such file or directory
Device serial is C02G71K3ML7H
LAPS Logs
LAPS Configuration has failed
Cryptkey has not been successfully configured
SecretKey has not been successfully configured
***** LAPS Account cycled 16/02/2023 13:32:40
Password length has been set to characters
does not exist. Creating local admin now
Device serial is C02G71K3ML7H
JAMF ID is
LAPS Configuration has failed
Cryptkey has not been successfully configured
SecretKey has not been successfully configured
-------------------------------------------------------------------------------
script MacOS - LAPS - Create Admin & Cycle Password...
Script exit code: 0
Script result: Log already exists. Continuing setup.....
***** LAPS Account cycled 16/02/2023 15:59:34
Password length has been set to characters
/Library/Application Support/JAMF/tmp/MacOS - LAPS - Create Admin & Cycle Password: line 58: ==: command not found
cut: [-bcf] list: values may not include zero
usage: grep [-abcdDEFGHhIiJLlMmnOopqRSsUVvwXxZz] [-A num] [-B num] [-C[num]]
[-e pattern] [-f file] [--binary-files=value] [--color=when]
[--context[=num]] [--directories=action] [--label] [--line-buffered]
[--null] [pattern] [file ...]
does not exist. Creating local admin now
2023-02-16 15:59:34.713 sysadminctl[36742:231693] Usage: sysadminctl
-deleteUser <user name> [-secure || -keepHome] (interactive || -adminUser <administrator user name> -adminPassword <administrator password>)
-newPassword <new password> -oldPassword <old password> [-passwordHint <password hint>]
-resetPasswordFor <local user name> -newPassword <new password> [-passwordHint <password hint>] (interactive] || -adminUser <administrator user name> -adminPassword <administrator password>)
-addUser <user name> [-fullName <full name>] [-UID <user ID>] [-GID <group ID>] [-shell <path to shell>] [-password <user password>] [-hint <user hint>] [-home <full path to home>] [-admin] [-roleAccount] [-picture <full path to user image>] (interactive] || -adminUser <administrator user name> -adminPassword <administrator password>)
-secureTokenStatus <user name>
-secureTokenOn <user name> -password <password> (interactive || -adminUser <administrator user name> -adminPassword <administrator password>)
-secureTokenOff <user name> -password <password> (interactive || -adminUser <administrator user name> -adminPassword <administrator password>)
-guestAccount <on || off || status>
-afpGuestAccess <on || off || status>
-smbGuestAccess <on || off || status>
-automaticTime <on || off || status>
-filesystem status
-screenLock <status || immediate || off || seconds> -password <password>
Pass '-' instead of password in commands above to request prompt.
'-adminPassword' used mostly for scripted operation. Use '-' or 'interactive' to get the authentication string interactively. This preferred for security reasons
*Role accounts require name starting with _ and UID in 200-400 range.
usage: grep [-abcdDEFGHhIiJLlMmnOopqRSsUVvwXxZz] [-A num] [-B num] [-C[num]]
[-e pattern] [-f file] [--binary-files=value] [--color=when]
[--context[=num]] [--directories=action] [--label] [--line-buffered]
[--null] [pattern] [file ...]
/Library/Application Support/JAMF/tmp/MacOS - LAPS - Create Admin & Cycle Password: line 140: /Users//Library/Preferences/com.apple.SetupAssistant.plist: No such file or directory
chown: /Users//Library/Preferences/com.apple.SetupAssistant.plist: No such file or directory
chmod: /Users//Library/Preferences/com.apple.SetupAssistant.plist: No such file or directory
Device serial is C02G71K3ML7H
Thanks for sharing this.
Was the script run from jamf or run locally? Has any modification to the script been done?
It looks like some variables are missing in the failed commands. Also not sure what the "line 58 command not found" error is, as in the script there's nothing on line 58. The result you've shared looks like it's trying to run == as a command which is very odd.
Thanks for sharing this.
Was the script run from jamf or run locally? Has any modification to the script been done?
It looks like some variables are missing in the failed commands. Also not sure what the "line 58 command not found" error is, as in the script there's nothing on line 58. The result you've shared looks like it's trying to run == as a command which is very odd.
We are running this script from the Jamf Only. We haven't made any modification in the script apart from removing the slack notification part from the script.
Its fails in line 58 which is
if $specialchar == true ; then
password=$(openssl rand -base64 32 | tr -d '/' | tr -d '\\' | tr -d ' ' | cut -c -$length | cut -c 2-)
We are running this script from the Jamf Only. We haven't made any modification in the script apart from removing the slack notification part from the script.
Its fails in line 58 which is
if $specialchar == true ; then
password=$(openssl rand -base64 32 | tr -d '/' | tr -d '\\' | tr -d ' ' | cut -c -$length | cut -c 2-)
Ah ok that's line 68 in the current version.
Are you entering a true or false flag in parameter 8 in the script policy? If the variable is left blank then the if statement will have nothing to compare so that could be why it's trying to run == as a command.
Ah ok that's line 68 in the current version.
Are you entering a true or false flag in parameter 8 in the script policy? If the variable is left blank then the if statement will have nothing to compare so that could be why it's trying to run == as a command.
Yes, i am entering a true flag in parameter 8 in the script policy. Its weird why is failing
Yes, i am entering a true flag in parameter 8 in the script policy. Its weird why is failing
It's really odd. It's not pulling in any of the parameters set in jamf or something is stripping the variables.
You can see all the parameter options are blank.
"Password length is set to (blank) characters"
"(blank) does not exist"
Then the if statement is failing as parameter 8 is coming through as blank.
You can also see the plist creation part is failing as there is no user being populated into the file path.
Really odd issue can't say I've seen this before. I would test another script to see if variables set in the jamf policy are being striped out as well.
It's really odd. It's not pulling in any of the parameters set in jamf or something is stripping the variables.
You can see all the parameter options are blank.
"Password length is set to (blank) characters"
"(blank) does not exist"
Then the if statement is failing as parameter 8 is coming through as blank.
You can also see the plist creation part is failing as there is no user being populated into the file path.
Really odd issue can't say I've seen this before. I would test another script to see if variables set in the jamf policy are being striped out as well.
Okay ..I have made the parameter vule as blank and assign the value in the script and running the script again and below is the output
===========================================
cript MacOS - LAPS - Create Admin & Cycle Password...
Script exit code: 1
Script result: Log already exists. Continuing setup.....
***** LAPS Account cycled 17/02/2023 15:15:29
Password length has been set to 16 characters
A Special character has been set in the password
GroupMembership: root XXXAdmin
XXXAdmin has already been created and is a local admin. Resetting local admin password....
error reading input file
2023-02-17 15:15:32.094 sysadminctl[13006:77173] Operation is not permitted without secure token unlock.
<dscl_cmd> DS Error: -14090 (eDSAuthFailed)
Authentication for node /Local/Default failed. (-14090, eDSAuthFailed)
Password validation failed.
It's really odd. It's not pulling in any of the parameters set in jamf or something is stripping the variables.
You can see all the parameter options are blank.
"Password length is set to (blank) characters"
"(blank) does not exist"
Then the if statement is failing as parameter 8 is coming through as blank.
You can also see the plist creation part is failing as there is no user being populated into the file path.
Really odd issue can't say I've seen this before. I would test another script to see if variables set in the jamf policy are being striped out as well.
I have removed the parameter and inserted the value in the script itself and below is the output
Running Script MacOS - LAPS - Create Admin & Cycle Password...
Script exit code: 1
Script result: Log already exists. Continuing setup.....
***** LAPS Account cycled 17/02/2023 15:15:29
Password length has been set to 16 characters
A Special character has been set in the password
GroupMembership: root xxxAdmin
xxxAdmin has already been created and is a local admin. Resetting local admin password....
error reading input file
2023-02-17 15:15:32.094 sysadminctl[13006:77173] Operation is not permitted without secure token unlock.
<dscl_cmd> DS Error: -14090 (eDSAuthFailed)
Authentication for node /Local/Default failed. (-14090, eDSAuthFailed)
Password validation failed.
I have removed the parameter and inserted the value in the script itself and below is the output
Running Script MacOS - LAPS - Create Admin & Cycle Password...
Script exit code: 1
Script result: Log already exists. Continuing setup.....
***** LAPS Account cycled 17/02/2023 15:15:29
Password length has been set to 16 characters
A Special character has been set in the password
GroupMembership: root xxxAdmin
xxxAdmin has already been created and is a local admin. Resetting local admin password....
error reading input file
2023-02-17 15:15:32.094 sysadminctl[13006:77173] Operation is not permitted without secure token unlock.
<dscl_cmd> DS Error: -14090 (eDSAuthFailed)
Authentication for node /Local/Default failed. (-14090, eDSAuthFailed)
Password validation failed.
Hello @perryd84
Did you get the chance to look into the above error "Operation is not permitted without secure token unlock"
Hello @perryd84
Did you get the chance to look into the above error "Operation is not permitted without secure token unlock"
Hi @Evinrude sorry completely missed these updates.
I would remove the local account completely before re-running the script. If the account has been created and the password reset has failed, the encoded password will be updated and escrowed to jamf but it will no longer be the same as the local account. In this case the real password will never be able to be recovered and reset so its best to have a clean slate.
I'm actually in the process of creating a reset script which will set the whole process back to a clean state to avoid any issues such as this.
@perryd84 , good afternoon.
For me, it was not clear, which user I use in the API credential?
Hi @caio_clemente
Really sorry I missed this message!
The encoded API account is a regular API account but encoded into a secure string.
You can use this small script to encode your API account.
https://github.com/PezzaD84/macOSLAPS/blob/main/Encode%20API%20Credentials
@perryd84 , good afternoon.
For me, it was not clear, which user I use in the API credential?
Perry has probably replied already. You create a new user in Jamf and then use that for the api creds.
Reply
Enter your E-mail address. We'll send you an e-mail with instructions to reset your password.