Convert OD user account to OS X local account

johnklimeck
Contributor II

Basically this is related to the context of migrating to an Active Directory account using Centrify Direct Control

Yet, Centrify DC only migrates from an existing user's local OS X account (linking with the accompanying user's local home folder).

Is there a tool, terminal commands, procedure, etc. that will convert the OD account to an OS X local account.

I am aware that I can create an OS X local account manually and then "move" / mv the contents into this new home folder, and then do a chown -R.

I undertand this is related to UID's, and that the actual OD user account is stored on the OD server.

We then use Centrify Account Migration Tool to "Link" this home folder to an AD user account name. It Links, and successfully logs in using AD creds, but the user profile / permissions are whacked. For example, do not see docs on the desktop, desktop picture, etc.

thanks in advance,

john k

1 ACCEPTED SOLUTION

johnklimeck
Contributor II

Reply to my own post....

Apparently all one has to do is create a local OS X account, with the same exact name as the OD user's home folder.

OS X will ask to use the Existing Home Folder (and auto fix all permissions).

Since I am testing this for a remote site, and do not have direct access to this machine and OD user home folder, I do not know for sure, if the user's profile prefs come over. It seems like it does not.

Not sure if the user's profile prefs (desktop picture, dock, etc) is located in that local home folder, or if it is stored in some folder on the OS X / OD server, it very well could be.

I am aware of the path for a local users profile:

/var/db/dslocal/nodes/Default/users

And I am guessing it is, username.plist

jk

View solution in original post

11 REPLIES 11

johnklimeck
Contributor II

Reply to my own post....

Apparently all one has to do is create a local OS X account, with the same exact name as the OD user's home folder.

OS X will ask to use the Existing Home Folder (and auto fix all permissions).

Since I am testing this for a remote site, and do not have direct access to this machine and OD user home folder, I do not know for sure, if the user's profile prefs come over. It seems like it does not.

Not sure if the user's profile prefs (desktop picture, dock, etc) is located in that local home folder, or if it is stored in some folder on the OS X / OD server, it very well could be.

I am aware of the path for a local users profile:

/var/db/dslocal/nodes/Default/users

And I am guessing it is, username.plist

jk

Andy_McCaskill
Contributor

Heads up on this. You need to go remove the (deleted) off of the user folder to make this work.

dan-snelson
Valued Contributor II

@johnklimeck Here's what we're using to convert Mobile AD accounts to local accounts:

function convertAccount() { # Convert account from mobile to local
    ScriptLog "* Convert account ..." 
    if [ "${loginPassword}" == "${confirmPassword}" ] && [ "${dblchk}" == 1 ]; then # The passwords match and the user has acknowldged they have a backup

        ScriptLog "* Convert account from mobile to local ..."    

        # Delete the currently logged-in user account
        ScriptLog "* Deleting ${loggedInUser} account from client-side directory ..."
        /usr/bin/dscl . delete /Users/"${loggedInUser}"

        # Determine the current highest user UID, in the 500 range
        maxid=$(/usr/bin/dscl . -list /Users UniqueID | /usr/bin/awk '{print $2}' | /usr/bin/grep -Ex '5[0-9][0-9]' | /usr/bin/sort -ug | /usr/bin/tail -1)

        if [ -z ${maxid} ]; then
            newid=501           # There aren't any user accounts in the 5nn range; use 501
        else
            newid=$((maxid+1))  # There are user accounts in the 5nn range; add one to the hightest
        fi


        # Create local user account ...
        ScriptLog "* Create ${loggedInUser} local account in client-side directory ..."
        /usr/sbin/sysadminctl -addUser "${loggedInUser}" -fullName "${userRealName}" -UID "${newid}" -password "${confirmPassword}" -home "/Users/${loggedInUser}" "${adminStatus}"

        # Reset ownership on home directory and append location
        ScriptLog "* Correct permissions for ${loggedInUser} ..."
        /usr/sbin/chown -R "${loggedInUser}":staff /Users/"${loggedInUser}"
        /usr/bin/dscl . -append /Users/"${loggedInUser}" NFSHomeDirectory /Users/"${loggedInUser}"/

        ScriptLog "* Sleep for five seconds ..."
        /bin/sleep 5

        # Force logout
        ScriptLog "* Force logout ..."
        /bin/ps -Ajc | /usr/bin/grep loginwindow | /usr/bin/awk '{print $2}' | /usr/bin/xargs /bin/kill -9

        ScriptLog "---"
        ScriptLog "- $loggedInUser account converted from Mobile to Local"
        ScriptLog "---"

        # Re-direct logging to the JSS
        exec 1>&3 2>&4
        /bin/echo >&1 "$loggedInUser account converted from Mobile to Local."

    else    # Password don't match; inform user and exit

        ScriptLog "* Error: Either passwords don't match, the user didn't authorize the change, or both; inform user and exit ... dblchk='${dblchk}'" 

        # The user has failed to match the password three consecutive times.
        /usr/local/jamf/bin/jamf displayMessage -message "Error -397; exiting."
        ScriptLog "* Error -397: The user failed to confirm the password three consecutive times."

        # Re-direct logging to the JSS
        exec 1>&3 2>&4
        /bin/echo >&1 "Error -397"
        exit 2 # exit with an error status      
    fi
}

thoule
Valued Contributor II

@johnklimeck You are correct that making an account with the same short name will override the OD account. While windows users need to prepend DOMAIN before the user account (DOMAINusername), Macs instead will search domains in order so you don't need to tell it where the account exists. The local computer domain is always searched first.

perrinbw
New Contributor II

@dan.snelson Can you explain more how you have setup this script in your JAMF environment?

dan-snelson
Valued Contributor II

@perrinbw My previous post was only a single function from a larger script, which we make available via Self Service.

I recommend reviewing @lisacherie's recent post, Converting AD Mobile Accounts to Local.

dan-snelson
Valued Contributor II

@perrinbw Here's our complete script, which relies on client-side functions (i.e., "source /path/to/client-side/functions/functions.sh") for logging and Pashua.

#!/bin/sh
####################################################################################################
#
# ABOUT
#
#   Convert Mobile Account to Local Account
#   Based on: https://jamfnation.jamfsoftware.com/discussion.html?id=12462#responseChild73117
#
#   This script is designed to remove a mobile user account and re-create
#   a local account with the same username and the password from user-input.
#   It will also give read/write permissions to the user's home folder.
#
####################################################################################################
#
# HISTORY
#
#   Version 1.0, 28-Apr-2016, Dan K. Snelson
#   Version 1.1, 02-May-2016, Dan K. Snelson
#       Removed code and verbiage about the user's keychain
#   Version 1.2, 03-May-2016, Dan K. Snelson
#       Fixed error when no users with 5nn UID existed
#
####################################################################################################
# Import general functions
source /path/to/client-side/functions/functions.sh
####################################################################################################

ScriptLog "###############################################"
ScriptLog "### Convert Mobile Account to Local Account ###"
ScriptLog "###############################################"

### Variables
loggedInUser=`/usr/bin/stat -f%Su /dev/console`
UserUID=`/usr/bin/dscl . read /Users/"${loggedInUser}" UniqueID | grep UniqueID: | cut -c 11-`
userRealName=`/usr/bin/dscl . -read /Users/"${loggedInUser}" | /usr/bin/grep RealName: | cut -c11-`
if [[ -z "${userRealName}" ]]; then
    userRealName=`/usr/bin/dscl . -read /Users/"${loggedInUser}" | awk '/^RealName:/,/^RecordName:/' | sed -n 2p | cut -c 2-`
fi
if [[ $(/usr/bin/dsmemberutil checkmembership -U "${loggedInUser}" -G admin) != *not* ]]; then
    adminStatus="-admin"  # User is a member of the admin group; retain admin rights
    userIsAdmin="Yes"
else
    adminStatus=""            # User is not a member of the admin group
    userIsAdmin="No"
fi


# Echo variables
ScriptLog "Variables ..."
ScriptLog "* loggedInUser=${loggedInUser}"
ScriptLog "* UserUID=${UserUID}"
ScriptLog "* userRealName=${userRealName}"
ScriptLog "* adminStatus=${userIsAdmin}"


### Define the functions
function validateCurrentUserID() { # Exit if UID is under 1000 (local account)
    ScriptLog "* Validate Current UserID ..."
    if [[ "${UserUID}" -lt 1000 ]]; then
        ScriptLog "* Error: The account '${loggedInUser}' is already a local account (${UserUID})."
        # Re-direct logging to the JSS
        exec 1>&3 2>&4
        /bin/echo >&1 "Error: The account '${loggedInUser}' is already a local account (${UserUID})."
        # Inform user of the error
        /usr/local/jamf/bin/jamf displayMessage -message "Error: The account '${loggedInUser}' is already a local account (${UserUID})."
        exit 2
    else
        ScriptLog "* The '${loggedInUser}' account is a mobile account (${UserUID}); proceeding ..."
    fi
}


function checkCancel() { # Check for cancel button
    #ScriptLog "* Check for cancel button ..."    
    if [ "${cb}" == 1 ]; then
        # The user clicked Cancel
        ScriptLog "* Cancelled by user."
        # Re-direct logging to the JSS
        exec 1>&3 2>&4
        /bin/echo >&1 "Cancelled by user."
        exit 2 # exit with an error status
    fi
}


function promptLoginPassword() { # Prompt for login password
    ScriptLog "* Prompt for Login Password ..."   
    pashuaDialog="
        # Set window title
        *.title = Convert Mobile Account to Local Account
        *.floating = 1

        # Specify image
        img.type = image
        img.path = /System/Library/CoreServices/Certificate Assistant.app/Contents/Resources/AppIcon.icns
        img.maxwidth = 64
        img.rely = 110

        # Introductory text
        txt.type = text
        txt.default = This script converts your Mobile Account, ${loggedInUser}, to a Local Account.[return][return]Click Cancel to exit without making any changes.[return][return]To continue, save your work -- you will be logged out -- enter your current login password and click Confirm Password ...
        #txt.height = 276
        txt.width = 350
        txt.x = 80
        txt.y = 135
        #txt.tooltip = Your current login password is the one you use to login to your computer.

        # Add a password field
        loginPassword.type = password
        loginPassword.label = Current Login Password
        loginPassword.mandatory = true
        loginPassword.width = 350
        loginPassword.x = 80
        loginPassword.y = 80
        loginPassword.tooltip = Your current login password is the one you use to login to your computer or unlock the screensaver.

        # Add checkboxes
        chk.rely = -10
        chk.relx = 80
        chk.type = checkbox
        chk.label = I have a current, known-working backup of my data.
        chk.tooltip = By checking this box, I acknowledge I have a known-working backup of my data.
        chk.default = 0
        chk.mandatory = true

        # Add a cancel button with default label
        cb.type = cancelbutton
        cb.tooltip = Cancel without saving changes.

        db.type = defaultbutton
        db.label = Confirm Password ...
        db.tooltip = Enter your current login password and click Confirm Password ...
        "

    pashua_run "${pashuaDialog}"
}


function confirmLoginPassword() { # Confirm login password
    ScriptLog "* Confirm Login Password ..."  
    pashuaDialog="
        # Set window title
        *.title = Convert Mobile Account to Local Account
        *.floating = 1

        # Specify image
        img.type = image
        img.path = /System/Library/CoreServices/Certificate Assistant.app/Contents/Resources/AppIcon.icns
        img.maxwidth = 64
        img.rely = 30

        # Introductory text
        txt.type = text
        txt.default = Please confirm your current login password and click Continue ...
        #txt.height = 276
        txt.width = 350
        txt.x = 80
        txt.y = 135
        #txt.tooltip = Confirm your current login password (the one you use to login to your computer).

        # Add a password field
        confirmPassword.type = password
        confirmPassword.label = Confirm Login Password
        confirmPassword.mandatory = true
        confirmPassword.width = 350
        confirmPassword.x = 80
        confirmPassword.y = 80
        confirmPassword.tooltip = Confirm your current login password (the one you use to login to your computer or unlock the screensaver).

        # Add checkboxes
        chk.rely = -10
        chk.relx = 80
        chk.type = checkbox
        chk.label = I have a current, known-working backup of my data.
        chk.tooltip = I acknowledge I have a known working backup of my data.
        chk.default = 1
        chk.disabled = 1
        chk.mandatory = true

        # Add a cancel button with default label
        cb.type = cancelbutton
        cb.tooltip = Cancel without saving changes.

        db.type = defaultbutton
        db.label = Continue ...
        db.tooltip = Confirm your current login password and click Continue ...
        "

    pashua_run "${pashuaDialog}"
}


function validateDataBackup() { # Ensure the user has selected the checkbox for data backup
    ScriptLog "* Validate Data Backup ..."    
    while [ "${chk}" == 0 ]; do
        pashuaDialog="
            # Set window title
            *.title = Convert Mobile Account to Local Account — Error
            *.floating = 1

            # Specify image
            img.type = image
            img.path = /System/Library/CoreServices/Problem Reporter.app/Contents/Resources/ProblemReporter.icns
            img.maxwidth = 64

            # Introductory text
            txt.type = text
            txt.default = You must check the box to indicate you have a current, known-working backup of your data.
            txt.height = 276
            txt.x = 80
            txt.y = 64
            "

        pashua_run "${pashuaDialog}"

        promptLoginPassword     # Prompt for login password

        checkCancel             # Check if the cancel button was clicked; if so, exit.

    done
}


function validateAuthorization() { # Ensure the user has selected the checkbox for data backup
    ScriptLog "* Validate Authorization to Convert Account ..."   
    while [ "${dblchk}" == 0 ]; do
        pashuaDialog="
            # Set window title
            *.title = Convert Mobile Account to Local Account — Error
            *.floating = 1

            # Specify image
            img.type = image
            img.path = /System/Library/CoreServices/Problem Reporter.app/Contents/Resources/ProblemReporter.icns
            img.maxwidth = 64

            # Introductory text
            txt.type = text
            txt.default = You must check the box to indicate you have a current, known-working backup of your data.
            txt.height = 276
            txt.x = 80
            txt.y = 64
            "

        pashua_run "${pashuaDialog}"

        return          # Return to the calling function

    done
}


function passwordMismatch() { # Inform user the passwords don't match
    ScriptLog "* Passwords Mismatch ..."  
    if [ "${loginPassword}" != "${confirmPassword}" ]; then
        pashuaDialog="
            # Set window title
            *.title = Convert Mobile Account to Local Account — Error
            *.floating = 1

            # Specify image
            img.type = image
            img.path = /System/Library/CoreServices/Problem Reporter.app/Contents/Resources/ProblemReporter.icns
            img.maxwidth = 64

            # Introductory text
            txt.type = text
            txt.default = Passwords do not match; please try again.[return](Attempt "${defaultPasswordAttempts}" of 3.)
            txt.height = 276
            txt.x = 80
            txt.y = 64
            "

        pashua_run "${pashuaDialog}"

    fi
}


function validatePasswords() { # Validate the passwords are identical
    ScriptLog "* Validate the passwords are identical ..."    

    passwordMismatch        # Inform user the passwords don't match

    confirmLoginPassword    # Confirm login password

    checkCancel             # Check if the cancel button was clicked; if so, exit.
}


function authorizeConversion() { # Authorize account conversion
    ScriptLog "* Authorize Account Conversion ..."    
    if [ "${loginPassword}" == "${confirmPassword}" ]; then # Double-check the passwords match before authorizing conversion
        pashuaDialog="
            # Set window title
            *.title = Convert Mobile Account to Local Account
            *.floating = 1

            # Specify image
            img.type = image
            img.path = /System/Library/CoreServices/Problem Reporter.app/Contents/Resources/ProblemReporter.icns
            img.maxwidth = 64
            img.rely = 135

            # Introductory text
            txt.type = text
            txt.default = By clicking Proceed, you acknowledge the following:[return]• You have a current, known-working backup[return]• You will be logged out[return]• Your Mobile Account, ${loggedInUser}, will be permanently converted to a Local Account[return][return]Click Cancel to exit without making any changes.[return][return]If you are certain you want to permanently convert your account, check the box to acknowledge you have a current, known-working backup of your data and click Permanently convert ${loggedInUser}.
            txt.width = 350
            txt.x = 80
            txt.y = 64

            # Add checkboxes
            dblchk.rely = -10
            dblchk.relx = 80
            dblchk.type = checkbox
            dblchk.label = I have a current, known-working backup of my data.
            dblchk.tooltip = I acknowledge I have a known working backup of my data.
            dblchk.default = 0
            #dblchk.disabled = 1
            dblchk.mandatory = true

            # Add a cancel button with default label
            cb.type = cancelbutton
            cb.tooltip = Cancel without saving changes.

            db.type = defaultbutton
            db.label = Permanently convert ${loggedInUser}
            db.tooltip = Click to convert your Mobile Account to a Local Account
            "

        pashua_run "${pashuaDialog}"

        checkCancel             # Check if the cancel button was clicked; if so, exit.

    fi
}


function convertAccount() { # Convert account from mobile to local
    ScriptLog "* Convert account ..." 
    if [ "${loginPassword}" == "${confirmPassword}" ] && [ "${dblchk}" == 1 ]; then # The passwords match and the user has acknowldged they have a backup

        ScriptLog "* Convert account from mobile to local ..."    

        # Delete the currently logged-in user account
        ScriptLog "* Deleting ${loggedInUser} account from client-side directory ..."
        /usr/bin/dscl . delete /Users/"${loggedInUser}"

        # Determine the current highest user UID, in the 500 range
        maxid=$(/usr/bin/dscl . -list /Users UniqueID | /usr/bin/awk '{print $2}' | /usr/bin/grep -Ex '5[0-9][0-9]' | /usr/bin/sort -ug | /usr/bin/tail -1)

        if [ -z ${maxid} ]; then
            newid=501           # There aren't any user accounts in the 5nn range; use 501
        else
            newid=$((maxid+1))  # There are user accounts in the 5nn range; add one to the hightest
        fi


        # Create local user account ...
        ScriptLog "* Create ${loggedInUser} local account in client-side directory ..."
        /usr/sbin/sysadminctl -addUser "${loggedInUser}" -fullName "${userRealName}" -UID "${newid}" -password "${confirmPassword}" -home "/Users/${loggedInUser}" "${adminStatus}"

        # Reset ownership on home directory and append location
        ScriptLog "* Correct permissions for ${loggedInUser} ..."
        /usr/sbin/chown -R "${loggedInUser}":staff /Users/"${loggedInUser}"
        /usr/bin/dscl . -append /Users/"${loggedInUser}" NFSHomeDirectory /Users/"${loggedInUser}"/

        #Delete the user's keychain folder.
#       ScriptLog "* Delete ${loggedInUser} keychain ..."
#       /bin/rm -Rf /Users/"${loggedInUser}"/Library/Keychains/*

        ScriptLog "* Sleep for five seconds ..."
        /bin/sleep 5

        # Force logout
        ScriptLog "* Force logout ..."
        /bin/ps -Ajc | /usr/bin/grep loginwindow | /usr/bin/awk '{print $2}' | /usr/bin/xargs /bin/kill -9

        ScriptLog "---"
        ScriptLog "- $loggedInUser account converted from Mobile to Local"
        ScriptLog "---"

        # Re-direct logging to the JSS
        exec 1>&3 2>&4
        /bin/echo >&1 "$loggedInUser account converted from Mobile to Local."

    else    # Password don't match; inform user and exit

        ScriptLog "* Error: Either passwords don't match, the user didn't authorize the change, or both; inform user and exit ... dblchk='${dblchk}'" 

        # The user has failed to match the password three consecutive times.
        /usr/local/jamf/bin/jamf displayMessage -message "Error -397; exiting."
        ScriptLog "* Error -397: The user failed to confirm the password three consecutive times."

        # Re-direct logging to the JSS
        exec 1>&3 2>&4
        /bin/echo >&1 "Error -397"
        exit 2 # exit with an error status      
    fi
}


### Call the functions

validateCurrentUserID   # Exit if UID is under 1000 (local account)

promptLoginPassword     # Prompt for login password

checkCancel             # Check if the cancel button was clicked; if so, exit.

validateDataBackup      # Ensure the user has selected the checkbox

confirmLoginPassword    # Prompt for login password

checkCancel             # Check if the cancel button was clicked; if so, exit.


# Ensure passwords match; if not, display an error and prompt to re-enter.
    defaultPasswordAttempts=0
    while [[ "${loginPassword}" != "${confirmPassword}" ]]; do

        defaultPasswordAttempts="$((defaultPasswordAttempts+1))"

        validatePasswords       # Validate the passwords are identical

        if [[ "${defaultPasswordAttempts}" -ge 3 ]]; then
            # The user has failed to match the password three consecutive times.
            /usr/local/jamf/bin/jamf displayMessage -message "Too many failed attempts to confirm password; exiting."
            ScriptLog "* Error: The user failed to confirm the password three consecutive times. defaultPasswordAttempts='${defaultPasswordAttempts}'"
            # Re-direct logging to the JSS
            exec 1>&3 2>&4
            /bin/echo >&1 "Error: The user failed to confirm the password three consecutive times."
            exit 2 # exit with an error status
        fi

    done


# Authorize conversion

    dblchk=0

    while [ "${loginPassword}" == "${confirmPassword}" ] && [ "${dblchk}" == 0 ]; do

        authorizeConversion     # Authorize conversion

        validateAuthorization   # Ensure the user has selected the checkbox to authorize conversion

        checkCancel             # Check if the cancel button was clicked; if so, exit.      

    done

    convertAccount          # Convert account from mobile to local


exit 0

dan-snelson
Valued Contributor II

@perrinbw Here's our client-side functions, which we source into our scripts:

#!/bin/sh
####################################################################################################
#
# ABOUT
#
#   Standard functions which are imported into other scripts
#
####################################################################################################
#
# HISTORY
#
#   Version 1.1, 30-Nov-2016, Dan K. Snelson
#
####################################################################################################
#
# LOGGING
#
####################################################################################################

# Variables

logFile="/var/log/com.company.division.log"

# Check for / create logFile
    if [ ! -f "${logFile}" ]; then
        # logFile not found; Create logFile
        /usr/bin/touch "${logFile}"
    fi

exec 3>&1 4>&2        # Save standard output and standard error
exec 1>>"${logFile}"    # Redirect standard output to logFile
exec 2>>"${logFile}"    # Redirect standard error to logFile

#set -xv; exec 1>>"${logFile}" 2>&1  # Enable all logging from this point forward


# Logging Functions

# Version 1
alias now="date '+%Y-%m-%d %H:%M:%S'"


function ScriptLog() { # Re-direct logging to the log file ...

    NOW=`date +%Y-%m-%d %H:%M:%S`    
    /bin/echo "${NOW}" " ${1}" >> ${logFile}

}


function jssLog() { # Re-direct logging to the JSS

    ScriptLog "${1}"

    exec 1>&3 2>&4
    /bin/echo >&1 ${1}

}



####################################################################################################
#
# Pashua
#
####################################################################################################

function pashua_run() {

    # Write config file
    local pashua_configfile=`/usr/bin/mktemp /tmp/pashua_XXXXXXXXX`
    echo "$1" > "$pashua_configfile"

    pashuapath='/usr/local/ics/scripts/Pashua.app/Contents/MacOS/Pashua'

    # Get result
    local result=$("$pashuapath" "$pashua_configfile")

    # Remove config file
    rm "$pashua_configfile"

    oldIFS="$IFS"
    IFS=$'
'

    # Parse result
    for line in $result; do
        local name=$(echo $line | sed 's/^([^=]*)=.*$/1/')
        local value=$(echo $line | sed 's/^[^=]*=(.*)$/1/')
        eval $name='$value'
    done

    IFS="$oldIFS"
}

####################################################################################################
#
# JAMF Display Message
#
####################################################################################################

function jamfDisplayMessage() {

    ScriptLog "${1}"
    /usr/local/jamf/bin/jamf displayMessage -message "${1}" &

}

####################################################################################################
#
# Decrypt Password
#
####################################################################################################

function decryptPassword () {

    /bin/echo "${1}" | /usr/bin/openssl enc -aes256 -d -a -A -S "${2}" -k "${3}"

}



####################################################################################################
#
# Reveal File in Finder
#
####################################################################################################

function revealMe() {

    /usr/bin/su - "`/bin/ls -l /dev/console | cut -d " " -f4`" -c "/usr/bin/open -R ${1}"

}

perrinbw
New Contributor II

@dan.snelson thank you so much. Going to investigate which route works best for us.

estes
New Contributor III

This one works for current logged in user and checks if they're in our "Teachers and others" AD group.

#!/bin/bash #Get the logged in user theUser=$(ls -l /dev/console | awk -F " " '{print $3}') if [[ $(/usr/bin/dsmemberutil checkmembership -U "${theUser}" -G "Teachers and others") != not ]]; then dseditgroup -v -o edit -n /Local/Default -a $theUser -t user admin echo "Added $theUser to the local admin group" else echo "$theUser not local admin" fi exit 0

This one looks at all users on the machine. Elevates them if they match the AD group, demotes them otherwise.

#!/bin/bash userList=$(/usr/bin/dscl . list /Users UniqueID | /usr/bin/awk '$2 > 510 { print $1 }') for u in ${userList} ; do /usr/bin/dsmemberutil checkmembership -U ${u} -G "Teachers and others" if [[ $(/usr/bin/dsmemberutil checkmembership -U ${u} -G "Teachers and others") != not ]]; then dseditgroup -v -o edit -n /Local/Default -a ${u} -t user admin logger -t makeAdmin "${u} is local admin" echo "Added ${u} to the local admin group" else dseditgroup -v -o edit -n /Local/Default -d ${u} -t user admin echo "${u} not local admin" fi done exit 0

damonsalvatore
New Contributor

This content helped me a lot thank you for sharing.