Skip to content

Latest commit

 

History

History
289 lines (251 loc) · 12.4 KB

README.md

File metadata and controls

289 lines (251 loc) · 12.4 KB

ongdb-lab-security

    细粒度图数据访问控制组件,数据库管理员通过配置特殊角色账户的形式实现,支持在线自定义配置进行热更新权限操作,不用重启数据库服务。读写权限的控制粒度可以细化到标签、关系、属性,并且区分不同的用户对数据删除权限进行严格管控。

    主要实现细粒度读写细粒度读权限的配置。细粒度写可以控制用户只能操作某些标签、关系以及属性,是否可以新建与修改属性、标签和关系,取决于权限的细粒度配置。细粒度读可以限制用户只能执行某些数据的查询,并支持指定具体的Query,相当于为用户指定了一个Query白名单。

    图数据库基于角色的访问控制体系,在使用时通过将不同角色组合,分配给同一用户多个角色,可以实现更丰富的访问控制功能。例如,某个用户具有部分子图的读取权限,但是也需要具备对某个标签的多个属性拥有修改、删除、创建的权限。

图数据库的主要角色权限类型:

编号 类型 说明
1 Reader 只读
2 Publisher 读写数据
3 Architect 定义索引、限制等数据库模式对象
4 Administrator 管理用户和角色,管理数据库运行
5 Editor 可以读写但是无法新建标签和关系
6 Define 自定义角色

    其中ongdb-lab-security组件主要是实现第六类Define权限配置,例如要根据特定标签、关系和属性上的过滤条件对图的一部分子图实现访问控制,则可以通过ongdb-lab-security组件实现。生成的配置文件在图数据库安装路径auth目录下。

    访问控制的基本思路是定义新用户和角色,为该角色指定只有运行某些扩展过程的权限,然后在扩展过程中根据调用过程的用户及其角色,应用不同的过滤条件,按照标签、关系类型、属性值对结果进行筛选。
    这些用户因为只有运行特定过程的权利,因此无法通过Browser登陆数据库来运行Cypher查询,而只能通过应用客户端访问数据库。

使用前准备

在图数据库节点执行安装组件、修改配置、重启图数据库操作;如果是集群环境所有节点需要执行相同操作。

  • 1.将ongdb-lab-security-*.jar放在plugins文件夹
  • 2.修改conf配置
// 为角色指定权限
dbms.security.procedures.roles=olab.security.publisher.*:publisher_proc;olab.security.reader*:reader_proc;olab.security.get*:publisher_proc,reader_proc;routing:publisher_proc,reader_proc;apoc.bolt.execute:publisher_proc,reader_proc;
  • 3.重启图数据库

使用步骤

1、创建角色

WITH ['reader_proc','publisher_proc'] AS roles
UNWIND roles AS role
CALL dbms.security.createRole(role) RETURN role;

2、配置账号

// 如果需要自定义修改用户则修改`reader_users`和`publisher_users`再进行下一步操作即可
// 预定义特殊Reader用户
WITH ['reader-1','reader-2'] AS reader_users
// 预定义特殊Publisher用户
WITH ['publisher-1','publisher-2'] AS publisher_users,reader_users
WITH apoc.coll.union(reader_users,publisher_users) AS users
UNWIND users AS user
// 默认密码`abc%pro`,初次登陆时不用修改口令
// CALL dbms.security.deleteUser(user) RETURN user;
CALL dbms.security.createUser(user,'abc%pro',false) RETURN user;

3、指定角色

  • 为特殊Reader用户指定角色
WITH ['reader-1','reader-2'] AS reader_users
UNWIND reader_users AS user
// 为特殊Reader用户指定角色
CALL dbms.security.addRoleToUser('reader_proc',user) RETURN user;
  • 特殊Publisher用户指定角色
WITH ['publisher-1','publisher-2'] AS publisher_users
UNWIND publisher_users AS user
// 为特殊Publisher用户指定角色
CALL dbms.security.addRoleToUser('publisher_proc',user) RETURN user;

4、Operator操作权限说明

    Operator参数定义了对标签、关系、属性的操作权限的级别定义,使用olab.security.setPublisher过程为用户分配数据编辑权限。拥有创建指定数据的特殊权限账户,在创建数据时节点和关系会默认带有系统用户名字段__system_users和字段用户归属标记字段__system_field_users,存储为一个数组格式,这两个字段主要使用JSON字符串保存数据创建人的信息。在使用DELETER_RESTRICT权限时,会根据该字段来判断用户是否对数据拥有删除权限。【该功能和READER_FORBID操作类型一起增加到To Do List】

    权限下发机制,当节点拥有一个PUBLISHER权限时,用户可以对已有数据进行编辑修改并且可以创建新数据,对所属属性都可以执行PUBLISHER操作,但是无法删除。如果这时对节点的属性指定了一个DELETER_RESTRICT权限,那么用户则可以对自己创建的属性执行删除操作。如果对节点的属性指定了一个DELETER权限,则当前用户可以删除任何其它用户创建的属性数据。

    需要注意的是,使用olab.security.setPublisherolab.security.setReader给原有用户增加权限时可以直接进行设置新权限,权限系统会自动进行追加。

操作级别 类型 说明
1 READER_FORBID 禁止读取
2 READER 可以读取
3 EDITOR 对已有数据的编辑修改权限
【需要注意的是当用户对标签或关系类型具有该权限时表示也可以新增删除标签或关系类型】
【属性设置为该权限时只可修改属性值】
4 PUBLISHER 对已有数据的编辑修改权限、拥有创建新数据权限
5 DELETER_RESTRICT 对已有数据的编辑修改权限、拥有创建新数据权限、拥有删除数据权限
【仅允许删除用户自己创建的数据】
【当属性设置为该权限时,如果用户对节点或关系存在大于该级别的权限则属性也可以执行一样的权限级别】
6 DELETER 对已有数据的编辑修改权限、拥有创建新数据权限、拥有删除数据权限

5、使用Administrator账户分别为reader-*、publisher-*账户配置可用的操作权限

  • Publisher-1配置权限

说明:

  1. 配置Publisher权限【合并权限列表】【admin】
  2. 对于properties配置字段值检查check时可以使用olab.security.getValueTypes查看可配置的值检查类型
  3. properties不为空时表示对可操作属性进行限制,为空时表示没有配置属性权限
  4. 对属性值进行检查:为用户设置权限时,对于值的类型也设置了check操作,在这里检查用户输入的值类型是否满足管理员限定的要求
  5. 对值也可以限制:设置权限时可设置invalid_values参数,表示对值进行验证,如果值包含在这个列表中则提示错误,通常使用在限制用户输入错误的值或限制用户不能设置特定的属性值
  6. constraint参数支持对属性增加EXISTS限制,表示该属性必须存在,不需要加限制则保留空字符串即可

olab.security.setPublisher入参:

  1. @param username:用户名
  2. @param nodeLabels:可操作的标签列表【可为空】【追加】 label properties[<field,operator>] operator
  3. @param relTypes:可操作的关系类型列表【可为空】【追加】 start_label type end_label properties[<field,operator[]>] operator
CALL olab.security.setPublisher('publisher-1',
[
	{
    label:'Person',
	invalid_values:['人物'],
    properties:[
    	{
        field:'name',
        operator:'DELETER_RESTRICT',
        check:'STRING',
        invalid_values:['001',''],
        constraint:''
        }
    ],
    operator:'EDITOR'
    }
    ,
    {
    label:'Movie',
    invalid_values:['电影'],
    properties:[
    	{
        field:'name',
        operator:'DELETER_RESTRICT',
        check:'STRING',
        invalid_values:['001',''],
        constraint:'EXISTS'
        }
    ],
    operator:'EDITOR'
    }
],
[
	{
    start_label:'Person',
    type:'ACTED_IN',
    invalid_values:['参演'],
    end_label:'Movie',
    operator:'DELETER_RESTRICT',
    properties:[
    	{
        field:'date',
        operator:'PUBLISHER',
        check:'INTEGER',
        invalid_values:['2021',''],
        constraint:'EXISTS'
        }
        ]
    }
]
) YIELD username,currentRole,nodeLabels,relTypes RETURN username,currentRole,nodeLabels,relTypes
  • Reader-1配置权限
// 配置Reader权限【合并权限列表】【admin】
// @param username:用户名
// @param queries:可执行查询列表 query_id query【可为空】【追加】【query_id不可重复】【Query需要返回属性键值格式,不支持直接返回节点和关系】
// 配置时可加入一个`description`字段对查询含义进行描述,方便使用者理解;该参数为可选参数
CALL olab.security.setReader('reader-1',
[
	{
    query_id:'query001',
    query:'MATCH (n) RETURN n.name AS name LIMIT 10'
    }
    ,
    {
    query_id:'query002',
    query:'MATCH (n) WITH n LIMIT 10 RETURN olab.result.transfer(n) AS mapList;',
    description:'查询任意十个节点并输出Table'
    }
    ,
    {
    query_id:'query003',
    query:'MATCH ()-[r]->() WITH r LIMIT 10 WITH olab.result.transfer(r) AS mapList UNWIND mapList AS map RETURN map;'
    }
    ,
    {
    query_id:'query004',
    query:'MATCH (tom {name:$name}) RETURN tom.name AS name,tom.born AS born;'
    }
]
) YIELD username,currentRole,queries RETURN username,currentRole,queries
  • 获取指定用户的权限列表
CALL olab.security.fetchUserAuth('reader-1') YIELD value RETURN value
  • 重置指定用户的权限列表
// @param username:用户名
CALL olab.security.clear('reader-1') YIELD username,currentRole RETURN username,currentRole
  • 获取所有的已配置权限列表
CALL olab.security.list() YIELD value RETURN value

使用案例

1、publisher_proc角色的账户使用

publisher-1用户为例

  • 1.查看拥有的权限
CALL olab.security.get() YIELD value RETURN value
// 对照权限定义
CALL olab.security.getAuth() YIELD operate,level,description RETURN operate,level,description
  • 2.合并节点
CALL olab.security.publisher.merge.node({label},{merge_field},{merge_value},{[other_pros]}) YIELD value RETURN value
  • 3.删除节点
CALL olab.security.publisher.delete.node({node_id}) YIELD value RETURN value
  • 4.合并关系
CALL olab.security.publisher.merge.relationship({start_id},{end_id},{merge_rel_type},{rel_pros}) YIELD value RETURN value
  • 5.删除关系
CALL olab.security.publisher.delete.relationship({rel_id}) YIELD value RETURN value
  • 6.修改节点的属性值
CALL olab.security.publisher.update.node({node_id},{field_name},{field_value}) YIELD value RETURN value
  • 7.修改关系的属性值
CALL olab.security.publisher.update.relationship({rel_id},{field_name},{field_value}) YIELD value RETURN value
  • 8.删除节点的属性键
CALL olab.security.publisher.remove.node.key({node_id},{field_name}) YIELD value RETURN value
  • 9.删除节点的某个标签
CALL olab.security.publisher.remove.node.label({node_id},{label}) YIELD value RETURN value
  • 10.删除关系的属性键
CALL olab.security.publisher.remove.relationship.key({rel_id},{field_name}) YIELD value RETURN value
  • 11.增加节点的标签
CALL olab.security.publisher.add.node.label({node_id},{label}) YIELD value RETURN value

2、reader_proc角色的账户使用

reader-1用户为例

  • 1.查看拥有的权限
CALL olab.security.get() YIELD value RETURN value
  • 2.执行查询
CALL olab.security.reader('query001',NULL) YIELD value RETURN value;
CALL olab.security.reader('query004',{name:'Tom Hanks'}) YIELD value RETURN value;

集群状态下使用

  • 在单机情况下下列写入操作可以正常执行,但是在集群状态下只读节点上该查询是无法正常执行的
CALL olab.security.publisher.merge.node('Person','name','test',NULL) YIELD value RETURN value
  • 集群状态下使用routing过程进行路由转发,并在auth文件下配置security_routing.access文件,并写入bolt协议映射的CORE节点的地址即可
// 配置好以后,在只读节点也可以运行该查询
CALL routing("publisher-1","abc%25pro","CALL olab.security.publisher.merge.node('Person','name','test',NULL) YIELD value RETURN value")