Created
January 27, 2018 08:33
-
-
Save lucascantor/f53d92bfe2231af15debefdcd1d3cc6a to your computer and use it in GitHub Desktop.
Generate and apply a standalone macOS password policy, exempting a specified local admin
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
########################################################################################################## | |
## Pupose: Create a pwpolicy XML file based upon variables and options included below. | |
## Policy is applied and then file gets deleted. Use "sudo pwpolicy -u <user> -getaccountpolicies" | |
## to see it, and "sudo pwpolicy -u <user> -clearaccountpolicies" to clear it. | |
## | |
## Usage: Only edit the variables in the Variable flowerbox below. | |
## Run as a policy from Casper, or standalone as root. | |
## | |
## Tested on: OS X 10.10 and 10.11 | |
## | |
## Authors: Danny Friedman, Civis Analytics IT Manager, CCA, civisanalytics.com | |
## Jeff Holland, Civis Analytics Sr. Security Engineer, CISSP/GCUX, civisanalytics.com | |
######################################################################################################### | |
# get logged-in user and assign it to a variable | |
LOGGEDINUSER=$(ls -l /dev/console | awk '{print $3}') | |
echo "LOGGEDINUSER is: $LOGGEDINUSER" | |
############################################################################## | |
# Variables for script and commands generated below. | |
# | |
# EDIT AS NECESSARY FOR YOUR OWN PASSWORD POLICY | |
# AND COMPANY INFORMATION | |
# | |
COMPANY_NAME="company.com" # Company name | |
LOCKOUT=60 # 1 minute lockout | |
MAX_FAILED=5 # 5 max failed logins before locking | |
MIN_LENGTH=10 # at least 10 chars for password | |
exemptAccount1="<exempt local admin username>" #Exempt account used for management. | |
# | |
############################################################################## | |
################################################# | |
##### create pwpolicy.plist in /private/var/tmp | |
# Password policy using variables above is: | |
# Change as necessary in variable flowerbox above | |
# -------------------------------------------------- | |
# pw's must be at least 8 chars | |
# 10 failed login attempts results in a 60 second lockout | |
echo "<dict> | |
<key>policyCategoryAuthentication</key> | |
<array> | |
<dict> | |
<key>policyContent</key> | |
<string>(policyAttributeFailedAuthentications < policyAttributeMaximumFailedAuthentications) OR (policyAttributeCurrentTime > (policyAttributeLastFailedAuthenticationTime + autoEnableInSeconds))</string> | |
<key>policyIdentifier</key> | |
<string>Authentication Lockout</string> | |
<key>policyParameters</key> | |
<dict> | |
<key>autoEnableInSeconds</key> | |
<integer>$LOCKOUT</integer> | |
<key>policyAttributeMaximumFailedAuthentications</key> | |
<integer>$MAX_FAILED</integer> | |
</dict> | |
</dict> | |
</array> | |
<key>policyCategoryPasswordContent</key> | |
<array> | |
<dict> | |
<key>policyContent</key> | |
<string>policyAttributePassword matches '.{$MIN_LENGTH,}+'</string> | |
<key>policyIdentifier</key> | |
<string>Has at least $MIN_LENGTH characters</string> | |
<key>policyParameters</key> | |
<dict> | |
<key>minimumLength</key> | |
<integer>$MIN_LENGTH</integer> | |
</dict> | |
</dict> | |
</array> | |
</dict>" > /private/var/tmp/pwpolicy.plist | |
##### end of pwpolicy.plist generation script | |
################################################### | |
#Check for non-admin account before deploying policy | |
if [ "$LOGGEDINUSER" != "$exemptAccount1" ]; then | |
chown $LOGGEDINUSER:staff /private/var/tmp/pwpolicy.plist | |
chmod 644 /private/var/tmp/pwpolicy.plist | |
# clear account policy before loading a new one | |
pwpolicy -u $LOGGEDINUSER -clearaccountpolicies | |
pwpolicy -u $LOGGEDINUSER -setaccountpolicies /private/var/tmp/pwpolicy.plist | |
elif [ "$LOGGEDINUSER" == "$exemptAccount1" ]; then | |
echo "Currently $exemptAccount1 is logged in and the password policy was NOT set. This script can only be run if the standard computer user is logged in." | |
rm -f /private/var/tmp/pwpolicy.plist | |
exit 1 | |
fi | |
#delete staged pwploicy.plist | |
rm -f /private/var/tmp/pwpolicy.plist | |
echo "Password policy successfully applied to $LOGGEDINUSER." | |
echo "Run \"sudo pwpolicy -u $LOGGEDINUSER -getaccountpolicies\" to see it." | |
echo "Run \"sudo pwpolicy -u $LOGGEDINUSER -clearaccountpolicies\" to remove it." | |
exit 0 |
@DDC-96 the /private/var/tmp location was chosen by the script's authors:
Danny Friedman, Civis Analytics IT Manager, CCA, civisanalytics.com
Jeff Holland, Civis Analytics Sr. Security Engineer, CISSP/GCUX, civisanalytics.com
I've just re-hosted it on GitHub after finding it elsewhere, and finding it useful, but it's VERY old at this point. It hasn't been tested since macOS 10.11 which came out nearly a decade ago now.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hello Lucas,
Thank you for this script. I'm considering a similar approach and have a question about your choice of location path, specifically using <pwpolicy.plist in /private/var/tmp>. Could you explain the reason behind this choice?
I ask because I've developed a similar pwpolicy using bash/XML, but I've set it to /tmp/pwpolicy.xml. While my script functions as intended, I've noticed the difference in staging directories.
I'd greatly appreciate any insights you can offer on this matter