Как я могу написать сценарий удаленного подключения с повышенными правами su? - PullRequest
0 голосов
/ 23 октября 2019

У меня есть сценарии и программы, которые запускают команды на удаленном компьютере, и мне нужно повысить некоторые команды, т.е. su. Поскольку это по сценарию, я не могу рассчитывать на пользователя, чтобы ввести пароль;он должен быть передан в su с помощью сценария.

Я пробовал несколько вещей, включая вывод пароля su следующим образом:

ssh user@host "echo password | su -c myCommand"

и

echo password | ssh user@host su -c myCommand

и в таких языках программирования, как C #, создавая новый процесс и читая его стандартный вывод и записывая пароль в его стандартный ввод.

Я пробовал некоторые альтернативные вещи, которые другие упоминали в Интернете, но они обычно включают команды, которыеУ меня нет на некоторых машинах. У некоторых из них нет expect или sudo или других альтернатив, упомянутых другими.

Как мне это сделать без установки каких-либо других инструментов?


Тег suговорит, что общая поддержка su не по теме, но речь идет не о поддержке или использовании su, а конкретно о проблеме программирования, которая требует повышенного использования su, так что, надеюсь, это не будет не по теме. Пользователям "Linux & Unix" и "Super User" также может быть интересен этот вопрос, но он действительно больше применим к программированию.

1 Ответ

1 голос
/ 23 октября 2019

TL; DR: Использование echo pass | ssh -t -t user@host 'su -c "command"'

Это вызвало у меня головную боль и заняло некоторое время, чтобы понять. В другом месте есть подсказки об ответе, но я нигде не видел явно сформулированного ответа, поэтому потребовалось немного поиграться с ним, чтобы получить право.

Использование ssh

 echo <password> | ssh -t -t <user>@<host> 'su -c "<command>"'

цитаты кажутся необходимыми. Если я пропустил одну или другую пару кавычек, я получил неправильные результаты для некоторых команд. Например, <…> ssh -t -t me@mypc su -c "ls -l /root/something_secure" даст мне содержимое ls домашнего каталога me, игнорируя -l и /root/something_secure. Поэтому мне нужно было настроить кавычки следующим образом.

-t - это то место, где находится магия для наших нужд, и да, вы должны поставить 2 из них. Выполнение echo pass | su -c command может закончиться неудачей, поскольку su не берет пароль от стандартного ввода. Поначалу выполнение echo pass | ssh <…> su -c command кажется хорошей идеей, потому что su необходимо получить ввод из ssh, а ssh получает его из стандартного ввода, но на самом деле su получает его из "tty", а не из стандартного ввода. -t говорит ssh подделать его, используя псевдо-tty, который отправляет стандартный ввод этому поддельному tty. Иногда ssh будет жаловаться и не захочет выделять псевдо-tty для вас, поэтому -t дважды говорит ssh о необходимости заткнуться и сделать это в любом случае.

-t 'Принудительное выделение псевдо-tty,Это может использоваться для выполнения произвольных программ на экране на удаленной машине, что может быть очень полезно, например, при реализации сервисов меню. Несколько опций -t принудительно назначают tty, даже если ssh не имеет локального tty.

From man ssh

Пример:

echo MySecretPass | ssh -t -t me@mydevice 'su -c "chown me /some/file"'

Ssh не имеет параметра пароля. Если вы не настроили безопасный пароль без пароля, вам следует это сделать. Читайте здесь . В противном случае этот ответ предоставит вам пароль для su, но вам все равно придется указать пароль для ssh для первоначального входа в систему через ssh.

Использование plink (ssh-like инструмент командной строки Putty для Windows)

echo <password> | plink -t -t -pw <password> <user>@<host> "su -c '<command>'"

Опять же, цитаты кажутся необходимыми. Если я их пропустил, результаты были неверными, как и в случае использования ssh.

Пример:

echo RootPass | plink -t -t -pw MePass me@mydevice "su -c 'echo Rooty!> /root/rootiness'"

Причина аналогична рассмотренному выше разделу ssh.

Ваш любимый язык программирования

Если ваш любимый язык программирования поддерживает возможность выполнения команды оболочки и управления стандартным вводом / выводом для нее, тогда вместо передачи echo вы можете вместо этоговыполните указанную выше команду ssh или plink (без эхо-сигнала по каналу), затем введите стандартный ввод пароля.

Так же для C #

Process process = new Process();
// If I remember correctly, I think UseShellExecute needs to be false to redirect std in/out
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.RedirectStandardInput = true;
// You can use either ssh or plink; I'll use plink here
process.StartInfo.FileName = "<path to plink>\\plink.exe";
process.StartInfo.Arguments = "-t -t -l " + username + " -pw " + password + " " + hostname + " 'su -c \"MyCommand\"'";
process.StartInfo.CreateNoWindow = true;
process.OutputDataReceived += new DataReceivedEventHandler(FunctionCallbackYouMake);
process.ErrorDataReceived += new DataReceivedEventHandler(AnotherFunctionYouMake);
// I'm not actually sure if this next line is necessary, but I've been using it because of an example I used
process.SynchronizingObject = null;
process.Start();

И затем прочитайте поступающие данныечерез соединение ssh (plink) с помощью функции обратного вызова, которую вы делаете и предоставляете OutputDataReceived. Он имеет вид void f(object sending_process, DataReceivedEventArgs event)

Вы можете записывать данные в process.StandardInput, включая пароль su, например

process.StandardInput.Write(password);
process.StandardInput.Flush();

Я также делал нечто подобное в JavaТак что я знаю, что вы можете делать там почти то же самое, но это было так долго, что я не вспоминаю все детали, но это также включает в себя объект процесса и настройку обработчиков std in / out. Если у меня будет время, я могу включить некоторые из этих деталей.

Независимо от того, какой язык или метод вы используете, некоторые программы могут блокироваться, если они получают слишком много информации в своих выходных потоках или потоках ошибок, поэтому убедитесь, чтовы регистрируетесь как для стандартного вывода, так и для стандартной ошибки, даже если вас это не волнует, даже если все, что вы делаете, это считываете их данные и отбрасываете их.

Но не задавайте пароль жестко!

Поскольку это для программирования, обычно нет необходимости жестко кодировать пароли в скриптах. Вы можете, если вам абсолютно необходимо, но желательно использовать переменные вместо имени пользователя, пароля и имени хоста, чтобы вы были более защищены и ваш инструмент стал более гибким.

Например, у меня есть строка в WindowsCMD, который делает следующее

echo %password% | plink -t -t -pw %password% %username%@%ip% "su -c '<what I want to do goes here>'"

И имя пользователя, пароль и ip предоставляются в качестве аргументов в файл cmd. Также обратите внимание на пример C # выше, они являются переменными.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...