如何在基于ElasticSearch的系统上实现ACL?

时间:2018-05-27 10:45:36

标签: node.js elasticsearch authorization acl

我有一个使用NodeJS和Elasticsearch的系统(RESTful),它实现了RBAC授权策略。 RBAC授权与其他API之前的授权服务器一起使用,根据授权用户角色的路由测试每个请求(使用承载令牌对用户进行身份验证)。

我喜欢这种设计,因为其他API不需要了解授权/身份验证服务。而且非常非常非常快,因为它每次收到测试身份验证的新请求时都使用内存缓存策略而不是向Elasticsearch发出请求。

但现在我需要实施ACL以提供更细粒度的授权控制。从REST的角度来看,该策略将在资源级别应用。示例:“POST:/ user / 123”仅授权给用户。

我已经与客户进行过调查,85%只会使用ACL的允许策略,默认情况下,ACL控件会拒绝所有内容。好的,现在我有了开发这个控件的所有信息。但我没有看到实现这一目标的最佳方法。

我的第一个想法是:

  1. 最重要的系统质量是可扩展的;

  2. 好吧,在内存缓存中做不到,我已经完成了一些模拟,有100万用户和100万资源(这可能是一个真实的场景)而且内存量很大,这个功能会有缓存成本高;

  3. 在这种情况下,身份验证服务无法处理ACL,因为它无法过滤搜索。 auth服务不拦截结果,仅根据角色验证标头和路由;

  4. 因此,有了这些要点,如果在Elasticsearch的每个文档中我都有一个名为“acl_allow_method_user”的新字段,这是一个方法+用户ID被授权使用此资源的数组?最终会得到这样的结论:

  5. "acl_allow_method_user":["POST:123434"]

    我还必须创建一个公共包,供所有API使用,以便在与Elasticsearch的每次交互中验证此策略,但我没有看到任何问题。

    1. 任何有ACL经验的人,这是一个很好的设计吗?

    2. Elasticsearch对数组字段的大小有限制吗?

    3. 性能怎么样?会对这种方法产生影响吗?

2 个答案:

答案 0 :(得分:1)

我建议为ACL使用单独的Elasticsearch索引,该索引应该比主文档索引小得多。这将允许您适当地调整ACL索引设置,例如(1)有多个分片低于你的主文档索引,(2)auto_expand_replicas设置为0-如果你想使用术语查询(例如:加载用户拥有的所有文件),和() 3)实施不同的保留/ GDPR政策。

然后,ACL索引可以包含每个ACL规则的文档,例如:用户id = 1,的docId = 123,OPTYPE = POST。请注意,此方法将允许您将来为其他类型的主体和资源定义ACL规则。此外,这可以支持可以动态匹配新文档的ACL,例如用户id = 1,OPTYPE = POST,图案=" *"将允许userId = 1的用户发布任何文档,实际上是一个系统管理员。从文档/用户中解耦ACL将允许您更新ACL而无需更新相应的文档,这将在Elasticsearch中执行得更好,Elasticsearch不会执行就地更新,而是删除并重新创建文档。此外,您还可以替换(PUT)整个文档,而无需担心保留相关的ACL。但是,您可能希望在删除文档或用户时清除ACL,这可以在删除期间或作为单独的计划清理过程完成。

现在ACL与文档本身是分开的,它们可以缓存在memcached或Redis集群中,而不需要太多内存。在典型的OLTP系统中,只有一小部分用户在任何时间点都处于活动状态,因此您可以适当配置LRU缓存以提高命中率。在不知道您的系统具有何种访问模式的情况下,很难提供进一步的建议。

要考虑的最后一点是 生成ACL。如果自动生成某些ACL,例如基于某种模式,那么也许您可以在系统中使用此模式,以避免每个文档的每个用户都有ACL规则。例如,如果从目录服务生成某些ACL,那么您可以在ACL管理系统中缓存(并定期刷新)LDAP规则。

答案 1 :(得分:0)

对于那些经历同样问题的人来说,我们得出的结论就是:在微服务中使用REST作为资源点的REST粒度代表了类似于多帐户系统的挑战。

它们是业务逻辑,每个服务都知道"如何"有人拥有资源(以及可能的特权)。标准化存储这些规则的数据的方式恰好与每项服务的逻辑知识背道而驰。

我们可以标准化的一点是每个微服务的ACL的端点(承担相同合同和签名的路由)。如果你真的想在API(服务)的私有环境中隔离ACL,因为我们有一个负责用户控制和权限的微服务,整个架构可以转向事件源。

没有ACL私有API隔离的示例:

  1. 我们有3项服务:" S(A)"它负责控制用户和特权," S(B)"和" S(C)"做任何普通任务。

  2. 前端应用程序必须了解S(A),S(B)和S(C)的端点,并提出控制每项服务的ACL策略的单独请求。

  3. 私有API隔离和事件源的示例:

    1. 存在相同的微服务。

    2. 前端应用程序向S(A)发出请求,将一些ACL策略应用于S(B)和S(C)。

    3. S(A)记录政策变更请求,并在通知政策变更的经纪人中触发事件。

    4. S(B)和S(C)捕获事件并在其逻辑中应用策略。

    5. S(B)和S(C)公布政策实施结果(授予或撤销)。

    6. S(A)捕获应用政策的结果事件并记录此结果。

    7. 我会选择@alecswan的答案作为正确答案,因为它是一个"起点"得出那个结论。

      还要感谢@xeye,它提醒我们注意业务逻辑部分。