Как определить в SQL, если пользователь может читать / писать / выполнять файл в системе разрешений Unix? - PullRequest
0 голосов
/ 31 октября 2018

Я пытаюсь написать приложение, где есть файлы и пользователи. Права доступа к файлам должны быть такими же, как в unix: чтение / запись / выполнение. Каждый файл принадлежит владельцу и группе, и для каждого файла есть «другие» пользователи (в зависимости от того, кто является владельцем, а кто принадлежит группе). Схема выглядит следующим образом:

create table s_file(
file_id INTEGER PRIMARY KEY,
parent_id INTEGER default NULL,
name,
content BLOB DEFAULT NULL,
owner_id INTEGER NOT NULL,
group_id INTEGER NOT NULL,
read_owner BOOLEAN not null default 1,
write_owner BOOLEAN not null default 1,
execute_owner BOOLEAN not null default 1,
read_group BOOLEAN not null default 1,
write_group BOOLEAN not null default 0,
execute_group BOOLEAN not null default 1,
read_other BOOLEAN not null default 1,
write_other BOOLEAN not null default 0,
execute_other BOOLEAN not null default 1
);

create table s_user( uid INTEGER PRIMARY KEY, 
               name NOT NULL, password NOT NULL);

create table s_group( gid INTEGER PRIMARY KEY, name NOT NULL);

create table s_user_in_group ( uid INTEGER NOT NULL, 
                         gid INTEGER NOT NULL);


insert into s_user(uid,name,password) values (1,'root','pw');
insert into s_user(uid,name,password) values (2,'gauss', 'pw');
insert into s_user(uid,name,password) values (3,'conway', 'pw');
insert into s_group(gid,name) values (1,'root');
insert into s_group(gid,name) values (2,'producer');
insert into s_group(gid,name) values (3,'gauss');
insert into s_group(gid,name) values (4,'conway');
insert into s_user_in_group(uid,gid) values (2,2),(2,3),(3,4);
insert into s_file(file_id,name,owner_id,group_id) values (1,'galois',1,1);
insert into s_file(file_id,parent_id,name,owner_id,group_id) values (2,1,'home',1,1);
insert into s_file(file_id,parent_id,name,owner_id,group_id,write_group) values (3,1,'models',1,2,1);
insert into s_file(file_id,parent_id,name,owner_id,group_id) values (4,2,'gauss',2,3);
insert into s_file(file_id,parent_id,name,owner_id,group_id) values (5,2,'conway',3,4);
insert into s_file(file_id,parent_id,name,owner_id,group_id,content) values (6,4,'boston.pfa',2,3,'cB');
insert into s_file(file_id,parent_id,name,owner_id,group_id,content) values (7,5,'iris.pfa',3,4,'cI');
insert into s_file(file_id,parent_id,name,owner_id,group_id,write_group,content) values (8,3,'boston.pfa',2,2,1,'CB');
insert into s_file(file_id,parent_id,name,owner_id,group_id,write_group,content) values (9,3,'iris.pfa',2,2,1,'CI');

Вот несколько примеров данных: Дерево файлов:

galois
|-- home
|   |-- gauss
|   |   +-- boston.pfa
|   +-- conway
|       +-- iris.pfa
+-- models
    |-- boston.pfa
    +-- iris.pfa

Я хотел бы написать запрос, если это возможно в sqlite, в противном случае с python, чтобы увидеть, например, если пользователь conway, может написать /galois/models/boston.pfa Согласно данным моего примера, которые вы можете найти ниже, это не должно быть возможным, так как conway не является ни владельцем, ни в группе производителей, а другим не разрешено писать. Итак, что я пытаюсь сделать, если это возможно в SQL, это следующая таблица / запись:

file_id, user_id, can_write/can_execute/can_read

Ниже приведены некоторые примеры данных:

sqlite> select file_id, parent_id, name, owner_id, group_id, write_owner,   write_group,write_other from s_file;
1||galois|1|1|1|0|0
2|1|home|1|1|1|0|0
3|1|models|1|2|1|1|0
4|2|gauss|2|3|1|0|0
5|2|conway|3|4|1|0|0
6|4|boston.pfa|2|3|1|0|0
7|5|iris.pfa|3|4|1|0|0
8|3|boston.pfa|2|2|1|1|0
9|3|iris.pfa|2|2|1|1|0


sqlite> select uid,name from s_user;
1|root
2|gauss
3|conway


sqlite> select gid,name from s_group;
1|root
2|producer
3|gauss
4|conway


sqlite> select uid,gid from s_user_in_group;
2|2
2|3
3|4

Есть предложения?

Спасибо за вашу помощь!

Редактировать : По предложению @Mike я бы поступил следующим образом: 1. Создайте представление

file_id, user_id, can_read, can_write, can_execute

с "локальными" разрешениями

  1. Используйте CTE, чтобы решить, может ли пользователь получить доступ (в виде unix) к определенному файлу для этого пользователь должен иметь права на выполнение каждой директории над файлом до корневого каталога.

Моя проблема состоит в том, чтобы решить, можно ли сделать первый шаг исключительно в sql (это было бы здорово) или мне нужно смешать его с python [В этом случае я бы также реализовал шаг 2. в python]

Или, может быть, у вас есть лучшее представление о том, как структурировать (схему) данные для достижения этой цели?

Еще раз спасибо за помощь!

1 Ответ

0 голосов
/ 31 октября 2018

Я нашел решение:

create view if not exists user_rights as
select u.uid,f.file_id, 
case 
  when f.owner_id = u.uid then f.read_owner
  when u.uid = uig.uid then max(f.read_group) else max(f.read_other) end as     can_read,
case 
 when f.owner_id = u.uid then f.write_owner
 when u.uid = uig.uid then max(f.write_group) else max(f.write_other) end as can_write,
case 
  when f.owner_id = u.uid then f.execute_owner
  when u.uid = uig.uid then max(f.execute_group) else max(f.execute_other) end as can_execute
      from s_user u,s_file f left join s_user_in_group uig on f.group_id = uig.gid group by u.uid,file_id;

Полное решение можно найти здесь:

https://github.com/orgesleka/unix-acl-sql

...