Я создаю приложение для macOS (используя SwiftUI), оно запускает скрипт. Для запуска скрипта мне нужен системный (или администраторский) пароль. потому что, когда я запускаю этот сценарий в Терминале, он запрашивает пароль пользователя, а затем запускает сценарий. Я могу запустить скрипт при нажатии кнопки с помощью безопасного поля, но Нецелесообразно показывать пользователю защищенное поле и запрашивать его системный пароль в приложении, хотя это противоречит рекомендациям Apple. Поэтому я удалил это поле. Теперь я понятия не имею, как запустить скрипт после аутентификации по системному паролю. Чтобы показать аутентификацию пользователя, я использую это.
let context = LAContext()
func authorize() {
var error: NSError? = nil // Create optional error variable
let reason = "This action requires your authentication for security purposes."
let policy: LAPolicy = .deviceOwnerAuthentication // Adjust policy based on device capabilities (e.g., biometrics, passcode)
context.evaluatePolicy(policy, localizedReason: reason, reply: { (success, error) in
if success {
// User was successfully authenticated
**// Proceed with your script execution here, but the problem is I dont have user password here, and not found even from the Keychain, because before fetch password from keychain it should be store there**
print("Success")
} else {
// Authentication failed or was canceled
if let error = error {
// Handle the error appropriately
print(error.localizedDescription)
}
}
})
}
Я думаю, мне следует сохранить пароль в связке ключей для обеспечения безопасности, а затем для доступа, но сначала мне нужно получить пароль, не нарушая направляющих линий Apple.
Вот и вся проблема, я не нашел связанной с этой штукой.
Отредактировано:
Когда я запускаю свой сценарий в случае успеха, он показывает сообщение в терминале Xcode ниже.
sudo: a password is required
sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper





Решение своей проблемы я нашел сам. В моем случае let context = LAContext() не работает и в этом нет необходимости.
Для запуска скрипта от имени администратора не нужно хранить пароль в связке ключей. При написании сценария в это время пишите сценарий с помощью этой штуки.
let osacScript = "osascript -e 'do shell script \"\(script)\" with administrator privileges'"
Мы можем написать скрипт sudo (скрипт sudo нужен, когда мы хотим выполнить некоторые действия, например создать папку или переместить папку), вот так
let osacScript = "osascript -e 'do shell script \"sudo \(script)\" with administrator privileges'"
Код, решивший мою проблему, приведен ниже:
func installScript(scriptPath: String, installingDir: String) {
let script = "\(scriptPath) --noprompt --dir \(installingDir) --key ABCKEY --region name-for-region --server https://myserver.com"
DispatchQueue.global(qos: .background).async { // I am using SwiftUI so to avoid blocking the UI running script in the background.
let osacScript = "osascript -e 'do shell script \"\(script)\" with administrator privileges'"
print(osacScript)
var arguments = [String]()
arguments.append("-c")
arguments .append(osacScript)
let process = Process()
process.launchPath = "/bin/bash" // Specify the shell to use
process.arguments = arguments
let pipe = Pipe()
process.standardOutput = pipe
process.standardError = pipe // Redirect standard error to the same pipe
let fileHandle = pipe.fileHandleForReading
process.launch()
process.waitUntilExit()
let data = fileHandle.readDataToEndOfFile()
let logFilePath = Bundle.main.path(forResource: "logfile", ofType: "txt")! // This thing can lead to error if file does not exist, so make sure it should be optional.
if let output = String(data: data, encoding: .utf8) {
print("output:\(output)")
// Write output to file
do {
try output.write(toFile: logFilePath, atomically: true, encoding: .utf8)
} catch {
print("Error writing to file: \(error)")
}
}
}
}