Native macOS agent that keeps the office VPN and the NAS shares working without the shell wrapper it replaces. - VPN: full port of the `ovpn` script — host-route pinning, gateway discovery via networksetup, tunnel liveness by address plus pushed route, startup grace, restart of a wedged daemon. Root steps are batched into one system authorization prompt. - SMB: mounts via NetFS, discovers shares from the server, detects mounts event-driven through NSWorkspace, matches the host by resolved alias so externally created mounts are recognised. - Credentials never pass through the process: the VPN auth file is written by `security` straight to disk, and the password is stored via SecItemAdd rather than a command line visible in ps. - UI: status window, settings editor, ⌘+/⌘− zoom that re-lays out rather than scaling a bitmap. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
104 lines
3.9 KiB
Bash
Executable File
104 lines
3.9 KiB
Bash
Executable File
#!/bin/bash
|
|
# Builds a transferable bundle: the universal .app, the sources to rebuild it,
|
|
# and install instructions.
|
|
set -euo pipefail
|
|
|
|
cd "$(dirname "$0")"
|
|
|
|
NAME="CampusNAS"
|
|
STAMP="$(date +%Y%m%d)"
|
|
OUT="dist/${NAME}-${STAMP}"
|
|
|
|
echo "==> universal build"
|
|
UNIVERSAL=1 ./build.sh >/dev/null
|
|
|
|
ARCHS="$(lipo -archs "build/${NAME}.app/Contents/MacOS/${NAME}")"
|
|
echo " architectures: ${ARCHS}"
|
|
|
|
rm -rf "$OUT"
|
|
mkdir -p "${OUT}/source"
|
|
|
|
echo "==> collecting"
|
|
# ditto keeps the bundle structure and the ad-hoc signature intact; cp -R does
|
|
# not always preserve extended attributes on a signed bundle.
|
|
ditto "build/${NAME}.app" "${OUT}/${NAME}.app"
|
|
|
|
cp -R Sources Package.swift build.sh package.sh README.md "${OUT}/source/"
|
|
|
|
cat > "${OUT}/INSTALL.md" <<'DOC'
|
|
# CampusNAS — установка на другой Mac
|
|
|
|
## Что внутри
|
|
|
|
- `CampusNAS.app` — готовое приложение, universal (Apple Silicon + Intel)
|
|
- `source/` — исходники, чтобы пересобрать при необходимости
|
|
- `README.md` в `source/` — как всё устроено и почему
|
|
|
|
## Установка
|
|
|
|
```bash
|
|
cp -R CampusNAS.app /Applications/
|
|
xattr -dr com.apple.quarantine /Applications/CampusNAS.app
|
|
open /Applications/CampusNAS.app
|
|
```
|
|
|
|
Вторая строка обязательна. Приложение подписано ad-hoc, без Developer ID,
|
|
поэтому файл, приехавший с другой машины, помечается карантином и Gatekeeper
|
|
его не пустит. Команда снимает эту метку.
|
|
|
|
Иконка появится в меню-баре. Окно — повторный запуск приложения либо
|
|
«Показать окно» в меню.
|
|
|
|
## Настройка
|
|
|
|
Меню-бар → **Настройки…** (⌘,):
|
|
|
|
- путь к профилю `.ovpn` и к бинарю `openvpn`
|
|
- IP VPN-сервера, сеть туннеля, офисная сеть
|
|
- запись Keychain, логин и пароль VPN
|
|
- логин SMB
|
|
|
|
Адрес NAS и список шар правятся в `~/.config/campusnas-monitor/config.json`,
|
|
он создаётся при первом запуске.
|
|
|
|
## Что нужно на целевой машине
|
|
|
|
- **openvpn** — `brew install openvpn`. Приложение само проверит наличие и
|
|
покажет кнопку установки, если не найдёт.
|
|
- **профиль `.ovpn`** — скопировать отдельно, в комплект он не входит: там
|
|
сертификаты.
|
|
- **пароль VPN** — ввести в окне настроек, он ляжет в Keychain.
|
|
- **пароль SMB** — спросит сам macOS при первом монтировании. Поставьте галку
|
|
«Запомнить пароль в связке ключей», иначе автомонтирование работать не будет.
|
|
|
|
Если NAS доступен только по имени, а DNS его не отдаёт — добавьте запись:
|
|
|
|
```bash
|
|
printf '192.168.77.43\tCAMPUSNAS\n' | sudo tee -a /etc/hosts
|
|
```
|
|
|
|
## Пересборка
|
|
|
|
```bash
|
|
cd source
|
|
UNIVERSAL=1 ./build.sh
|
|
```
|
|
|
|
Нужен Xcode с командными утилитами. Собирается за несколько секунд.
|
|
|
|
## Чего приложение не делает
|
|
|
|
Не хранит паролей. Пароль VPN пишется прямо в Keychain и читается оттуда
|
|
системной утилитой при подключении. Пароль SMB приложение не видит вообще —
|
|
им занимается macOS.
|
|
DOC
|
|
|
|
echo "==> archiving"
|
|
cd dist
|
|
ditto -c -k --sequesterRsrc --keepParent "${NAME}-${STAMP}" "${NAME}-${STAMP}.zip"
|
|
cd ..
|
|
|
|
SIZE="$(du -h "dist/${NAME}-${STAMP}.zip" | cut -f1)"
|
|
echo
|
|
echo "Готово: $(pwd)/dist/${NAME}-${STAMP}.zip (${SIZE})"
|