Solicitar privilégio root de dentro de um script


23

Eu tenho um script que pode ser executado como sudo script.shoupkexec script.sh

Seria muito melhor do ponto de vista do usuário se o script pedisse a senha do usuário ao executá-lo apenas pelo nome script.sh.

Como posso "incorporar" a solicitação pkexecou sudoa execução de todo o script com privilégios de root?

Observe que executar tudo com sudo sh -cpode não ser a melhor solução, pois tenho funções no script.

Respostas:


55

Isso vai funcionar:

echo "$(whoami)"

[ "$UID" -eq 0 ] || exec sudo "$0" "$@"

exemplo:

./test.sh 
blade
[sudo] password for blade: 
root

3
O que é bom sobre isso é recursão com exec- chamada em si, mas ao mesmo tempo de processo de substituição, por isso fazemos várias instâncias não desova do script
Sergiy Kolodyazhnyy

1
Recursão ao resgate !!! Lembre-me de adicionar uma recompensa a essa daqui a alguns dias!
Fabby

6
Algo a ter em atenção ao fazer isso é a escalação de privilégios; basicamente, quanto mais comandos você executa como root, mais oportunidades existem para um hacker mal-intencionado explorar algo para obter acesso a uma conta root. Não estou dizendo que é sempre errado fazer com que todo o script seja executado como root, mas vale a pena pensar um pouco antes de decidir fazê-lo. Eu acho que seria bom (embora não seja necessário) se a resposta tocasse nisso.
David Z

Se você tiver um valor de tempo limite decente definido em / etc / sudoers, poderá opcionalmente colocar o sudo na frente de cada comando no script que realmente precisa de acesso root e ele solicitará apenas uma vez. Uma coisa que eu sempre errei é que chamar esse script de uma GUI não funcionará porque o sudo obtém / dev / null para entrada de senha e falha. É com isso que o gksudo e o kdesudo foram projetados para lidar, porque eles usarão o gui para solicitar a senha.
31516 Joe

1
@ Coder256: Não acho que sua edição esteja correta. "$@"expandirá para várias palavras, uma para cada parâmetro.
jwodder

12

Se você quiser um diálogo bonito, tente algo assim. Eu retirei isso de outra coisa que escrevi, então tem coisas extras que você pode não precisar ou querer, mas mostra a ideia geral:

brand="My Software"

# Check that the script is running as root. If not, then prompt for the sudo
# password and re-execute this script with sudo.
if [ "$(id -nu)" != "root" ]; then
    sudo -k
    pass=$(whiptail --backtitle "$brand Installer" --title "Authentication required" --passwordbox "Installing $brand requires administrative privilege. Please authenticate to begin the installation.\n\n[sudo] Password for user $USER:" 12 50 3>&2 2>&1 1>&3-)
    exec sudo -S -p '' "$0" "$@" <<< "$pass"
    exit 1
fi

diálogo sudo

Isso usa whiptail, que você pode instalar se ainda não o tiver:

sudo apt-get install whiptail

1
Por que você está salvando a senha em uma variável?
heemayl

10
Não ligue exec echo [PASSWORD]! Irá gerar um processo com a senha na linha de comando que qualquer usuário pode ver. Use o comando interno ( echoforce a versão builtin echointerna com ) ou o basismo <<<(assim :) sudo ... <<< "$pass"; Sh e outras conchas têm aqui documentos para esses casos. Além disso, cite a senha, caso ela contenha caracteres especiais.
David Foerster

Como alternativa, coloque o whiptailcomando em um script separado e use algo como SUDO_ASKPASS=/path/to/askpass-with-whiptail.sh sudo -A -p "My password prompt" -- "$0" "$@"para sudolidar com o prompt de senha personalizado.
David Foerster

@DavidFoerster Isso pode funcionar, mas você precisa de dois scripts ou escreve seu script askpass em um arquivo temporário e passa-o para o sudo.
Michael Hampton

Ok, no entanto, outros já observaram que é indesejável passar a senha para uma variável. A abordagem maneira id esta é passar saída do diálogo para pipe nomeado como mostrei aqui askubuntu.com/a/704643/295286
Sergiy Kolodyazhnyy

11

A resposta de blade19899 é realmente o caminho a percorrer, no entanto, também se pode chamar sudo basho shebang:

#!/usr/bin/sudo bash
# ...

A ressalva óbvia é que isso funcionará apenas enquanto o script for chamado ./scripte falhará assim que o script for chamado bash script.


5
Esse é um dos motivos pelos quais você nunca deve digitar bash scriptna linha de comando para chamar um script. Se o script especificar algo diferente bashda #!linha, a chamada com bash scriptfalhará. Se eu tentasse invocar um script python usando bash script.pyele também falharia.
kasperd

1
Você pode executá-lo com perl script, no entanto. O Perl, em um esforço para ser realmente muito bom, verifica a linha shebang e, se não está invocando o perl, executa o programa correto.
tbodt

Isso é ruim porque está executando todos os comandos no script com sudo. É melhor isolar os poucos comandos que realmente precisam do sudo e adicioná-los quando necessário. Não inclua a avaliação de funções nessas chamadas de sudo; elas devem ser o mais claras e mínimas possível.
Douglas Held

@DouglasHeld Embora eu possa concordar com isso, é isso que a pergunta está pedindo: "Como posso" incorporar "a solicitação ao pkexec ou ao sudo para executar o script inteiro com privilégios de root?". Certamente haveria casos de uso nos quais ser capaz de fazer isso seria útil.
kos

6

Prefácio os comandos dentro do script que precisam de acesso root sudo- se o usuário ainda não obteve permissões, o script solicita uma senha nesse ponto.

exemplo

#!/bin/sh 
mem=$(free  | awk '/Mem:/ {print $4}')
swap=$(free | awk '/Swap:/ {print $3}')

if [ $mem -lt $swap ]; then
    echo "ERROR: not enough RAM to write swap back, nothing done" >&2
    exit 1
fi

sudo swapoff -a && 
sudo swapon -a

Este script pode ser executado como sudo <scriptname>ou como <scriptname>. Nos dois casos, ele solicitará a senha apenas uma vez.


2
O problema aqui é que pode haver vários comandos que precisam de acesso root, o que significa chamar sudo25 comandos diferentes redundantes - é mais fácil chamar sudo uma vez. Aqui, no entanto, o motivo pelo qual o script chama sudo apenas uma vez é porque o sudo tem um tempo de 15 minutos - comandos que demoram mais do que isso precisam ser re-solicitados. Seu caminho funciona apenas. . . não da maneira que eu preciso para funcionar.
31815 Sergi Kolodyazhnyy

@Serg Para um script pequeno, o jeito que eu tinha era rápido e fácil - eu realmente não sou um programador elegante!
Charles Green

Você é o melhor postador de programador nesta página. Você está usando o sudo exatamente como deveria ser usado - somente onde necessário e com resultados muito claros esperados.
Douglas Held

4

Parece que ninguém mais abordou a preocupação óbvia aqui. A inserção do sudoscript que você distribui promove maus hábitos do usuário . (Suponho que você esteja distribuindo porque menciona "do ponto de vista do usuário".)

A verdade é que há uma diretriz no uso de aplicativos e scripts semelhante ao princípio de segurança do banco: Nunca forneça suas informações pessoais a alguém que ligue para você e diga que está ligando "do seu banco" e que exista por razões semelhantes.

A regra para aplicativos é:

Nunca digite sua senha quando solicitado, a menos que tenha certeza do que está sendo feito. Isso se aplica triplamente a qualquer pessoa com sudoacesso.

Se você estiver digitando sua senha porque executou sudona linha de comando, ótimo. Se você está digitando porque executou um comando SSH, tudo bem. Se você está digitando quando faz login no seu computador, ótimo, é claro.

Se você acabou de executar um script estrangeiro ou executável e digitar sua senha de forma discreta quando solicitado, não terá idéia do que o script está fazendo com ele. Poderia estar armazenando-o em um arquivo temporário em texto sem formatação, pelo que você sabe, e pode até falhar na limpeza depois de si próprio.

Obviamente, existem preocupações separadas e adicionais sobre a execução de um conjunto desconhecido de comandos root, mas o que estou falando aqui é manter a segurança da própria senha . Mesmo supondo que o aplicativo / script não seja malicioso, você ainda deseja que sua senha seja manipulada com segurança para impedir que outros aplicativos o sigam e usem maliciosamente.

Portanto, minha resposta pessoal a isso é que a melhor coisa a ser inserida no seu script se ele precisar de privilégios de root é:

#!/bin/bash
[ "$UID" -eq 0 ] || { echo "This script must be run as root."; exit 1;}

# do privileged stuff, etc.

Embora eu concorde totalmente com você, um usuário que executa algo sem saber o que faz e como sudo script_nameé vulnerável, é o mesmo. Talvez essa idéia promova maus hábitos - não vou dizer nada sobre isso. Mas a chave é saber o que um programa faz, e isso é responsabilidade do usuário. Essa é a idéia por trás do software de código aberto. Quanto ao meu próprio roteiro, bem. . . um script é texto simples - os usuários podem lê-lo se eles querem saber o que ele faz
Sergiy Kolodyazhnyy

@SergiyKolodyazhnyy é semelhante, mas se você digitar sua senha diretamente no script, é realmente pior. Um script executado com sudo ainda não sabe sua senha.
Wildcard

1

Eu fiz assim:

echo -n "Enter password for sudo rights: "
read -s pass

echo $pass | sudo -S [your command here]

4
Cite pelo menos suas variáveis.
Muru

E citar suas variáveis pode nem ajudar se sua senha começar com um hífen.
Curinga
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.