Script per creare token sicuri in macOS: una guida per i professionisti IT

Nell’attuale panorama IT, la gestione degli account utente e la garanzia di un accesso sicuro sono fondamentali per mantenere una solida sicurezza del sistema. Uno degli aspetti chiave di questa gestione su macOS è l’uso di token sicuri. I token sicuri sono fondamentali per varie funzioni di sicurezza, tra cui l’abilitazione di FileVault e l’esecuzione di alcune attività amministrative.

In questo articolo analizzeremo uno script che automatizza il processo di concessione dell’accesso sicuro con token agli account utente su macOS, spiegandone l’importanza, le funzionalità e i casi d’uso per i professionisti IT e i Managed Service Provider (MSP).

Background

I token sicuri sono una funzione di sicurezza di macOS che fornisce ulteriori misure di autenticazione, in particolare per quanto riguarda la crittografia FileVault. Per i professionisti IT e gli MSP, la gestione di questi token è essenziale per mantenere ambienti sicuri su numerosi dispositivi.

Lo script fornito semplifica il processo di concessione dell’accesso con token sicuro a un account utente, creando persino l’account se non esiste già. Questa automazione è particolarmente vantaggiosa in ambienti su larga scala, dove la configurazione manuale sarebbe poco pratica e dispendiosa in termini di tempo.

Lo script per creare token sicuri in macOS

#!/usr/bin/env bash
# Description: Grants secure token access to Service Account. Account will be created if it doesn't exist. Service Accounts will not show up at the desktop login.
# Release Notes: Initial Release
#
# Custom Fields:
#  New Account Password Custom Field: A secure custom field that stores the password for the new user account.
#  Optional Authentication Account Username Custom Field: A secure custom field that stores the username of the admin account that has secure token already on the device.
#
# Parameters:
#  username: Username to grant secure token access to
#  password: Password of user to grant secure token access to
#  adminuser: (Optional) Secure token Admin username - leave blank to prompt local user
#  adminpassword: (Optional) Secure token Admin password - leave blank to prompt local user
#
# Usage: ./Create-SecureTokenAccount.sh <-u|--username <arg>> <-p|--password <arg>> [-a|--adminuser <arg>] [-d|--adminpassword <arg>]
# <> are required
# [] are optional
# Example: ./Create-SecureTokenAccount.sh --username test --password Password1 --adminuser admin --adminpassword Password2
#
# Notes:
# By using this script, you indicate your acceptance of the following legal terms as well as our Terms of Use at https://www.ninjaone.com/terms-of-use.
# Ownership Rights: NinjaOne owns and will continue to own all right, title, and interest in and to the script (including the copyright). NinjaOne is giving you a limited license to use the script in accordance with these legal terms. 
# Use Limitation: You may only use the script for your legitimate personal or internal business purposes, and you may not share the script with another party. 
# Republication Prohibition: Under no circumstances are you permitted to re-publish the script in any script library or website belonging to or under the control of any other software provider. 
# Warranty Disclaimer: The script is provided “as is” and “as available”, without warranty of any kind. NinjaOne makes no promise or guarantee that the script will be free from defects or that it will meet your specific needs or expectations. 
# Assumption of Risk: Your use of the script is at your own risk. You acknowledge that there are certain inherent risks in using the script, and you understand and assume each of those risks. 
# Waiver and Release: You will not hold NinjaOne responsible for any adverse or unintended consequences resulting from your use of the script, and you waive any legal or equitable rights or remedies you may have against NinjaOne relating to your use of the script. 
# EULA: If you are a NinjaOne customer, your use of the script is subject to the End User License Agreement applicable to you (EULA).
#
#

die() {
    local _ret="${2:-1}"
    test "${_PRINT_HELP:-no}" = yes && print_help >&2
    echo "$1" >&2
    exit "${_ret}"
}

begins_with_short_option() {
    local first_option all_short_options='upadvh'
    first_option="${1:0:1}"
    test "$all_short_options" = "${all_short_options/$first_option/}" && return 1 || return 0
}

GetCustomField() {
    customfieldName=$1
    dataPath=$(printenv | grep -i NINJA_DATA_PATH | awk -F = '{print $2}')
    value=""
    if [ -e "${dataPath}/ninjarmm-cli" ]; then
        value=$("${dataPath}"/ninjarmm-cli get "$customfieldName")
    else
        value=$(/Applications/NinjaRMMAgent/programdata/ninjarmm-cli get "$customfieldName")
    fi
    if [[ "${value}" == *"Unable to find the specified field"* ]]; then
        echo ""
        return 1
    else
        echo "$value"
    fi
}

# THE DEFAULTS INITIALIZATION - OPTIONALS
_arg_username=
_arg_password=
_arg_adminuser=
_arg_adminpassword=

print_help() {
    printf '%s\n' "Grants secure token access to an account. Account will be created if it doesn't exist."
    printf 'Usage: %s <-u|--username <arg>> <-p|--password <arg>> [-a|--adminuser <arg>] [-d|--adminpassword <arg>] [-h|--help]\n' "$0"
    printf '\t%s\n' "-u, --username: Username to grant secure token access to. (Required)"
    printf '\t%s\n' "-p, --password: Password of user to grant secure token access to. (Required)"
    printf '\t%s\n' "-a, --adminuser: (Optional) Secure token Admin username. (Leave blank to prompt local user)"
    printf '\t%s\n' "-d, --adminpassword: (Optional) Secure token Admin password. (Leave blank to prompt local user)"
    printf '\t%s\n' "-h, --help: Prints help"
}

parse_commandline() {
    while test $# -gt 0; do
        _key="$1"
        case "$_key" in
        -u | --username)
            test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
            _arg_username="$2"
            shift
            ;;
        --username=*)
            _arg_username="${_key##--username=}"
            ;;
        -u*)
            _arg_username="${_key##-u}"
            ;;
        -p | --password)
            test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
            _arg_password="$2"
            shift
            ;;
        --password=*)
            _arg_password="${_key##--password=}"
            ;;
        -p*)
            _arg_password="${_key##-p}"
            ;;
        -a | --adminuser)
            test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
            _arg_adminuser="$2"
            shift
            ;;
        --adminuser=*)
            _arg_adminuser="${_key##--adminuser=}"
            ;;
        -a*)
            _arg_adminuser="${_key##-a}"
            ;;
        -d | --adminpassword)
            test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
            _arg_adminpassword="$2"
            shift
            ;;
        --adminpassword=*)
            _arg_adminpassword="${_key##--adminpassword=}"
            ;;
        -d*)
            _arg_adminpassword="${_key##-d}"
            ;;
        -h | --help)
            print_help
            exit 0
            ;;
        -h*)
            print_help
            exit 0
            ;;
        *)
            _PRINT_HELP=yes die "FATAL ERROR: Got an unexpected argument '$1'" 1
            ;;
        esac
        shift
    done
}

parse_commandline "$@"

# Get Script Variables and override parameters
if [[ -n $(printenv | grep -i newAccountUsername | awk -F = '{print $2}') ]]; then
    _arg_username=$(printenv | grep -i newAccountUsername | awk -F = '{print $2}')
fi
if [[ -n $(printenv | grep -i newAccountPasswordCustomField | awk -F = '{print $2}') ]]; then
    # Get the password from the custom field
    if ! _arg_password=$(GetCustomField "$(printenv | grep -i newAccountPasswordCustomField | awk -F = '{print $2}')"); then
        # Exit if the custom field is empty
        if [[ -z "${_arg_password}" ]]; then
            echo "[Error] Custom Field ($(printenv | grep -i newAccountPasswordCustomField | awk -F = '{print $2}')) was not found. Please check that the custom field contains a password."
            exit 1
        fi
        # Exit if the custom field is not found
        echo "[Error] Custom Field ($(printenv | grep -i newAccountPasswordCustomField | awk -F = '{print $2}')) was not found. Please check the custom field name."
        exit 1
    fi
fi
if [[ -n $(printenv | grep -i optionalAuthenticationAccountUsername | awk -F = '{print $2}') ]]; then
    _arg_adminuser=$(printenv | grep -i optionalAuthenticationAccountUsername | awk -F = '{print $2}')
fi
if [[ -n $(printenv | grep -i optionalAuthenticationAccountPasswordCustomField | awk -F = '{print $2}') ]]; then
    # Get the password from the custom field
    if ! _arg_adminpassword=$(GetCustomField "$(printenv | grep -i optionalAuthenticationAccountPasswordCustomField | awk -F = '{print $2}')"); then
        # Exit if the custom field is empty
        if [[ -z "${_arg_adminpassword}" ]]; then
            echo "[Error] Custom Field ($(printenv | grep -i optionalAuthenticationAccountPasswordCustomField | awk -F = '{print $2}')) was not found. Please check that the custom field contains a password."
            exit 1
        fi
        # Exit if the custom field is not found
        echo "[Error] Custom Field ($(printenv | grep -i optionalAuthenticationAccountPasswordCustomField | awk -F = '{print $2}')) was not found. Please check the custom field name."
        exit 1
    fi
fi

# If both username and password are empty
if [[ -z "${_arg_username}" ]]; then
    echo "[Error] User Name is required."
    if [[ -z "${_arg_password}" ]]; then
        echo "[Error] Password is required, please set the password in the secure custom field."
    fi
    exit 1
fi

# If username is not empty and password is empty
if [[ -n "${_arg_username}" ]] && [[ -z "${_arg_password}" ]]; then
    echo "[Error] Password is required, please set the password in the secure custom field."
    exit 1
fi

# If username is not empty and password is empty
if [[ -n "${_arg_adminuser}" ]] && [[ -z "${_arg_adminpassword}" ]]; then
    echo "[Error] Password is required, please set the password in the secure custom field."
    exit 1
fi

UserAccount=$_arg_username
UserPass=$_arg_password
UserFullName="ServiceAccount"
secureTokenAdmin=$_arg_adminuser
secureTokenAdminPass=$_arg_adminpassword
macOSVersionMajor=$(sw_vers -productVersion | awk -F . '{print $1}')
macOSVersionMinor=$(sw_vers -productVersion | awk -F . '{print $2}')
macOSVersionBuild=$(sw_vers -productVersion | awk -F . '{print $3}')

# Check script prerequisites.

# Exits if macOS version predates the use of SecureToken functionality.
# Exit if macOS < 10.
if [ "$macOSVersionMajor" -lt 10 ]; then
    echo "[Warn] macOS version ${macOSVersionMajor} predates the use of SecureToken functionality, no action required."
    exit 0
# Exit if macOS 10 < 10.13.4.
elif [ "$macOSVersionMajor" -eq 10 ]; then
    if [ "$macOSVersionMinor" -lt 13 ]; then
        echo "[Warn] macOS version ${macOSVersionMajor}.${macOSVersionMinor} predates the use of SecureToken functionality, no action required."
        exit 0
    elif [ "$macOSVersionMinor" -eq 13 ] && [ "$macOSVersionBuild" -lt 4 ]; then
        echo "[Warn] macOS version ${macOSVersionMajor}.${macOSVersionMinor}.${macOSVersionBuild} predates the use of SecureToken functionality, no action required."
        exit 0
    fi
fi

# Exits if $UserAccount already has SecureToken.
if sysadminctl -secureTokenStatus "$UserAccount" 2>&1 | grep -q "ENABLED"; then
    echo "${UserAccount} already has a SecureToken. No action required."
    exit 0
fi

# Exits with error if $secureTokenAdmin does not have SecureToken
# (unless running macOS 10.15 or later, in which case exit with explanation).

if [ -n "$secureTokenAdmin" ]; then
    if sysadminctl -secureTokenStatus "$secureTokenAdmin" 2>&1 | grep -q "DISABLED"; then
        if [ "$macOSVersionMajor" -gt 10 ] || [ "$macOSVersionMajor" -eq 10 ] && [ "$macOSVersionMinor" -gt 14 ]; then
            echo "[Warn] Neither ${secureTokenAdmin} nor ${UserAccount} has a SecureToken, but in macOS 10.15 or later, a SecureToken is automatically granted to the first user to enable FileVault (if no other users have SecureToken), so this may not be necessary. Try enabling FileVault for ${UserAccount}. If that fails, see what other user on the system has SecureToken, and use its credentials to grant SecureToken to ${UserAccount}."
            exit 0
        else
            echo "[Error] ${secureTokenAdmin} does not have a valid SecureToken, unable to proceed. Please update to another admin user with SecureToken."
            exit 1
        fi
    else
        echo "[Info] Verified ${secureTokenAdmin} has SecureToken."
    fi
fi

# Creates a new user account.
create_user() {
    # Check if the user account exists
    if id "$1" >/dev/null 2>&1; then
        echo "[Info] Found existing user account $1."
    else
        echo "[Warn] Account $1 doesn't exist. Attempting to create..."
        # Create a new user
        dscl . -create /Users/"$1"
        # Add the display name of the User
        dscl . -create /Users/"$1" RealName "$3"
        # Replace password_here with your desired password to set the password for this user
        dscl . -passwd /Users/"$1" "$2"
        # Set the Unique ID for the New user. Replace with a number that is not already taken.
        LastID=$(dscl . -list /Users UniqueID | sort -nr -k 2 | head -1 | grep -oE '[0-9]+$')
        NextID=$((LastID + 1))
        dscl . -create /Users/"$1" UniqueID $NextID
        # Set the group ID for the user
        dscl . -create /Users/"$1" PrimaryGroupID 20
        # Append the User with admin privilege. If this line is not included the user will be set as standard user.
        # sudo dscl . -append /Groups/admin GroupMembership "$1"
        echo "[Info] Account $1 created."
    fi
}
# Adds SecureToken to target user.
securetoken_add() {
    if [ -n "$3" ]; then
        # Admin user name was given. Do not prompt the user.
        sysadminctl \
            -secureTokenOn "$1" \
            -password "$2" \
            -adminUser "$3" \
            -adminPassword "$4"
    else
        # Admin user name was not given. Prompt the local user.
        currentUser=$(stat -f%Su /dev/console)
        currentUserUID=$(id -u "$currentUser")
        launchctl asuser "$currentUserUID" sudo -iu "$currentUser" \
            sysadminctl \
            -secureTokenOn "$1" \
            -password "$2" \
            interactive
    fi
    # Verify successful SecureToken add.
    secureTokenCheck=$(sysadminctl -secureTokenStatus "${1}" 2>&1)
    if echo "$secureTokenCheck" | grep -q "DISABLED"; then
        echo "[Error] Failed to add SecureToken to ${1}. Please rerun policy; if issue persists, a manual SecureToken add will be required to continue."
        exit 126
    elif echo "$secureTokenCheck" | grep -q "ENABLED"; then
        echo "[Info] Successfully added SecureToken to ${1}."
    else
        echo "[Error] Unexpected result, unable to proceed. Please rerun policy; if issue persists, a manual SecureToken add will be required to continue."
        exit 1
    fi
}

# Create new user if it doesn't already exist.
create_user "$UserAccount" "$UserPass" "$UserFullName"
# Add SecureToken using provided credentials.
securetoken_add "$UserAccount" "$UserPass" "$secureTokenAdmin" "$secureTokenAdminPass"

 

Analisi dettagliata

Panoramica dello script

Lo script in questione è progettato per garantire l’accesso sicuro tramite token a un account utente su macOS, con la possibilità di creare l’account se non esiste già. Ecco una descrizione dettagliata, passo per passo, di come funziona lo script per creare token sicuri in macOS:

  1. Parsing dei parametri: Lo script per creare token sicuri in macOS inizia definendo una funzione die per gestire gli errori e una funzione print_help per visualizzare le informazioni di utilizzo. Analizza quindi gli argomenti della riga di comando per estrarre il nome utente, la password e, facoltativamente, il nome utente e la password dell’amministratore.
  2. Variabili d’ambiente: Controlla la presenza di variabili d’ambiente che possono sovrascrivere i parametri della riga di comando. Se sono impostate variabili d’ambiente specifiche, lo script per creare token sicuri in macOS recupera i loro valori per utilizzarli come parametri.
  3. Controllo della versione di macOS: Lo script per creare token sicuri in macOS controlla la versione di macOS per verificare che supporti la funzionalità di token sicuro. Esce se la versione di macOS è troppo vecchia per utilizzare i token sicuri.
  4. Controllo dello stato del token sicuro: Controlla se l’account utente specificato ha già un token sicuro. Se l’account utente dispone già di un token sicuro, lo script per creare token sicuri in macOS termina, poiché non sono necessarie ulteriori azioni.
  5. Controllo del token utente amministratore: Se viene fornito un nome utente amministratore, lo script per creare token sicuri in macOS verifica che questo utente amministratore abbia un token sicuro. Se non c’è, lo script esce con un errore, a meno che la versione di macOS sia la 10.15 o successiva; in quel caso si consiglia di utilizzare un processo diverso.
  6. Creazione dell’account utente: Lo script per creare token sicuri in macOS include una funzione per creare un nuovo account utente se non esiste già. Assegna un ID univoco, imposta una password e configura altri attributi necessari.
  7. Concessione di un token sicuro: Lo script per creare token sicuri in macOS tenta di concedere un token sicuro all’account utente specificato, utilizzando le credenziali fornite. Se viene fornito il nome utente dell’amministratore, vengono utilizzate quelle credenziali; altrimenti, viene richiesta l’autenticazione dell’utente locale.

Casi d’uso potenziali

Immagina un professionista IT di nome Alex che gestisce un parco di dispositivi macOS per una grande azienda. Alex deve assicurarsi che tutti gli account utente su questi dispositivi abbiano token sicuri per la crittografia FileVault. Controllare e concedere manualmente i token sicuri su ogni dispositivo richiederebbe molto tempo.

Distribuendo questo script per creare token sicuri in macOS attraverso uno strumento di gestione centralizzato, Alex può automatizzare il processo, assicurandosi che tutti gli account utente dell’organizzazione dispongano dei token sicuri necessari e mantenendo così la conformità con i criteri di sicurezza dell’azienda.

Confronti

Altri metodi per creare token sicuri in macOS comportano in genere l’intervento manuale attraverso le Preferenze di sistema di macOS o l’uso di comandi sysadminctl individualmente per ogni utente. Pur funzionando, questi metodi non sono scalabili per la gestione di un gran numero di dispositivi. Lo script per creare token sicuri in macOS automatizza queste fasi, rendendole più efficienti e riducendo la probabilità di errore umano.

Domande frequenti

  • Cosa succede se l’account utente esiste già?

    Lo script per creare token sicuri in macOS verifica l’esistenza dell’account utente e, se esiste già, salta la fase di creazione.

  • Posso utilizzare questo script per creare token sicuri in macOS su versioni precedenti di macOS?

    Lo script per creare token sicuri in macOS include controlli per garantire che venga eseguito solo sulle versioni di macOS che supportano i token sicuri, in particolare macOS 10.13.4 e versioni successive.

  • Cosa succede se l’utente amministratore non ha un token sicuro?

    Lo script per creare token sicuri in macOS esce con un errore se l’utente amministratore non dispone di un token sicuro, tranne che su macOS 10.15 o successivo, dove viene suggerita una procedura alternativa.

Implicazioni

La concessione di token sicuri agli account utente è fondamentale per abilitare FileVault ed eseguire le attività amministrative in modo sicuro. L’automazione di questo processo contribuisce a mantenere elevati standard di sicurezza, a garantire la conformità ai criteri organizzativi e a ridurre il rischio di accessi non autorizzati.

Raccomandazioni

  • Aggiorna regolarmente lo script: Assicurati che lo script per creare token sicuri in macOS sia aggiornato con le ultime modifiche di macOS e di seguire le pratiche di sicurezza.
  • Campi personalizzati sicuri: Utilizza campi personalizzati sicuri per memorizzare informazioni sensibili come le password.
  • Gestione centralizzata: Distribuisci lo script per creare token sicuri in macOS attraverso uno strumento di gestione centralizzato per garantire la coerenza tra tutti i dispositivi.

Considerazioni finali

Automatizzare il processo di concessione dei token sicuri mediante questo script per creare token sicuri in macOS migliora notevolmente l’efficienza e la sicurezza della gestione dei dispositivi macOS. Per i professionisti IT e gli MSP, questo script è uno strumento prezioso per mantenere solide pratiche di sicurezza.

NinjaOne offre soluzioni complete che si integrano perfettamente con script come questo, fornendo un approccio strutturato alla gestione e alla sicurezza IT. Utilizzando NinjaOne, è possibile ottimizzare i flussi di lavoro e garantire che tutti i dispositivi siano sicuri e conformi ai criteri dell’organizzazione.

Passi successivi

La creazione di un team IT efficiente ed efficace richiede una soluzione centralizzata che funga da principale strumento per la fornitura di servizi. NinjaOne consente ai team IT di monitorare, gestire, proteggere e supportare tutti i dispositivi, ovunque essi si trovino, senza la necessità di una complessa infrastruttura locale.

Per saperne di più su NinjaOne Endpoint Management, fai un tour dal vivo, o inizia la tua prova gratuita della piattaforma NinjaOne.

Categorie:

Ti potrebbe interessare anche

×

Guarda NinjaOne in azione!

Inviando questo modulo, accetto La politica sulla privacy di NinjaOne.

Termini e condizioni NinjaOne

Cliccando sul pulsante “Accetto” qui sotto, dichiari di accettare i seguenti termini legali e le nostre condizioni d’uso:

  • Diritti di proprietà: NinjaOne possiede e continuerà a possedere tutti i diritti, i titoli e gli interessi relativi allo script (compreso il copyright). NinjaOne ti concede una licenza limitata per l’utilizzo dello script in conformità con i presenti termini legali.
  • Limitazione d’uso: Puoi utilizzare lo script solo per legittimi scopi personali o aziendali interni e non puoi condividere lo script con altri soggetti.
  • Divieto di ripubblicazione: In nessun caso ti è consentito ripubblicare lo script in una libreria di script appartenente o sotto il controllo di un altro fornitore di software.
  • Esclusione di garanzia: Lo script viene fornito “così com’è” e “come disponibile”, senza garanzie di alcun tipo. NinjaOne non promette né garantisce che lo script sia privo di difetti o che soddisfi le tue esigenze o aspettative specifiche.
  • Assunzione del rischio: L’uso che farai dello script è da intendersi a tuo rischio. Riconosci che l’utilizzo dello script comporta alcuni rischi intrinseci, che comprendi e sei pronto ad assumerti.
  • Rinuncia e liberatoria: Non riterrai NinjaOne responsabile di eventuali conseguenze negative o indesiderate derivanti dall’uso dello script e rinuncerai a qualsiasi diritto legale o di equità e a qualsiasi rivalsa nei confronti di NinjaOne in relazione all’uso dello script.
  • EULA: Se sei un cliente NinjaOne, l’uso dello script è soggetto al Contratto di licenza con l’utente finale (EULA) applicabile.