fleet/docs/solutions/macos/scripts/aws-ec2-mac-setup.sh
Dave Siederer c61ea7e5cd
Create aws-ec2-mac-setup.sh (#35217)
Script to run during the first launch of an AWS EC2 Mac instance to make
it easier to set up the Amazon Machine Image (AMI). Uses data from
https://github.com/aws-samples/amazon-ec2-mac-mdm-enrollment-automation/blob/main/Secret_SecretsManager_CF.yaml
that the AWS instance accesses at runtime.

Co-authored-by: Brock Walters <153771548+nonpunctual@users.noreply.github.com>
2025-11-05 12:51:24 -05:00

136 lines
6 KiB
Bash

#!/bin/bash
# This script is to set up an AWS EC2 Mac instance with auto-login for MDM enrollment.
# Paste this script into the "User data" field when launching your EC2 Mac instance.
# Once launched, connect via VNC or Apple Screen Sharing to accept the permissions prompts.
# Once the prompts are accepted, after clicking OK, create the image:
# In the AWS console, go to EC2, click the instance in the list, then click Image and templates -> Create image.
# Launching new instances from this AMI will automatically enroll them into MDM.
# Set the below to your AWS Secrets Manager secret containing credentials.
# Credential block template available at enroll-ec2-mac repo. This secret name will also be written to the image for enrollment as part of this script.
credentialID="SET-TO-YOUR-SECRETS-MANAGER-SECRET-NAME"
# Path prefix for AWS CLI.
PATH="/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/homebrew/bin:/opt/homebrew/sbin"
# JSONVoorhees: made from code by Matthew Warren, under MIT license.
# https://macblog.org/parse-json-command-line-mac/
function jsonParse() (
JSONVar="${1}"
INCOMINGDATA="${2}"
JSONReturn=$( osascript -l 'JavaScript' <<< "function run() { var jsoninfo = JSON.parse(\`$INCOMINGDATA\`) ; return jsoninfo.$JSONVar;}" )
echo "${JSONReturn}"
)
# The below retry function is used for AWS Secrets Manager retrieval only.
function retry() {
local n max waitFor
n=1
max=5
waitFor=15
while true; do
"${@}" && break || {
if [[ "${n}" -lt "${max}" ]]; then
((n++))
echo "Command failed. Attempt ${n}/${max}:" >&2;
sleep "${waitFor}";
else
echo "The command has failed after ${n} attempts." ; exit 111
fi
}
done
}
### Metadata token for authorization to retrieve data from local EC2 Mac instance,
MDToken=$(curl -X PUT "http://169.254.169.254/latest/api/token" -s -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
### Get current AWS region from running instance metadata.
### If Secrets Manager secret is in a different region, uncomment below to set a static region.
currentRegion=$(curl -H "X-aws-ec2-metadata-token: $MDToken" -s http://169.254.169.254/latest/meta-data/placement/region)
# currentRegion="us-east-1"
# Retrieves credentials from AWS Secrets Manager. To set statically, comment out credentialBlock and set EBSAdminUser and EBSAdminPassword.
credentialBlock=$(retry aws secretsmanager get-secret-value --region "$currentRegion" --secret-id "$credentialID" --query SecretString --output text)
# EBSAdminUser is "ec2-user" by default. If another account is named, it will be created (as an administrator).
EBSAdminUser=$(jsonParse "localAdmin" "$credentialBlock")
EBSAdminPassword=$(jsonParse "localAdminPassword" "$credentialBlock")
function createUserAccount () (
userToCreate="${1}"
userPassword="${2}"
userID="${3}"
sudo /usr/sbin/sysadminctl -addUser "$userToCreate" -fullName "$userToCreate" -UID "$userID" -GID 80 -shell /bin/zsh -password "$userPassword" -home "/Users/$userToCreate"
sudo /usr/sbin/createhomedir -c -u "$userToCreate"
)
function kcpasswordEncode () (
thisString="${1}"
cipherHex_array=( 7D 89 52 23 D2 BC DD EA A3 B9 1F )
thisStringHex_array=( $(/bin/echo -n "${thisString}" | xxd -p -u | sed 's/../& /g') )
if [ "${#thisStringHex_array[@]}" -lt 12 ]; then
padding=$(( 12 - ${#thisStringHex_array[@]} ))
elif [ "$(( ${#thisStringHex_array[@]} % 12 ))" -ne 0 ]; then
padding=$(( (12 - ${#thisStringHex_array[@]} % 12) ))
else
padding=12
fi
for ((i=0; i < $(( ${#thisStringHex_array[@]} + ${padding})); i++)); do
charHex_cipher=${cipherHex_array[$(( $i % 11 ))]}
charHex=${thisStringHex_array[$i]}
printf "%02X" "$(( 0x${charHex_cipher} ^ 0x${charHex:-00} ))" | xxd -r -p > /dev/stdout
done
)
# If account exists, do not create it.
if ( dscl . -list /Users | grep -q "$EBSAdminUser" ); then
echo "$EBSAdminUser account already exists."
else
# Creates and elevates account to admin.
highestUID=$(dscl . -list /Users UniqueID | sort -nr -k 2 | head -1 | grep -oE '[0-9]+$')
((newUserUID=highestUID+1))
echo "Creating $EBSAdminUser account (UID $newUserUID)."
createUserAccount "$EBSAdminUser" "$EBSAdminPassword" $newUserUID
sudo /usr/bin/dscl . -append /Groups/admin GroupMembership "$EBSAdminUser"
fi
# Sets password for user account using variables above.
echo "Setting password for $EBSAdminUser account."
sudo /usr/bin/dscl . -passwd "/Users/$EBSAdminUser" "$EBSAdminPassword"
# Invisible directory for staging.
stagingDir="/Users/Shared/._ec2-auto-login"
sudo mkdir -p "$stagingDir"
sudo chown 501:20 "$stagingDir"
sudo chmod -R 775 "$stagingDir"
# Enable auto-login for user.
sudo defaults write "/Library/Preferences/com.apple.loginwindow" autoLoginUser "$EBSAdminUser"
# Set name of Secret for enroll-ec2-mac script to run.
sudo defaults write "/Users/$EBSAdminUser/Library/Preferences/com.amazon.dsx.ec2.enrollment.automation" MMSecret "$credentialID"
sudo chown $EBSAdminUser:staff "/Users/$EBSAdminUser/Library/Preferences/com.amazon.dsx.ec2.enrollment.automation.plist"
kcpasswordEncode "$EBSAdminPassword" > "$stagingDir/kcpassword"
sudo cp "$stagingDir/kcpassword" "/etc/"
sudo chown root:wheel "/etc/kcpassword"
sudo chmod u=rw,go= "/etc/kcpassword"
# Downloads and installs the latest enroll-ec2-mac.scpt, including loading the LaunchAgent for setup.
sudo curl -H 'Accept: application/vnd.github.v3.raw' https://api.github.com/repos/aws-samples/amazon-ec2-mac-mdm-enrollment-automation/contents/enroll-ec2-mac.scpt | sudo tee "/Users/Shared/enroll-ec2-mac.scpt" > /dev/null ; sudo chmod +x "/Users/Shared/enroll-ec2-mac.scpt"; osascript "/Users/Shared/enroll-ec2-mac.scpt" --setup && echo "Setup Done" || echo "Setup Not Done"
# Enable Screen Sharing for remote GUI connection.
sudo launchctl enable system/com.apple.screensharing ; sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.screensharing.plist
# Sets a flag to prevent script from attempting to run twice.
if [ -f "$stagingDir/.userSetupComplete" ]; then
# Clean up auto-login database.
rm -rf "$stagingDir/kcpassword"
sleep 1
else
touch "$stagingDir/.userSetupComplete"
sudo launchctl reboot
fi