Учитывая, что у пользователя root есть некоторые учетные данные (скажем, ключ API), заданные в переменной среды, и при наличии непривилегированного пользователя John, как я могу позволить Джону выполнить сценарий, который использует указанный ключ API, без риска утечки его значения Джону ?
1 ответ
Вопрос кажется немного не сфокусированным.
Вопрос сам по себе говорит о получении значения из «переменной среды суперпользователя» (т. Е. «Корневой переменной среды»). Я даже не уверен, что это значит. Вы говорите, что Джон должен получить значение из среды (другого) пользователя, вошедшего в систему как «root», или который работает как «root» через
su
илиsudo
? Или вы говорите о среде процесса (возможно, фонового), выполняющегося от имени пользователя root?Но, какие бы детали вы ни имели в виду, звучит так, будто ключ очень динамичный и эфемерный. Поскольку я не понимаю, что это значит, я не скажу, что это невозможно, но звучит сложно.
Но затем в комментарии вы говорите о создании сценария исполняемого, но не читаемого. Это говорит о том, что вы готовы иметь ключ, жестко запрограммированный в сценарии, если пользователи без прав root не могут его прочитать. Это говорит о том, что ключ очень статичен и меняется настолько редко, что вы готовы изменять скрипт каждый раз, когда ключ меняется.
U & L имеет длинную тему на эту тему:может ли скрипт быть исполняемым, но не читаемым? К сожалению, большинство ответов отрицательные или являются отклонениями, отклонениями или обходными путями, некоторые из которых работают лучше, чем другие. Например, Сантана предлагает создать запись в
/etc/sudoers
которая позволит Джону запускать сценарий с повышенными разрешениями, но при этом не сможет читать его самому. Но если сценарию не нужны повышенные разрешения (кроме получения ключа), вы не хотите запускать его с повышенными разрешениями.Однако в этом связанном вопросе (о суперпользователе ) я представляю хитрый способ сделать скрипт исполняемым, но не читаемым, обернув его в программу на Си. Как я объясняю в этом ответе, эта техника не является надежной; Есть способы, которыми информация может просочиться.
ИМХО, наиболее разумная / правдоподобная интерпретация заключается в том, что ключ хранится в файле, который Джон не может прочитать. Традиционным способом реализации таких соглашений является setUID и / или setGID. (
sudo
также полезно.)
Вот пример того, как это сделать. Напишите программу на C, например:
#include <stdio.h> #include <stdlib.h> #define KEY_FILE (appropriate pathname) #define SCRIPT (appropriate pathname) main() { FILE *key_fp; char key[80]; (adjust as appropriate) gid_t gid; uid_t uid; char *args[10]; (adjust as appropriate) key_fp = fopen(KEY_FILE, "r"); if (key_fp == NULL) { perror(KEY_FILE); exit(1); } (your code to read and validate key) fclose(key_fp); if (setenv("KEY", key, 1) != 0) { fprintf(stderr, "Problem with setenv().\n"); exit(1); } gid = getgid(); uid = getuid(); // use // if (setresgid(gid, gid, gid) != 0 || setresuid(uid, uid, uid) != 0) // if they’re available; otherwise if (setregid(gid, gid) != 0 || setreuid(uid, uid) != 0) { fprintf(stderr, "Problem dropping privileges.\n"); exit(1); } args[0] = "scriptname"; (adjust as appropriate) args[1] = NULL; execv(SCRIPT, args); perror(SCRIPT); exit(1); }
Определите KEY_FILE
для полного пути к файлу, который содержит ключ, и задайте SCRIPT
для полного пути к файлу, который содержит скрипт.
Убедитесь, что у Джона есть доступ на чтение к сценарию, но не к файлу ключа, и что у него нет прав на запись ни в один из каталогов в любом из путей.
Сделайте так, чтобы эта программа могла читать файл ключа, задав для него setUID и / или setGID. Он прочитает ключ, вставит его в среду, сбросит привилегии и выполнит скрипт.
(Вы можете захотеть изменить приведенный выше код, чтобы аргументы командной строки, передаваемые программе, передавались в сценарий.)
Как указано выше, сценарий будет выполняться с UID и GID Джона, но с ключом в среде.
В некоторых системах Джон может читать среду сценария из /proc/(pid_of_script)/environ
или с помощью ps
.
Если это так, может быть полезно, чтобы скрипт немедленно скопировал ключ в локальную (не экспортируемую) переменную и сбросил переменную KEY
.
Вероятно, для сценария будет безопасно передать ключ программе
- через канал (например,
printf "%s" (key_value) | (program)
), - через здесь документ, или
- через строку здесь.
Риски передачи ценности через окружающую среду упомянуты выше.
Избегайте передачи его в качестве параметра командной строки, так как это определенно может быть видно по ps
.
Если вы хотите, чтобы программа работала через sudo
, вам может понадобиться жестко кодировать UID и GID Джона, потому что sudo
устанавливает как действительные, так и действительные идентификаторы.