Firmware password rotation using a script?

Valued Contributor


I'm tasked with rotating the firmware password on our fleet. Clearing and setting is fine, either using a policy or a simple script. My issue is that the old password could potentially be one of two values. Both are known so I was thinking of future-proofing with a script containing an array that would attempt to clear it using any values in that array and set the new password once it succeeds.

I'm not a bash expert so before I go down that rabbit hole I was wondering if anyone has had to do this, and if someone has already gone to the effort of writing such a script that they would be willing to share. I am aware of solutions that will store a temporary file containing a password in an obscure folder, but that's not an option for me since my users are admins on their machines.

Here's what I have so far, the script sets an array with the possible current values and verifies that a password is set. From there it verifies the passwords in the array and uses that to delete the current password. If that returns "Password removed" it then sets the new password.

The problem I'm running into is that the 'delete' portion of the script returns '0', presumably because I'm trying multiple old passwords. This doesn't change if the old password is incorrect so I'm definitely going wrong somewhere.

Note: I am NOT a bash expert, and my use of 'sudo' in the script is for local testing purposes only.


    # Assign the new firmware password to a variable

    # Declare an array with the possible existing firmware passwords
    array=( oldpassword1 oldpassword2 oldpassword3 )

    # Verify whether a firmware password is set
    echo "Checking for existing firmware password."
    checkFirmwarePassword=$( sudo /usr/sbin/firmwarepasswd -check )

    # If a firmware password is not set, stop the script and report failure to Jamf
    if [ "$checkFirmwarePassword" = "Password Enabled: No" ]; then
        echo "No firmware password set. This will be set using another policy."
        exit 1
            echo "Firmware password is set. Rotating."
            for i in "${array[@]}"
                printf "%s
" "$i" > sudo "/usr/sbin/firmwarepasswd" "-delete"
                echo $removeResult
                if [[ "$removeResult" =~ "Password removed" ]]; then
                echo "Firmware password removed! Setting new password"
                    # Set the password, exit and report success to Jamf
                    sudo /usr/sbin/firmwarepasswd -setpasswd "$newPassword"
                    exit 0
                    echo "Firmware password verification failed. Exiting!"
                    exit 1

Thanks a lot,


Contributor III

I have not used a script specifically in this instance but one workflow (if i'm recalling correctly, it has been awhile and was sort of built on a whim) was a combination of
• Policies (a couple for a different scopings and passwords)
• Smart Groups
• Extension attributes

The extension attributes were mainly breadcrumbs for our smart groups/policies to see which device had what password assigned or would need a certain password assigned, and it rotated that worked for our small fleet (security ops team), i would set the intervals based on either a check-in frequency or when the device last loaded the EA breadcrumb.

and for the policies I used this Jamf guide:

so after X days or on this check-in, it would run a firmware password removal policy, then get a different breadcrumb and get a different password.

but sounds like your script could be used in conjunction with a similar workflow?

Valued Contributor

Thanks for your reply @walt. We have an extension attribute that shows whether or not the password is set, and the intention is to have this policy scoped to clients that do have an EFI password. I simply included some validation just in case a machine with a firmware password set hadn't inventoried and reported the status as such. I'm also trying to future plan for the next rotation by using an array of old values.

Where I'm stuck is the '0' result I'm getting for the variable 'removeResult' when deleting the password whereas if I run the command locally I get the expected "Password removed" result. I'm sure there's something simple being missed, but at least the array is being passed successfully.

Valued Contributor II

@jtrant In case you aren't already familiar with Firmware Password Manager.

Valued Contributor

Thanks @dan-snelson, I'm aware of Firmware Password Manager but my issue is that all of my devices have firmware passwords and things will get confusing when passwords get cleared by one policy but set by another.

What I'm trying to achieve is rotate the password once per machine, and if a machine is re-enrolled (we clear policy logs during re-enrollment) the policy will run again, try all three passwords, clear it and set the new password.

I'm trying to avoid a situation where we have policy failures because Jamf is trying to remove a firmware password using one policy (potentially using the wrong 'old' password) and failing to set the new one because there's already a firmware password set.

My issue is compounded by the fact that users are local admin, so I can't store the password locally, even temporarily.

Thanks in advance,

Valued Contributor III

So i have a question, if we wanted to rotate the firmware password enmasse, couldn't we just run a removal using the EFI firmware tab in a policy (which I believe requires a restart) and then we could set a the new password after they ran the first policy?

Gabe Shackney
Princeton Public Schools