1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
|
.. _sudo:
Using Sudo
==========
There are 3 ways of using ``sudo`` to execute commands in your script. These
are listed in order of usefulness and security. In most cases, you should just
use a variation of :ref:`contrib_sudo`.
.. _contrib_sudo:
sh.contrib.sudo
---------------
Because ``sudo`` is so frequently used, we have added a contrib version of the
command to make sudo usage more intuitive. This contrib version is simply a
wrapper around the :ref:`sudo_raw` raw command, but we bake in some
:ref:`special keyword argument <special_arguments>` to make it well-behaved. In
particular, the contrib version allows you to specify your password at execution
time via terminal input, or as a string in your script.
Terminal Input
^^^^^^^^^^^^^^
Via a :ref:`with context <with_contexts>`:
.. code-block:: python
import sh
with sh.contrib.sudo:
print(ls("/root"))
Or alternatively via :ref:`subcommands <subcommands>`:
.. code-block:: python
import sh
print(sh.contrib.sudo.ls("/root"))
Output:
.. code-block:: none
[sudo] password for youruser: *************
your_root_files.txt
In the above example, ``sh.contrib.sudo`` automatically asks you for a password
using :func:`getpass.getpass` under the hood.
This method is the most secure, because it lowers the chances of doing something
insecure, like including your password in your python script, or by saying that
a particular user can execute anything inside of a particular script (the
NOPASSWD method).
.. note::
``sh.contrib.sudo`` does not do password caching like the sudo binary does.
Thie means that each time a sudo command is run in your script, you will be
asked to type in a password.
String Input
^^^^^^^^^^^^
You may also specify your password to ``sh.contrib.sudo`` as a string:
.. code-block:: python
import sh
password = get_your_password()
with sh.contrib.sudo(password=password, _with=True):
print(ls("/root"))
.. warning::
This method is less secure because it becomes tempting to hard-code your
password into the python script, and that's a bad idea. However, it is more
flexible, because it allows you to obtain your password from another source,
so long as the end result is a string.
/etc/sudoers NOPASSWD
---------------------
With this method, you can use the raw ``sh.sudo`` command directly, because
you're being guaranteed that the system will not ask you for a password. It
first requires you set up your user to have root execution privileges
Edit your sudoers file:
.. code-block:: none
$> sudo visudo
Add or edit the line describing your user's permissions:
.. code-block:: none
yourusername ALL = (root) NOPASSWD: /path/to/your/program
This says ``yourusername`` on ``ALL`` hosts will be able to run as root, but
only root ``(root)`` (no other users), and that no password ``NOPASSWD`` will be
asked of ``/path/to/your/program``.
.. warning::
This method can be insecure if an unprivileged user can edit your script,
because the entire script will be exited as a privileged user. A malicious
user could put something bad in this script.
.. _sudo_raw:
sh.sudo
-------
Using the raw command ``sh.sudo`` (which resolves directly to the system's
``sudo`` binary) without NOPASSWD is possible, provided you wire up the special
keyword arguments on your own to make it behave correctly. This method is
discussed generally for educational purposes; if you take the time to wire up
``sh.sudo`` on your own, then you have in essence just recreated
:ref:`contrib_sudo`.
.. code-block:: python
import sh
# password must end in a newline
my_password = "password\n"
# -S says "get the password from stdin"
my_sudo = sh.sudo.bake("-S", _in=my_password)
print(my_sudo.ls("root"))
_fg=True
--------
Another less-obvious way of using sudo is by executing the raw ``sh.sudo``
command but also putting it in the foreground. This way, sudo will work
correctly automatically, by hooking up stdin/out/err automatically, and by
asking you for a password if it requires one. The downsides of using
:ref:`_fg=True <fg>`, however, are that you cannot capture its output -- everything is
just printed to your terminal as if you ran it from a shell.
.. code-block:: python
import sh
sh.sudo.ls("/root", _fg=True)
|