Skip to content

Commit

Permalink
Merge branch 'release/0.2.1'
Browse files Browse the repository at this point in the history
  • Loading branch information
a-vogel committed Sep 4, 2024
2 parents af34ce2 + 3979ec3 commit fb316f3
Show file tree
Hide file tree
Showing 12 changed files with 59 additions and 39 deletions.
14 changes: 11 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,19 @@

## Unreleased

### Info
- See [Testing methods](./README.md#testing-methods) and [To Do](./README.md#to-do) sections of the README if you plan to use *misty* at the current state.


## [0.2.1](https://github.com/wycomco/misty/releases/tag/v0.2.1) – 2024-09-04 (Pre-release)

### Security
- Sanity check for launchdaemon’s start time
- Sanity check for launchdaemon’s start time – [PR#1](https://github.com/wycomco/misty/pull/1), [PR#10](https://github.com/wycomco/misty/pull/10)
- Move *misty* dirs (usr, skel, Logs) from `/Users/Shared/Mist` to `/var/root/misty`[PR#4](https://github.com/wycomco/misty/pull/4), [PR#13](https://github.com/wycomco/misty/pull/13)

### Info
- See [Testing methods](./README.md#testing-methods) and [To do](./README.md#to-do) sections of the README if you plan to use *misty* at the current state.
### Fixed
- Error messages only get prepended by a timestamp if *misty* is running as a launchd job – [PR#11](https://github.com/wycomco/misty/pull/11)
- Removed initial start value for LaunchDaemon in config.txt (fix for [0.1.7](https://github.com/wycomco/misty/releases/tag/v0.1.7)) – [PR#8](https://github.com/wycomco/misty/pull/8)


## [0.2.0](https://github.com/wycomco/misty/releases/tag/v0.2.0) – 2024-08-22 (Pre-release)
Expand Down
25 changes: 16 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

This script checks for the availability of new macOS releases currently supported by Apple, using *mist-cli* (not included in this project’s installer). It also requires a *munki* repo to be already set up. Please see the [System Requirements](#system-requirements) section below for links.

Since this is a pre-release with frequent updates, the binary has not yet been signed or notarized. To open the downloaded installer, please right-click the `.pkg` file and select 'Open'.
*misty* can be used with a local repository and with SMB or Samba shares.

Since this is a pre-release with frequent updates, the installer has not yet been signed or notarized. To run the downloaded installer, please right-click the `.pkg` file and select 'Open'.

See the [Changelog](./CHANGELOG.md) for details on version history and updates.

Expand All @@ -27,9 +29,9 @@ The script does not have any command line options. You specify them in the confi

### First Run: Customization

Please run the script using `sudo misty`. The script will then create a `usr/` subfolder in `/Users/Shared/Mist/`, which should already be present after installing *mist-cli*. A configuration file will be created that you should customize to suit your needs. The script will also ask if you require localizations. If you do, localization templates for the relevant plist files will be copied to the `usr/` subfolder, which you should adjust to your language(s).
Please run the script using `sudo misty`. The script will then create a `usr/` subfolder in `/var/root/misty/`. The subfolder `misty` will be created automatically during installation. A configuration file will be created that you should customize to suit your needs. You need root privileges to access the folder `/var/root/misty/` and any subfolders or files in it. The script will also ask if you require localizations. If you do, localization templates for the relevant plist files will be copied to the `usr/` subfolder, which you should adjust to your language(s).

You can also place a script called `postinstall.sh` into your usr folder that will be executed after each new import of at least one major version. Make sure it is executable by running `chmod +x /Users/Shared/Mist/usr/postinstall.sh` in the terminal. The script will run after the misty run has finished, so you may find it useful for `sed`ing plists or altering anything else that is not covered by *misty* itself.
You can also place a script called `postinstall.sh` into your usr folder that will be executed after each new import of at least one major version. Make sure it is executable by running `chmod +x /var/root/misty/usr/postinstall.sh` in the terminal. The script will run after the misty run has finished, so you may find it useful for `sed`ing plists or altering anything else that is not covered by *misty* itself.

During the first run, a LaunchDaemon (`/Library/LaunchDaemons/de.wycomco.misty.plist`) will be enabled if not running yet. You will be asked at what time *misty* should run.

Expand Down Expand Up @@ -58,13 +60,15 @@ Each run of *misty* compares the full versions of each major version in the `Log

## Folder Structure

As mentioned above, *mist-cli* is required for running this script. Its installer creates a folder `Mist` inside `/Users/Shared`. We are using this folder. Inside that folder, we have several subfolders:
As mentioned above, *mist-cli* is required for running this script. Its installer creates a folder `Mist` inside `/Users/Shared`. New macOS versions are downloaded to that folder and `munkiimport`ed from that location. After successful import, the installers will be deleted.

We also create a folder `misty` under `/var/root/`. Inside that folder, we have several subfolders:

- `skel/`: These are the template files. Do not edit files in here. *misty* may not work properly if the files in this directory are edited, and updates may overwrite some files too. Don’t change anything in there.
- `usr/`: This is your place to edit configuration files to suit your needs.
- `Logs/`: A changelog will be created and updated each time updates get imported. Also, there are files for each major version called `previous_state_[major_version].txt`. These are looked up by *misty* on each run. If you want to recreate installers for a major version already present in the repo, please look at the [Testing Methods](testing-methods) section below.

During the packaging process, the installer for the respective major version will be present inside the `/Users/Shared/Mist` folder. It is deleted after all related plists have been created.
When run as a launchd job, the log files `/var/log/misty.log` (for stdout) and `/var/log/misty_error.log` (for stderr) will be created.

The script *misty* itself is located in `/usr/local/wycomo` and has an alias in `/usr/local/bin/`.

Expand Down Expand Up @@ -96,19 +100,23 @@ After that, also grant FDA using the same way described for `/bin/zsh` to

If you are still facing issues, also grant `Terminal.app` (located in `/Applications/Utlities`) Full Disk Access.

## Testing Methods
## Contributing

This is a pre-release. Being said that, you are highly encouraged to test it in your environment and provide feedback using issues or pull requests.

*misty* will do nothing if it thinks all is up to date. If you really are up to date with all three major versions, you can do the following:
*misty* makes use of [git-flow](https://github.com/nvie/gitflow). Branch name for production releases is *main*, branch name for "next release" development is *dev*. The version tag prefix is *v*. All other values are the default ones. You can install git-flow using [homebrew](https://brew.sh/) by entering `brew install git-flow` in the terminal.

### Testing methods

*misty* will do nothing if it thinks all is up to date. If you are up to date with all three major versions in the repo, you can do the following:

1. In the repo, rename the dmg file of the macOS installer to an earlier version. Then, rename all plist files of that version, too. Edit each plist file so the `item_installer_location` is updated to the name of the renamed dmg file. Don’t forget to also adjust the `version` string at the bottom of the files. This will ensure that the removal of older versions (at least two) will get tested.
2. Alternatively, just delete all plists and the corresponding dmg. If you followed step 1, ignore this step.
3. Do a `makecatalogs` on the repo.
4. For each major version that you altered or deleted, you need to edit the file `/Users/Shared/Mist/previous_state_[major_version].txt`. Just change the current version key to another number. You need root permissions for that.
5. Then you can run *misty* manually or wait for the LaunchDaemon to do its job.

## Known issues
## Known Issues

- The reload of the launchdaemon does not work if *misty* was invoked by its launchdaemon. Please run *misty* in Terminal using `sudo misty` if you have changed the start time in the config file. This will trigger a proper reload of the daemon (and do nothing else unless a new macOS version is found).

Expand All @@ -118,7 +126,6 @@ This is a pre-release. It is working, but we have some tasks on our to-do list:

- Testing in different environments, preferably with SMB and Samba shares.
- Ensure all items that require FDA are mentioned.
- Move `RepoUser` and `RepoPass` out of a file under `/Users/Shared` being accessible for all users.
- Check for available space. We need to check the space on the munki repo, but more importantly, the space on the system disk. If not enough space is available, the resulting installer .app will not be complete, resulting in unusable plists and payloads being offered to clients. There exists a check with hard-coded values that stops the import process for each major version, but more testing needs to be done to ensure the values are appropriate.
- Improve message output.
- Harmonize variable names.
Expand Down
2 changes: 1 addition & 1 deletion misty/build-info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@
<key>suppress_bundle_relocation</key>
<true/>
<key>version</key>
<string>0.2.0</string>
<string>0.2.1</string>
</dict>
</plist>
55 changes: 31 additions & 24 deletions misty/payload/usr/local/wycomco/misty
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ cleanup() {
chown "$Repo_uid_gid" "$pkgsdir/$munki_name-$fqos.dmg"
chown "$Repo_uid_gid" "$pkgsinfodir/arm64/${munki_name}-$fqos.plist" "$pkgsinfodir/arm64/${munki_name}_arm-$fqos.plist" \
"$pkgsinfodir/$deploy_name-$fqos.plist" "$pkgsinfodir/x86_64/$munki_name-$fqos.plist"
rm -rf "$Base_Path/Install macOS $os_nice.app"
rm -rf "$Mist_Path/Install macOS $os_nice.app"
mv "$LogPath"/current_state_"$os_major".txt "$LogPath"/previous_state_"$os_major".txt
echo "Last update for macOS "$os_nice" ran on $(date)" >> "$LogPath"/changelog.txt
}
Expand Down Expand Up @@ -192,6 +192,7 @@ extract_macos_version() {
}

extract_time_input() {
DaemonTime="valid"
if [[ ! $time_input =~ ^[0-9]{1,2}:[0-9]{1,2}$ ]]; then
log_message "stderr" "Error: Invalid format for variable time_input in config.txt. Expected format is HH:MM."
DaemonTime="invalid"
Expand Down Expand Up @@ -248,7 +249,7 @@ munkiimport_stage_os() {
--maximum_os_version="$os_maxi" --minimum_os_version="$os_mini" \
--arch=arm64 --RestartAction=RequireRestart --repo-url=file://"$RepoPath" \
--subdirectory="$munki_path" --unattended_install --unattended_uninstall \
--pkgvers="$fqos" "$Base_Path/Install macOS $os_nice.app" > /dev/null
--pkgvers="$fqos" "$Mist_Path/Install macOS $os_nice.app" > /dev/null
sleep 20 # wait for plist to be created
# File name and plist content manipulations
mv "$pkgsdir/Install macOS $os_nice-$fqos.dmg" "$pkgsdir/$munki_name-$fqos.dmg"
Expand Down Expand Up @@ -282,7 +283,7 @@ munkiimport_startos() {
--maximum_os_version="$os_maxi" --minimum_os_version="$os_mini" \
--arch=x86_64 --RestartAction=RequireRestart --repo-url=file://"$RepoPath" \
--subdirectory="$munki_path" \
--pkgvers="$fqos" "$Base_Path/Install macOS $os_nice.app" > /dev/null
--pkgvers="$fqos" "$Mist_Path/Install macOS $os_nice.app" > /dev/null
sleep 20 # wait for plist to be created
rm "$pkgsdir/Install macOS $os_nice-$fqos.dmg"
mv "$pkgsinfodir/$munki_name-$fqos-x86_64" "$pkgsinfodir/x86_64/$munki_name-$fqos.plist"
Expand Down Expand Up @@ -416,14 +417,17 @@ rm_previous_files() {
# Global definitions, checks #
################################################################################

export PATH="/bin:/usr/bin:/usr/local/bin:/usr/local/munki:/usr/libexec:$PATH"
export PATH="/bin:/usr/bin:/usr/libexec:/usr/local/bin:/usr/local/munki:/usr/sbin:$PATH"

# Redirecting stderr to the log_message function
exec 2> >(while IFS= read -r line; do log_message "stderr" "$line"; done)
# Ensure error messages from external programs also get prepended by a timestamp if not running in a terminal
if [[ ! -t 1 ]]; then
exec 2> >(while IFS= read -r line; do log_message "stderr" "$line"; done)
fi

repo_required=28 # Size required on repo for arm64 and x86_64 installer in GB, needed during creation
diskspace_required=30 # Size required on boot disk for installer and cache in GB
Base_Path="/Users/Shared/Mist"
Base_Path="/var/root/misty"
Mist_Path="/Users/Shared/Mist"
LogPath="$Base_Path/Logs"
Template="$Base_Path/skel"
DaemonPath="/Library/LaunchDaemons/de.wycomco.misty.plist"
Expand All @@ -444,6 +448,7 @@ if [ $? -ne 0 ]; then
fi
if [[ ! -d "$LogPath" ]]; then
mkdir -p "$LogPath"
chmod 0700 "$LogPath"
fi
if [[ ! -d "$Template" || ! $(ls -A "$Template") ]]; then
log_message "stderr" "Error: The directory \"$Template\" either does not exist or is empty. Please reinstall misty."
Expand All @@ -456,16 +461,26 @@ fi

if [[ ! -d "$Base_Path/usr" ]]; then
mkdir -p "$Base_Path/usr"
chmod 777 "$Base_Path/usr"
chmod 0700 "$Base_Path"
chmod 0700 "$Base_Path/usr"
fi
if [[ ! -f "$Base_Path/usr/config.txt" ]]; then
currentUser=$(echo "show State:/Users/ConsoleUser" | scutil | awk '/Name :/ { print $3 }')
cp "$Template/config.txt" "$Base_Path/usr"
log_message "stdout" "Config file created in $Base_Path/usr/"
while true; do
echo
echo "Please enter the time when the script should start in 24 hour format (HH:MM): "
read time_input
extract_time_input
# Loop to prompt user for valid time input
while true; do
echo "Please enter the time when the script should start in 24-hour format (HH:MM): "
read time_input
extract_time_input
# If time is valid, break the loop
if [[ $DaemonTime != "invalid" ]]; then
break
else
echo "Invalid time format. Please enter a valid time in HH:MM format."
fi
done
PlistBuddy -c "Set :StartCalendarInterval:Hour $DaemonHour" $DaemonPath
PlistBuddy -c "Set :StartCalendarInterval:Minute $DaemonMinute" $DaemonPath
echo "# Start of script in the LaunchDaemon" >> "$Base_Path/usr/config.txt"
Expand All @@ -480,18 +495,10 @@ if [[ ! -f "$Base_Path/usr/config.txt" ]]; then
[Yy]* )
cp "$Template/localized_arm.txt" "$Template/localized_deploy.txt" "$Template/localized_stage_os.txt" "$Template/localized_startos.txt" "$Base_Path/usr"
sed -i '' 's/localization="no"/localization="yes"/g' "$Base_Path"/usr/config.txt
echo "Please adjust the file config.txt and any localized_*.txt files in $Base_Path/usr to your needs now."
chmod 666 "$Base_Path/usr/*.txt"
echo "A finder window will open in 5 seconds."
sleep 5
su -l "$currentUser" -c "open $Base_Path/usr"
echo "Please adjust the file config.txt and any localized_*.txt files in $Base_Path/usr to your needs now using an editor like vi or nano."
exit 0 ;;
[Nn]* )
echo "Please adjust the file $Base_Path/usr/config.txt to your needs now."
chmod 666 "$Base_Path/usr/*.txt"
echo "A finder window will open in 5 seconds."
sleep 5
su -l "$currentUser" -c "open $Base_Path/usr"
echo "Please adjust the file $Base_Path/usr/config.txt to your needs now using an editor like vi or nano."
exit 0;;
* ) echo "Please answer using [y] or [n].";;
esac
Expand All @@ -502,8 +509,8 @@ fi
# Import config, more definitions #
################################################################################

# Load definitions from config file in /Users/Shared/Mist/usr
source "$Base_Path"/usr/config.txt
# Load definitions from config file in /var/root/misty/usr
source "$Base_Path/usr/config.txt"
echo "RepoPath: $RepoPath" > /dev/null
echo "Is_SMB: $Is_SMB" > /dev/null
echo "RepoUser: $RepoUser" > /dev/null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,3 @@ munki_catalog_14="testing"
munki_category="Utilities"
# If turned to "yes", localizations will be used. If not present yet, copy the files starting with "localized_" from the skel/ dir into the usr/ folder and adjust to your needs
localization="no"
# Start of script in the LaunchDaemon
time_input="22:00"

0 comments on commit fb316f3

Please sign in to comment.