Guida completa per ottenere informazioni sulle estensioni dei browser su macOS

Le estensioni del browser sono strumenti potenti che migliorano le funzionalità dei browser web, ma possono anche comportare rischi per la sicurezza se non vengono gestite correttamente. Per i professionisti IT e i Managed Service Provider (MSP) responsabili del mantenimento di un ambiente informatico sicuro ed efficiente, è fondamentale disporre di un metodo per organizzare un inventario delle estensioni dei vari browser su sistemi macOS.

In questo articolo analizzeremo uno script completo che mostra tutte le estensioni dei browser installate su Safari, Chrome, Firefox ed Edge in macOS. La comprensione e la gestione di queste estensioni possono rafforzare in modo significativo la sicurezza di un’organizzazione.

Background

Nel panorama informatico moderno, garantire che tutto il software, comprese le estensioni dei browser, sia aggiornato e sicuro è un compito fondamentale. Le estensioni possono fornire grandi vantaggi, ma presentano anche potenziali vulnerabilità che i malintenzionati possono sfruttare.

Questo script è stato progettato per aiutare i professionisti IT a raccogliere in modo rapido ed efficiente informazioni sulle estensioni del browser installate su più browser su sistemi macOS. Questa funzionalità è essenziale per mantenere la conformità alla sicurezza e garantire che vengano utilizzate solo le estensioni autorizzate.

Lo script per visualizzare le estensioni dei browser

#!/usr/bin/env bash

#
# Description: Get the browser extensions for Safari, Chrome, Firefox, and Edge that are installed on a macOS system.
#
# Usage: [multilineCustomFieldName] [wysiwygCustomFieldName]
#
# Release Notes: Fixed 10% width bug.
# 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).
#
# Example Output:
#
# Safari Extensions:
# User: john, Name: com.betafish.adblock-mac.SafariMenu, Id: 3KKZV48AQD
# User: ken, Name: com.rockysandstudio.MKPlayer.MKPlayer-Extension, Id: 2N35YUC83U
#
# Chrome Extensions:
# User: john, Name: Chrome Web Store Payments, Id: nmmhkkegccagdldgiimedpiccmgmieda, Version: 1.0.0.6, Profile Name: test1
# User: john, Name: Turn Off the Lights, Id: bfbmjmiodbnnpllbbbfblcplfjjepjdn, Version: 4.2.6.0, Profile Name: test2
# User: ken, Name: Google Docs Offline, Id: ghbmnnjooekpmoecnnnilnnbdlolhkhi, Version: 1.76.1, Profile Name: Person 1
#
# Firefox Addons:
# User: john, Name: Return YouTube Dislike, Id: {762f9885-5a13-4abd-9c77-433dcd38b8fd}, Description: Returns ability to see dislike statistics on youtube, Profile Name: default-release
# User: john, Name: Stylebot, Id: {52bda3fd-dc48-4b3d-a7b9-58af57879f1e}, Description: Change the appearance of the web instantly, Profile Name: default-release
# User: ken, Name: Search by Image, Id: {2e5ff8c8-32fe-46d0-9fc8-6b8986621f3c}, Description: A powerful reverse image search tool, with support for various search engines, such as Google, Bing, Yandex, Baidu and TinEye., Profile Name: default-release
#
# Edge Extensions:
# User: john, Name: Google Docs Offline, Id: ghbmnnjooekpmoecnnnilnnbdlolhkhi, Version: 1.76.2, Profile Name: test 3
# User: john, Name: Edge relevant text changes, Id: jmjflgjpcpepeafmmgdpfkogkghcpiha, Version: 1.2.1, Profile Name: test 3
# User: ken, Name: Google Docs Offline, Id: ghbmnnjooekpmoecnnnilnnbdlolhkhi, Version: 1.76.2, Profile Name: Profile 1

_arg_multilineField=$1
_arg_wysiwygField=$2

# Determines whether or not help text is necessary and routes the output to stderr
die() {
    local _ret="${2:-1}"
    echo "$1" >&2
    test "${_PRINT_HELP:-no}" = yes && print_help >&2
    exit "${_ret}"
}

# Prints the help text
print_help() {
    echo "Get the browser extensions for Safari, Chrome, Firefox, and Edge that are installed on a macOS system."
    echo "Usage: [multilineCustomFieldName] [wysiwygCustomFieldName]"
}

# Check if --help or -h is passed as an argument
for _arg in "$@"; do
    case "$_arg" in
    --help | -h)
        print_help
        exit 0
        ;;
    esac
done

# Set the custom field value using ninjarmm-cli
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
}

# Check if the multilineCustomFieldName is set as environment variables
multiline=$(printenv | grep -i multilineCustomFieldName | awk -F = '{print $2}')
if [[ -n "$multiline" ]] && [[ "${multiline}" != "null" ]]; then
    _arg_multilineField=$(printenv | grep -i multilineCustomFieldName | awk -F = '{print $2}')
fi

# Check if the wysiwygCustomFieldName is set as environment variables
wysiwygField=$(printenv | grep -i wysiwygCustomFieldName | awk -F = '{print $2}')
if [[ -n "$wysiwygField" ]] && [[ "${wysiwygField}" != "null" ]]; then
    _arg_wysiwygField=$(printenv | grep -i wysiwygCustomFieldName | awk -F = '{print $2}')
fi

# Check if both _arg_multilineField and _arg_wysiwygField are set and not empty
if [[ -n "$_arg_multilineField" && -n "$_arg_wysiwygField" ]]; then
    # Convert both field names to uppercase to check for equality
    multiline=$(echo "$_arg_multilineField" | tr '[:lower:]' '[:upper:]')
    wysiwyg=$(echo "$_arg_wysiwygField" | tr '[:lower:]' '[:upper:]')

    # If the converted names are the same, it means both fields cannot be identical
    # If they are, terminate the script with an error
    if [[ "$multiline" == "$wysiwyg" ]]; then
        _PRINT_HELP=yes die '[Error] Multline Field and WYSIWYG Field cannot be the same name. https://ninjarmm.zendesk.com/hc/en-us/articles/360060920631-Custom-Fields-Configuration-Device-Role-Fields'
    fi
fi

# Warn that if not running as root, the script may not be able to access all user directories
if [[ $EUID -ne 0 ]]; then
    echo "[Warn] This script may not be able to access all user directories unless run as root."
fi

# Converts a string input into an HTML table format
convertToHTMLTable() {
    local _arg_delimiter=" "
    local _arg_inputObject

    # Process command-line arguments for the function
    while test $# -gt 0; do
        _key="$1"
        case "$_key" in
        --delimiter | -d)
            test $# -lt 2 && echo "[Error] Missing value for the optional argument" >&2 && return 1
            _arg_delimiter=$2
            shift
            ;;
        --*)
            echo "[Error] Got an unexpected argument" >&2
            return 1
            ;;
        *)
            _arg_inputObject=$1
            ;;
        esac
        shift
    done

    # Handles missing input by checking stdin or returning an error
    if [[ -z $_arg_inputObject ]]; then
        if [ -p /dev/stdin ]; then
            _arg_inputObject=$(cat)
        else
            echo "[Error] Missing input object to convert to table" >&2
            return 1
        fi
    fi

    local htmlTable="<table>\n"
    htmlTable+=$(printf '%b' "$_arg_inputObject" | head -n1 | awk -F "$_arg_delimiter" '{
    printf "<tr>"
    for (i=1; i<=NF; i+=1)
      { printf "<th>"$i"</th>" }
    printf "</tr>"
    }')
    htmlTable+="\n"
    htmlTable+=$(printf '%b' "$_arg_inputObject" | tail -n +2 | awk -F "$_arg_delimiter" '{
    printf "<tr>"
    for (i=1; i<=NF; i+=1)
      { printf "<td>"$i"</td>" }
    print "</tr>"
    }')
    htmlTable+="\n</table>"

    printf '%b' "$htmlTable" '\n'
}

createExtList() {
    userHome=$1
    browser=$2 # chrome or edge
    user_name=$(echo "$userHome" | cut -d "/" -f 3)
    if [[ "${browser}" == "chrome" ]]; then
        manifests=$(find "${userHome}/Library/Application Support/Google/Chrome" -type f -name 'manifest.json' 2>/dev/null | grep "Extensions")
        profileLocalState="${userHome}/Library/Application Support/Google/Chrome/Local State"
    elif [[ "${browser}" == "edge" ]]; then
        manifests=$(find "${userHome}/Library/Application Support/Microsoft Edge" -type f -name 'manifest.json' 2>/dev/null | grep "Extensions")
        profileLocalState="${userHome}/Library/Application Support/Microsoft Edge/Local State"
    fi

    en_messages="_locales/en/messages.json"
    enUS_messages="_locales/en_US/messages.json"

    while IFS= read -r manifest; do
        # Check if we can read the manifest file
        if [ ! -f "$manifest" ]; then
            continue
        fi

        profileName=$(
            # Get profile name from profileLocalState that contains json data
            # "profile.info_cache.Default" is the default profile
            osascript -l JavaScript -e "
                    var profileLocalState = JSON.parse(ObjC.unwrap($.NSString.alloc.initWithDataEncoding($.NSData.dataWithContentsOfFile('$profileLocalState'), $.NSUTF8StringEncoding)));
                    // Get each profile name based on the profile path
                    if ('$browser' === 'chrome') {
                        var profilePathName = '$manifest'.split('/')[7];
                    } else if ('$browser' === 'edge') {
                        var profilePathName = '$manifest'.split('/')[6];
                    }
                    for (var key in profileLocalState.profile.info_cache) {
                        if (key.toLowerCase() === profilePathName.toLowerCase()) {
                            var profileName = profileLocalState.profile.info_cache[key].name;
                            break;
                        }
                    }
                    profileName;
                "
        )

        # Get the id of the extension from the manifest path by splitting the path on '/' and getting the 9th element
        if [[ "${browser}" == "chrome" ]]; then
            extID=$(awk -F '/' '{print $10}' <<<"$manifest")
        elif [[ "${browser}" == "edge" ]]; then
            extID=$(awk -F '/' '{print $9}' <<<"$manifest")
        fi
        # Get name from manifest
        name=$(
            osascript -l JavaScript -e "
                var data = JSON.parse(ObjC.unwrap($.NSString.alloc.initWithDataEncoding($.NSData.dataWithContentsOfFile('$manifest'), $.NSUTF8StringEncoding)));
                var name = data.name;
                name;
            "
        )
        # Get version from manifest
        version=$(
            osascript -l JavaScript -e "
                var data = JSON.parse(ObjC.unwrap($.NSString.alloc.initWithDataEncoding($.NSData.dataWithContentsOfFile('$manifest'), $.NSUTF8StringEncoding)));
                var version = data.version;
                version;
            "
        )

        # Get the name of the extension from the messages.json file if the name contains "__MSG_"
        if [[ "${name}" =~ "__MSG_" ]]; then
            name=$(echo "$name" | sed 's/__MSG_//g' | sed 's/__$//g')
            if [ -f "$(dirname "$manifest")/$en_messages" ]; then
                # Check if message.json exists in en folder
                name=$(
                    osascript -l JavaScript -e "
                        var data = JSON.parse(ObjC.unwrap($.NSString.alloc.initWithDataEncoding($.NSData.dataWithContentsOfFile('$(dirname "$manifest")/$en_messages'), $.NSUTF8StringEncoding)));
                        var searchKey = '$name';
                        var asLowercase = searchKey.toLowerCase();
                        var name = data[Object.keys(data).find(key => key.toLowerCase() === asLowercase)].message;
                        name;
                    " 2>/dev/null
                )
            elif [ -f "$(dirname "$manifest")/$enUS_messages" ]; then
                # Check if message.json exists in enUS folder
                name=$(
                    osascript -l JavaScript -e "
                        var data = JSON.parse(ObjC.unwrap($.NSString.alloc.initWithDataEncoding($.NSData.dataWithContentsOfFile('$(dirname "$manifest")/$enUS_messages'), $.NSUTF8StringEncoding)));
                        var searchKey = '$name';
                        var asLowercase = searchKey.toLowerCase();
                        var name = data[Object.keys(data).find(key => key.toLowerCase() === asLowercase)].message;
                        name;
                    " 2>/dev/null
                )
            fi
        fi
        if [[ -n "$name" ]]; then
            printf "%s|%s|%s|%s|%s\n" "$user_name" "$profileName" "$name" "$extID" "$version"
        else
            printf "%s|%s|%s|%s|%s\n" "$user_name" "$profileName" "Name Not Found" "$extID" "$version"
        fi
    done <<<"$manifests"
}

# Get a list of all users in the /Users directory except Shared
users=()
for user in /Users/*; do
    if [[ -d "$user" && ! "$user" =~ /Users/Shared ]]; then
        users+=("${user##*/}")
    fi
done

# Error when no users are found
if [[ ${#users[@]} -eq 0 ]]; then
    _PRINT_HELP=no die "[Error] No user directories found in /Users"
fi

safari_title="Safari Extensions"
safari_extensions=""
chrome_title="Chrome Extensions"
chrome_extensions=""
firefox_title="Firefox Addons"
firefox_addons=""
edge_title="Edge Extensions"
edge_extensions=""

# Safari
for user in "${users[@]}"; do
    ext_plist="/Users/$user/Library/Containers/com.apple.Safari/Data/Library/Safari/AppExtensions/Extensions.plist"
    pattern='(com\..*)\s\((.*)\)'
    if [[ -f "$ext_plist" ]]; then
        safari_extensions+=$'\n'"$(
            grep -Eo "$pattern" "$ext_plist" | while read -r line; do
                ext_name=$(echo "$line" | awk -F ' ' '{print $1}')
                ext_id=$(echo "$line" | awk -F ' ' '{print $2}' | tr -d '()')
                printf "%s|%s|%s\n" "$user" "$ext_name" "$ext_id"
            done
        )"
    fi
done

# Chrome
for user in "${users[@]}"; do
    # Add a newline to the beginning of the string to separate the results from the previous user
    chrome_extensions+=$'\n'"$(createExtList "/Users/$user" "chrome")"
done

# Firefox Get installed Addons (not extensions)
firefox_addons=$(
    # Loop through each user profile
    for user in "${users[@]}"; do
        firefox_path="/Users/$user/Library/Application Support/Firefox"
        profile_dir="$firefox_path/Profiles"
        # Check if Profiles directory exists
        if [[ -d "$profile_dir" ]]; then
            profiles_ini_path="$firefox_path/profiles.ini"
            # Check if profiles.ini file exists
            if [[ -f "$profiles_ini_path" ]]; then
                profiles_ini=$(cat "$profiles_ini_path")
                # Parse the profiles.ini file and get the profile names and paths
                # Get each section
                awk -F '=' '/\[/{print $1}' <<<"$profiles_ini" | while read -r section; do
                    # Get the profile name
                    profile_name=$(
                        awk -F'=' -v section="$section" -v k="Name" '
                        $0==section{ f=1; next }
                        /\[/{ f=0; next }
                        f && $1==k{ print $0 }
                        ' <<<"$profiles_ini" | sed 's/^Name=//'
                    )
                    # Get the profile path
                    profile_path=$(
                        awk -F'=' -v section="$section" -v k="Path" '
                        $0==section{ f=1; next }
                        /\[/{ f=0; next }
                        f && $1==k{ print $0 }
                        ' <<<"$profiles_ini" | sed 's/^Path=//'
                    )
                    # Get the addons json file path
                    ext_dir="$firefox_path/$profile_path/addons.json"
                    if [[ -f "$ext_dir" ]]; then
                        # Get name, id, and description from the addons.json file
                        ff_results=$(
                            osascript -l JavaScript -e "
                                var data = JSON.parse(ObjC.unwrap($.NSString.alloc.initWithDataEncoding($.NSData.dataWithContentsOfFile('$ext_dir'), $.NSUTF8StringEncoding)));
                                var addons = data.addons;
                                var result = '';
                                for (var i = 0; i < addons.length; i++) {
                                    var addon = addons[i];
                                    result += addon.name + ',' + addon.id + ',' + addon.description + '\n';
                                }
                                result;
                            "
                        )
                        Old_IFS=$IFS
                        echo "$ff_results" | while IFS=, read -r name id description; do
                            printf "%s|%s|%s|%s|%s\n" "$user" "$profile_name" "$name" "$id" "$description"
                        done
                        IFS=$Old_IFS
                    fi
                done
            fi
        fi
    done
)

# Edge
for user in "${users[@]}"; do
    # Add a newline to the beginning of the string to separate the results from the previous user
    edge_extensions+=$'\n'"$(createExtList "/Users/$user" "edge")"
done

if [[ -n $_arg_multilineField ]] || [[ -n $_arg_wysiwygField ]]; then
    # Add headers if a custom field is set
    if [[ -n "${safari_extensions}" ]]; then
        safari_extensions=$(echo -e "User|Name|Id\n$safari_extensions")
    fi
    if [[ -n "${chrome_extensions}" ]]; then
        chrome_extensions=$(echo -e "User|Profile Name|Name|Id|Version\n$chrome_extensions")
    fi
    if [[ -n "${firefox_addons}" ]]; then
        firefox_addons=$(echo -e "User|Profile Name|Name|Id|Description\n$firefox_addons")
    fi
    if [[ -n "${edge_extensions}" ]]; then
        edge_extensions=$(echo -e "User|Profile Name|Name|Id|Version\n$edge_extensions")
    fi
fi

# Checks if there is a multiline custom field set
if [[ -n $_arg_multilineField ]]; then
    echo ""
    echo "Attempting to set Custom Field '$_arg_multilineField'..."

    # Formats the extension data for the multiline custom field
    multilineValue=""
    # Check if any browser extensions were found
    if [[ -n "$safari_title" ]] && [[ -n "${safari_extensions}" ]]; then
        multilineValue+=$'\n'
        multilineValue+="$safari_title:"
        multilineValue+=$'\n'
        multilineValue+=$(
            # Convert the safari_extensions string to a table format. Skip the first line as it is the header
            echo "$safari_extensions" | tail -n +2 | while IFS='|' read -r user name id; do
                printf "User: %s, Name: %s, Id: %s\n" "$user" "$name" "$id"
            done
        )
    fi
    if [[ -n "$chrome_title" ]] && [[ -n "${chrome_extensions}" ]]; then
        multilineValue+=$'\n'
        multilineValue+="$chrome_title:"
        multilineValue+=$'\n'
        multilineValue+=$(
            # Convert the chrome_extensions string to a table format. Skip the first line as it is the header
            echo "$chrome_extensions" | tail -n +2 | while IFS='|' read -r user_name profileName name id version; do
                if [[ -n "$name" ]]; then
                    printf "User: %s, Profile Name: %s, Name: %s, Id: %s, Version: %s\n" "$user_name" "$profileName" "$name" "$id" "$version"
                fi
            done
        )
    fi
    if [[ -n "$firefox_title" ]] && [[ -n "${firefox_addons}" ]]; then
        multilineValue+=$'\n'
        multilineValue+="$firefox_title:"
        multilineValue+=$'\n'
        multilineValue+=$(
            # Convert the firefox_addons string to a table format. Skip the first line as it is the header
            echo "$firefox_addons" | tail -n +2 | while IFS='|' read -r user profileName name id description; do
                if [[ -n "$name" ]]; then
                    printf "User: %s, Profile Name: %s, Name: %s, Id: %s, Description: %s\n" "$user" "$profileName" "$name" "$id" "$description"
                fi
            done
        )
    fi
    if [[ -n "$edge_title" ]] && [[ -n "${edge_extensions}" ]]; then
        multilineValue+=$'\n'
        multilineValue+="$edge_title:"
        multilineValue+=$'\n'
        multilineValue+=$(
            # Convert the edge_extensions string to a table format. Skip the first line as it is the header
            echo "$edge_extensions" | tail -n +2 | while IFS='|' read -r user_name profileName name id version; do
                if [[ -n "$name" ]]; then
                    printf "User: %s, Profile Name: %s, Name: %s, Id: %s, Version: %s\n" "$user_name" "$profileName" "$name" "$id" "$version"
                fi
            done
        )
    fi
    # if all multilineValue is empty, set it to "No browser extensions found"
    if [[ -z "$multilineValue" ]]; then
        multilineValue="No browser extensions found"
    fi

    # Tries to set the multiline custom field using ninjarmm-cli and captures the output
    if ! output=$(printf '%b' "$multilineValue" | /Applications/NinjaRMMAgent/programdata/ninjarmm-cli set --stdin "$_arg_multilineField" 2>&1); then
        echo "[Error] $output" >&2
        EXITCODE=1
    else
        echo "[Info] Successfully set Custom Field '$_arg_multilineField'!"
    fi
fi

# Checks if there is a WYSIWYG custom field set
if [[ -n $_arg_wysiwygField ]]; then
    echo ""
    echo "Attempting to set Custom Field '$_arg_wysiwygField'..."

    # Initializes an HTML formatted string with headers and extension details
    # Check if any browser extensions were found
    if [[ -n "$safari_title" ]] && [[ -n "${safari_extensions}" ]]; then
        htmlObject+="<h2>$safari_title</h2>"
        htmlObject+=$(echo "$safari_extensions" | convertToHTMLTable --delimiter '|')
    fi
    if [[ -n "$chrome_title" ]] && [[ -n "${chrome_extensions}" ]]; then
        htmlObject+="<h2>$chrome_title</h2>"
        htmlObject+=$(echo "$chrome_extensions" | convertToHTMLTable --delimiter '|')
    fi
    if [[ -n "$firefox_title" ]] && [[ -n "${firefox_addons}" ]]; then
        htmlObject+="<h2>$firefox_title</h2>"
        htmlObject+=$(echo "$firefox_addons" | convertToHTMLTable --delimiter '|')
    fi
    if [[ -n "$edge_title" ]] && [[ -n "${edge_extensions}" ]]; then
        htmlObject+="<h2>$edge_title</h2>"
        htmlObject+=$(echo "$edge_extensions" | convertToHTMLTable --delimiter '|')
    fi
    # if all htmlObject is empty, set it to "No browser extensions found"
    if [[ -z "$htmlObject" ]]; then
        htmlObject="<p>No browser extensions found</p>"
    fi
    # Replace <table> with <table style='white-space:nowrap;'>
    htmlObject=${htmlObject//<table>/<table style=\'white-space:nowrap;\'>}
    # Tries to set the WYSIWYG custom field using ninjarmm-cli and captures the output
    if ! output=$(printf '%b' "$htmlObject" | /Applications/NinjaRMMAgent/programdata/ninjarmm-cli set --stdin "$_arg_wysiwygField" 2>&1); then
        echo "[Error] $output" >&2
        EXITCODE=1
    else
        echo "[Info] Successfully set Custom Field '$_arg_wysiwygField'!"
    fi
fi

# If both _arg_multilineField and _arg_wysiwygField are not set, or if there is an error saving to the custom fields, print the results
if [[ -z $_arg_multilineField && -z $_arg_wysiwygField ]] || [[ $EXITCODE -ne 0 ]]; then
    echo ""
    echo "$safari_title:"
    echo "$safari_extensions" | while IFS='|' read -r user name id; do
        if [[ -n "$name" ]]; then
            printf "User: %s, Name: %s, Id: %s\n" "$user" "$name" "$id"
        fi
    done
    echo ""
    echo "$chrome_title:"
    echo "$chrome_extensions" | while IFS='|' read -r user profileName name id version; do
        if [[ -n "$name" ]]; then
            printf "User: %s, Profile Name: %s, Name: %s, Id: %s, Version: %s\n" "$user" "$profileName" "$name" "$id" "$version"
        fi
    done
    echo ""
    echo "$firefox_title:"
    echo "$firefox_addons" | while IFS='|' read -r user profileName name id description; do
        if [[ -n "$name" ]]; then
            printf "User: %s, Profile Name: %s, Name: %s, Id: %s, Description: %s\n" "$user" "$profileName" "$name" "$id" "$description"
        fi
    done
    echo ""
    echo "$edge_title:"
    echo "$edge_extensions" | while IFS='|' read -r user profileName name id version; do
        if [[ -n "$name" ]]; then
            printf "User: %s, Profile Name: %s, Name: %s, Id: %s, Version: %s\n" "$user" "$profileName" "$name" "$id" "$version"
        fi
    done
    # If no extensions are found, print a message
    if [[ -z "$safari_extensions" ]] && [[ -z "$chrome_extensions" ]] && [[ -z "$firefox_addons" ]] && [[ -z "$edge_extensions" ]]; then
        echo "[Info] No Browser Extensions Found"
    fi
fi

# Checks if an error code is set and exits the script with that code
if [[ -n $EXITCODE ]]; then
    echo "[Error] Failed to save browser extensions to custom field '$_arg_multilineField' or '$_arg_wysiwygField'."
    exit "$EXITCODE"
fi

 

Analisi dettagliata

Lo script per visualizzare tutte le estensioni dei browser inizia definendo il suo scopo e il suo utilizzo, fornendo una descrizione chiara e un esempio di output. Quindi controlla la presenza di argomenti di aiuto e imposta i valori dei campi personalizzati usando ninjarmm-cli, uno strumento per la gestione dei campi personalizzati in NinjaOne.

1. Inizializzazione e gestione degli argomenti

  • Lo script per visualizzare tutte le estensioni dei browser si inizializza controllando se sono stati forniti argomenti di aiuto (–help o -h). In caso affermativo, stampa le istruzioni d’uso ed esce.
  • Definisce una funzione GetCustomField per recuperare i valori dei campi personalizzati usando ninjarmm-cli.

2. Controlli delle variabili d’ambiente

  • Lo script per visualizzare tutte le estensioni dei browser controlla se multilineCustomFieldName e wysiwygCustomFieldName sono impostati come variabili d’ambiente, aggiornando di conseguenza gli argomenti dello script.

3. Identificazione della directory utenti

  • Identifica le directory degli utenti in /Users, esclusa la directory Shared, e raccoglie tutti gli account utente del sistema.

4. Estensioni di Safari

  • Per ogni utente, lo script per visualizzare tutte le estensioni dei browser cerca i file plist delle estensioni di Safari ed estrae i dettagli delle estensioni utilizzando le espressioni regolari.

5. Estensioni per Chrome ed Edge

  • Lo script utilizza la funzione createExtList per trovare ed elencare le estensioni dei browser Chrome ed Edge. Analizza i file manifest.json nelle directory delle estensioni dei browser, estraendo i nomi delle estensioni, gli ID e le versioni.

6. Componenti aggiuntivi per Firefox

  • Per Firefox, lo script per visualizzare tutte le estensioni dei browser analizza i file profiles.ini e addons.json per elencare i componenti aggiuntivi installati, compresi nomi, ID e descrizioni.

7. Impostazione e output del campo personalizzato

  • Se sono impostati campi personalizzati, lo script per visualizzare tutte le estensioni dei browser formatta i dati raccolti in tabelle HTML o in testo semplice, quindi tenta di impostare questi campi usando ninjarmm-cli. Se l’impostazione dei campi non riesce, lo script mostra i dati raccolti nella console.

Questo approccio strutturato garantisce una copertura completa di tutti i principali browser e fornisce un inventario chiaro e dettagliato delle estensioni installate.

Casi d’uso potenziali

Immagina un MSP incaricato di garantire la sicurezza di tutti i computer dei clienti. Utilizzando questo script, l’MSP può generare rapidamente un elenco di tutte le estensioni dei browser installate sui sistemi macOS dei clienti. Per esempio, se viene scoperta una vulnerabilità di sicurezza in un’estensione specifica, l’MSP può utilizzare lo script per identificare quali clienti hanno installato l’estensione e intraprendere le azioni appropriate per ridurre il rischio.

Confronti

Altri metodi per elencare le estensioni dei browser prevedono in genere controlli manuali o l’uso di strumenti specifici per il browser, che possono richiedere molto tempo ed essere soggetti a errori. Questo script fornisce una soluzione unificata e automatizzata che funziona su più browser, facendo risparmiare tempo e riducendo la probabilità di sviste. Inoltre, l’integrazione con NinjaOne consente di centralizzare la gestione e la reportistica, cosa che non è possibile fare con i metodi manuali.

Domande frequenti

  • Come gestisce lo script i diversi profili utente?
    Lo script per visualizzare tutte le estensioni dei browser esegue l’iterazione di ogni directory di utenti in /Users ed elabora ogni profilo trovato nelle rispettive directory del browser.
  • Cosa succede se lo script non può accedere a una directory utente?
    Lo script per visualizzare tutte le estensioni dei browser avverte che potrebbe essere necessario l’accesso di root per leggere tutte le directory utente. L’esecuzione dello script come root garantisce un accesso completo.
  • Lo script può essere utilizzato su sistemi non MacOS?
    No, questo script per visualizzare tutte le estensioni dei browser è stato progettato specificamente per macOS a causa dei percorsi e degli strumenti utilizzati.

Implicazioni

I risultati di questo script forniscono informazioni critiche sulle estensioni installate su più browser, evidenziando potenziali rischi per la sicurezza. Disponendo di un inventario chiaro, i professionisti IT possono garantire la conformità ai criteri di sicurezza, rilevare le estensioni non autorizzate e affrontare tempestivamente eventuali vulnerabilità.

Raccomandazioni

  • Esegui lo script per visualizzare tutte le estensioni dei browser con permessi root per garantire l’accesso a tutte le directory utente.
  • Controlla regolarmente gli elenchi delle estensioni dei browser per identificare e rimuovere quelle non necessarie o potenzialmente dannose.
  • Integra lo script per visualizzare tutte le estensioni dei browser con uno strumento di monitoraggio come NinjaOne per una gestione e una reportistica continue.

Considerazioni finali

La gestione delle estensioni dei browser è un aspetto fondamentale per mantenere un ambiente IT sicuro. Questo script fornisce una soluzione potente e automatizzata per mostrare tutte le estensioni dei principali browser su macOS, rendendolo uno strumento prezioso per i professionisti IT e gli MSP. Integrandolo con NinjaOne, puoi migliorare la capacità di monitorare e gestire le estensioni del browser, garantendo un ambiente informatico sicuro e conforme.

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.