У меня есть ситуация, когда я хотел бы поднять права, которые у меня есть в веб-среде, чтобы я мог получить доступ к последовательному устройству.
В конкретном случае у меня есть веб-интерфейс для настройки модема, который появляется на /dev/ttyUSB[0-9]
.
Ноль или более модемов будут подключены конечным пользователем. Я пишу какое-то программное обеспечение, способное распознавать USB-модем, читая /sys/devices
и разговаривая с модемом, используя некоторые AT-команды.
Я хотел бы открыть устройство и сделать что-то вроде:
ser = serial.Serial(tty, baudrate=115200, timeout=10)
ser.write('AT+CGSN\r\n')
imei = ser.readline()
Проблема заключается в том, что pyserial
делает это: self.fd = os.open(self.portstr, os.O_RDWR|os.O_NOCTTY|os.O_NONBLOCK)
, чтобы открыть последовательный порт, где portstr /dev/ttyUSB0
, но он делает это как пользователь nobody
, который непривилегирован.
Последовательные порты этой системы принадлежат root: uucp и установлены как 0660 (т.е. rw-rw----
).
Каков наилучший способ для пользователя, такого как nobody
, у кого должно быть как можно меньше разрешений, чтобы открыть файл в dev?
Идеи, которые я буду рассматривать:
sudo
./dev/
(инструкции по правильному использованию udev оценены!)Настроить правило udev, чтобы chgrp нового устройства никому, если приемлемо, чтобы каждому доступу через веб-интерфейс разрешался тот же доступ к устройству. Вот что я вложил в свой пакет eee-bpw в файл /etc/udev/rules.d/99-bpw.rules.
# Sierra Wireless AirCard 880 U
BUS=="usb", KERNEL=="ttyUSB2*", ACTION=="add", \
PRODUCT=="1199/6855/0", DEVNAME=="/dev/tts/USB2", \
OWNER="root", GROUP="dialout", \
SYMLINK+="bpw", RUN="/usr/sbin/bpw"
Заменить кого-либо для dialout. В этом конкретном правиле предполагается, что имя устройства будет /dev/ttyUSB 2, но вы можете значительно расширить это правило, см. Документацию udev.
Есть и другой способ: Unix/Linux позволяет отправлять дескрипторы файлов через сокеты Unix. Там даже модуль Perl для этого: PassAccessRights.pm. Не удалось найти аналогичный модуль для Python, но его можно было легко реализовать.
В этом случае я бы написал демон, который запускал системный пользователь, который принимал сокетные соединения и передавал их на соответствующее устройство, а затем использовал сокеты в веб-приложении для общения с демоном. Это также помогает блокировать веб-приложение при открытии устройства, которое не совсем готово к работе с пользователями, разрешить блокировки немного более безопасно, чем вы могли бы с CGI и т.д.
Однако, если вы хотите предоставить приложению возможность напрямую общаться с устройствами, дайте им те же разрешения, что и null.
"Каков наилучший способ для пользователя, такого как никто, у кого должно быть как можно меньше разрешений, чтобы открыть файл в dev?"
На самом деле вам лучше использовать mod_wsgi в демонском режиме для вашего веб-приложения. Пользователь mod_wsgi может быть любым пользователем (и группой), которое вы предоставляете.
Вы можете работать как пользователь с соответствующими правами.
См. http://code.google.com/p/modwsgi/wiki/ConfigurationDirectives#WSGIDaemonProcess
Идея sudo может быть возможна. IIRC, вы можете установить определенные команды для использования, но не требуя пароля.
Другой вариант - поставить nobody
в группу, которая имеет доступ к требуемому устройству, или запустить Apache как группу, которая имеет доступ.
Если вы используете fastcgi (или equiv), я думаю, вы можете запустить скрипты как владеющий пользователь (некоторые общие хосты делают это).
Чтобы изменить разрешения файлов в /dev
, просто chmod.