Prompt local user to change password

g_rodgers
New Contributor

Hi all, our teacher MacBooks are not bound to AD, we manually create a local account as and when a MacBook is deployed to a member of staff, and we set that user as an enabled FileVault2 user. My question is, is it possible (by way of a script, config profile or whatever) to prompt the local user to change their password every x number of weeks?

Many thanks.

4 REPLIES 4

chad_fox
Contributor II

I did a search and came up with these:

https://jamfnation.jamfsoftware.com/discussion.html?id=6301

https://jamfnation.jamfsoftware.com/discussion.html?id=4504

https://jamfnation.jamfsoftware.com/discussion.html?id=18574

tobiaslinder
Contributor II
Contributor II

Hi
I did run into problems when I just enforced the password change. So I used a soft but annoying approach.

1.
Create an extension attribute that searches for password age:

#!/usr/bin/python2.7
import datetime
import plistlib
import subprocess

# Obtain username from last logged in user
user = plistlib.readPlistFromString(subprocess.check_output(['/usr/bin/syslog', '-F', 'xml', '-k', 'Facility', 'com.apple.system.lastlog', '-k', 'Sender', 'loginwindow']))[-1]['ut_user']

# Use 'dcsl' to read 'PasswordPolicyOptions' data
# This first method works on 10.9 or earlier clients, or 10.10 clients that migrated from earlier versions
output = subprocess.check_output(['/usr/bin/dscl', '.', '-read', '/Users/' + user, 'PasswordPolicyOptions'])
try:
    plist = plistlib.readPlistFromString('
'.join(output.split()[1:]))

    # When read from 'PasswordPolicyOptions' the date is a 'datetime' object
    lastSetDate = plist['passwordLastSetTime'].date()
except Exception:
    # If 'passwordLastSetTime' does not exist the data will be found in 'accountPolicyData'
    # This is expected on 10.10 or newer clients that were not migrated
    output = subprocess.check_output(['/usr/bin/dscl', '.', '-read', '/Users/' + user, 'accountPolicyData'])
    try:
        # The syntax below strips the first line from 'output' which is not valid XML
        plist = plistlib.readPlistFromString('
'.join(output.split()[1:]))

        # When read from 'accountPolicyData' the date is in a floating point/real number timestamp format
        lastSetDate = datetime.datetime.utcfromtimestamp(plist['passwordLastSetTime']).date()
    except Exception:
        try:
            # If 'passwordLastSetTime' does not exist fall back to the account creation timestamp
            lastSetDate = datetime.datetime.utcfromtimestamp(plist['creationTime']).date()
        except Exception:
            # If unable to determine any usable timestamp from the above, exit with a 'No Value' result
            print("<result>No Value</result>")
            raise SystemExit

# 'datetime' supports addition and subtraction between 'datetime.date' objects
# We use this here to obtain the number of days from today and the 'lastSetDate'
today = datetime.datetime.utcnow().date()
passwordAge = (today - lastSetDate).days

# Output the result for the extension attribute
print("<result>{0}</result>".format(passwordAge))

2.
Create a smart group that searches for devices that have a password age of more then 30 days

3.
Create a policy that runs daily on the devices that are in the group from step 2 with this script:

#!/bin/bash

LoggedInUser=`who | grep console | awk '{print $1}'`
now=`date`

if [ "$LoggedInUser" == "" ]; then
    echo "No Logged in User" > /Library/Application Support/JAMF/password.txt
else
        RESPONSE=`/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper -windowType hud -lockhud -heading "Password change" -description "Your password is older then 30 days. Please change it!" -button1 "Change" -button2 "Cancel" -cancelButton "2"`

        if [ "$RESPONSE" == "0" ]; then
        open /System/Library/PreferencePanes/Accounts.prefPane/
        else
            echo "$LoggedInUser chose Cancel on $HOSTNAME at $now" > /Library/Application Support/JAMF/password.txt
        fi
fi
exit

fvialva
New Contributor

What did you use for the criteria for the password age. I am trying to implement a similar process for my company

tobiaslinder
Contributor II
Contributor II

Hi @fvialva You can just use the extension attribute above and then create a smart group that scopes machines that have a certain password age.