App Store Inventory Management on macOS
Efficiently manage and track App Store applications across your MacFleet devices with comprehensive inventory tools. This tutorial covers app discovery, license compliance, usage analytics, and enterprise-grade reporting for Mac App Store applications.
Understanding App Store App Management
App Store applications on macOS contain unique identifiers and receipts that enable enterprise tracking:
Core Components
- MAS Receipts - Digital receipts stored in app bundles for verification
- Bundle Identifiers - Unique app identification across the App Store ecosystem
- Version Tracking - App version management and update compliance
- License Management - Enterprise license allocation and compliance monitoring
- Usage Analytics - Application usage patterns and adoption metrics
Enterprise Benefits
- Software Asset Management - Complete inventory of App Store applications
- License Compliance - Track enterprise app licenses and allocations
- Security Monitoring - Identify unauthorized or non-compliant applications
- Cost Optimization - Optimize App Store spending and license utilization
- Policy Enforcement - Ensure compliance with enterprise app policies
Basic App Store App Discovery
Simple App Store App List
#!/bin/bash
# Basic App Store app discovery
echo "📱 Discovering App Store Applications"
echo "===================================="
echo ""
app_store_apps=$(find /Applications -path '*Contents/_MASReceipt/receipt' -maxdepth 4 -print | \
sed 's#.app/Contents/_MASReceipt/receipt#.app#g; s#/Applications/##')
if [[ -n "$app_store_apps" ]]; then
echo "App Store Applications Found:"
echo "$app_store_apps" | sort
local app_count=$(echo "$app_store_apps" | wc -l | xargs)
echo ""
echo "Total App Store apps: $app_count"
else
echo "No App Store applications found in /Applications"
fi
Enhanced App Discovery with Details
#!/bin/bash
# Comprehensive App Store app discovery with metadata
discover_app_store_apps() {
echo "🔍 Comprehensive App Store App Discovery"
echo "======================================="
echo ""
local apps_found=0
local total_size=0
# Find all App Store apps with receipts
while IFS= read -r -d '' app_path; do
if [[ -n "$app_path" ]]; then
local app_name=$(basename "$app_path" .app)
local app_bundle_id=""
local app_version=""
local app_size=""
local install_date=""
# Get bundle identifier
if [[ -f "$app_path/Contents/Info.plist" ]]; then
app_bundle_id=$(defaults read "$app_path/Contents/Info.plist" CFBundleIdentifier 2>/dev/null || echo "Unknown")
app_version=$(defaults read "$app_path/Contents/Info.plist" CFBundleShortVersionString 2>/dev/null || echo "Unknown")
fi
# Get app size
if [[ -d "$app_path" ]]; then
app_size=$(du -sh "$app_path" 2>/dev/null | cut -f1 || echo "Unknown")
# Convert size to bytes for totaling
local size_bytes=$(du -s "$app_path" 2>/dev/null | cut -f1 || echo "0")
total_size=$((total_size + size_bytes))
fi
# Get installation/modification date
if [[ -f "$app_path/Contents/_MASReceipt/receipt" ]]; then
install_date=$(stat -f "%Sm" -t "%Y-%m-%d %H:%M:%S" "$app_path/Contents/_MASReceipt/receipt" 2>/dev/null || echo "Unknown")
fi
echo "App: $app_name"
echo " Bundle ID: $app_bundle_id"
echo " Version: $app_version"
echo " Size: $app_size"
echo " Install Date: $install_date"
echo " Path: $app_path"
echo ""
((apps_found++))
fi
done < <(find /Applications -name "*.app" -path '*Contents/_MASReceipt/receipt' -exec dirname {} \; 2>/dev/null | \
sed 's|/Contents/_MASReceipt||' | sort -u | tr '\n' '\0')
# Summary statistics
echo "=== Discovery Summary ==="
echo "Total App Store apps found: $apps_found"
echo "Total disk space used: $(echo "scale=2; $total_size / 1024 / 1024" | bc 2>/dev/null || echo "Unknown") MB"
echo "Average app size: $(echo "scale=2; $total_size / $apps_found / 1024 / 1024" | bc 2>/dev/null || echo "Unknown") MB"
echo "Scan completed: $(date)"
return $apps_found
}
# Execute discovery
discover_app_store_apps
Enterprise App Inventory Management
Comprehensive App Inventory Script
#!/bin/bash
# Enterprise App Store inventory management
generate_app_store_inventory() {
local output_format="${1:-json}"
local include_metadata="${2:-true}"
local export_path="${3:-/tmp}"
echo "📊 Generating Enterprise App Store Inventory"
echo "==========================================="
echo "Output format: $output_format"
echo "Include metadata: $include_metadata"
echo ""
local timestamp=$(date +"%Y%m%d_%H%M%S")
local hostname=$(hostname)
local report_file="$export_path/app_store_inventory_${hostname}_${timestamp}"
# System information
local device_info=$(system_profiler SPHardwareDataType | grep -E "(Model Name|Serial Number)" | \
awk -F': ' '{print $2}' | xargs | tr ' ' '_')
local macos_version=$(sw_vers -productVersion)
local current_user=$(stat -f%Su /dev/console 2>/dev/null || echo "$USER")
# Initialize inventory data structure
local inventory_data=""
local app_count=0
local total_size_bytes=0
echo "Scanning applications..."
# Discover all App Store applications
while IFS= read -r -d '' app_path; do
if [[ -d "$app_path" && -f "$app_path/Contents/_MASReceipt/receipt" ]]; then
local app_name=$(basename "$app_path" .app)
local bundle_id=""
local version=""
local build_version=""
local size_bytes=0
local size_human=""
local install_date=""
local last_modified=""
local executable_path=""
local app_category=""
local developer_name=""
local app_store_url=""
# Extract app metadata
if [[ -f "$app_path/Contents/Info.plist" ]]; then
bundle_id=$(defaults read "$app_path/Contents/Info.plist" CFBundleIdentifier 2>/dev/null || echo "unknown")
version=$(defaults read "$app_path/Contents/Info.plist" CFBundleShortVersionString 2>/dev/null || echo "unknown")
build_version=$(defaults read "$app_path/Contents/Info.plist" CFBundleVersion 2>/dev/null || echo "unknown")
executable_path=$(defaults read "$app_path/Contents/Info.plist" CFBundleExecutable 2>/dev/null || echo "unknown")
app_category=$(defaults read "$app_path/Contents/Info.plist" LSApplicationCategoryType 2>/dev/null || echo "unknown")
fi
# Get app size
size_bytes=$(du -sk "$app_path" 2>/dev/null | cut -f1 || echo "0")
size_bytes=$((size_bytes * 1024)) # Convert KB to bytes
size_human=$(du -sh "$app_path" 2>/dev/null | cut -f1 || echo "unknown")
total_size_bytes=$((total_size_bytes + size_bytes))
# Get timestamps
install_date=$(stat -f "%Sm" -t "%Y-%m-%d %H:%M:%S" "$app_path/Contents/_MASReceipt/receipt" 2>/dev/null || echo "unknown")
last_modified=$(stat -f "%Sm" -t "%Y-%m-%d %H:%M:%S" "$app_path" 2>/dev/null || echo "unknown")
# Try to extract additional metadata if requested
if [[ "$include_metadata" == "true" ]]; then
# Look for team identifier
local team_id=""
if command -v codesign >/dev/null 2>&1; then
team_id=$(codesign -dv "$app_path" 2>&1 | grep "TeamIdentifier" | awk -F'=' '{print $2}' || echo "unknown")
fi
# Check if app is running
local is_running="false"
if pgrep -f "$app_name" >/dev/null 2>&1; then
is_running="true"
fi
# Get app permissions (simplified check)
local has_camera_permission="unknown"
local has_microphone_permission="unknown"
local has_location_permission="unknown"
if [[ -f "$app_path/Contents/Info.plist" ]]; then
if defaults read "$app_path/Contents/Info.plist" NSCameraUsageDescription >/dev/null 2>&1; then
has_camera_permission="requested"
else
has_camera_permission="not_requested"
fi
if defaults read "$app_path/Contents/Info.plist" NSMicrophoneUsageDescription >/dev/null 2>&1; then
has_microphone_permission="requested"
else
has_microphone_permission="not_requested"
fi
if defaults read "$app_path/Contents/Info.plist" NSLocationUsageDescription >/dev/null 2>&1; then
has_location_permission="requested"
else
has_location_permission="not_requested"
fi
fi
fi
# Format output based on requested format
case "$output_format" in
"json")
local app_json="{
\"app_name\": \"$app_name\",
\"bundle_id\": \"$bundle_id\",
\"version\": \"$version\",
\"build_version\": \"$build_version\",
\"size_bytes\": $size_bytes,
\"size_human\": \"$size_human\",
\"install_date\": \"$install_date\",
\"last_modified\": \"$last_modified\",
\"app_path\": \"$app_path\",
\"executable_path\": \"$executable_path\",
\"category\": \"$app_category\""
if [[ "$include_metadata" == "true" ]]; then
app_json="$app_json,
\"team_id\": \"$team_id\",
\"is_running\": $is_running,
\"camera_permission\": \"$has_camera_permission\",
\"microphone_permission\": \"$has_microphone_permission\",
\"location_permission\": \"$has_location_permission\""
fi
app_json="$app_json}"
if [[ $app_count -gt 0 ]]; then
inventory_data="$inventory_data,$app_json"
else
inventory_data="$app_json"
fi
;;
"csv")
if [[ $app_count -eq 0 ]]; then
# CSV header
if [[ "$include_metadata" == "true" ]]; then
inventory_data="App Name,Bundle ID,Version,Build Version,Size (Bytes),Size (Human),Install Date,Last Modified,App Path,Category,Team ID,Is Running,Camera Permission,Microphone Permission,Location Permission"
else
inventory_data="App Name,Bundle ID,Version,Build Version,Size (Bytes),Size (Human),Install Date,Last Modified,App Path,Category"
fi
fi
local csv_line="\"$app_name\",\"$bundle_id\",\"$version\",\"$build_version\",$size_bytes,\"$size_human\",\"$install_date\",\"$last_modified\",\"$app_path\",\"$app_category\""
if [[ "$include_metadata" == "true" ]]; then
csv_line="$csv_line,\"$team_id\",$is_running,\"$has_camera_permission\",\"$has_microphone_permission\",\"$has_location_permission\""
fi
inventory_data="$inventory_data\n$csv_line"
;;
"text"|*)
inventory_data="$inventory_data
App: $app_name
Bundle ID: $bundle_id
Version: $version ($build_version)
Size: $size_human ($size_bytes bytes)
Install Date: $install_date
Last Modified: $last_modified
Path: $app_path
Category: $app_category"
if [[ "$include_metadata" == "true" ]]; then
inventory_data="$inventory_data
Team ID: $team_id
Currently Running: $is_running
Camera Permission: $has_camera_permission
Microphone Permission: $has_microphone_permission
Location Permission: $has_location_permission"
fi
inventory_data="$inventory_data
"
;;
esac
((app_count++))
fi
done < <(find /Applications -name "*.app" -type d -print0 2>/dev/null)
# Generate final report
local total_size_human=$(echo "scale=2; $total_size_bytes / 1024 / 1024 / 1024" | bc 2>/dev/null || echo "unknown")
case "$output_format" in
"json")
local final_report="{
\"report_metadata\": {
\"timestamp\": \"$(date -u +"%Y-%m-%dT%H:%M:%SZ")\",
\"hostname\": \"$hostname\",
\"device_info\": \"$device_info\",
\"macos_version\": \"$macos_version\",
\"current_user\": \"$current_user\",
\"total_apps\": $app_count,
\"total_size_bytes\": $total_size_bytes,
\"total_size_gb\": \"$total_size_human GB\"
},
\"applications\": [$inventory_data]
}"
echo "$final_report" > "${report_file}.json"
echo "✅ JSON report saved to: ${report_file}.json"
;;
"csv")
echo -e "$inventory_data" > "${report_file}.csv"
echo "✅ CSV report saved to: ${report_file}.csv"
;;
"text"|*)
{
echo "MacFleet App Store Inventory Report"
echo "=================================="
echo "Generated: $(date)"
echo "Hostname: $hostname"
echo "Device: $device_info"
echo "macOS Version: $macos_version"
echo "Current User: $current_user"
echo "Total Apps: $app_count"
echo "Total Size: $total_size_human GB"
echo ""
echo "Applications:"
echo "============"
echo "$inventory_data"
} > "${report_file}.txt"
echo "✅ Text report saved to: ${report_file}.txt"
;;
esac
# Summary output
echo ""
echo "=== Inventory Summary ==="
echo "Apps discovered: $app_count"
echo "Total size: $total_size_human GB"
echo "Report format: $output_format"
echo "Report location: $report_file"
echo ""
return $app_count
}
# Usage examples
echo "📊 Enterprise App Store Inventory Management"
echo ""
echo "1. Generate JSON inventory with metadata"
generate_app_store_inventory "json" "true" "/tmp"
echo ""
echo "2. Generate CSV inventory (basic)"
generate_app_store_inventory "csv" "false" "/tmp"
echo ""
echo "3. Generate text inventory with metadata"
generate_app_store_inventory "text" "true" "/tmp"
App Compliance and Security Analysis
#!/bin/bash
# App Store app compliance and security analysis
analyze_app_compliance() {
echo "🔒 App Store Application Compliance Analysis"
echo "==========================================="
echo ""
local compliance_issues=0
local security_concerns=0
local policy_violations=0
# Define enterprise policy rules
local blocked_apps=("Games" "Social Media" "Dating") # Example categories
local required_apps=("Microsoft Word" "Microsoft Excel" "Slack") # Example required apps
local max_app_age_days=365 # Apps older than 1 year flagged
local min_security_permissions=("Camera" "Microphone" "Location")
echo "Analyzing App Store applications for compliance..."
echo ""
# Track required apps
local found_required_apps=()
local missing_required_apps=()
# Analyze each App Store application
while IFS= read -r -d '' app_path; do
if [[ -d "$app_path" && -f "$app_path/Contents/_MASReceipt/receipt" ]]; then
local app_name=$(basename "$app_path" .app)
local bundle_id=""
local version=""
local category=""
local install_date=""
local days_since_install=""
echo "Analyzing: $app_name"
# Get app metadata
if [[ -f "$app_path/Contents/Info.plist" ]]; then
bundle_id=$(defaults read "$app_path/Contents/Info.plist" CFBundleIdentifier 2>/dev/null || echo "unknown")
version=$(defaults read "$app_path/Contents/Info.plist" CFBundleShortVersionString 2>/dev/null || echo "unknown")
category=$(defaults read "$app_path/Contents/Info.plist" LSApplicationCategoryType 2>/dev/null || echo "unknown")
fi
# Get install date and calculate age
if [[ -f "$app_path/Contents/_MASReceipt/receipt" ]]; then
install_date=$(stat -f "%Sm" -t "%Y-%m-%d" "$app_path/Contents/_MASReceipt/receipt" 2>/dev/null || echo "unknown")
if [[ "$install_date" != "unknown" ]]; then
local install_epoch=$(date -j -f "%Y-%m-%d" "$install_date" "+%s" 2>/dev/null || echo "0")
local current_epoch=$(date "+%s")
days_since_install=$(( (current_epoch - install_epoch) / 86400 ))
fi
fi
# Check against blocked apps/categories
local is_blocked=false
for blocked_category in "${blocked_apps[@]}"; do
if [[ "$category" =~ "$blocked_category" ]] || [[ "$app_name" =~ "$blocked_category" ]]; then
echo " ❌ POLICY VIOLATION: App category '$category' is blocked"
is_blocked=true
((policy_violations++))
break
fi
done
# Check app age
if [[ -n "$days_since_install" && "$days_since_install" -gt "$max_app_age_days" ]]; then
echo " ⚠️ COMPLIANCE: App is older than $max_app_age_days days ($days_since_install days)"
((compliance_issues++))
fi
# Check for security permissions
local permission_count=0
if [[ -f "$app_path/Contents/Info.plist" ]]; then
if defaults read "$app_path/Contents/Info.plist" NSCameraUsageDescription >/dev/null 2>&1; then
echo " 🔒 SECURITY: App requests camera access"
((permission_count++))
fi
if defaults read "$app_path/Contents/Info.plist" NSMicrophoneUsageDescription >/dev/null 2>&1; then
echo " 🔒 SECURITY: App requests microphone access"
((permission_count++))
fi
if defaults read "$app_path/Contents/Info.plist" NSLocationUsageDescription >/dev/null 2>&1; then
echo " 🔒 SECURITY: App requests location access"
((permission_count++))
fi
if [[ "$permission_count" -gt 2 ]]; then
echo " ⚠️ SECURITY CONCERN: App requests multiple sensitive permissions"
((security_concerns++))
fi
fi
# Check against required apps
for required_app in "${required_apps[@]}"; do
if [[ "$app_name" =~ "$required_app" ]]; then
found_required_apps+=("$required_app")
fi
done
# Code signing verification
if command -v codesign >/dev/null 2>&1; then
if ! codesign -v "$app_path" >/dev/null 2>&1; then
echo " ❌ SECURITY: Invalid code signature"
((security_concerns++))
fi
fi
echo " ✅ Analysis complete"
echo ""
fi
done < <(find /Applications -name "*.app" -type d -print0 2>/dev/null)
# Check for missing required apps
for required_app in "${required_apps[@]}"; do
local found=false
for found_app in "${found_required_apps[@]}"; do
if [[ "$found_app" == "$required_app" ]]; then
found=true
break
fi
done
if [[ "$found" == "false" ]]; then
missing_required_apps+=("$required_app")
fi
done
# Generate compliance report
echo "=== Compliance Analysis Report ==="
echo "Policy violations: $policy_violations"
echo "Compliance issues: $compliance_issues"
echo "Security concerns: $security_concerns"
echo ""
if [[ ${#missing_required_apps[@]} -gt 0 ]]; then
echo "Missing required applications:"
for missing_app in "${missing_required_apps[@]}"; do
echo " - $missing_app"
done
echo ""
fi
if [[ ${#found_required_apps[@]} -gt 0 ]]; then
echo "Found required applications:"
for found_app in "${found_required_apps[@]}"; do
echo " ✅ $found_app"
done
echo ""
fi
# Overall compliance score
local total_issues=$((policy_violations + compliance_issues + security_concerns + ${#missing_required_apps[@]}))
if [[ "$total_issues" -eq 0 ]]; then
echo "🎉 COMPLIANCE STATUS: FULLY COMPLIANT"
elif [[ "$total_issues" -le 3 ]]; then
echo "⚠️ COMPLIANCE STATUS: MINOR ISSUES ($total_issues issues)"
else
echo "❌ COMPLIANCE STATUS: MAJOR ISSUES ($total_issues issues)"
fi
return $total_issues
}
# Execute compliance analysis
analyze_app_compliance
Fleet Management and Reporting
Enterprise Fleet App Management
#!/bin/bash
# Enterprise fleet-wide App Store management
manage_fleet_app_inventory() {
local operation="${1:-discover}" # discover, report, compliance, update
local fleet_config_file="${2:-/etc/macfleet/app_config.json}"
local output_dir="${3:-/var/log/macfleet}"
echo "🚀 MacFleet Enterprise App Store Management"
echo "=========================================="
echo "Operation: $operation"
echo "Config file: $fleet_config_file"
echo "Output directory: $output_dir"
echo ""
# Ensure output directory exists
mkdir -p "$output_dir"
# Device identification
local device_id=$(system_profiler SPHardwareDataType | grep "Serial Number" | awk -F': ' '{print $2}' | xargs)
local device_name=$(hostname)
local timestamp=$(date +"%Y%m%d_%H%M%S")
local report_file="$output_dir/fleet_app_report_${device_id}_${timestamp}.json"
case "$operation" in
"discover")
echo "🔍 Fleet App Discovery Mode"
echo "==========================="
# Generate comprehensive app inventory
local app_data=$(generate_comprehensive_app_data)
# Create fleet report
local fleet_report="{
\"device_info\": {
\"device_id\": \"$device_id\",
\"device_name\": \"$device_name\",
\"timestamp\": \"$(date -u +"%Y-%m-%dT%H:%M:%SZ")\",
\"macos_version\": \"$(sw_vers -productVersion)\",
\"current_user\": \"$(stat -f%Su /dev/console 2>/dev/null || echo "$USER")\"
},
\"app_inventory\": $app_data,
\"operation\": \"fleet_discovery\"
}"
echo "$fleet_report" > "$report_file"
echo "✅ Fleet discovery report saved: $report_file"
;;
"compliance")
echo "📋 Fleet Compliance Check"
echo "========================="
# Run compliance analysis
local compliance_result=$(analyze_fleet_compliance)
# Create compliance report
local compliance_report="{
\"device_info\": {
\"device_id\": \"$device_id\",
\"device_name\": \"$device_name\",
\"timestamp\": \"$(date -u +"%Y-%m-%dT%H:%M:%SZ")\"
},
\"compliance_results\": $compliance_result,
\"operation\": \"compliance_check\"
}"
echo "$compliance_report" > "$report_file"
echo "✅ Compliance report saved: $report_file"
;;
"report")
echo "📊 Fleet Reporting Mode"
echo "======================"
# Generate all report formats
echo "Generating comprehensive fleet reports..."
generate_app_store_inventory "json" "true" "$output_dir"
generate_app_store_inventory "csv" "true" "$output_dir"
generate_app_store_inventory "text" "true" "$output_dir"
echo "✅ All fleet reports generated in: $output_dir"
;;
"update")
echo "🔄 Fleet Update Check"
echo "===================="
# Check for app updates
check_app_store_updates
;;
*)
echo "❌ Unknown operation: $operation"
echo "Available operations: discover, report, compliance, update"
return 1
;;
esac
return 0
}
# Helper function to generate comprehensive app data
generate_comprehensive_app_data() {
local apps_json="["
local first_app=true
while IFS= read -r -d '' app_path; do
if [[ -d "$app_path" && -f "$app_path/Contents/_MASReceipt/receipt" ]]; then
local app_name=$(basename "$app_path" .app)
local bundle_id=$(defaults read "$app_path/Contents/Info.plist" CFBundleIdentifier 2>/dev/null || echo "unknown")
local version=$(defaults read "$app_path/Contents/Info.plist" CFBundleShortVersionString 2>/dev/null || echo "unknown")
local size_bytes=$(du -sk "$app_path" 2>/dev/null | cut -f1 || echo "0")
size_bytes=$((size_bytes * 1024))
if [[ "$first_app" == "false" ]]; then
apps_json="$apps_json,"
fi
apps_json="$apps_json{
\"name\": \"$app_name\",
\"bundle_id\": \"$bundle_id\",
\"version\": \"$version\",
\"size_bytes\": $size_bytes,
\"path\": \"$app_path\"
}"
first_app=false
fi
done < <(find /Applications -name "*.app" -type d -print0 2>/dev/null)
apps_json="$apps_json]"
echo "$apps_json"
}
# Check for App Store updates
check_app_store_updates() {
echo "Checking for available App Store updates..."
# Use softwareupdate to check for available updates
local updates_available=$(softwareupdate -l 2>/dev/null | grep -i "app store" || echo "")
if [[ -n "$updates_available" ]]; then
echo "📦 App Store updates available:"
echo "$updates_available"
else
echo "✅ All App Store apps are up to date"
fi
# Also check Mac App Store directly if available
if command -v mas >/dev/null 2>&1; then
echo ""
echo "Checking with mas-cli..."
mas outdated 2>/dev/null || echo "mas-cli not available or no updates found"
fi
}
# Usage examples
echo "Fleet Management Examples:"
echo "========================="
echo ""
echo "1. Discovery mode:"
manage_fleet_app_inventory "discover"
echo ""
echo "2. Compliance check:"
manage_fleet_app_inventory "compliance"
echo ""
echo "3. Generate all reports:"
manage_fleet_app_inventory "report"
App Store Connect Integration
Enterprise App Management with App Store Connect
#!/bin/bash
# Enterprise App Store Connect integration for license management
manage_app_store_licenses() {
echo "📄 App Store Connect License Management"
echo "======================================"
echo ""
# Note: This requires enterprise App Store Connect access
# and proper API credentials configuration
local license_report_file="/tmp/app_store_licenses_$(date +%Y%m%d_%H%M%S).json"
echo "Analyzing App Store app licensing..."
echo ""
# Track apps that may require business licenses
local business_apps=()
local consumer_apps=()
local unknown_apps=()
while IFS= read -r -d '' app_path; do
if [[ -d "$app_path" && -f "$app_path/Contents/_MASReceipt/receipt" ]]; then
local app_name=$(basename "$app_path" .app)
local bundle_id=$(defaults read "$app_path/Contents/Info.plist" CFBundleIdentifier 2>/dev/null || echo "unknown")
# Categories that typically require business licenses
local business_categories=("Developer Tools" "Business" "Productivity" "Graphics & Design")
local is_business_app=false
# Check if app is business-oriented
if [[ -f "$app_path/Contents/Info.plist" ]]; then
local category=$(defaults read "$app_path/Contents/Info.plist" LSApplicationCategoryType 2>/dev/null || echo "unknown")
for biz_cat in "${business_categories[@]}"; do
if [[ "$category" =~ "$biz_cat" ]]; then
is_business_app=true
break
fi
done
# Also check common business app patterns
if [[ "$app_name" =~ (Microsoft|Adobe|Slack|Zoom|Teams|Office) ]]; then
is_business_app=true
fi
fi
if [[ "$is_business_app" == "true" ]]; then
business_apps+=("$app_name ($bundle_id)")
echo "💼 Business app detected: $app_name"
else
# Consumer apps that might be acceptable
if [[ "$app_name" =~ (Calculator|TextEdit|Safari|Mail|Photos) ]]; then
consumer_apps+=("$app_name ($bundle_id)")
echo "👤 Consumer app: $app_name"
else
unknown_apps+=("$app_name ($bundle_id)")
echo "❓ Unknown category: $app_name"
fi
fi
fi
done < <(find /Applications -name "*.app" -type d -print0 2>/dev/null)
# Generate license compliance report
{
echo "{"
echo " \"license_analysis\": {"
echo " \"timestamp\": \"$(date -u +"%Y-%m-%dT%H:%M:%SZ")\","
echo " \"device_id\": \"$(system_profiler SPHardwareDataType | grep "Serial Number" | awk -F': ' '{print $2}' | xargs)\","
echo " \"business_apps\": ["
local first=true
for app in "${business_apps[@]}"; do
if [[ "$first" == "false" ]]; then echo ","; fi
echo " \"$app\""
first=false
done
echo " ],"
echo " \"consumer_apps\": ["
first=true
for app in "${consumer_apps[@]}"; do
if [[ "$first" == "false" ]]; then echo ","; fi
echo " \"$app\""
first=false
done
echo " ],"
echo " \"unknown_apps\": ["
first=true
for app in "${unknown_apps[@]}"; do
if [[ "$first" == "false" ]]; then echo ","; fi
echo " \"$app\""
first=false
done
echo " ],"
echo " \"summary\": {"
echo " \"total_business_apps\": ${#business_apps[@]},"
echo " \"total_consumer_apps\": ${#consumer_apps[@]},"
echo " \"total_unknown_apps\": ${#unknown_apps[@]},"
echo " \"requires_license_review\": $([[ ${#business_apps[@]} -gt 0 || ${#unknown_apps[@]} -gt 0 ]] && echo "true" || echo "false")"
echo " }"
echo " }"
echo "}"
} > "$license_report_file"
echo ""
echo "=== License Analysis Summary ==="
echo "Business apps found: ${#business_apps[@]}"
echo "Consumer apps found: ${#consumer_apps[@]}"
echo "Unknown apps found: ${#unknown_apps[@]}"
echo ""
if [[ ${#business_apps[@]} -gt 0 || ${#unknown_apps[@]} -gt 0 ]]; then
echo "⚠️ License review required for business/unknown applications"
echo "📄 License report saved: $license_report_file"
else
echo "✅ No business licensing concerns detected"
fi
return 0
}
# Execute license management
manage_app_store_licenses
Important Notes
Enterprise Management Features
- Comprehensive Inventory - Complete App Store application discovery and tracking
- Compliance Monitoring - Policy enforcement and security analysis
- License Management - Enterprise App Store Connect integration
- Fleet Reporting - Multi-format reporting (JSON, CSV, text) with metadata
- Security Analysis - Permission auditing and code signature verification
- Update Management - App Store update detection and management
App Store Receipt System
- MAS Receipts - Digital proof of App Store purchase located in
Contents/_MASReceipt/receipt
- Bundle Identification - Unique app tracking via CFBundleIdentifier
- Version Tracking - App version and build number management
- Installation Metadata - Install date and modification tracking
- License Verification - Enterprise license compliance and allocation
Security and Compliance
- Permission Auditing - Camera, microphone, location access monitoring
- Code Signature Verification - Validate app integrity and authenticity
- Policy Enforcement - Blocked app categories and required app validation
- Age Analysis - Identify outdated applications requiring updates
- Team Identifier Tracking - Developer team identification for enterprise policies
Usage Examples
# Basic App Store app discovery
find /Applications -path '*Contents/_MASReceipt/receipt' -maxdepth 4 -print | \
sed 's#.app/Contents/_MASReceipt/receipt#.app#g; s#/Applications/##'
# Enterprise inventory with JSON output
generate_app_store_inventory "json" "true" "/tmp"
# Compliance analysis
analyze_app_compliance
# Fleet management - discovery mode
manage_fleet_app_inventory "discover"
# License management
manage_app_store_licenses