LINUX.ORG.RU

Как лучше передать данные доступные только root'у в Java-процесс?

 ,


0

1

Есть сервис написанный на Java. Работать он должен без прав root’а. Как этот сервис может получить данные доступ к которым есть только у root’а? Допустим что эти данные в процессе работы сервиса не меняются.

Например, можно было бы запускать сервис с правами root’а, а по завершению инициализации переключиться на нужного пользователя, но судя по всему в Java нет стандартных средств для переключения пользователя. Можно написать скрипт который будет запускать Java-сервис и передавать ему данные в каком-нибудь формате, например, на stdin. Есть еще варианты?


сделать второй сервис, работающий от рута, экспортировать данные из него в сервис на java

bvn13 ★★★★★
()
Ответ на: комментарий от bvn13

Во втором сервисе придется решать вопросы с несанкционированным доступом. Хочется иметь в меру простое и безопасное решение.

ricie
() автор топика
Последнее исправление: ricie (всего исправлений: 1)
Ответ на: комментарий от ricie

Через environment. Заведи отдельного пользователя для своего сервиса и напиши systemd.service, который будет его запускать:

[Unit]
Description=My java service

[Service]
Type=simple
ExecStart=/usr/bin/env java -jar /opt/myjava/service.jar
EnvironmentFile=-/etc/default/myjavaservice
User=myjavaservice

[Install]
WantedBy=multi-user.target

А в /etc/default/myjavaservice напиши SECRET=123 и поставь права 0600 и рута владельцем.

Если systemd свежий, то можно сделать ещё лучше — DynamicUser=yes.

kmeaw ★★★
()

Посмотри, можно ли твои данные через capabilities получать. Скорее всего, полный рут тебе не нужен.

hateyoufeel ★★★★★
()
Ответ на: комментарий от ricie

т.е. приложение должно отдать эти данные только определенному процессу ?? так сразу бы и сказал.
в проге, считывающие необходимые данные под рутом, считывать PPID (Parent Process ID), смотреть по нему кто вызвал прогу и соответственно ответить.
у бинаря проги соответственно владелец root и setuid.

можно через судо накостылить желаемое.

pfg ★★★★★
()
Последнее исправление: pfg (всего исправлений: 1)

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

В любом же случае кто-то должен иметь права root (пусть и на короткое время), чтобы эти данные прочитать. Почему бы их не писать в БД (на свой вкус и задачу), а потом авторизуясь читать в Java?! БД выступит в качестве прокси, а процессы останутся каждый в своей песочнице.

Stack77
()

Через Unix-сокет возможно передать открытый дескриптор другому процессу.

Arlecchino ★★
()
Ответ на: комментарий от hateyoufeel

Мне нужно прочитатать несколько файлов, доступных только root’у, и вывод команды, доступной опять же только root’у. Я так понимаю capabilities здесь не поможет.

ricie
() автор топика

commons-daemons умеет downgrading user. Если не хочется завязываться на systemd, это самый разумный вариант.

Legioner ★★★★★
()
Последнее исправление: Legioner (всего исправлений: 3)
Ответ на: комментарий от ricie

Во втором сервисе придется решать вопросы с несанкционированным доступом. Хочется иметь в меру простое и безопасное решение.

Ну, а как еще просто и безопасно сделать? Вы же безопасность в первую очередь ставите. Я бы вынес простую БД типа «ключ-значение» удаленно с авторизацией. Первый процесс в неё пишет в нужный момент, второй читает когда хочет.

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

Распределение прав для того и создано, чтобы ограничить доступ. Socket, fifo, shared memory, etc спорное решение, это не даст гарантии безопасности. ИМХО.

Stack77
()
Ответ на: комментарий от pfg

т.е. приложение должно отдать эти данные только определенному процессу ?? так сразу бы и сказал.

По-моему и так очевидно что данные, доступ к которым есть только у root’а, нельзя отдавать кому попало.

ricie
() автор топика
Последнее исправление: ricie (всего исправлений: 1)
Ответ на: комментарий от Stack77

Хотя, в Вашем случае, если базу от root запускать и основной пишущий процесс тоже root, то можно и на одной машине в принципе. Другой процесс будет по авторизации доступ получать. Только же ключи или пароль к БД в шифрованном виде хранить обязательно.

Это мое мнение, конечно, но сомневаюсь, что кто-то предложит более безопасный способ проксирования данных разных прав доступа.

Stack77
()
Ответ на: комментарий от Stack77

Ну, а как еще просто и безопасно сделать? Вы же безопасность в первую очередь ставите. Я бы вынес простую БД типа «ключ-значение» удаленно с авторизацией. Первый процесс в неё пишет в нужный момент, второй читает когда хочет.

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

Распределение прав для того и создано, чтобы ограничить доступ. Socket, fifo, shared memory, etc спорное решение, это не даст гарантии безопасности. ИМХО.

Приведу пример - httpd имеет родительский процесс который работает с правами root’а, а дочерние процессы, обрабатывающие запросы, работают с правами apache. Вроде на безопасность не жалуются.

ricie
() автор топика
Ответ на: комментарий от ricie

Если родитель форкает, то естественно дочерний процесс получит некоторые данные от родителя. Но, если у Вас стоит Nginx, к примеру, и через сокет вызывает apache, то apache получит только те данные, которые были переданы по сокету и доступа к root данным у него не будет (если он конечно, не состоит в группе).

Stack77
()
Ответ на: комментарий от ricie

в разных системах/сборках разный уровень безопасности и доверия к разным частям даже самой ос :)
множество рутовых данных доступно на чтение любому пользователю потому, что чтение не создает дырки в безопасности. хотя и при хитроумном использовании может и не такое произойти :)
полностью защищенная система не имеет связи с внешним миром.

я лишь предложил вынести чтение рутовых данных в отдельный бинарь и через стандартный метод setuid наделить сей бинарь возможностью запускаться от рута, плюс прикостылить защиту связи (согласен примитивную) между основной и рутовой программами.
вариантов вообще много, вплоть до модулей ядра с интерфейсом в /sys /dev

pfg ★★★★★
()
Ответ на: комментарий от ricie

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

если тебе нужно всего один раз при старте программы сделать чтото от рута, то в системд для этого есть опции.

pfg ★★★★★
()
Ответ на: комментарий от pfg

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

Не только порт открыть. В случае SSL/TLS файл с приватным ключом обычно только root может читать.

ricie
() автор топика
Ответ на: комментарий от pfg

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

Вынести чтение в отдельную программу я и сам предложил в посте открывающем тему:

Можно написать скрипт который будет запускать Java-сервис и передавать ему данные в каком-нибудь формате, например, на stdin.

ricie
() автор топика

Так может эти файлы и не должны быть доступны только руту в данном случае? Начзначь соответствующие права и группу, да и всё. Или можешь костылтнуть, прописав нужное в sudoers, да вызывать с sudo костыль, который передаст данные твоей проге, хотя бы тупо через stdout.

WitcherGeralt ★★
()
Ответ на: комментарий от ricie

Приведу пример - httpd имеет родительский процесс который работает с правами root’а, а дочерние процессы, обрабатывающие запросы, работают с правами apache. Вроде на безопасность не жалуются.

это делается через понижение привилегий. родительский процесс запускается от рута, форкается, затем в дочернем процессе понижает сам себе привилегии до нужных. как это в джаве сделать - ну хз. это тебе жвм наверное надо запустить ещё одну, потом посмотри в сторону setuid(), setgid().

anonymous
()
Ответ на: комментарий от ricie

ну к примеру такой вариант скрипта для головного системд. ExecStartPre выполняется от root, ExecStart выполняется от user/group. записывать в какойнить файлик в /run/ с правильными правами, и «после прочтения сжечь» :)

[Service]
User=%user%
Group=%group%

PermissionsStartOnly=yes
ExecStartPre=/path/bin/save_root_to_file

ExecStart=/path/bin/my_exec

правда PermissionsStartOnly недавно объявлен устаревшим, и заменен на префикс к исполняемому пути, но я этого пока не читал :(. пока в режиме поддержки legacy работает и ладно.

pfg ★★★★★
()
Последнее исправление: pfg (всего исправлений: 2)

Ты хочешь странного. Можно вызывать из твоего сервиса sudo cat secretfile и добавить в sudoers пользователя, под которым запускается сервис, и что ему можно запускать команду cat secretfile без пароля. Таки образом сервис получает не всего рута, а лишь чтение этого файла. Однако, то, что файл доступен только из под рута намекает на то, что его содержимое ценно и не стоит давать к нему доступ кому зря, а тут мы получается дали доступ некоему сервису, которому не особо доверяем, выглядит как будто мы создали дырку в безопасности. Хотелось бы все же деталей о том что за задача решается

cobold ★★★★★
()
Ответ на: комментарий от anonymous

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

Как это делается в нативных приложениях я знаю.

как это в джаве сделать - ну хз.

А вот как такое делают в джаве хотелось бы понять.

ricie
() автор топика
Ответ на: комментарий от ricie

Может быть сделать тоже самое через Jni ?

anonymous
()
Ответ на: комментарий от cobold

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

С чего вы решили что этому сервису не особо доверяют? Принцип минимальных привилегий. Здесь уже приводился пример с httpd, который стартует от root’a, а затем понижает свои привилегии.

ricie
() автор топика
Ответ на: комментарий от Legioner

commons-daemons умеет downgrading user. Если не хочется завязываться на systemd, это самый разумный вариант.

Спасибо, интересный вариант.

ricie
() автор топика

Есть еще варианты?

Я бы просто писал нужные данные в рутовом процессе в виде файлов на диск в папку «/tmp/», а из пользовательского процесса читал бы эти файлы и удалял их после прочтения. Чтобы не задергивать жесткий диск папку «/tmp» можно разместить в оперативной памяти при загрузке операционной системы.

Enthusiast ★★★
()
Ответ на: комментарий от ricie

С того что его не запускают под рутом прикрываясь «принципом минимальных привилегий» благодаря чему и появился этот тред, а откуда этот принцип взялся? Что за ним стоит?

cobold ★★★★★
()
Ответ на: комментарий от anonymous

setuid(), setgid()

Чтобы сбросить сразу {R,E,S}{U,G}ID, проще использовать setresuid() и setresgid(). Ещё, в Linux есть fsuid и fsgid, про которые тоже стоит помнить. ЕМНИП, они изменяются через setfsuid() и setfsgid().

Arlecchino ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.