systemd具有未知的DynamicUser UID

时间:2018-10-11 08:44:15

标签: systemd

问题

systemd具有DynamicUser功能,请参见https://www.freedesktop.org/software/systemd/man/systemd.exec.html#DynamicUser=

我还使用:PermissionsStartOnly=true来更改权限,因为这需要root用户。

但是,尽管ExecStart知道该动态用户的正确UID,但是ExecStartPostExecStartPre却不知道,因为它们是以root用户身份运行(UID = 0),因此我不知道怎么穿。

希望:我想使用systemd的动态用户方面,但是在不知道UID的情况下我无法整理文档,因此动态用户可以访问它们。

问题

systemd中还有其他可用于将文件权限映射到此临时用户的东西吗?

使用“静态”用户的代码:

acmeSupplied = fold (identifier: con: if (config.nixcloud.TLS.certs.${identifier}.mode) == "ACME" then con ++ [
  (nameValuePair "nixcloud.TLS-acmeSupplied-${identifier}" (let
    c = config.nixcloud.TLS.certs.${identifier};
    allDomains = concatMapStringsSep " " (x: "--domains=${x}") ( [ c.domain ] ++ c.extraDomains);
    email = if (isString c.email) then c.email else "info@${c.domain}";
    hash = hashIdentifierACMEOptions identifier;
  in {
    description = "nixcloud.TLS: create acmeSupplied certificate for ${identifier}";
    preStart = ''
      mkdir -p ${stateDir}/${identifier}/acmeSupplied/${hash}
      chmod 0750 ${stateDir}/${identifier}/acmeSupplied -R
      chown nc-lego:${filterIdentifier identifier} ${stateDir}/${identifier} -R
    '';
    script = ''
      cd ${stateDir}/${identifier}/acmeSupplied
      ${pkgs.nixcloud.lego}/bin/lego ${allDomains} --email=${email} --exclude=dns-01 --exclude=tls-alpn-01 --webroot=/run/nixcloud/lego/${identifier}/challenges --path=${stateDir}/${identifier}/acmeSupplied/${hash} --accept-tos --server=${c.acmeApiEndpoint} run
      ${pkgs.nixcloud.lego}/bin/lego ${allDomains} --email=${email} --exclude=dns-01 --exclude=tls-alpn-01 --webroot=/run/nixcloud/lego/${identifier}/challenges --path=${stateDir}/${identifier}/acmeSupplied/${hash} --accept-tos --server=${c.acmeApiEndpoint} renew --days 15
    '';
   postStart = ''
      chown nc-lego:${filterIdentifier identifier} ${stateDir}/${identifier} -R
      chmod 0750 ${stateDir}/${identifier}/acmeSupplied -R
    '';
    serviceConfig = {
      #DynamicUser = true;
      User = "nc-lego";
      ReadWritePaths = "-${stateDir}/${identifier}/acmeSupplied";
      SupplementaryGroups = "${filterIdentifier identifier}";
      PermissionsStartOnly = true;
      Type = "oneshot";
      RuntimeDirectory = "nixcloud/lego/${identifier}/challenges";
    };
    before = [ "nixcloud.TLS-acmeSupplied-certificates.target" ];
    wantedBy = [ "nixcloud.TLS-acmeSupplied-certificates.target" ];
  }))
] else con) [] (attrNames config.nixcloud.TLS.certs);

带有“ DynamicUser”的代码:

acmeSupplied = fold (identifier: con: if (config.nixcloud.TLS.certs.${identifier}.mode) == "ACME" then con ++ [
  (nameValuePair "nixcloud.TLS-acmeSupplied-${identifier}" (let
    c = config.nixcloud.TLS.certs.${identifier};
    allDomains = concatMapStringsSep " " (x: "--domains=${x}") ( [ c.domain ] ++ c.extraDomains);
    email = if (isString c.email) then c.email else "info@${c.domain}";
    hash = hashIdentifierACMEOptions identifier;
  in {
    description = "nixcloud.TLS: create acmeSupplied certificate for ${identifier}";
    preStart = ''
      mkdir -p ${stateDir}/${identifier}/acmeSupplied/${hash}
      chmod 0750 ${stateDir}/${identifier}/acmeSupplied -R
      chown nixcloud.TLS-acmeSupplied-mail.nix.lt:${filterIdentifier identifier} ${stateDir}/${identifier} -R
    '';
    script = ''
      cd ${stateDir}/${identifier}/acmeSupplied
      ${pkgs.nixcloud.lego}/bin/lego ${allDomains} --email=${email} --exclude=dns-01 --exclude=tls-alpn-01 --webroot=/run/nixcloud/lego/${identifier}/challenges --path=${stateDir}/${identifier}/acmeSupplied/${hash} --accept-tos --server=${c.acmeApiEndpoint} run
      ${pkgs.nixcloud.lego}/bin/lego ${allDomains} --email=${email} --exclude=dns-01 --exclude=tls-alpn-01 --webroot=/run/nixcloud/lego/${identifier}/challenges --path=${stateDir}/${identifier}/acmeSupplied/${hash} --accept-tos --server=${c.acmeApiEndpoint} renew --days 15
    '';
   postStart = ''
      chown nixcloud.TLS-acmeSupplied-mail.nix.lt:${filterIdentifier identifier} ${stateDir}/${identifier} -R
      chmod 0750 ${stateDir}/${identifier}/acmeSupplied -R
    '';
    serviceConfig = {
      DynamicUser = true;
      ReadWritePaths = "-${stateDir}/${identifier}/acmeSupplied";
      SupplementaryGroups = "${filterIdentifier identifier}";
      PermissionsStartOnly = true;
      Type = "oneshot";
      RuntimeDirectory = "nixcloud/lego/${identifier}/challenges";
    };
    before = [ "nixcloud.TLS-acmeSupplied-certificates.target" ];
    wantedBy = [ "nixcloud.TLS-acmeSupplied-certificates.target" ];
  }))
] else con) [] (attrNames config.nixcloud.TLS.certs);

错误消息:

mailserver-nix-lt> updating GRUB 2 menu...
mailserver-nix-lt> activating the configuration...
mailserver-nix-lt> setting up /etc...
mailserver-nix-lt> setting up tmpfiles
mailserver-nix-lt> reloading the following units: dbus.service
mailserver-nix-lt> warning: the following units failed: nixcloud.TLS-acmeSupplied-mail.nix.lt.service
mailserver-nix-lt> 
mailserver-nix-lt> ● nixcloud.TLS-acmeSupplied-mail.nix.lt.service - nixcloud.TLS: create acmeSupplied certificate for mail.nix.lt
mailserver-nix-lt>    Loaded: loaded (/nix/store/i4nxkvw8bf9vs2brhj3lyjakxklq0rxg-unit-nixcloud.TLS-acmeSupplied-mail.nix.lt.service/nixcloud.TLS-acmeSupplied-mail.nix.lt.service; enabled; vendor preset: enabled)
mailserver-nix-lt>    Active: failed (Result: exit-code) since Thu 2018-10-11 10:55:46 CEST; 22ms ago
mailserver-nix-lt>   Process: 20613 ExecStartPre=/nix/store/c69ccjnc2n5y6g1p9q168kjlgf2w3l10-unit-script/bin/nixcloud.TLS-acmeSupplied-mail.nix.lt-pre-start (code=exited, status=1/FAILURE)
mailserver-nix-lt>  Main PID: 20243 (code=exited, status=0/SUCCESS)
mailserver-nix-lt> 
mailserver-nix-lt> Oct 11 10:55:46 mail.nix.lt systemd[1]: Starting nixcloud.TLS: create acmeSupplied certificate for mail.nix.lt...
mailserver-nix-lt> Oct 11 10:55:46 mail.nix.lt nixcloud.TLS-acmeSupplied-mail.nix.lt-pre-start[20613]: chown: invalid user: ‘nixcloud.TLS-acmeSupplied-mail.nix.lt:nc-mail-nix-lt’
mailserver-nix-lt> Oct 11 10:55:46 mail.nix.lt systemd[1]: nixcloud.TLS-acmeSupplied-mail.nix.lt.service: Control process exited, code=exited status=1
mailserver-nix-lt> Oct 11 10:55:46 mail.nix.lt systemd[1]: nixcloud.TLS-acmeSupplied-mail.nix.lt.service: Failed with result 'exit-code'.
mailserver-nix-lt> Oct 11 10:55:46 mail.nix.lt systemd[1]: Failed to start nixcloud.TLS: create acmeSupplied certificate for mail.nix.lt.
mailserver-nix-lt> error: Traceback (most recent call last):
  File "/nix/store/ixarqxfbhr06fp8y8pj5dcm1rhar2j15-nixops-1.6/lib/python2.7/site-packages/nixops/deployment.py", line 731, in worker
    raise Exception("unable to activate new configuration")
Exception: unable to activate new configuration

DynamicUser上的文档所述:

If these options are not used and
           dynamic user/group allocation is enabled for a unit, the name of
           the dynamic user/group is implicitly derived from the unit name.
           If the unit name without the type suffix qualifies as valid user
           name it is used directly, otherwise a name incorporating a hash
           of it is used.

但是这个哈希是什么?

1 个答案:

答案 0 :(得分:1)

  

但是,尽管ExecStart知道该动态用户的正确UID,但 ExecStartPost和ExecStartPre 却不知道,因为它们是作为root用户运行(UID = 0)所以我不知道怎么穿。

我认为这不是真的– ExecStartPre=ExecStartPost=以相同的User=Group=(以及相同的CapabilityBoundingSet=,{{ 1}}等)作为主要可执行文件,除非配置不同(使用SystemCallFilter=+!前缀–参见!!)。我测试了with this test service

  

希望:我想使用systemd的动态用户方面,但是在不知道UID的情况下我无法整理文档,因此动态用户可以访问它们。

这不是必需的。您的服务应将状态存储在其man 5 systemd.service中,将运行时文件存储在其StateDirectory=中,将数据存储在其RuntimeDirectory=中,并登录其CacheDirectory=(如果它具有自己的任何日志记录) –但请考虑使用日志),并从其LogsDirectory=中读取配置(但无论如何该服务均不可写)。 systemd会自动为您管理这些目录的所有权,并且它们遵循标准的UNIX约定(它们是ConfigurationDirectory=/var/lib/run/var/cache,{{ 1}} –有关详细信息,请参见/var/logthis blog post

如果您的守护程序不能仅限于这些标准目录,那么最简单的解决方案可能是不使用/etc –使用静态分配的用户进行更复杂的设置不会有什么可耻的。但是考虑使用man 5 systemd.exec(请参阅DynamicUser=(而不是直接调用systemd-sysusers / man 5 sysusers.d)来创建用户,尤其是在编写分发程序包时,这很明显软件包安装了用户(通过检查哪个软件包拥有各自的adduser配置文件)。