权限和访问控制
用于权限和访问控制的图数据库
授权和访问控制解决方案存储有关参与方(例如,安全管理员)和资源(例如,业务用户和所有者)的信息,以及管理这些资源访问的规则。控制系统随后应用这些规则来确定谁可以代表另一个用户访问或操作一组动作。传统上,访问控制的实现方式是使用目录服务或在应用程序后端构建自定义解决方案。不幸的是,在关系型数据库上开发的层次目录结构会随着数据集的增大而遭受连接(join)性能瓶颈,变得缓慢且无响应,最终导致糟糕的最终用户体验。
复杂性扼杀一切
使用 Neo4j 这样的图数据库进行访问控制的关键优势在于,可以显著降低引入高风险的复杂需求。当一个业务部门提出一组访问控制用例的需求时,负责交付系统的软件开发人员往往会遇到相当大的阻力。这种阻力就是我喜欢称之为软件工程项目中的“复杂性妥协”。
Neo4j 解决复杂性问题
复杂性妥协是工程团队随着时间积累技术债务的关键因素之一。Neo4j 经过精心设计和打造,能够优雅地降低软件项目的复杂性。Neo4j 是一个成熟的数据库解决方案,受到沃尔玛、Glassdoor、思科系统、惠普、CrunchBase/AOL 等众多顶级企业的工程团队的信赖。数十万工程小时投入到 Neo4j 的开发中,使其成为专门处理图结构数据的 NoSQL 数据库中最成熟的之一。
Neo4j 可以存储复杂且密集连接的访问控制结构,涵盖数十亿参与方和资源。它提供了类似 SQL 数据库的熟悉感,但旨在处理您最复杂的用例和需求,这些需求涉及层次结构和非层次结构数据。
本教程涵盖内容
与网络管理和分析一样,图数据库访问控制解决方案允许自上而下和自下而上的查询。本教程将探讨如何使用 Neo4j 和 Cypher 来确定
-
特定的安全管理员可以管理哪些资源——公司结构、产品、服务、协议、账户和最终用户?
-
最终用户可以在哪些资源上执行操作?
-
给定特定资源,谁可以修改其访问设置或权限?
ACME 系统中的访问控制
本教程演示了虚构公司 ACME Systems 的组织结构。在 ACME Systems 中,安全管理员被分配到一个或多个用户组,这些用户组通过下面描述的继承关系连接到部分而非全部公司。如果一个公司未连接到某个用户组,它将继承父公司中安全管理员的权限。
每个公司通过 WORKS_FOR
关系被分配一个或多个业务用户,每个业务用户通过 HAS_ACCOUNT
关系被分配一个或多个账户。
-
ALLOWED_INHERIT
将安全管理员组连接到组织单元,允许该组内的安全管理员管理该组织单元。此权限由父组织单元的子单元继承。 -
ALLOWED_DO_NOT_INHERIT
以一种方式将安全管理员组连接到组织单元,允许该组内的管理员管理该组织单元,但不包括其任何子单元。 -
DENIED
禁止安全管理员访问组织单元。此权限由父组织单元的子单元继承。DENIED
优先于ALLOWED_INHERIT
,但从属于ALLOWED_DO_NOT_INHERIT
。
访问控制级别及其交互
虽然不极其复杂,但此 GraphGist 包含许多相互关联的部分。让我们从简单到复杂的查询逐步探索不同类型的访问控制。
ALLOWED_INHERIT
同样,ALLOWED_INHERIT
将管理员组连接到组织单元,从而允许该组内的管理员管理该组织单元。此权限由父组织单元的子单元继承。
在 ACME Systems 中,安全管理员 Ben 可以管理 Skunkworks 和 Spinoff 两家公司的员工,这得益于 Group1(Ben 是其成员)与 Acme 之间以及 Group1 与 Startup 之间的 ALLOWED_INHERIT
关系。
MATCH paths=(admin:administrator {name:'Ben'})-[:MEMBER_OF]->()-[:ALLOWED_INHERIT]->(c1:company)<-[:CHILD_OF*0..3]-(c2:company)<-[:WORKS_FOR]-(employee)-[:HAS_ACCOUNT]->(account)
RETURN admin.name AS Admin, c1.name AS `Parent Company`, c2.name AS `Child Company`, employee.name AS Employee
ALLOWED_DO_NOT_INHERIT
同样,ALLOWED_DO_NOT_INHERIT
以一种方式将管理员组连接到组织单元,允许该组内的管理员管理该组织单元,但不包括其任何子单元。Sarah 作为 Group 2 的成员,可以管理 Acme,但不能管理其子单元 Spinoff,因为 Group 2 通过 ALLOWED_DO_NOT_INHERIT
关系而不是 ALLOWED_INHERIT
关系连接到 Acme。
此查询探讨了由于 ALLOWED_DO_NOT_INHERIT
关系,管理员 Sarah 不允许管理哪些用户
MATCH paths=(admin:administrator {name:'Sarah'})-[:MEMBER_OF]->()-[:ALLOWED_DO_NOT_INHERIT]->(c1:company)<-[:CHILD_OF*1..3]-(c2:company)<-[:WORKS_FOR]-(employee)-[:HAS_ACCOUNT]->(account)
RETURN admin.name AS Admin, c1.name AS `Parent Company`, c2.name AS `Child Company`, employee.name AS Employee
DENIED
同样,DENIED
禁止管理员访问组织单元。此权限由父组织单元的子单元继承。在 ACME Systems 中,管理员 Liz 及其对 Big Co、Acquired Ltd、Subsidiary 和 One-Map Shop 的权限最能说明这一点。
让我们看看没有 DENIED
限制的 Liz
MATCH paths=(admin:administrator { name:'Liz' })-[:MEMBER_OF]->()-[:ALLOWED_INHERIT]->(:company)<-[:CHILD_OF*0..3]-(:company)<-[:WORKS_FOR]-(employee)-[:HAS_ACCOUNT]->(account)
RETURN paths
让我们看看有 DENIED
限制的 Liz
MATCH paths=(admin:administrator { name:'Liz' })-[:MEMBER_OF]->()-[:ALLOWED_INHERIT]->(:company)<-[:CHILD_OF*0..3]-(c:company)<-[:WORKS_FOR]-(employee)-[:HAS_ACCOUNT]->(account)
WHERE NOT ((admin)-[:MEMBER_OF]->()-[:DENIED]->()<-[:CHILD_OF*0..3]-(c))
RETURN paths
由于她属于 Group 4 并且 Group 4 对 Big Co 拥有 ALLOWED_INHERIT
权限,Liz 可以管理 Big Co。但尽管这是一个可继承的关系,Liz 无法管理 Acquired Ltd 或 Subsidiary。Liz 所属的 Group 5 被 DENIED
访问 Acquired Ltd 及其子单元(包括 Subsidiary)。
然而,Liz 可以管理 One-Map Shop,这要归功于授予 Liz 所属的最后一个组 Group 6 的 ALLOWED_DO_NOT_INHERIT
权限。
让我们再次查看查询,这次添加 ALLOWED_DO_NOT_INHERIT
MATCH paths=(admin:administrator {name:'Liz'})-[:MEMBER_OF]->()-[:ALLOWED_INHERIT]->()<-[:CHILD_OF*0..3]-(c:company)<-[:WORKS_FOR]-(employee)-[:HAS_ACCOUNT]->(account)
WHERE NOT ((admin)-[:MEMBER_OF]->()-[:DENIED]->()<-[:CHILD_OF*0..3]-(c))
RETURN paths
UNION
MATCH paths=(admin:administrator {name:'Liz'})-[:MEMBER_OF]->()-[:ALLOWED_DO_NOT_INHERIT]->()<-[:WORKS_FOR]-(employee)-[:HAS_ACCOUNT]->(account)
RETURN paths
回想一下,DENIED
优先于 ALLOWED_INHERIT
,但从属于 ALLOWED_DO_NOT_INHERIT
。因此,如果管理员通过 ALLOWED_DO_NOT_INHERIT
和 DENIED
连接到某个公司,则 ALLOWED_DO_NOT_INHERIT
优先。
注意:Cypher 同时支持 UNION
和 UNION ALL
操作符。UNION
从最终结果集中消除重复结果,而 UNION ALL
包含所有重复项。
查找管理员所有可访问资源
让我们进一步了解图数据库管理员在内省或探索数据库时可能看到的内容。每当现场管理员登录系统时,他/她都会看到一个基于浏览器的列表,其中包含他/她可以管理的所有员工和员工账户。
让我们看看任何管理员可以访问的所有资源
MATCH paths=(admin:administrator)-[:MEMBER_OF]->()-[:ALLOWED_INHERIT]->()<-[:CHILD_OF*0..3]-(company)<-[:WORKS_FOR]-(employee)-[:HAS_ACCOUNT]->(account)
WHERE NOT ((admin)-[:MEMBER_OF]->()-[:DENIED]->()<-[:CHILD_OF*0..3]-(company))
RETURN admin.name AS Admin, employee.name AS Employee, collect(account.name) AS Accounts
ORDER BY Admin ASC
UNION
MATCH paths=(admin)-[:MEMBER_OF]->()-[:ALLOWED_DO_NOT_INHERIT]->()<-[:WORKS_FOR]-(employee)-[:HAS_ACCOUNT]->(account)
RETURN admin.name AS Admin, employee.name AS Employee, collect(account.name) AS Accounts
ORDER BY Admin ASC
此查询匹配每个管理员所有可访问的资源,同时考虑了 ALLOWED_INHERIT
、ALLOWED_DO_NOT_INHERIT
和 DENIED
控制之间的交互。
确定管理员是否拥有资源访问权限
我们刚刚查看的查询返回了管理员可以管理的员工和账户列表。在 Web 应用程序中,这些资源(员工、账户)中的每一个都可以通过其自己的 URI 访问。给定一个友好的 URI(例如,http: //acme/accounts/ 5436),如何阻止管理员意外更改未经授权的账户?
我们需要一个查询来确定管理员是否拥有特定资源的访问权限
MATCH p=(admin:administrator)-[:MEMBER_OF]->()-[:ALLOWED_INHERIT]->()<-[:CHILD_OF*0..3]-(company:company)
WHERE NOT ((admin)-[:MEMBER_OF]->()-[:DENIED]->()<-[:CHILD_OF*0..3]-(company))
RETURN admin.name AS Admin, collect(company.name) AS Resource
UNION
MATCH p=(admin)-[:MEMBER_OF]->()-[:ALLOWED_DO_NOT_INHERIT]->(company)
RETURN admin.name AS Admin, collect(company.name) AS Resource
查找账户管理员
前两个查询代表了图的“自上而下”视图。在本教程的最终查询中,我们将讨论数据的“自下而上”视图。给定一个资源——无论是员工还是账户——谁可以管理它?
这是查询
MATCH p=(resource {name:'Acct 10'})-[:WORKS_FOR|HAS_ACCOUNT*1..2]-(company)-[:CHILD_OF*0..3]->()<-[:ALLOWED_INHERIT]-()<-[:MEMBER_OF]-(admin)
WHERE NOT ((admin)-[:MEMBER_OF]->()-[:DENIED]->()<-[:CHILD_OF*0..3]-(company))
RETURN resource.name AS Resource, collect(admin.name) AS Admins
UNION
MATCH p=(resource {name:'Acct 10'})-[:WORKS_FOR|HAS_ACCOUNT*1..2]-(company)<-[:ALLOWED_DO_NOT_INHERIT]-()<-[:MEMBER_OF]-(admin)
RETURN resource.name AS Resource, collect(admin.name) AS Admins
此查询类似于前两个自上而下的查询,但方向相反。请注意 Cypher 如何使用 OR
管道来选择员工或账户资源。
总结
在 Neo4j 中建模资源图非常自然,因为所建模的领域本质上就是图。Neo4j 提供快速、安全的访问,并能回答重要问题,例如
-
用户可以访问哪些订阅,用户是否拥有给定资源的访问权限,以及客户是哪些协议的参与方?
这些操作的速度和准确性至关重要,因为用户登录系统后,必须等待授权计算完成后才能继续操作。
Neo4j 为密集连接的权限树提供了亚秒级查询的可能性,从而提高了系统的性能特性。此外,Neo4j 允许在图中忠实地再现客户的结构和内容层次结构,无需修改,从而消除了为特定应用程序存储数据而进行的数据重复和反规范化。通过无需为特定应用程序的性能需求而对数据进行特殊处理,Neo4j 为在其他应用程序中扩展和重用客户图提供了基础。
参考资料
本 GraphGist 包含 Ian Robinson 和 Jim Webber 合著的 O’Reilly 出版社《图数据库》一书中的内容。您可以在 https://www.graphdatabases.com/ 免费获取电子书版本。
有用的后续步骤
请访问社区管理的开发者资源网站:https://www.neo4j.com/developer
此页面有帮助吗?