mirror of
https://github.com/fleetdm/fleet
synced 2026-05-14 12:38:41 +00:00
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>
136 lines
6 KiB
Bash
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
|