Reiniciando o serviço systemd apenas como um usuário específico?

9

Eu criei alguns serviços systemd que basicamente funcionam:

localização:

/etc/systemd/system/multi-user.target.wants/publicapi.service

conteúdo:

[Unit]
Description=public api startup script

[Service]
Type=oneshot
RemainAfterExit=yes
EnvironmentFile=-/etc/environment
WorkingDirectory=/home/techops
ExecStart=/home/techops/publicapi start
ExecStop=/home/techops/publicapi stop

[Install]
WantedBy=multi-user.target

Quando tento reiniciar o serviço como usuário techops na linha de comando, obtenho a seguinte saída:

==== AUTHENTICATING FOR org.freedesktop.systemd1.manage-units ===
Authentication is required to start 'publicapi.service'.
Multiple identities can be used for authentication:
 1.  Myself,,, (defaultuser)
 2.  ,,, (techops)
Choose identity to authenticate as (1-2):

Quero que apenas os techops possam reiniciar os serviços e que esse prompt não apareça ao fazer login como techops. Como eu posso fazer isso?

Eu li que existem abordagens diferentes com o polkit-1 ou sudoers, mas não tenho certeza.

[ATUALIZAÇÃO] 27/01/2019 16:40
Obrigado por esta resposta abrangente a Thomas e Perlduck. Isso me ajudou a melhorar meu conhecimento do systemd.

De acordo com a abordagem para iniciar o serviço sem um prompt de senha, quero pedir desculpas por não enfatizar o problema real o suficiente:

Na verdade, o mais importante para mim é que nenhum outro usuário que não seja o techops deve parar ou iniciar o serviço. Mas, pelo menos nas duas primeiras abordagens, ainda posso executar service publicapi stope recebo o prompt ==== AUTHENTICATING FOR org.freedesktop.systemd1.manage-units ===novamente. Quando escolho o usuário padrão e conheço a senha, pude parar todos os serviços. Quero negar que esse usuário faça isso, mesmo que ele tenha a senha . Informações importantes de plano de fundo para entender melhor por que essa é a parte mais importante para mim:
O usuário padrão é o único usuário exposto ao ssh, mas esse usuário não pode fazer mais nada (exceto mudar para outros usuários, se você tiver a senha desses outros usuários) . Mas, no momento, ele pode iniciar ou interromper os serviços, mas esse usuário não deve fazer isso.
Se alguém obtiver a senha do defaultuser e efetuar login via ssh, ele poderá interromper todos os serviços no momento. Isto é o que eu quis dizer com "Eu quero que apenas os técnicos possam reiniciar os serviços". Desculpe, eu não era tão exato na minha pergunta inicial. Eu pensei que sudo o usuário techops talvez ignorasse esse problema, mas não. O problema em si não é executar o comando sem o prompt da senha. (Eu poderia facilmente fazer isso como usuário do techops quando apenas executar /home/techops/publicapi start). O problema em si é impedir que o usuário padrão inicie esses serviços.

E eu esperava que qualquer uma das soluções pudesse fazer isso.

Comecei com as abordagens de Thomas. A abordagem com o sudo funciona quando não quero que a senha dos techops do usuário seja solicitada quando executo os comandos conforme explicado, por exemplo

sudo systemctl start publicapi.service
sudo systemctl stop publicapi.service

A segunda abordagem ainda não funciona para mim. Não consigo iniciar o serviço sem o prompt de senha ==== AUTHENTICATING FOR org.freedesktop.systemd1.manage-units ===e a interrupção pode fazer login como usuário padrão quando tenho a senha deste usuário.

Com a terceira abordagem, o serviço nem inicia mais no processo de inicialização, por isso não tenho certeza se essa abordagem é a correta para mim. Não consigo nem com o systemctl enable publicapi.serviceque me leva ao seguinte erro:

Failed to enable unit: Unit file mycuisine-publicapi.service does not exist.

O erro não ocorre quando eu movo todos os serviços novamente para / etc / systemd / system / e executo systemctl enable publicapi.service. Em seguida, o serviço é iniciado novamente na inicialização.

Todas essas abordagens ajudarão mais ou menos a ignorar o prompt de senha do usuário do techops, mas quando executo service publicapi stopou systemctl stop publicapi com o usuário padrão , posso interromper os serviços se tiver a senha. Mas meu objetivo é impedir que o usuário padrão inicie ou interrompa os serviços.

Bevor
fonte
1
Para a terceira abordagem, você deve executar systemctl --user ...como usuário e techopsnão como root. Nem a minha sugestão, nem a um dos @PerlDuck dá quaisquer sudodireitos ao seu defaultuser mas apenas para o TechOps usuário.
Thomas
1
O usuário padrão está configurado como sudo? Nesse caso, você deve remover o usuário de grupos secundários e verificar seu /etc/sudoersarquivo se houver uma referência para esse usuário.
Thomas
@ Thomas Ah, é isso. Funciona como esperado agora. Obrigado.
Bevor

Respostas:

17

Para conseguir que o usuário techopspossa controlar o serviço publicapi.servicesem fornecer uma senha, você tem diferentes possibilidades. Qual deles é adequado para você não pode ser respondido, pois você deve escolher por si mesmo.


A sudoabordagem clássica é talvez a mais utilizada, pois existe há muito tempo. Você precisaria criar, por exemplo, o arquivo da seguinte maneira.
Observe que o diretório drop-in /etc/sudoers.destá ativo apenas quando #includedir /etc/sudoers.destá definido /etc/sudoers. Mas esse deve ser o caso se você estiver usando uma distribuição moderna do Ubuntu. Como rootexecutar:

cat > /etc/sudoers.d/techops << SUDO
techops ALL= NOPASSWD: /bin/systemctl restart publicapi.service
techops ALL= NOPASSWD: /bin/systemctl stop publicapi.service
techops ALL= NOPASSWD: /bin/systemctl start publicapi.service
SUDO

Agora você deve poder executar os systemctlcomandos como usuário techopssem fornecer uma senha, acrescentando sudo-os aos comandos.

sudo systemctl start publicapi.service
sudo systemctl stop publicapi.service
sudo systemctl restart publicapi.service

O segundo método seria usar o PolKit (renomeado para PolicyKit ) para permitir que o usuário techopscontrole systemdserviços. Dependendo da versão polit, você pode fornecer aos usuários normais o controle sobre as unidades do systemd.
Para verificar a versão do polkit , basta executar pkaction --version.

  • com o polkit versão 0.106 e superior , você pode permitir que os usuários controlem unidades específicas do sistema.
    Para fazer isso, você pode criar uma regra como root:

    cat > /etc/polkit-1/rules.d/10-techops.rules << POLKIT
    polkit.addRule(function(action, subject) {
        if (action.id == "org.freedesktop.systemd1.manage-units" &&
            action.lookup("unit") == "publicapi.service" &&
            subject.user == "techops") {
            return polkit.Result.YES;
        }
    });
    POLKIT
    
  • com o polkit versão 0.105 e inferior : você pode permitir que os usuários controlem as unidades do systemd. Infelizmente, isso inclui todas as unidades systemd e talvez você não queira fazer isso. Não tenho certeza se existe uma maneira de limitar o acesso a unidades específicas do sistema com a versão 0.105 ou inferior, mas talvez alguém possa esclarecer.
    Para habilitar isso, você pode criar um arquivo como root:

    cat > /etc/polkit-1/localauthority/50-local.d/org.freedesktop.systemd1.pkla << POLKIT
    [Allow user techops to run systemctl commands]
    Identity=unix-user:techops
    Action=org.freedesktop.systemd1.manage-units
    ResultInactive=no
    ResultActive=no
    ResultAny=yes
    POLKIT
    

Nos dois casos, você pode executar systemctl [start|stop|restart] publicapi.servicecomo usuário techopssem fornecer uma senha. No último caso (polkit <= 0.105), o usuário techopspode controlar qualquer unidade systemd.


Uma terceira opção seria fazer o serviço de um serviço de usuário, que não precisa sudoou polkitconfigurações. Isso coloca tudo sob o controle do usuário e só funciona se o serviço real iniciado com /home/techops/publicapi startpode executar sem rootprivilégios.

Primeiro, você precisa ativar o tempo restante para o usuário techops. Isso é necessário para iniciar o serviço do usuário na inicialização. Como rootexecutar:

loginctl enable-linger techops

Em seguida, você deve mover o systemdarquivo da unidade para o techopsdiretório do usuário. Como usuário, techopsexecute os comandos da seguinte maneira.

mkdir -p ~/.config/systemd/user

cat > ~/.config/systemd/user/publicapi.service << UNIT
[Unit]
Description=public api startup script

[Service]
Type=oneshot
RemainAfterExit=yes
EnvironmentFile=-/etc/environment
WorkingDirectory=/home/techops
ExecStart=/home/techops/publicapi start
ExecStop=/home/techops/publicapi stop

[Install]
WantedBy=default.target
UNIT

Observe que WantedBydeve ser o default.targetque não existe multi-user.targetno contexto do usuário.

Agora recarregue a configuração e ative o serviço. Novamente como usuário techopsexecute os comandos.

systemctl --user daemon-reload
systemctl --user enable publicapi.service
systemctl --user start publicapi.service

Em geral, você deve colocar suas unidades systemd /etc/systemd/system/não diretamente /etc/systemd/system/multi-user.target.wants. Quando você executa, systemctl enable publicapi.serviceum link simbólico será criado etc/systemd/system/multi-user.target.wantsou o destino especificado para essa unidade.

Como já mencionado, se o serviço / processo em si puder ser executado sem privilégios de root, considere adicionar User=techopsao seu arquivo de unidade para executar o processo com uma conta de usuário não privilegiada.

Thomas
fonte
Muito bom. Você até pensou no destino WantedBy diferente para as unidades de usuário. Obviamente, este não é o primeiro arquivo de unidade que você escreveu :-)
PerlDuck
Tanques @PerlDuck. = 0)
Thomas
Obrigado pela sua resposta. Isso parcialmente responde à minha pergunta, mas ainda tenho o meu problema inicial. (Atualizei a pergunta)
Bevor
Desculpe, por .pklanão funcionar. Isso precisa de uma [section]entrada. Resposta atualizada.
Thomas
5

Primeiro de tudo, você não coloca um arquivo de unidade no diretório /etc/systemd/system/multi-user.target.wants. Este diretório é mantido por systemde pelos systemctlcomandos. Coloque o arquivo da unidade /etc/systemd/systeme ative-o com

sudo systemctl enable publicapi.service

Isso criará um link simbólico abaixo multi-user.target.wants(ou onde quer que você systemctlsaiba) para honrar as linhas

[Install]
WantedBy=multi-user.target

na unidade.

Em seguida, crie um sudoersarquivo abaixo /etc/sudoers.d:

sudo visudo -f /etc/sudoers.d/techops

com o seguinte conteúdo:

Cmnd_Alias HANDLE_PUBLICAPI = \
    /bin/systemctl start   publicapi.service \
    /bin/systemctl stop    publicapi.service \
    /bin/systemctl restart publicapi.service

techops ALL = (root) NOPASSWD: HANDLE_PUBLICAPI

Não use um editor comum (por exemplo sudo vim /etc/sudoers.d/techops) para editar esse arquivo, porque se você colocar algum erro de sintaxe, não poderá executar sudonovamente. visudopor outro lado, verifica a sintaxe do arquivo antes de sair do editor.

Agora o usuário techopspode executar

sudo systemctl start publicapi.service

e os outros dois sem fornecer uma senha. Observe que você deve digitar o comando e os parâmetros exatamente como fornecido no sudoersarquivo (exceto a /bin/systemctlparte que pode ser reduzida para apenas systemctl).

Por exemplo, sudo /bin/systemctl start publicapi(sem .service) solicitaria uma senha.

PerlDuck
fonte