0

我为我的一个项目在 TypeScript 中创建了一个自动安装脚本(编译为 JavaScript 并在 Node.js 下运行),该脚本曾经运行良好,但现在由于“需要交互式身份验证”错误而失败,该错误来自polkit,这显然是 Raspbian 使用的安全策略服务。

该脚本使用 启动sudo,因此它应该以完全管理员权限运行失败的事情,即停止我自己的服务 ( service weatherService stop),以及创建或修改其中定义该服务的/etc/default/文件/etc/init.d/

我能猜到的是最近的一些安全更新让我很伤心,但具体是什么,我不知道。当我在谷歌上搜索我收到的特定错误消息时polkit,大多数讨论似乎都围绕着哪些用户是 sudo-ers 以及 sudo-ers 可以做什么。但是我作为“pi”用户尝试做的所有事情,在运行时sudo,都是我仍然可以在终端窗口中毫无问题地做的事情,并且不会弹出任何“交互式身份验证”迫使我进行任何身份验证。

代码太大,无法在此处发布,但可以在 Github 上找到:https ://github.com/kshetline/aw-clock/

...特别是在这个文件中:https ://github.com/kshetline/aw-clock/b ... r/build.ts

以下是一些关键片段:

        try {
          await monitorProcess(spawn('service', ['weatherService', 'stop']), spin, ErrorMode.ANY_ERROR);
        }
        catch (err) {
          const msg = err.message || err.toString();

          // Grief from polkit?
          if (/Interactive authentication required/i.test(msg)) {
             // Blah, blah, blah...
          }
        }

import { ChildProcess, execSync, spawn as nodeSpawn } from 'child_process';


export function spawn(command: string, args: string[], options?: any): ChildProcess;
export function spawn(command: string, uid?: number, args?: string[], options?: any): ChildProcess;
export function spawn(command: string, uidOrArgs?: string[] | number, optionsOrArgs?: any, options?: any): ChildProcess {
  let uid: number;
  let args: string[];

  if (isNumber(uidOrArgs)) {
    uid = uidOrArgs;
    args = optionsOrArgs || [];
  }
  else {
    args = uidOrArgs || [];
    options = optionsOrArgs;
    uid = options?.uid;
  }

  if (uid != null) {
    options = options ?? {};
    options.uid = uid;

    if (!options.env) {
      options.env = {};
      Object.assign(options.env, process.env);
    }

    options.env.HOME = userHome;
    options.env.LOGNAME = sudoUser;
    options.env.npm_config_cache = userHome + '/.npm';
    options.env.USER = sudoUser;
  }

  if (isWindows) {
    if (/^(chmod|chown|id)$/.test(command)) {
      // Effectively a "noop"
      command = 'rundll32';
      args = [];
    }
    else if (command === 'rm') {
      // Ad hoc, not a general solution conversion of rm!
      command = 'rmdir';
      args = ['/S', '/Q', args[1].replace(/\//g, '\\')];
    }
    else if (command === 'which')
      command = 'where';

    const cmd = process.env.comspec || 'cmd';

    if (options?.uid != null) {
      options = Object.assign({}, options);
      delete options.uid;
    }

    return nodeSpawn(cmd, ['/c', command, ...args], options);
  }
  else
    return nodeSpawn(command, args, options);
}

export function monitorProcess(proc: ChildProcess, markTime: () => void = undefined, errorMode = ErrorMode.DEFAULT): Promise<string> {
  let errors = '';
  let output = '';

  return new Promise<string>((resolve, reject) => {
    const slowSpin = unref(setInterval(markTime || NO_OP, MAX_MARK_TIME_DELAY));

    proc.stderr.on('data', data => {
      (markTime || NO_OP)();
      data = stripFormatting(data.toString());

      // This gets confusing, because a lot of non-error progress messaging goes to stderr, and the
      //   webpack process doesn't exit with an error for compilation errors unless you make it do so.
      if (/(\[webpack.Progress])|Warning\b/.test(data))
        return;

      errors += data;
    });
    proc.stdout.on('data', data => {
      (markTime || NO_OP)();
      data = data.toString();
      output += data;

      if (errorish(data))
        errors = errors ? errors + '\n' + data : data;
    });
    proc.on('error', err => {
      clearInterval(slowSpin);

      if (errorMode !== ErrorMode.NO_ERRORS)
        resolve(output);
      else
        reject(err);
    });
    proc.on('close', () => {
      clearInterval(slowSpin);

      if (errorMode !== ErrorMode.NO_ERRORS && errors && (errorMode === ErrorMode.ANY_ERROR || errorish(errors)))
        reject(errors.replace(/\bE:\s+/g, '').trim());
      else
        resolve(output);
    });
  });
}

尽管上面的代码很复杂,用于监控进程输出流、处理不同的操作系统和设置一些环境变量,但它实际上只是 Node.jsspawn函数的包装,以及我曾经能够执行的命令的事实成功产卵现在因这个polkit问题而失败。

polkit服务似乎是一个巨大的蠕虫罐,有许多单独的复杂策略文件定义了谁可以做什么和做什么。因为我试图用我的脚本做的事情就是做一个 sudo-er 通常有权做的事情,我什至不知道为什么polkit关心,或者这个“交互式身份验证”看起来像什么——它不像出现一些提示,用户或我的脚本无论如何都可以尝试与之交互。

我真正希望(对成功的期望很低)是阅读本文的人会有“哦,那个问题!” 反应。除此之外,对于任何不熟悉类似问题的人来说,这个故障将很难描述得足够好。

4

0 回答 0