如何允许仅某些脚本的输出写入目录?

如何允许仅某些脚本的输出写入目录?

我想允许用户运行任何一组脚本并将输出写入指定目录,但不允许该用户的任何其他脚本或命令写入该指定目录。

目的是将指定的目录从系统 rsync 出来,但仅限于已批准的脚本。用户可以不受限制地运行其他脚本,但除已批准的脚本外,不得将输出导出到环境之外。

尝试解决问题

我尝试设置两个用户“普通”和“受限”,并使用“受限”拥有的输出目录和批准的脚本,因此“普通”以“受限”的身份运行脚本,允许输出进入受限目录,这是有效的,但没有什么可以阻止“普通”以“受限”的身份运行未经批准的脚本,允许输出进入“受限”目录,而这正是我希望防止的。

答案1

您可以执行以下操作:

您将需要两个用户“普通”和“受限”,但不要将受限用户的密码告诉普通用户。然后调用:

visudo 

并添加所有您想让普通用户以受限用户身份执行的脚本,如下所示:

normal ALL=(restricted) NOPASSWD: scriptDir/script.sh

然后让用户正常调用脚本,例如:

su -c scriptDir/script.sh restricted

通过这种方式,你可以控制希望普通用户以受限方式执行的脚本

答案2

通过安装实用程序(getfacl 和 setfacl)设置 ACL - 访问控制列表。

您可以设置每个用户的 ACL,但通常更简单的方法是将对文件系统的某个部分具有相同权限的用户放在一个组中,并为该组设置 ACL。例如,如果 html-writers 组中的用户应该对 /var/www/html 下的树具有读写访问权限

您可以使用 setfacl:

setfacl -m 组:html-writers u:用户名:rwx myfolder

这会为特定用户设置权限,而不会改变目录的所有权。

答案3

听起来你正在尝试使用不允许您执行所需操作的工具来解决问题。如果您依赖 ACL 或 Unix 权限,那么有关目录的权限取决于试图更改它们的用户。因此,无论如何,如果用户可以写入目录,他们就可以创建除您希望他们创建的文件之外的文件。

但是,如果用户无法写入目录,但您希望脚本能够写入,那么您必须以可以写入的用户身份运行该脚本。这可以通过两种方式完成,如果您必须使用脚本,那么正如@Wissam Al-Roujoulah 所提到的,您可以使用 sudo。如果您可以将预期的行为放入二进制文件而不是脚本中,那么您可以对其使用 setuid,并对其进行配置,以便组中的任何成员都可以运行该二进制文件,但该二进制文件将以不同的用户身份运行。

脚本中 sudo 的问题与不能在脚本中使用 setuid 的原因相同。有人使用 shell 变量来破坏脚本的行为实在是太容易了,所以请谨慎行事。

我通过编写一个非常基本的 .c 文件解决了您的问题,该文件像脚本一样运行系统命令,然后让编译后的二进制文件 setuid 允许用户使用它。就我而言,我想从各个位置清除缓存文件夹,二进制文件需要以 root 身份运行,但我希望非特权用户能够运行它。

我把文件缩减了很多,因为我的原始文件包含了清除不同位置的多种不同类型的缓存的选项,但你应该明白我的意思了。我还包含了我用来审计日志的代码,因为它显示了如何将信息放入系统日志中,如果你想使用它而不是文件的话。

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <syslog.h>

int has_root_euid()
{
  if (geteuid()==0) {
    return 1;
  }
  return 0;
}

int main (int argc, char * argv[])
{
  int retval;
  uid_t uid;

  uid = getuid();

  openlog (argv[0], LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1);
  syslog (LOG_NOTICE, "UID %d ran clearcache", uid);
  closelog();

  if (!has_root_euid()) {
    printf("Insufficient permissions to clear WSDL cache.\n");
  } else {
    printf("Clearing WSDL cache: rm -f /tmp/wsdl*\n");
    setuid(0);
    retval = system("rm -f /tmp/wsdl*");
    setuid(uid);
    printf("System returns (%d). \n", retval);
  }
  return 0;
}

相关内容